具有 API 权限的 Azure CLI SP 创建

Azure CLI SP creation w/ API permissions

我正在尝试编写一个简单的脚本来创建一个分配了一些 Microsoft Graph API 权限的 SP。我认为我需要做的是创建一个具有贡献者角色的 SP,然后从 Microsoft Graph API 向其分配我需要的 API 权限,然后授予管理员许可。它确实 运行 完成了,但是当我查看门户管理员同意时没有被授予,然后当我尝试手动分配时,我得到以下信息:

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]

这是脚本,欢迎任何建议:

#!/bin/bash

## Usage: ./setup-sp.sh <app-name>
set -eou pipefail

getPermissionId () {
  #  = name of permission, e.g. User.ReadWrite.All
  echo `az ad sp list \
    --query "[?appDisplayName=='Microsoft Graph'].{permissions:oauth2Permissions}[0].permissions[?value==''].id" \
    --all \
    --output tsv`
}

APP_NAME=

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"

代码中有两个问题。

首先,根据此处 https://docs.microsoft.com/en-us/graph/permissions-reference#retrieving-permission-ids 的查询查找 API 权限 ID 的代码实际上返回的是 AD 图的 ID,而不是 Microsoft Graph。

其次,az ad app permission admin-consent 已弃用,az ad sp permission grant 仅适用于委派权限,不适用于应用程序权限 (https://github.com/Azure/azure-cli/issues/12137#issuecomment-596567479)。解决办法是先拉取SP和Microsoft Graph的Object IDAPI,然后直接用az rest到POSTgrant。这是工作副本:

#!/bin/bash

## Usage: ./setup-sp.sh <app-name>
set -eou pipefail

APP_NAME=

# 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 () {
  #  = name of permission, e.g. User.ReadWrite.All
  echo `az ad sp show --id $API_ID --query "appRoles[?value==''].id" --output tsv`
}

grantPermission () {
  #  = SP objectId
  #  = resourceId
  #  = permissionId

  az rest \
    --method POST \
    --uri "https://graph.microsoft.com/v1.0/servicePrincipals//appRoleAssignments" \
    --headers '{"Content-Type": "application/json"}' \
    --body "{\"principalId\": \"\", \"resourceId\": \"\", \"appRoleId\": \"\"}" \
    --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://docs.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"