skip to Main Content

I’m trying to write a script to update the permissions for a managed identity using Powershell and the REST API, but I’m running into a problem and I don’t know how to troubleshoot it any further.

My script connects to an App Registration with App ID and Secret, generates a token and I use that token in my "Invoke-RestMethod" command.

Connecting works fine, and I can run GET commands against the endpoints, but trying to update it using a POST gives me an error of "Not a valid reference update".

This is the ‘bit of code:

# Payload in Hashtable
$POSTBody = @{
    principalID = "$($MIDData.id)"
    resourceID = "$ObjectID"
    appRoleId = "$($TEMProle.id)"
}


# check if Hashtable converts to JSON
$POSTBody | convertto-json

$AppRoleAssignment = "https://graph.microsoft.com/beta/servicePrincipals/$ObjectID/appRoleAssignedTo"

Invoke-RestMethod -Uri $AppRoleAssignment -Headers @{Authorization = "Bearer $($TokenAccess)" }  -Method POST -Body $($POSTBody | convertto-json) -ContentType "application/json"

I’m confident my variables are correct. I’ve tried hard-coding them as well, but I get the same result.

Any wisdom or guidance would be most appreciated.

2

Answers


  1. Note that, you need to pass Object ID of Microsoft Graph Enterprise Application for resourceID parameter.

    In my case, I ran below API call to get the object ID of Microsoft Graph service principal:

    GET https://graph.microsoft.com/v1.0/servicePrincipals?$filter=appId eq '00000003-0000-0000-c000-000000000000'
    

    enter image description here

    Now I ran below PowerShell script to generate token and call API to add User.Read.All permission of Application type to managed identity:

    $AppId = "appID"
    $ClientSecret = "secret"
    $TenantId = "tenantID"
    
    $TokenEndpoint = "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token"
    $Body = @{
        client_id     = $AppId
        scope         = "https://graph.microsoft.com/.default"
        client_secret = $ClientSecret
        grant_type    = "client_credentials"
    }
    
    $TokenResponse = Invoke-RestMethod -Uri $TokenEndpoint -Method Post -Body $Body -ContentType "application/x-www-form-urlencoded"
    $AccessToken = $TokenResponse.access_token
    
    $PrincipalId = "fd0e0b8b-53f6-4bcd-a723-xxxxx"   # Managed identity Object ID
    $ResourceId = "c68a82f4-ecea-4f65-8047-xxxxx"     # Microsoft Graph Enterprise App Object ID
    $AppRoleId = "df021288-bdef-4463-88db-98f22de89214"      # User.Read.All permission App Role ID
    
    $POSTBody = @{
        principalId = $PrincipalId
        resourceId  = $ResourceId
        appRoleId   = $AppRoleId
    }
    
    $POSTBodyJSON = $POSTBody | ConvertTo-Json 
    
    $AppRoleAssignment = "https://graph.microsoft.com/beta/servicePrincipals/$ResourceId/appRoleAssignedTo"
    
    try {
        $Response = Invoke-RestMethod -Uri $AppRoleAssignment `
            -Headers @{Authorization = "Bearer $AccessToken"} `
            -Method POST `
            -Body $POSTBodyJSON `
            -ContentType "application/json"
    
        Write-Host "App Role Assignment Successful:"
        Write-Host ($Response | ConvertTo-Json -Depth 10 -Compress)
    } catch {
        Write-Error "Error assigning App Role: $($_.Exception.Message)"
    }
    

    Response:

    enter image description here

    To confirm that, I checked the same in Azure Portal where User.Read.All permission of Application type added successfully to managed identity like this:

    enter image description here

    Reference:

    Grant an appRoleAssignment for a service principal – Microsoft Graph

    Login or Signup to reply.
  2. Need attention to the id you passed in.

    1. PrincipalId: the Object ID of the service principal, not the Application ID
    2. AppRoleId: the permission Id, It is related to the resourceId. If you set microsoft graph Group.Read.All, the example id is 5b567255-7703-4780-807c-7be8301ae99b, just check here
    3. resourceId: The service principal Object id of the resource. If the resource is Microsoft Graph, which have the Application ID 00000003-0000-0000-c000-000000000000, and the Object ID 3b7856dd-b583-4c67-aea4-fe8ec1af1dd0, Just use the Object Id, not the Application ID
    $headers = @{
        "Content-Type" = "application/json"
        "Authorization" = "Bearer " + $Token
    }
    
    $uri = "https://graph.microsoft.com/v1.0/servicePrincipals/{0}/appRoleAssignments" -f $PrincipalId
    
    $body = @{
        principalId = $PrincipalId
        resourceId  = $ResourceId
        appRoleId   = $AppRoleId
    }
    
    $bodyString = $body | ConvertTo-Json -Depth 10
    
    $response = Invoke-RestMethod -Method Post -Uri $uri -Body $bodyString -Headers $headers
    
    return $response
    

    I have a example in postman, it is the same as script. Noting my passing Ids.

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search