このエントリは2021/12/24現在の情報に基づいています。将来の機能追加や変更に伴い、記載内容からの乖離が発生する可能性があります。
以前以下のようなエントリを書いた。
前回のエントリでは、Service Principalのシークレットを使ってAzure Loginアクションを呼び出していたが、GitHub ActionsがOpenID ConnectでAzure ADと連携できるようになった結果、Service Principalのシークレットを使う必要がなくなった。備忘録として設定を記載しておく。
OpenID Connectとの連携に関する詳細は以下のドキュメントに記載がある。
Configuring OpenID Connect in Azure (Use OpenID Connect within your workflows to authenticate with Azure.)
https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-azure
GitHub Actions を使用して Azure に接続する / Use GitHub Actions to connect to Azure
https://docs.microsoft.com/azure/developer/github/connect-from-azure
手順
以下の流れで実施する。なお、Azure上の操作はAzure CLI、GitHub ActionsのランナーはGitHub-hostedのLinuxを使っているが、もちろんWindowsでもよい。
- GitHub Actionsを表すApplicationをAzure ADに作成する
- 1.で作成したApplicationのService Principalを作成する
- 2.で作成したService PrincipalにサブスクリプションスコープでのContributor(共同作成者)ロールを割り当てる
- 1.で作成したApplicationにフェデレーション資格情報を追加する
- 1.で作成したApplicationのApplication ID、Azure ADのテナントID、AzureのSubscription IDを表すシークレットをGitHub Secretに作成する
- GitHub Actionsのflowで、OpenID Connect認証を使ってAzure ADログインを構成し、動作確認する
- API Managementのプロビジョニングに必要なARMテンプレート(もしくはBicep)とパラメータをGitHubリポジトリに追加する
- GitHub Actionsのflowを変更し、プロビジョニングのステップを追加する
- 動作確認
1. GitHub Actionsを表すApplicationをAzure ADに作成する
コマンドは以下。
az ad app create --display-name <Application Name>
出力結果は以下(一部省略およびマスキングしている)。appId、objectIdはメモしておく。
{
"acceptMappedClaims": null,
"addIns": [],
"allowGuestsSignIn": null,
"allowPassthroughUsers": null,
"appId": "<Application ID>",
...,
"displayName": "<コマンドで指定したApplication Name>",
...,
"objectId": "<ApplicationのObject ID>",
...
}
2. 1.で作成したApplicationのService Principalを作成する
コマンドは以下。
az ad sp create --id <1.で作成したApplicationのappId>
出力結果は以下。(一部省略およびマスキングしている)。objectId(このObject IDは上記コマンドで作成したService PrincipalのObject ID)はメモしておく。
{
"accountEnabled": "True",
"addIns": [],
"alternativeNames": [],
"appDisplayName": "<1.で作成したApplicationのApplication Name>",
"appId": "<1.で作成したApplicationのappId>",
"appOwnerTenantId": "<Azure ADのテナントID>",
...,
"displayName": "<1.で作成したApplicationのApplication Name>",
...,
"objectId": "<Service PrincipalのObject ID>",
"objectType": "ServicePrincipal",
...,
"servicePrincipalNames": [
"<1.で作成したApplicationのappId>"
],
"servicePrincipalType": "Application",
...
}
3. 2.で作成したService PrincipalにSubscriptionスコープでのContributor(共同作成者)ロールを割り当てる
コマンドは以下。
az role assignment create \
--role contributor \
--subscription <サブスクリプションID> \
--assignee-object-id <2で作成したService PrincipalのObject ID> \
--assignee-principal-type ServicePrincipal
出力結果は以下(一部省略およびマスキングしている)。
{
"canDelegate": null,
...,
"principalId": "<2で作成したService PrincipalのObject ID>",
"principalType": "ServicePrincipal",
...,
"type": "Microsoft.Authorization/roleAssignments"
}
4. 1.で作成したApplicationにフェデレーション資格情報を追加する
コマンドは以下、といいつつ実体はREST APIの呼び出しである。詳細は以下のドキュメントにも記載がある。
GitHub リポジトリを信頼するようにアプリを構成します。 (プレビュー) / Configure an app to trust a GitHub repo (preview)
https://docs.microsoft.com/azure/active-directory/develop/workload-identity-federation-create-trust-github
以下のドキュメントにも記載があるように、subjectの設定が細々しているので注意が必要。以下はrepositoryとbranchの組み合わせの例。表現の都合上改行を入れているが、リクエスト本体のJSONは改行無しで指定する。
az rest --method POST \
--uri 'https://graph.microsoft.com/beta/applications/<1で作成したApplicationのObject ID>/federatedIdentityCredentials' \
--body '{"name":"<フェデレーション資格情報の名前>", "issuer":"https://token.actions.githubusercontent.com",
"subject":"repo:<GitHubのユーザー名>/<リポジトリ名>:refs/heads/<Branch名>",
"description":"<フェデレーション資格情報の補足コメント>",
"audiences":["api://AzureADTokenExchange"]}'
出力結果は以下(一部省略している)。
{
"@odata.context": "https://graph.microsoft.com/beta/$metadata#applications('<1で作成したApplicationのObject ID>')/federatedIdentityCredentials/$entity",
"audiences": [
"api://AzureADTokenExchange"
],
"description": "<フェデレーション資格情報の補足コメント>",
...,
"issuer": "https://token.actions.githubusercontent.com",
"name": "<フェデレーション資格情報の名前>",
"subject": "<GitHubのユーザー名>/<リポジトリ名>:refs/heads/<Branch名>"
}
これ以後は、GitHub Actionsでの作業に移る。
5. 1.で作成したApplicationのApplication ID、Azure ADのテナントID、AzureのSubscription IDを表すシークレットをGitHub Secretに作成する
GitHub Actionsで使うために、3個のシークレットを作成する。リポジトリレベルでも、環境 (environment)、組織 (organization) レベルでもかまわないが、シークレットのKeyは固定である点に注意。
- AZURE_CLIENT_ID (1.で作成したApplicationのappId)
- AZURE_TENANT_ID (Subscriptionが属するAzure ADのtenant ID)
- AZURE_SUBSCRIPTION_ID (AzureのSubscription ID)
6. GitHub Actionsのflowで、OpenID Connect認証を使ってAzure ADログインを構成し、動作確認する
以下のドキュメントにあるYAMLを使って試すのがいちばんかんたん。
Azure CLIの場合(Linux):
https://docs.microsoft.com/ja-jp/azure/developer/github/connect-from-azure?tabs=azure-cli%2Clinux#set-up-azure-login-with-openid-connect-authentication
PowerShellの場合(Windows)
https://docs.microsoft.com/ja-jp/azure/developer/github/connect-from-azure?tabs=azure-cli%2Cwindows#set-up-azure-login-with-openid-connect-authentication
Azure CLIに比べて、PowerShellは実行に要する時間が倍ほど違う(CLIは30秒程度、PowerShellは1分程度)ようだが、今回はパフォーマンス確認は目的ではないので深く追わない。
7. API Managementのプロビジョニングに必要なARMテンプレート(もしくはBicep)とパラメータをGitHubリポジトリに追加する
今回は(今回も)ARMテンプレートでプロビジョニングする。利用するARMテンプレートは以下から利用できるもので、Managed Identityを有効化したAPI Managementインスタンスを作成する。
Azure API Management Service – with Managed Identity
https://github.com/Azure/azure-quickstart-templates/tree/master/quickstarts/microsoft.apimanagement/api-management-create-with-msi
ARMテンプレート(azuredeploy.json
)とパラメータファイル(azuredeploy.parameters.json
)をリポジトリに作成する(2021/12/24現在、Bicepのスクリプトも存在するが、必要であればクローンしておく)。
8. GitHub Actionsのflowを変更し、プロビジョニングのステップを追加する
ARMテンプレートを実行するためのActionは以下を利用する。前エントリでは別のものを使っていたが、今回はパラメータファイルの設定をオーバーライドしたいので、Microsoft純正のものを使う。
Deploy Azure Resource Manager (ARM) Template
https://github.com/marketplace/actions/deploy-azure-resource-manager-arm-template
プロビジョニング先のリソースグループはARMテンプレート内で作成されないので、flow内で作成する必要がある。そのために必要なAzure CLIの実行Actionと、リポジトリのCheckoutのためのActionを利用する。
Azure CLI Action
https://github.com/marketplace/actions/azure-cli-action
Checkout
https://github.com/marketplace/actions/checkout
作成したflowは以下の通り。リソースグループ名をユニークにするために $(date +%s)
を使っている。もちろん、API Managementインスタンス名をユニークにするのであれば、ARMテンプレート内で実施することになるが、ARMテンプレートの関数utcNow()
を使う場合、Parameterのデフォルト値としてのみ設定できるので注意が必要。
utcNow
https://docs.microsoft.com/azure/azure-resource-manager/templates/template-functions-date#utcnow
name: Run Azure Login with OpenID Connect via Azure CLI
on: [push]
permissions:
id-token: write
contents: read
jobs:
Create-API-Management-Instance-with-GitHub-Actions:
runs-on: ubuntu-latest
env:
ResourceGroup_Base: APIM-rg
ResourceGroupLocation: "japaneast"
steps:
- name: Checkout
uses: actions/checkout@v2.4.0
- name: OIDC Login to Azure Public Cloud with Azure CLI
uses: Azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Generate unique variable based on timestamp
run: echo ResourceGroupName=${{ env.ResourceGroup_Base }}-$(date +%s) >> $GITHUB_ENV
- name: Create Resource Group with Azure CLI
uses: Azure/CLI@v1
with:
inlineScript: |
az group create -n ${{ env.ResourceGroupName }} -l ${{ env.ResourceGroupLocation }}
echo "Azure resource group created"
- name: Create API Management Instance with ARM action
uses: Azure/arm-deploy@v1
with:
template: azuredeploy.json
resourceGroupName: ${{ env.ResourceGroupName }}
parameters: azuredeploy.parameters.json publisherName=${{ secrets.PUBLISHER_NAME }} publisherEmail=${{ secrets.PUBLISHER_MAIL }}
パラメータファイル (azuredeploy.parameters.json
) は以下のような感じ。Consumption tierを使う場合、skuCountはゼロにしないといけない点は前回のエントリと同じ。
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"sku": {
"value": "Consumption"
},
"publisherEmail": {
"value": "email@example.com"
},
"publisherName": {
"value": "templateTest"
},
"skuCount": {
"value": 0
}
}
}
9. 動作確認
実行すると、リソースグループは接頭辞 (APIM-rg) にランダムな数値文字を追加しているので、ユニークなリソースグループ名を作成できること、そのリソースグループ内にAPI Managementインスタンス (Consumption tier) が作成できることを確認できる。Flowの実行状況は以下の通り。

作成したAPI ManagementインスタンスをAzure Portalで開き、Managed Identityの状況を確認すると、System Managed Identityが有効化されていることを確認できる。

おまけ
このエントリで作成したGitHub Actionsのフローは以下で公開している。
Provision API Management Instance with GitHub Actions
https://github.com/anishi1222/Create-API-Management-Instance-with-GitHub-Actions