本記事はAP Tech Blog Week Vol.5のものになります。
- はじめに
- 背景
- Microsoft Graph APIとは
- 実装の流れ
- Entra IDアプリケーションの設定
- GitHub Actionsワークフローの作成
- ユーザー招待処理の作成(Node.js)
- 動作確認
- おわりに
はじめに
こんにちは、ACS事業部 CIチームの平井です。この記事では、GitHub Actionsを使ってOIDCを利用し、Microsoft Graph APIでEntra IDユーザーを招待する方法をご紹介します。 ユーザー招待システムを構築するためのヒントとして、参考にしていただけたらと思います。
背景
Azure ADへのユーザー招待を自動化するにあたり、当初はTerraformのazureadプロバイダーでazuread_invitation
リソースを使用する予定でした。しかし、実装する過程で以下のような課題に直面しました。
ユーザープロパティが設定できない
通常、招待時にユーザープロパティを設定したいところですが、azuread_invitation
リソースだけではこれができません。設定するためには、次の複雑な手順を踏む必要がありました。
azuread_invitation
でユーザーを招待terraform import
コマンドで招待したユーザーリソースをインポートazuread_user
リソースでプロパティを更新
このように、シンプルに見えるユーザー招待も、Terraformでは複数のステップが必要となり、運用が煩雑化してしまいます。
そこで行きついたのがMicroSoft Graph APIをGitHub ActionsのOIDCで使用する方法でした。
Microsoft Graph APIとは
Microsoft Graph APIはMicrosoftのクラウドサービスに対するRESTful APIです。Entra IDを含むMicrosoft 365のサービスを統合的に操作することができます。azureadプロバイダーも内部的にはMicrosoft Graph APIを利用して動いています。
実装の流れ
では早速実装に入ります。今回は簡易的に招待の際、表示名、姓、名のプロパティを設定する実装になります。 流れとしては以下のように進んでいきます。
- Entra IDアプリケーションの設定
- GitHub Actionsワークフローの作成
- ユーザー招待処理の作成(Node.js)
Entra IDアプリケーションの設定
まずはEntra IDにアプリケーションを登録し、フェデレーションの設定をします。以下の記事を参考に進めていきましょう。 zenn.dev
アプリケーションの作成が完了したら、ユーザー招待を行う上で必要なAPIの権限を付与していきます。 必要な権限は以下の二つです。
- Directory.ReadWrite.All
- User.ReadWrite.All
このように付与できていればEntra IDアプリケーションの設定は終了です。
GitHub Actionsワークフローの作成
GitHub ActionsでOIDC認証を使用してMicrosoft Graph APIを呼び出すワークフローを作成します。
ファイル名:.github/workflows/invitation_workflow.yml
name: user invitation on: workflow_dispatch: inputs: user_email: description: "Email of the user to invite" required: true display_name: description: "Display name of the user to invite" required: true first_name: description: "First name of the user to invite" required: true last_name: description: "Last name of the user to invite" required: true permissions: id-token: write contents: read jobs: invite_user: runs-on: ubuntu-latest environment: name: staging defaults: run: working-directory: ./invitation steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: "20" cache: "npm" cache-dependency-path: "invitation/package-lock.json" - name: Install dependencies run: npm ci - name: Login in to Azure uses: azure/login@v2 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - name: Invite user env: TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} USER_EMAIL: ${{ github.event.inputs.user_email }} DISPLAY_NAME: ${{ github.event.inputs.display_name }} FIRST_NAME: ${{ github.event.inputs.first_name }} LAST_NAME: ${{ github.event.inputs.last_name }} run: npm start
なお、以下のGitHubシークレットの設定が必要です:
- AZURE_CLIENT_ID: アプリケーションのクライアントID
- AZURE_TENANT_ID: テナントID
- AZURE_SUBSCRIPTION_ID: サブスクリプションID
ユーザー招待処理の作成(Node.js)
最後にユーザー招待処理の実装していきます。
# プロジェクトディレクトリの作成 mkdir user-invitation cd user-invitation # package.jsonの作成 npm init -y # 必要なパッケージのインストール npm install @azure/identity @microsoft/microsoft-graph-client isomorphic-fetch
package.json
に以下の内容を追加
"scripts": { "start": "node userInvitaiton.js" }, "type": "module",
ユーザー招待処理コードを追加します。 今回利用するAPIエンドポイントのリファレンスになります。
こちらをもとに作成していきます。
ファイル名:/invitation/userInvitaiton.js
import { DefaultAzureCredential } from "@azure/identity"; import { Client } from "@microsoft/microsoft-graph-client"; import { TokenCredentialAuthenticationProvider } from "@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials/index.js"; import "isomorphic-fetch"; const credential = new DefaultAzureCredential(); // Microsoft Graph APIクライアントを初期化 const authProvider = new TokenCredentialAuthenticationProvider(credential, { scopes: ["https://graph.microsoft.com/.default"], }); const client = Client.initWithMiddleware({ authProvider: authProvider }); // ユーザーの招待内容 const invitation = { invitedUserEmailAddress: process.env.USER_EMAIL, inviteRedirectUrl: `https://myapplications.microsoft.com/?tenantId=${process.env.TENANT_ID}`, sendInvitationMessage: true, // メール通知を送信する }; // 招待ユーザーのプロパティ const properties = { displayName: process.env.DISPLAY_NAME, givenName: process.env.FIRST_NAME, surname: process.env.LAST_NAME, }; // ユーザーの招待とプロパティの設定 async function sendInvitation() { try { const invitationResponse = await client.api("/invitations").post(invitation); const userId = invitationResponse.invitedUser.id; console.log( `Invitation sent to ${process.env.USER_EMAIL} with id: ${userId}` ); return userId; } catch (error) { console.error("Errer sending invitation:", error); throw error; } } async function updateProperties() { try { const userId = await sendInvitation(); await client.api(`/users/${userId}`).patch(properties); console.log(`User ${userId} properties updated`); } catch (error) { console.error("Error updating user properties:", error); throw error; } } updateProperties().catch((error) => { console.error(error); process.exit(1); });
これで準備は終わりました。コードをPushして、さっそくワークフローの動作確認をしていきます。
動作確認
リポジトリのActionsタブより、user invitationをworkflow_dispatchで動かします。
無事ワークフローが実行できました。
Azureポータルより招待ユーザーが実際に作成されたか確認してみます。
無事、招待ユーザーの表示名、姓、名のプロパティが設定されています。
おわりに
今回はGitHub Actionsを使ってOIDCを利用し、Microsoft Graph APIでユーザーを招待する方法をご紹介しました。今回は一つのユーザーのみの招待ですが、ワークフロー内でマトリックスを使用することで 単一のワークフローで複数のユーザーを並行して処理することも可能になります。この記事が皆さんの学びや実践に少しでも役立てば嬉しいです。
私達ACS事業部はAzure・AKSなどのクラウドネイティブ技術を活用した内製化のご支援をしております。
また、一緒に働いていただける仲間も募集中です!
今年もまだまだ組織規模拡大中なので、ご興味持っていただけましたらぜひお声がけください。