简体   繁体   中英

Using Microsoft Graph SDK for Powershell to Assign Role to App Service Principal?

I am using https://github.com/microsoftgraph/msgraph-sdk-powershell , as I need Powershell 7 support for my script, the AzureAD module has a ton of issues in anything but Powershell 5 on Windows I am finding. Basically, I am trying to create an app registration in a B2C tenant. The problem I was having, was my script seemed fine but I wasn't able to grant any admin consent to any of the scopes defined. Then I noticed the issue - when you create an app registration in the portal it automatically gets a service principal, which New-MgApplication does not do.

I have the below script which works, up until I try and assign the service principal to my app using New-MgServicePrincipalAppRoleAssignment , where it breaks down with the error: New-MgServicePrincipalAppRoleAssignment_CreateExpanded: Not a valid reference update.

I am unsure if this is the function appropriate for my need or whether New-MgRoleManagementDirectoryRoleAssignment is the correct function.

function Upsert-AppRegistration {
    Param(
        [string] $TemplateParametersFile,
        [string] $ResourceGroupName
    )

    $templateParameters = Get-Content $TemplateParametersFile | ConvertFrom-Json
    $customerName = $templateParameters.parameters.customerName.value
    $deploymentIdentifier = $templateParameters.parameters.deploymentIdentifier.value
    $b2cTenantId = $templateParameters.parameters.b2cTenantId.value
    $b2cTenantName = $templateParameters.parameters.b2cTenantName.value

    $GraphConnection = Connect-Graph -TenantId $b2cTenantId -Scopes "User.Read","User.ReadWrite.All","Mail.ReadWrite",`
            "Directory.ReadWrite.All","Chat.ReadWrite", "People.Read", `
            "Group.Read.All", "Directory.AccessAsUser.All", "Tasks.ReadWrite", `
            "Sites.Manage.All"

    [string[]]$webRedirectUris = 
        "https://localhost:5050/LoginView",
        "https://localhost:5050/DashboardView",
        "https://localhost:5050/UsersView",
        "https://localhost:5050/OrdersView"

    # Our custom app.login scope for delegated permissions from front-end login
    $oauth2PermissionScopes = @{
        "Id" = [guid]::NewGuid().guid
        "Value" = "app.login"
        "AdminConsentDescription" = "This will provide the application access to login"
        "AdminConsentDisplayName" = "Admin delegated login"
        "IsEnabled" = $true
        "Type" = "Admin"
    }

    [object[]]$appLoginScope = @{
        "Id" = $oauth2PermissionScopes.Id
        "Type" = "Scope"
    }

    # Microsoft.Graph ResourceAccess scopes and roles
    $mgOfflineAccessScope = @{
        "Id" = "7427e0e9-2fba-42fe-b0c0-848c9e6a8182"
        "Type" = "Scope"
    }

    $mgOpenidScope = @{
        "Id" = "37f7f235-527c-4136-accd-4a02d197296e"
        "Type" = "Scope"
    }

    $mgDirectoryReadWriteAllRole = @{
        "Id" = "19dbc75e-c2e2-444c-a770-ec69d8559fc7"
        "Type" = "Role"
    }

    $mgResourceAccess = $mgOfflineAccessScope, $mgOpenidScope, $mgDirectoryReadWriteAllRole

    [object[]]$requiredResourceAccess = @{
        "ResourceAppId" = "00000003-0000-0000-c000-000000000000"
        "ResourceAccess" = $mgResourceAccess
    }
    $mgApplicationParams = @{
        "DisplayName" = "${customerName}-${deploymentIdentifier}"
        "ApiOauth2PermissionScopes" = $oauth2PermissionScopes
        "ApiRequestedAccessTokenVersion" = 2
        "ImplicitGrantSettingEnableAccessTokenIssuance" = $true
        "ImplicitGrantSettingEnableIdTokenIssuance" = $true
        "RequiredResourceAccess" = $requiredResourceAccess
        "WebLogoutUrl" = "https://localhost:5050/LogoutView"
        "WebRedirectUris" = $webRedirectUris
        "IdentifierUris" = "https://$b2cTenantName.onmicrosoft.com/app"
    }

    # We need to create our application before we can add permissions to our custom scope
    $mgApplication = New-MgApplication @mgApplicationParams

    # Now our application has an Id so we can finish setting up the RequiredResourceAccess

    $newRequiredResourceAccess =  $requiredResourceAccess + @{
        "ResourceAppId" = $mgApplication.AppId
        "ResourceAccess" = $appLoginScope
    }

    # Azure doesn't always update immediately, make sure app exists before we try to update its config
    $appExists = $false
    while (!$appExists) {
        Start-Sleep -Seconds 2
        $appExists = Get-MgApplication -ApplicationId $mgApplication.Id
    }

    $mgApplicationParams.Add("ApplicationId", $mgApplication.Id)
    $mgApplicationParams.RequiredResourceAccess = $newRequiredResourceAccess
    Update-MgApplication @mgApplicationParams

    $appServicePrincipal = New-MgServicePrincipal -AppId $mgApplication.AppId -Tags @("WindowsAzureActiveDirectoryIntegratedApp")

    $result = New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $appServicePrincipal.Id `
        -AppRoleId 19dbc75e-c2e2-444c-a770-ec69d8559fc7 `
        -ResourceId 429a2356-9cdc-475e-8caf-cfe8b7c77db8 `
        -PrincipalType "ServicePrincipal"

    # @TODO Generate app client secret 
    $appClientSecret = "--SECRET--"

    Write-Host "Created the app registration ${customerName}-${deploymentIdentifier} with client Id:",
        $mgApplication.AppId -ForegroundColor Yellow

    @{
        "appClientId" = $mgApplication.AppId
        "appClientSecret" = $appClientSecret
    }
}

Turns out I did not need to assign a role to my service principal for it work and everything to show up correctly. It was a combination of Azure's UI being laggy and also key was adding the Tag in the service principal, which when I posted this I had not yet tested.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM