Reputation: 432
I'm trying to write a simple script to create an SP that is assigned some Microsoft Graph API permissions. I think what I need to do is create an SP with a Contributor role, then assign it the API permissions I need from Microsoft Graph API, and then grant admin consent. It does run to completion, however then when I look in the portal admin consent hasn't been granted, and when I then try to assign manually, I get the following:
Grant consent failed with error: Claim is invalid: 204e0828-b5ca-4ad8-b9f3-f32a958e7cc4 does not exist on resource application 00000003-0000-0000-c000-000000000000. [zPYKlPo0GJHRzGclFADr9k]
Here's the script, any suggestions are welcome:
#!/bin/bash
## Usage: ./setup-sp.sh <app-name>
set -eou pipefail
getPermissionId () {
# $1 = name of permission, e.g. User.ReadWrite.All
echo `az ad sp list \
--query "[?appDisplayName=='Microsoft Graph'].{permissions:oauth2Permissions}[0].permissions[?value=='$1'].id" \
--all \
--output tsv`
}
APP_NAME=$1
echo "Getting subscription ID"
SUBSCRIPTION_ID=$(az account show --query id --output tsv)
echo "Subscription ID is: $SUBSCRIPTION_ID"
echo "Creating an App Registration and associated Service Principal"
SP=$(az ad sp create-for-rbac --role Contributor --name $APP_NAME --scopes /subscriptions/$SUBSCRIPTION_ID)
echo "The following is your Service Principal credentials, store them securely!"
echo $SP
APP_ID=$(echo $SP | jq -r .appId)
echo "Application ID is: $APP_ID"
# Microsoft Graph API Id
API_ID="00000003-0000-0000-c000-000000000000"
# IDs for various Application Roles
echo "Getting API permission IDs"
USER_READWRITE_ALL_ID=$(getPermissionId User.ReadWrite.All)
GROUP_READWRITE_ALL_ID=$(getPermissionId Group.ReadWrite.All)
APPLICATION_READWRITE_ALL_ID=$(getPermissionId Application.ReadWrite.All)
# Add permissions to SP
echo "Adding API permissions to SP"
az ad app permission add \
--id $APP_ID \
--api $API_ID \
--api-permissions \
$USER_READWRITE_ALL_ID=Role \
$GROUP_READWRITE_ALL_ID=Role \
$APPLICATION_READWRITE_ALL_ID=Role
echo "Granting access for Microsoft Graph API"
az ad app permission grant --id $APP_ID --api $API_ID
echo "Granting admin-consent for API permissions"
az ad app permission admin-consent --id $APP_ID
echo "Done. Check out your SP at: https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/Overview/appId/$APP_ID"
Upvotes: 1
Views: 1061
Reputation: 432
There were two issues in the code.
First, the code to find the API permission IDs that was based on the query from here https://learn.microsoft.com/en-us/graph/permissions-reference#retrieving-permission-ids was actually returning the ID for AD graph, not Microsoft Graph.
Second, az ad app permission admin-consent
is deprecated and the az ad sp permission grant
only works for Delegated permissions, not Application permissions (https://github.com/Azure/azure-cli/issues/12137#issuecomment-596567479). The solution is to first pull the Object ID of the SP and Microsoft Graph API, and then use az rest
to POST the grant directly. Here's the working copy:
#!/bin/bash
## Usage: ./setup-sp.sh <app-name>
set -eou pipefail
APP_NAME=$1
# Microsoft Graph API Id
API_ID="00000003-0000-0000-c000-000000000000"
USER_READWRITE_ALL_ROLE="User.ReadWrite.All"
GROUP_READWRITE_ALL_ROLE="Group.ReadWrite.All"
APPLICATION_READWRITE_ALL_ROLE="Application.ReadWrite.All"
getPermissionId () {
# $1 = name of permission, e.g. User.ReadWrite.All
echo `az ad sp show --id $API_ID --query "appRoles[?value=='$1'].id" --output tsv`
}
grantPermission () {
# $1 = SP objectId
# $2 = resourceId
# $3 = permissionId
az rest \
--method POST \
--uri "https://graph.microsoft.com/v1.0/servicePrincipals/$1/appRoleAssignments" \
--headers '{"Content-Type": "application/json"}' \
--body "{\"principalId\": \"$1\", \"resourceId\": \"$2\", \"appRoleId\": \"$3\"}" \
--only-show-errors
}
echo "Getting subscription ID"
SUBSCRIPTION_ID=$(az account show --query id --output tsv)
echo "Subscription ID is: $SUBSCRIPTION_ID"
echo "Creating an App Registration and associated Service Principal"
SP=$(az ad sp create-for-rbac --role Contributor --name $APP_NAME)
echo "The following is your Service Principal credentials, store them securely!"
echo $SP
APP_ID=$(echo $SP | jq -r .appId)
echo "Application ID is: $APP_ID"
echo "Getting your users' Object ID"
USER_ID=$(az ad signed-in-user show --query objectId --output tsv)
echo "Object ID: $USER_ID"
echo "Adding you as owner of the Service Principal"
az ad app owner add --id $APP_ID --owner-object-id $USER_ID
# IDs for various Application Roles
echo "Getting API permission IDs"
USER_READWRITE_ALL_ID=$(getPermissionId $USER_READWRITE_ALL_ROLE)
GROUP_READWRITE_ALL_ID=$(getPermissionId $GROUP_READWRITE_ALL_ROLE)
APPLICATION_READWRITE_ALL_ID=$(getPermissionId $APPLICATION_READWRITE_ALL_ROLE)
echo "$USER_READWRITE_ALL_ROLE = $USER_READWRITE_ALL_ID"
echo "$GROUP_READWRITE_ALL_ROLE = $GROUP_READWRITE_ALL_ID"
echo "$APPLICATION_READWRITE_ALL_ROLE = $APPLICATION_READWRITE_ALL_ID"
# Add permissions to SP
echo "Adding API permissions to SP"
az ad app permission add \
--id $APP_ID \
--api $API_ID \
--api-permissions \
$USER_READWRITE_ALL_ID=Role \
$GROUP_READWRITE_ALL_ID=Role \
$APPLICATION_READWRITE_ALL_ID=Role
# NOTE: az cli does not have a command to consent for application permissions
# see here: https://github.com/Azure/azure-cli/issues/12137#issuecomment-596567479
# and here: https://learn.microsoft.com/en-us/graph/api/serviceprincipal-post-approleassignments?view=graph-rest-1.0&tabs=http
echo "Granting consent for API permissions"
APP_OBJECT_ID=$(az ad sp show --id $APP_ID --query "objectId" --output tsv)
API_OBJECT_ID=$(az ad sp show --id $API_ID --query "objectId" --output tsv)
grantPermission $APP_OBJECT_ID $API_OBJECT_ID $USER_READWRITE_ALL_ID
grantPermission $APP_OBJECT_ID $API_OBJECT_ID $GROUP_READWRITE_ALL_ID
grantPermission $APP_OBJECT_ID $API_OBJECT_ID $APPLICATION_READWRITE_ALL_ID
echo "Done. Check out your SP at: https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/Overview/appId/$APP_ID"
Upvotes: 1