Azure Active Directory Assessment | Part VI

Alex ter Neuzen 4 min read

In the previous post, Azure Active Directory Assessment | Part V, we have collected all the information within Conditional Access and the App Registrations. Slowly we have now already a big ton of data to export. But before we do that, we are going to get another thing.

Azure Active Directory Roles#

Azure Active Directory supports two type of roles in the RBAC (Role-Based-Access-Control). The Azure AD Built-in roles or custom roles. These roles have a predefined set of permissions within Azure Active Directory. (link to Microsoft documentation).

If the tenant is using Azure AD Premium 2, there is a possibility that identities are member of a role, but it is not active. You need to activate the role after you login and provide additional security checks like Multi-Factor Authentication. This is called JIT access (Just In Time). Only with an AAD Premium 2 license you will be able to get the assigned roles. Therefore we need to make an exclusion in the script so it will continue even AAD Premium 2 is not present

powershell

# setting url
$url = "https://graph.microsoft.com/beta/roleManagement/directory/roleAssignmentSchedules"
try {
    $assignedRoles = Invoke-RestMethod -method GET -Headers $header -Uri $url
  
}
catch {
    $webError = $_.Exception
    $ErrorDetail = $_
    If ($ErrorDetail.ErrorDetails.message -like "*Access token has expired or is not yet valid.*") {
        #region connection
        # Get an access token for the Microsoft Graph API
        do {
            $accessToken = (Get-MSALToken -Clientid $ConnectionDetails.ClientId -ClientSecret $connectionDetails.ClientSecret -TenantId $ConnectionDetails.TenantId -ForceRefresh).AccessToken
            Start-Sleep -seconds 2
        } while (
            $accessToken -eq $null
        )
        $header = @{
            'Authorization' = "BEARER $accesstoken"
            'Content-type'  = "application/json"
        }
        try {
        $assignedRoles = Invoke-RestMethod -method GET -Headers $header -Uri $url
        $p2 = $true
        }
        Catch {
            $webError = $_.Exception
            $ErrorDetail = $_
        }
    }
    if ($($errordetail.ErrorDetails.Message) -like "*The tenant needs an AAD Premium 2 license.*") {
        Write-Output "ERROR: This tenant need AAD Premium 2 License to get roles"
        $assignedRoles = $null
        $p2 = $false
    }
    else {
        break
    }
}

# getting role definitions
$url = "https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions"
$roleDefinitions = RunQueryAndProcess

# if AADp2 license is present getting eligible assignments
if ($p2){
    $url = "https://graph.microsoft.com/beta/roleManagement/directory/roleEligibilitySchedules"
    $eligibleRoles = RunQueryAndProcess
}

Now we have all information. Let’s process it.

powershell
if ($p2 -eq $false) {
    # donothing
}
else {
    Write-Output "INFO: Processing all roles ..."
    $tableAssignedRoles = @()
    $tableAssignedRolesCount = @()

    forEach ($role in $assignedRoles.value) {
        $assignType = $null
        $groupName = $null
        $upn = $null
        $user = $null

        $user = ($Users | Where-Object { $_.id -eq $role.principalId }).UserprincipalName
        $roledef = ($roleDefinitions | Where-Object { $_.id -eq $role.roleDefinitionId })
        $status = $role.status
        $membertype = $role.memberType
        $createdDateTime = $role.createdDateTime
        $lastchanged = $role.modifiedDateTime
        $appScopeId = $role.appScopeId
        $startDateTime = $role.scheduleinfo.startDateTime
        $expiration = $role.scheduleinfo.expiration.type
        $expirationEndTime = $role.scheduleinfo.expiration.endDateTime
        $expirationDuration = $role.scheduleinfo.expiration.duration

        if ($user) {
            $assignType = "User"
            $groupName = ""
            $upn = $user
        }
        elseif (!($user)) {
            $group = ($groups | Where-Object { $_.id -eq $role.principalId })
            if ($group) {
                $url = "https://graph.microsoft.com/v1.0/groups/" + $group.id + "/members"
                $GroupMembers = RunQueryAndProcess
                $members = $GroupMembers.userPrincipalName -Join ","
                $assignType = "Group"
                $groupName = $group.DisplayName
                $upn = $members
            }

            if (!($group)) {
                $url = "https://graph.microsoft.com/v1.0/directoryObjects/" + $Role.principalId
                $servicePrincipal = (RunQueryAndProcess).displayName
                $assignType = "ServicePrincipal"
                $groupName = ""
                $upn = $servicePrincipal
            }
        }
  

        $object = [PSCustomObject]@{
            "ID"                    = $roledef.id
            "Rolename"              = $roledef.DisplayName
            "Description"           = $roledef.Description
            "isBuiltIn"             = $roledef.isBuiltIn
            "isEnabled"             = $roledef.isEnabled
            "Status"                = $status
            "assignMent"            = "Active"
            "Membertype"            = $membertype
            "appScopeId"            = $appScopeId
            "createdDateTime"       = $createdDateTime
            "startDateTime"         = $startDateTime
            "lastChanged"           = $lastchanged
            "expiration"            = $expiration
            "expirationEndDateTime" = $expirationEndTime
            "expirationDuration"    = $expirationDuration
            "assignType"            = $assignType
            "groupName"             = $groupName
            "User"                  = $upn

        }
        $tableAssignedRoles += $object

    }
    $Count = 0
    forEach ($eligiblerole in $eligibleRoles) {
        $usermember = $null
        $group = $null
        $roleName = ($roleDefinitions | Where-Object { $_.id -eq $eligiblerole.roleDefinitionId })
        $roleDescription = ($roleDefinitions | Where-Object { $_.id -eq $eligiblerole.roleDefinitionId })
        $userMember = ($users | Where-Object { $_.id -eq $eligiblerole.principalId })

        $expiration = $eligiblerole.scheduleinfo.expiration.type
        $expirationEndTime = $eligiblerole.scheduleinfo.expiration.endDateTime
        $expirationDuration = $eligiblerole.scheduleinfo.expiration.duration

        if ($usermember) {
            $type = "User"
            $groupname = ""
            $member = $userMember.UserprincipalName
        }
        elseif (!($usermember)) {
            $group = ($groups | Where-Object { $_.id -eq $id.principalId })
            if ($Group) {
                $type = "Group"
                $Groupname = $Group.DisplayName
                $Member = ""
            }
        }

        $object = [PSCustomObject]@{
            "ID"                    = $rolename.ID
            "RoleName"              = $rolename.DisplayName
            "Description"           = $roleDescription.description
            "assignType"            = $type
            "groupName"             = $GroupName
            "isBuiltIn"             = $rolename.isBuiltIn
            "isEnabled"             = $rolename.isEnabled
            "User"                  = $member
            "assignMent"            = "Eligible"
            "createdDateTime"       = $eligiblerole.createdDateTime
            "status"                = $eligiblerole.status
            "membertype"            = $eligiblerole.memberType
            "expiration"            = $expiration
            "expirationEndDateTime" = $expirationEndTime
            "expirationDuration"    = $expirationDuration

        }
        $tableAssignedRoles += $object

    }
    $Unique = $tableAssignedRoles | Sort-Object -Unique "Rolename"
    forEach ($Role in $Unique) {
        $Countactive = $null
        $CountEligible = $null
        $CountActive = ($tableAssignedRoles | Where-Object { $_.Rolename -eq $role.rolename -and $_.assignment -eq "Active" }).Count
        $CountEligible = ($tableAssignedRoles | Where-Object { $_.Rolename -eq $role.rolename -and $_.assignment -eq "Eligible" }).Count
        $object = [PSCustomObject]@{
            "ID"            = $Role.id
            "Rolename"      = $role.Rolename
            "Description"   = $Role.Description
            "countActive"   = $Countactive
            "countEligible" = $CountEligible
        }
        $tableAssignedRolesCount += $Object
    }

    Write-Output "INFO: Processing all roles ...[DONE]"
    Write-Output ""
}