【Azure Blob Storage】403 エラーのトラブルシューティング！【Log Analytics】

# はじめに
どうも、ATL のヴィリアスです。

先日、Azure Blob Storage 上の Blob にアクセスする ASP.NET Core MVC 8 の Web アプリを開発していました。
途中、Blob へのアクセス時に 403 エラーを返される事象に遭遇し、問題解決まで少々詰まってしまったので、今回は備忘録を残します。

## 補足: Web アプリ
- Azure Portal の [アプリの登録] および [エンタープライズアプリケーション] にて、当該 Web アプリを登録しています。  
そのため、Web アプリにはクライアント ID (アプリケーション ID) やクライアントシークレットなど付与がされています。
- 403 エラー発生当初、Web アプリには RBAC 設定としてロール "**ストレージ BLOB データ共同作成者**" が付与されていました。

# 結論: Log Analytics を使おう
- 何かよく分からないエラーが出力されたら、**Log Analytics** に出力、調査すれば OK！

ログには、エラー解消の糸口が何かしら出力されています。
今回はストレージアカウントが対象ですが、もちろんそれ以外リソースにおけるトラブルシューティングにも使えます！

# Azure Blob Storage に 403 エラーでアクセスできない
**まずは Azure Blob Storage のログを Log Analytics に出力します。**

:::note info
Log Analytics は事前に作成しておきます。
:::

対象のストレージアカウントを開き、左メニューから [**監視**] > [**診断設定**] をクリックします。
少し待つと "blob, "queue", "table", "file" といった選択画面が表示されます。

今回は Blob に対する 403 エラーを解消するので "blob" を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/eb40cfd8-5823-4924-823f-1f5ce3aced3b.png)

:::note info
スクリーンショットでは、すでに [診断の状態] が "有効" となっていますが、初めて設定する際は "無効" になっています。
:::

選択後、[**+ 診断設定を追加する**] をクリックし、診断設定を入力していきます。

設定値は以下のとおりです。
> - **ログ**
>   - カテゴリグループ
>     - ☑ audit
>     - ☑ allLogs
> - **宛先の詳細**
>     - Log Analytics ワークスペースへの送信
>       - サブスクリプション
>         - ※ 任意
>       - Log Analytics ワークスペース
>         - ※ 任意

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/d01f2521-1771-4052-8176-bdde9aa46774.png)

ここまで設定すれば、Log Analytics に Azure Blob Storage に対するアクセスログなどが出力されるようになります！

**このあと 403 エラーの原因を見ていくので、Log Analytics を設定した現在の状態で 403 エラーを発生させ、ログを出力しておきます。**

:::note warn
[**監視 (クラシック)**] > [**診断設定 (クラシック)**] の [**BLOB のプロパティ**] にて、ログ出力を "オン" にすると、対象ストレージアカウントにコンテナー ```$log``` が生成されます。
今回は使用していませんが、そちらにログ情報を出力していくことも可能なようです。
:::
 
# Log Analytics で 403 エラーの原因を探る
**設定した Log Analytics で出力されたログを見ていきます。**

Log analytics にアクセスし、左メニューから [**ログ**] をクリック、その後 KQL を入力していきます。

以下は「<対象のストレージアカウント名> にてステータスコード 403 が返されたログを、最新日時順にして抽出する KQL」です。
```SQL
StorageBlobLogs
| where AccountName == "<対象のストレージアカウント名>"
| where StatusCode == 403
| sort by TimeGenerated desc
```

KQL 実行後、[**結果**] にログが出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/25a8839e-ca2e-47c9-b86f-4a151afe3c50.png)

:::note info
必要に応じて、[時刻の表示] を "ローカル時刻" に変更します。
ロケールされたログ出力時刻で閲覧できます。
:::

403 エラーのログ内容を展開してみると、[AuthorizationDetails] 内に [result] が "Denied" されている要素を確認できます。
**[action] には Denied (拒否された、403 エラーが返された) アクションが記載されています。**

例えば、上記のスクリーンショットでは ```Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/read``` のアクションを実行しようとして Denied されていますね。

このログから、Web アプリには Blob にアクセスしようとしたときに ```Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/read``` のアクションを実行できる権限 (ロール) を付与されていないということが分かります。

**ということで、次は当該アクションを実行できるロールを Web アプリに付与していきます。**

# 403 エラーを返されてしまう Web アプリの RBAC 設定を確認する
冒頭の Web アプリの補足にも記載しましたが、エラー発生当初、Web アプリにはロール "**ストレージ BLOB データ共同作成者**" が付与されていました。

このロールが本当に ```Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/read``` のアクションを実行できないのか (アクションを拒否されてしまうのか) を確認してみます。

以下のドキュメントにて、"ストレージ BLOB データ共同作成者" が許可されているアクションを確認できます。

https://learn.microsoft.com/ja-jp/azure/role-based-access-control/built-in-roles/storage#storage-blob-data-contributor

ドキュメントを見ると、"ストレージ BLOB データ共同作成者" には ```Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/read``` が含まれていないことが分かります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/4bbf74d5-ce25-4068-b88b-08686af0086f.png)

そのため、アクションを拒否されてしまうのは当然ですね。

**それでは続いて、当該アクションを実行できるロールを Web アプリに割り当てていきます。**
 
# Web アプリに対して、許可アクションが含まれるロールを割り当てる
先ほど、```Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/read``` を実行できるロールが必要ということが分かりました。

ドキュメントをもう一度見てみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/703b36aa-fb2d-4440-9885-a7e486211e50.png)

どうやら "**ストレージ BLOB データ所有者**" の方では ```Microsoft.Storage/storageAccounts/blobServices/containers/*``` (コンテナーのフル アクセス許可) が含まれているようです。

\* (ワイルドカード) で一緒くたにアクションが表現されていますが、当然 ```Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/read``` も含まれます。

**今回はこのロールを Web アプリに割り当てます。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124150/4df0f8dc-068e-4c19-a43c-2ebdafd24588.png)

:::note warn
システム要件やセキュリティ要件上、```Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/read``` のためだけに、"ストレージ BLOB データ所有者" のように強力なロールを割り当てたくないことがあるかもしれません。
その場合、必要とするアクションだけを含む **専用のカスタムロール** を作成して、Azure リソースに割り当てる方式が有効です。
:::

**そうすれば、403 エラーが解消されて Blob にアクセスできるようになります！**

# おわりに
今まで Log Analytics のことはボンヤリとしか把握していませんでしたが、今回 Azure Blob Storage での事象に遭遇したことで「こんな風に使えばいいんだな」という感覚を少し掴めました。

Azure は今後も業務で使用していくので、何かしら有用な情報を会得したらどんどん備忘録を残していければと思います！

それではまた、次の記事で。