functions/azure/Add-ServicePrincipalPermission.ps1

function Add-ServicePrincipalPermission {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [Alias('AppId')]
        [guid]$ServicePrincipalObjectId,

        [Parameter(Mandatory = $true)]
        [Alias('Roles')]
        [string[]]$RoleNames
    )

    $headers = @{
        Authorization = Get-RequestHeaderAuthorization -RequestUri 'https://graph.microsoft.com'
        "Content-Type" = "application/json"
    }

    # Ermittle Microsoft Graph App-ID
    $graphAppId = Get-KnownResourceAppId -MicrosoftGraph
    $graphSpUri = "https://graph.microsoft.com/v1.0/servicePrincipals?`$filter=appId eq '$graphAppId'"
    $graphSp = Invoke-RestMethod -Method GET -Uri $graphSpUri -Headers $headers
    if (-not $graphSp.value) {
        Write-Error "Unable to retrieve Microsoft Graph Service Principal!"
        return $false
    }

    $graphSpId = $graphSp.value[0].id

    # Hole alle verfügbaren Rollen für MS Graph
    $graphSpFull = Invoke-RestMethod -Method GET -Uri "https://graph.microsoft.com/v1.0/servicePrincipals/$graphSpId" -Headers $headers

    $roles = @()
    foreach ($roleName in $RoleNames) {
        $role = $graphSpFull.appRoles | Where-Object { $_.value -eq $roleName -and $_.allowedMemberTypes -contains "Application" }
        if (-not $role) {
            Write-Error "Role '$roleName' not found!"
            return $false
        }
        $roles += $role
    }

    $results = @()
    foreach ($role in $roles) {
        $assignmentPayload = @{
            principalId   = $ServicePrincipalObjectId
            resourceId    = $graphSpId
            appRoleId     = $role.id
        } | ConvertTo-Json -Depth 3

        Write-verbose "Add role '$($role.value)'"
        try {
            $results += Invoke-RestMethod -Method POST -Uri "https://graph.microsoft.com/v1.0/servicePrincipals/$ServicePrincipalObjectId/appRoleAssignments" `
                -Headers $headers -Body $assignmentPayload
        } catch {
            if ($_.Exception.Response.StatusCode.Value__ -eq 409) {
                Write-Warning "Role '$($role.value)' already assigned."
            } else {
                Write-Error $_
                return $false
            }
        }
    }

    return $results
}