
GitHub Actionsを使用してAzureに接続する
GitHub ActionsからAzureに接続する場合、OIDC Connectionで実現することが多いと思います。
OIDC Connectionを利用するとパスワードなど秘匿情報を登録する必要もなく、安全性の高い方式です。 パスワードの代わりにGitHubとAzureの双方にそれぞれの情報を登録しておくことが必要です。
登録する内容は、Azure側(Entra ID Application登録側)にはGitHub側のOrganization名とリポジトリ名、および環境名といった情報を、GitHub側にはAzure Entra ID Appliation登録のテナントID、クライアントID、接続するサブスクリプションIDといった情報です。

一般的にはこうした情報を手作業で登録しています。リポジトリ1つに対して行っているだけならばそれほど大変ではありませんが、 複数のリポジトリに同じような作業を繰り返していると、ID情報などの取得と設定が意外と面倒な作業と感じるものです。
そこでBackstageを活用してこの作業を省力化することにしました。
BackstageによるOIDC Connection登録の省力化
以前にも紹介していますが、Backstageには(Scaffolder)Templateという機能があります。
この機能は事前に実行したい内容をテンプレートとして用意し、その内容を実行したいときに少数のパラメータ値を加えてテンプレートを実行することで繰り返し作業を楽にするというものです。
一般的にはGitリポジトリの新規作成や更新、Pull Request作成といった用途で利用していることが多いのですが、実はもっと様々な機能を実現することができます。また、Pluginを独自に開発することで必要な機能を追加していくことも可能です。今回は以下のような機能を用意・活用します。
- GitHub Environmentの登録(OSSとして公開されています。アクション名は
github:environment:create) - Azure Entra ID OIDC登録(こちらは独自実装したものです)
テンプレートを作成するにあたって、入力作業をより簡略化できるようにするため、AzureサブスクリプションやAzure Entra ID Application登録を(Client ID等必要となる情報とともに)Backstage のResource Catalogとして登録することにしました。これによるテンプレートを実行する際にAzureのテナントIDなどをユーザーが入力しなくても済むようにしています。
処理の流れとしては以下のようなことを想定します。
入力パート
Entra ID Applcation登録とAzure Subscriptionを選択

登録対象のGitHubリポジトリを選択

実行パート
- GitHub EnvironmentsにAzureの認証必要情報を登録
- Azure Application登録のフェデレーション情報としてGitHubの認証情報を登録
テンプレートとしては以下のような内容です。
apiVersion: scaffolder.backstage.io/v1beta3 # https://backstage.io/docs/features/software-catalog/descriptor-format#kind-template kind: Template metadata: name: example-ms-app-federation title: Entra ID App Federation登録 description: An example template for screating an MS Graph App federation spec: owner: user:guest type: ops parameters: - title: App Registration Info require: - appReg - appId - name properties: signin: type: string ui:field: MicrosoftSignIn ui:options: requestUserCredentials: secretsKey: AZURE_USER_OAUTH_TOKEN appEntity: title: Pick Application Entity type: string ui:field: EntityPicker ui:options: catalogFilter: - kind: 'Resource' spec.type: 'entraid-application' subscriptionEntity: title: Pick Subscription Entity type: string ui:field: EntityPicker ui:options: catalogFilter: - kind: 'Resource' spec.type: 'azure-subscription' name: title: Federatoin name type: string - title: GitHub Environment required: - repoUrl properties: repoUrl: title: Repository Location type: string ui:field: RepoUrlPicker ui:options: allowedHosts: - github.com requestUserCredentials: secretsKey: GITHUB_USER_OAUTH_TOKEN environment: title: GitHub Environment type: string steps: - id: subscription name: Fetch Subscription action: catalog:fetch input: entityRef: ${{ parameters.subscriptionEntity }} - id: application name: Fetch App Registration action: catalog:fetch input: entityRef: ${{ parameters.appEntity }} - id: register-federation name: Register Federation action: msgraph:githubFederation:new input: applicationId: ${{ steps.application.output.entity.metadata.annotations | pick('azure.com/entraid-app-client-id') }} organization: ${{ (parameters.repoUrl | parseRepoUrl).owner }} repository: ${{ (parameters.repoUrl | parseRepoUrl).repo }} entityType: type: 'environment' environment: ${{ parameters.environment }} name: ${{ parameters.name }} description: Federation created by PlaTT token: ${{ secrets.AZURE_USER_OAUTH_TOKEN }} - id: createGitHubEnvironment name: Create GitHub Environment action: github:environment:create input: repoUrl: ${{ parameters.repoUrl }} name: ${{ parameters.environment }} environmentVariables: AZURE_TENANT_ID: ${{ steps.subscription.output.entity.metadata.annotations | pick('azure.com/tenant-id') }} AZURE_SUBSCRIPTION_ID: ${{ steps.subscription.output.entity.metadata.annotations | pick('azure.com/subscription-id') }} AZURE_CLIENT_ID: ${{ steps.application.output.entity.metadata.annotations | pick('azure.com/entraid-app-client-id') }} token: ${{ secrets.GITHUB_USER_OAUTH_TOKEN }} output: links: - title: Repository Environment url: ${{ ('https://' ~ parameters.repoUrl | replace('?owner=', '/') | replace('&repo=', '/')) }}/settings/environments/ - title: App Registration url: https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/Credentials/appId/${{ steps.application.output.entity.metadata.annotations | pick('azure.com/entraid-app-client-id') }}/isMSAApp~/false
実行すると、Azure側にはGitHubの情報が、GitHub側にはAzure Entra IDの情報が登録されます。入力情報がかなり削減され、またAzureとGitHubの双方に反映されるため、間違うこともありません。
さらにこのステップをリポジトリ作成テンプレートの中に追加することで、リポジトリ作成時点からGitHubリポジトリとAzureとのOIDC Connection登録が完了している状態とすることができます。
このように、BackstageのTemplate機能を利用することでOIDC Connection登録作業も省力化、簡略化することができます。
最後に
Backstageには他にも開発者の認知負荷を低減する様々な機能が存在します。その効果も使い方次第でより大きくなります。 弊社ではOSSであるBackstageをManaged Serviceとして提供させて頂いております。
今回紹介した機能についてはMicrosoft Entra ID関連の部分は独自に拡張したものです。
ご興味のある方がいらっしゃいましたらぜひ弊社までご連絡ください。よろしくお願いします。