【第18回】Azureで社内システム再現（クラウド編）｜Graph API×AutomationでCSV自動生成

## 概要

これまでの「オンプレ編」では、Azure の仮想マシン（IaaS）を使って、社員番号から名前を検索できるシンプルな社内システムを構築してきました。Active Directory、SQL Server、ADFS などを組み合わせ、オンプレミスの構成を仮想的に再現しています。

※全体構成の詳細は、[【第0回】Azureで社内システム再現（オンプレ編）｜構成図と動作の流れ](https://qiita.com/your-link-here) をご参照ください。

クラウド編では、これまでの構成をベースにしつつ、Azure のマネージドサービス（PaaS）を中心とした構成へ段階的に移行していきます。

※クラウド移行全体の設計方針については、[【第10.5回】Azureで社内システム再現（クラウド編）｜オンプレ構成をどうクラウドに移行するか？](https://qiita.com/saba_infra/items/4ff691131593e947d6cf) にまとめています。

## システム構成（今回の対象範囲）

![cloud_automaiton.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4037248/27499949-e0db-4d3b-9dcd-e9a7276f0737.png)

今回は、Entra ID に登録されたユーザー情報を Graph API 経由で取得し、CSV ファイルとして Azure Blob ストレージに自動保存する構成を実装しました。

図の赤枠で示した部分が、今回構築した処理の中心となります。  
Automation をトリガーに、Graph API に接続 → ユーザー情報を取得 → ストレージに出力、という一連のフローを構成しています。

---

具体的には、以下の作業を行いました：

- **Automation アカウントを作成し、マネージド ID を有効化**
- **ランブックを作成し、ユーザー情報を取得して CSV に出力・アップロードする処理を実装**
- **必要な PowerShell モジュールをインポート**
- **Graph API のアプリケーション権限（User.Read.All）を PowerShell 経由で付与**
- **Blob ストレージとコンテナを用意し、マネージド ID にロールを割り当て**
- **実行結果を確認し、Blob に出力されたファイルの内容を検証**



##  Azure Automation アカウントの作成

ユーザー情報を自動取得するための **Automation アカウント**を作成します。  
このアカウントは、他のサービスと同じリージョンに配置しました。

![Automation アカウントの作成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4037248/ad7f2bba-eed1-4c7f-9aa1-83bbd14a28e6.png)

作成時の「詳細設定」タブにて、**システム割り当てのマネージド ID を有効化**しておきます。  
このマネージド ID は、後のステップでストレージアカウントへのアクセス権を付与する際に必要となります。

![マネージド ID を有効化](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4037248/5de74b44-56d8-4b73-a891-f29a95bf32a1.png)

> Automation からストレージへ CSV ファイルをアップロードするためには、事前にこのマネージド ID を有効にしておく必要があります。

---



## モジュールのインストール（バージョンに注意）

Graph API を使って Entra ID のユーザー情報を取得するために、Automation アカウントに以下のモジュールをインストールします。

- Microsoft.Graph.Authentication（Graph API への接続に使用）
- Microsoft.Graph.Users（ユーザー情報の取得に使用）

これらは、スクリプト内の Connect-MgGraph や Get-MgUser で使われています。

![スクリーンショット 2025-04-03 10.41.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4037248/c13c066b-91c6-4ea8-9ec2-7060fd04c911.png)


今回は **バージョン 2.25.0 をCLIで指定してインストール**しています。

> 通常、GUIから追加すると 2.26 系がインストールされますが、PowerShell 7.2 の環境では以下の既知の問題により認証エラーになりました。
![スクリーンショット 2025-04-17 20.12.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4037248/8d20f2eb-8f93-49f1-8dd2-095d89703ccb.png)
>https://learn.microsoft.com/en-us/answers/questions/2237145/invalid-jwt-access-token

---

## Graph API のアクセス許可を付与する

Automation アカウントが Entra ID（旧 Azure AD）のユーザー情報を取得するには、Graph API へのアクセス権限が必要です。  
ここでは、Automation のマネージド ID に **Graph API の「アプリケーション権限」** を付与します。

### マネージド ID が有効になっていることを確認

Automation アカウントの「ID」設定で、**システム割り当てのマネージド ID がオンになっている**ことを確認します。

![スクリーンショット 2025-04-03 11.00.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4037248/c2117452-1efa-453f-897e-93d89a695de3.png)


---

### エンタープライズ アプリケーションを確認

Entra IDの「エンタープライズ アプリケーション」から、Automation のマネージド ID を確認します。

![エンタープライズ アプリケーションを開く](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4037248/cd4b55b2-46c1-4009-9a43-b106061a383e.png)

アクセス許可の画面を見ると、**Microsoft Graph の API 権限が何も付与されていない**状態です。

![アクセス許可がない状態](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4037248/9b8030a1-a26f-4b5b-ade3-6c6a87706c1f.png)

以下の記事にも記載がある通り、**システム割り当てマネージド ID の場合、Azure Portal の UI では Microsoft Graph のアクセス許可を直接追加できません**。  
そのため、CLI や PowerShell（Microsoft Graph API 経由）で明示的に権限を付与する必要があります。

>https://techcommunity.microsoft.com/blog/integrationsonazureblog/grant-graph-api-permission-to-azure-automation-system-assigned-managed-identity/4278846

---

## Graph API のアクセス権を PowerShell で付与する

Automation アカウントのマネージド ID に対して、Microsoft Graph の User.Read.All アプリケーション権限を付与します。

### スクリプト
```
# Automation アカウントのマネージド ID（Service Principal ID）
$spId = "803e39c4-735b-4fc8-9454-7adb533ca5ff"

# Microsoft Graph のサービスプリンシパルを取得
$graphSp = Get-MgServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'"

# User.Read.All のロールを取得（アプリケーション権限）
$userReadRole = $graphSp.AppRoles | Where-Object {
    $_.Value -eq "User.Read.All" -and $_.AllowedMemberTypes -contains "Application"
}

# アクセス権限を割り当てる
New-MgServicePrincipalAppRoleAssignment `
    -PrincipalId $spId `
    -ResourceId $graphSp.Id `
    -AppRoleId $userReadRole.Id
```

---

### 割り当てた権限を Azure Portal で確認

PowerShell スクリプトで User.Read.All のアクセス権を付与した後、  
Azure Portal の「エンタープライズ アプリケーション」から対象アプリ（マネージド ID）を開くと、**アクセス許可が正しく反映されていること**が確認できます。

![スクリーンショット 2025-04-03 11.07.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4037248/f785f6e0-39f5-4257-924e-071f744e63c3.png)

これで Automation アカウントは、Graph API を通じて Entra ID のユーザー情報を取得する準備が整いました。

---
## ストレージアカウントの作成とロールの割り当て

Automation で生成された CSV ファイルを保存するために、Blob ストレージを準備します。

### ストレージアカウントの作成

まずは新しくストレージアカウントを作成します。  
このアカウントが、CSV ファイルのアップロード先となります。

![ストレージアカウントの作成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4037248/f7b0243d-5fda-454f-bf0b-4ef2a1ef659b.png)

---

### BLOB コンテナの作成

次に、ストレージアカウント内に empdata という名前の Blob コンテナを作成します。  
Automation のスクリプトから出力された CSV ファイルは、このコンテナに保存されます。

![コンテナの作成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4037248/8819509b-6e3d-4d92-90e4-f28c208b73a5.png)

---

### マネージド ID にロールを割り当てる

Automation アカウントのシステム割り当てマネージド ID に対して、  
以下のロールをストレージアカウントに付与します。

- **ストレージ BLOB データ共同作成者**  

- **ストレージ アカウント共同作成者**  


このロールを割り当てることで、Automation ランブックから Blob コンテナに対してファイルの作成やアップロードが可能になります。

![ロールの割り当て](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4037248/19827d22-11b0-4c38-bfe9-40f30a53c094.png)

---
## ランブックの実行と動作確認

設定したランブックを実行し、Entra ID のユーザー情報が正しく取得され、Blob ストレージに CSV ファイルとして出力されるかを確認します。

---

### ランブックの実行結果

Automation ランブックを実行したところ、**正常に完了**しました。

![ランブックの実行結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4037248/5fdf15b9-7b25-448e-9399-1dbb93a990ec.png)

---

### Blob ストレージにファイルが出力されたことを確認

Blob コンテナ empdata 内に、**実行時刻のタイムスタンプを含む CSV ファイル**が作成されていることを確認しました。

![ファイルの存在を確認](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4037248/c9d62e24-7a7a-4963-84f5-d8bca387663e.png)

---

### CSV ファイルの内容を確認

実際にファイルをダウンロードし、中身を確認したところ、**ユーザー名と従業員 ID が正しく出力されている**ことを確認できました。

![CSV の中身を確認](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4037248/9affb525-c7ca-49ad-9ecf-662c13c328af.png)

---

ここまでで、Automation を使った Entra ID ユーザー情報の取得と Blob への自動保存処理が完成しました。