errorline1
errorline1

Reputation: 432

Azure CLI SP creation w/ API permissions

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

Answers (1)

errorline1
errorline1

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

Related Questions