skip to Main Content

I am trying to read global admins out of a portal using PowerShell.
I know I am very close, I can read VMs and other information out.

I connect in with this:

Connect-AzAccount -CertificateThumbprint $certThumbPrint -ApplicationId $applicationID -Tenant $tenantID -ServicePrincipal
# Verify connection
if (-not (Get-AzContext)) {
    Write-Host "Failed to connect to Azure. Please check your credentials and try again." -ForegroundColor Red
    return
}

I read VMs with this:

# Get a list of VMs
$vms = Get-AzVM 

# Display VM information
foreach ($vm in $vms) {
    Write-Host "VM Name: $($vm.Name), Resource Group: $($vm.ResourceGroupName)"
    # Add more details as needed
}

I try to read global admins with this but get unauthorized error:

Connect-MgGraph -ClientId $applicationID -TenantId $tenantID -CertificateThumbprint $certThumbPrint
# Connect-MgGraph -ClientId $appId -TenantId $tenantId -CertificateThumbprint $thumbprint

$adminRole = Get-MgDirectoryRole -Filter "DisplayName eq '$roleName'"

if ($adminRole) {
    $roleMembers = Get-MgDirectoryRoleMember -DirectoryRoleId $adminRole.Id

    if ($roleMembers) {
        $roleMembers | ForEach-Object {
            [PSCustomObject]@{
                DisplayName = $_.AdditionalProperties["displayName"]
                Id          = $_.Id
            }
        } | Format-Table DisplayName, Id
    } else {
        Write-Host "No members found for the role: $roleName"
    }
} else {
    Write-Host "Role '$roleName' not found"
}

Get-MgDirectoryRole_List:
Line |
4 | $adminRole = Get-MgDirectoryRole -Filter "DisplayName eq ‘$roleName’"
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Insufficient privileges to complete the operation.

Status: 403 (Forbidden)
ErrorCode: Authorization_RequestDenied
Date: 2024-11-06T22:30:03

Headers:
Cache-Control : no-cache
Vary : Accept-Encoding
Strict-Transport-Security : max-age=31536000

App registration permissions:
enter image description here

I feel like I’m missing something small and simple here.

Thank you all.

2

Answers


  1. Initially, I created one app registration and uploaded certificate in it like this:

    enter image description here

    Now, I added Directory.Read.All permission of Application type in it with admin consent as below:

    enter image description here

    When I ran same script in my environment, I got the response with list of users having "Global Administrator" role successfully as below:

    $applicationID = "appId"
    $tenantID = "tenantId"
    $certThumbPrint = "65876F7BB07xxxxxxxx4848DDE"
    $roleName = "Global Administrator"
    
    Connect-MgGraph -ClientId $applicationID -TenantId $tenantID -CertificateThumbprint $certThumbPrint -Scopes "Directory.Read.All"
    
    $adminRole = Get-MgDirectoryRole -Filter "DisplayName eq '$roleName'"
    
    if ($adminRole) {
        $roleMembers = Get-MgDirectoryRoleMember -DirectoryRoleId $adminRole.Id
    
        if ($roleMembers) {
            $roleMembers | ForEach-Object {
                [PSCustomObject]@{
                    DisplayName = $_.AdditionalProperties["displayName"]
                    Id          = $_.Id
                }
            } | Format-Table DisplayName, Id
        } else {
            Write-Host "No members found for the role: $roleName"
        }
    } else {
        Write-Host "Role '$roleName' not found"
    }
    

    Response:

    enter image description here

    In your case, try running below PowerShell command after connecting to MS Graph and confirm whether it has Directory.Read.All permission in Scopes parameter or not:

    Get-MgContext 
    

    enter image description here

    If the permission is not present in Scopes parameter, try removing the added permission in app registration and add it again by granting admin consent.

    Login or Signup to reply.
  2. It feels quite weird here, I have copied you code and test, all good.

    But my connection using service principal secret here which I think there is no real difference here.

    I have the same application permission as you.

    Show in application registrations

    enter image description here

    Show in Enterprise applications

    enter image description here


    Your code with slight connecting method changed (not impact I think)

    $roleName = "Global Administrator"
    
    $ApplicationClientId = 'xxxx'
    $ApplicationClientSecret = 'xxxx'
    $TenantId = 'xxx' 
    
    $SecureClientSecret = ConvertTo-SecureString -String $ApplicationClientSecret -AsPlainText -Force
    $ClientSecretCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ApplicationClientId, $SecureClientSecret
    
    Connect-MgGraph -TenantId $TenantId -ClientSecretCredential $ClientSecretCredential
    
    $adminRole = Get-MgDirectoryRole -Filter "DisplayName eq '$roleName'"
    
    if ($adminRole) {
        $roleMembers = Get-MgDirectoryRoleMember -DirectoryRoleId $adminRole.Id
    
        if ($roleMembers) {
            $roleMembers | ForEach-Object {
                [PSCustomObject]@{
                    DisplayName = $_.AdditionalProperties["displayName"]
                    Id          = $_.Id
                }
            } | Format-Table DisplayName, Id
        } else {
            Write-Host "No members found for the role: $roleName"
        }
    } else {
        Write-Host "Role '$roleName' not found"
    }
    

    My result:

    enter image description here

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