【Azure】サービスプリンシパルを整理しよう

# 1.はじめに
はい、アベンドカレンダー5日目、12日目、19日目担当です。とうとうアベンドカレンダーも終盤ですね。
早いものです。~~一週間も二週間も…~~

とうとう私の担当としては最後の日になりました。

それでは19日目は、サービスプリンシパルについて書いていきたいと思います。
ラストなのにすっごい地味な記事になりそうですが、頑張ってついてきてください！

# 2.サービスプリンシパルを利用する

さて、あなたの会社でアプリケーションを開発したとしましょう。
完成間もなく、セキュリティ監査で問題が見つかります。
__「このシステムでは、構成ファイル上にIDやパスワードを格納しています。これは重大な欠陥です。」__
そう、このシステムでは、ソースコード上に資格情報を記述してしまっていたのです。
これを解決するために、Azure上ではサービスプリンシパルを検討することになりました。

・・・っていうのが、よくあるストーリーでしょうか。
実際ソースコード上に平文で資格情報が記載してあることで、情報漏洩につながります。
また、ユーザーを実際の認証に利用していると、その利用したユーザーが退職したりするとアプリケーション自体が利用できなくなってしまいます。
さらにそのユーザーの資格情報が漏洩してしまった場合、ソースコードの修正が必要になりますし、それに伴う手間も馬鹿にできません。

Azure上ではこれを解決する方法として、__サービスプリンシパル__を利用します。

# 3. サービスプリンシパル

サービスプリンシパルは、AzureADアプリケーションとして作成します。
AzureADアプリケーションを説明しだすと~~めんどくさ…~~長くなるので割愛しますが、要するにAzureADに作成したアプリケーションのID・パスワードの認証を委任することができる機能です。
このアプリケーションとサービスプリンシパルは、1対1か、1対多の関係で紐づくことになります。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626338/27beb1ce-dfe5-2e3a-fd3c-79d201f5d121.png)|
|:--|

AzureADアプリケーションについては、以下の公式ドキュメントを読んでみましょう。
[Azure Active Directory のアプリケーション オブジェクトとサービス プリンシパル オブジェクト]
(https://docs.microsoft.com/ja-jp/azure/active-directory/develop/app-objects-and-service-principals)

>アプリケーション - この種類のサービス プリンシパルは、単一のテナントまたはディレクトリ内のグローバル アプリケーション オブジェクトのローカル表現、つまりアプリケーション インスタンスです。 この場合、サービス プリンシパルは、アプリケーション オブジェクトから作成された具象インスタンスであり、そのアプリケーション オブジェクトから特定のプロパティが継承されます。 サービス プリンシパルは、アプリケーションが使用される各テナントで作成され、グローバルに一意なアプリ オブジェクトが参照されます。 サービス プリンシパル オブジェクトには、特定のテナント内でアプリが実際に実行できること、アプリにアクセスできるユーザー、アプリからアクセスできるリソースを定義します。
>アプリケーションにテナント内のリソースへのアクセス許可が与えられると（登録または同意時に）、サービスプリンシパルオブジェクトが作成されます。Azureポータルを使用してアプリケーションを登録すると、サービスプリンシパルが自動的に作成されます。Azure PowerShell、Azure CLI、Microsoft Graph、およびその他のツールを使用して、テナントにサービスプリンシパルオブジェクトを作成することもできます。

うん、__何を言っているのかさっぱりわからねぇ・・・__

アプリケーションサービスプリンシパルは、

- テナントやディレクトリ内に接続してくる、外部のアプリケーションを形にしたもの
- サービスプリンシパルには、テナントでできることやアクセスできるユーザー、リソースが定義される
-  アプリケーションとサービスプリンシパルは同時に作成される

って感じですかね。

それで、AzureADアプリケーションオブジェクトを作成することで、サービスプリンシパルも作成することになるわけです。
サービスプリンシパルは__Azure ロールベースのアクセス制御 (Azure RBAC) で利用することができます。__
アクセスが必要なリソースに対して、Azure RBACで適切にアクセス権限を付加することにより、この資格情報を持って、Azure上で他のリソースにアクセスすることができるようになります。
外部アプリから接続する際は、このサービスプリンシパルの情報を持って、Azureのリソースへ接続するわけです。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626338/0dcaa9df-0e94-6ba4-f567-c3c5f6ddf019.png)|
|:--|

#4.マネージドIDって？

ここまででサービスプリンシパルをみてきましたが、サービスプリンシパルにはマネージドIDという概念があります。
サービスプリンシパルは外部アプリケーションが認証するために必要だったわけですが、Azureだけでシステムが完結している場合、外部からアクセスさせる必要もありません。
その場合はよりセキュアに扱える、マネージドIDを利用するのが便利です。

マネージドIDを利用すると、利用者側が意識することもなく、資格情報のローテーションや証明書の置き換えを自動的にやってくれます（つまりマネージド、ってわけですね）。
マネージドIDには__「システム割り当てマネージド ID」、「ユーザー割り当てマネージド ID」__の2種類があります。

## システムマネージドID

システムマネージドIDは、利用するAzureリソースに__直接紐づく形で__、生成されるサービスプリンシパルを利用します。
システムマネージドIDの場合は、そのAzureリソースのみからの要求を受け付けることになります。
リソースが削除されると、システムマネージドIDも一緒に削除されます。

## ユーザーマネージドID
ユーザーマネージドIDは、利用するAzureリソースに__直接紐づかない形で__、生成されるサービスプリンシパルを利用します。
そのため複数のリソースに割り当てることができ、大変便利です。

複数のリソースが同じリソースにアクセスする必要があるのであれば、こちらを利用します。

# 5.おわりに

今回はサービスプリンシパルについて書いてみました。
正直ややこしい上によくわからないカタカナ言葉がたくさんできてくるのでめちゃくちゃ苦労しました。。。

結局サービスプリンシパルは

- 外部アプリケーションから認証が必要なときに利用する
- Azureリソースしか使っていない場合は、マネージドIDの利用を検討する

っていうのが一言でいうまとめですかね。

#参考

もう何十回も読ませていただいている、サービスプリンシパルの詳細な認証処理に関する記事です。ありがてぇありがてぇ…
[もう多分怖くないサービスプリンシパル](https://tech-lab.sios.jp/archives/23371)

○Azure公式ドキュメント
[Azure Active Directory のアプリケーション オブジェクトとサービス プリンシパル オブジェクト]
(https://docs.microsoft.com/ja-jp/azure/active-directory/develop/app-objects-and-service-principals)
[Azure リソースのマネージド ID とは]
(https://docs.microsoft.com/ja-jp/azure/active-directory/managed-identities-azure-resources/overview)