はじめての Azure リソース マネージド ID (概要編)

#はじめに

突然ですが、Azure 上に VM と SQL DB があるとして、SQL DB 上のデータを取得するために、json ファイルに SQL DB 接続用の資格情報をハードコーディングした設定ファイル (connect.json) があるとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/1819b3b6-0305-330b-f9eb-d09dfe7d9c20.png)

一見何も問題がないように見えるかもしれません、ちゃんと接続できる資格情報を書いているんだったら DB に接続できるんだし、これで問題ないんじゃないかと。果たしてそうでしょうか？「一体いつからこの設定が問題ないと錯覚していた？」と某氏の有名なセリフが聞こえてきそうじゃなありませんか？

完全に Closed な環境で実行しているのなら内部犯行でも起きない限りは問題ないかもしれません。
しかし、仮に GitHub など外部の誰からでも参照できるようなサイトにファイルを公開してしまったら、こんなことが普通に起こり得ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/9527a78e-c84f-930b-1900-35db9b510bbe.png)

つまり、SQL DB に接続できる資格情報が丸見えなので、悪い人が同じ資格情報を使って SQL DB 上のデータを引っこ抜いてこれてしまう訳です。

このようなことが起きないようにするために、今回は Azure AD が提供している ***マネージド ID*** をご紹介したいと思います。
ものすごく簡略化した絵で恐縮ですが、こんな感じでマネージド ID を使うと資格情報をハードコーディングする必要がなくなるため、セキュアに対象の SQL DB にアクセスすることができるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/67688489-3634-2ff0-6973-a566c9270af7.png)

実際には登場人物はマネージド ID だけではなくて、裏で動いている様々なサービスと連携してこの仕組みを実現しています。
今回はマネージド ID がどうやって構成されるのか、またマネージド ID を使うとどのような流れでバックエンドのアプリケーションにアクセスできるようになるかについて触れていきたいと思います。

※今回はあくまでマネージド ID がどんなものなのか概要のみの説明になります。実際に Azure ポータルなどを利用して構成をするお話は別途時間を作って資料を用意したいと思っています。(やるとは言っていない)

#押さえておきたい用語

まず、ここから何枚か絵で説明していきますが、ベースとなっているのは下記 Microsoft の公開情報になります。

-参考情報
Azure リソースのマネージド ID とは
URL:https://docs.microsoft.com/ja-jp/azure/active-directory/managed-identities-azure-resources/overview#how-can-i-use-managed-identities-for-azure-resources

この公開情報の内容が素晴らしいので、この公開情報を見て理解できた方、もしくはすでに実際にマネージド ID の設計・構成・運用をされているような方は完全にここからの説明は釈迦に説法なので、これ以降の内容を読んでいただく必要はございません。

まず上記公開情報で書かれている ***用語*** はこの後の絵でも出てきますので押さえてもらう必要があります。
公開情報の内容をそのまま載せてしまいます、分かりやすいので。

| 用語|      意味| 
|:-----------------|:------------------|
|クライアント ID        |   Azure AD によって生成される一意識別子で、初期プロビジョニングの間にアプリケーションおよびサービス プリンシパルと結び付けられます。 |    
| プリンシパル ID        |   マネージド ID に対するサービス プリンシパル オブジェクトのオブジェクト ID であり、Azure リソースへのロールベースのアクセス権を付与するために使用されます。|  
|Azure Instance Metadata Service (IMDS)        |   Azure Resource Manager を使用して作成されたすべての IaaS VM にアクセスできる REST エンドポイントです。 このエンドポイントは、VM からのみアクセスできる、よく知られているルーティング不可 IP アドレス (169.254.169.254) で使用できます。 |  

まず、***クライアント ID*** はマネージド ID の作成を ***Azure Resource Manager  (ARM/アーム)*** (長いので以降 ARM と表記) から Azure AD に命じられたタイミングで Azure AD が登録するアプリケーションにつけられる唯一無二の ID になります。

次に ***プリンシパル ID*** は同じく ***ARM*** から Azure AD に命じられたタイミングで Azure AD が作成する ***サービス プリンシパル*** で「プリンシパル ID ＝ オブジェクト ID」という風に理解してください。

また、このサービス プリンシパルに対して、RBAC (ロールベースのアクセス制御) を付与することで、バックエンドのアプリケーションに対して RBAC として割り当てたロール (権限) のみマネージド ID に実行させることができます。

つまり、マネージド ID をゲットしたからと言って何でもかんでもできるわけではなく、必要な権限だけをきちんと付与してあげて不必要な権限は割り当てないようにしましょう、ということです。

逆にいうとサービス プリンシパルに何も RBAC のロールを付与しないとマネージド ID をゲットしても何も権限がないので、バックエンドのアプリケーションに対して何も操作ができません。

そもそもサービス プリンシパルって何？って思っている方は、こちらの Qiita の記事がとても参考になるのでご覧ください。私も見まくってます。

-参考情報
[Azure AD のサービスプリンシパルを 3 つのユースケースから眺めてみた](https://qiita.com/watahani/items/1f3f533097b7a15d6698)

最後に ***Azure Instance Metadata Service (IMDS)***  (長いの以降 IMDS と表記)ですが、この用語はあまり聞きなれない用語かもしれません。
公開情報にも書いてあるとおり、Azure VM からのみアクセス可能なリンクローカル アドレスというルーティングすることができないアドレス (169.254.169.254) を利用して Azure VM と IMDS が通信することで、マネージド ID を作成したり、 Azure VM から IMDS に対してアクセス トークンの要求をする際に利用するエンドポイントになります。

リンクローカル アドレスって何？って興味を持たれた方は、こちらに RFC 3927 があるのでご参考まで。

-参考情報
[ Dynamic Configuration of IPv4 Link-Local Addresses](https://tools.ietf.org/html/rfc3927)

#システム割り当てマネージド ID が有効化されるまでの流れ。

さて、実際にマネージド ID が有効化されるまでどのような流れをたどっていくのかを見ていきます。

今回 ***システム割り当てマネージド ID*** と見出しに記載しているのは理由があります。
後半に触れますが、マネージド ID は ***システム割り当てマネージド ID*** と  ***ユーザー割り当てマネージド ID*** の 2 つのマネージド ID が実は存在します。

今回は ***システム割り当てマネージド ID*** の流れを説明しますが、***ユーザー割り当てマネージド ID*** の利用フローも概ね同じです。
ですので、まずは ***システム割り当てマネージド ID*** の流れを抑えることでマネージド ID の概要をつかんでほしいと思っています。

ベースとなっている情報は繰り返しとなりますが、最初に紹介した Microsoft の公開情報内に記載されている下記フロー図になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/13a4189f-b060-523b-4132-8acee2c00a4d.png)

上のフロー図に書かれている ① から ⑦ の番号とこれから紹介する絵にかかれている ① から ⑦ の番号は合わせるようにしています。
まずは、 ① の ARM にマネージド ID 有効化を要求してから、フローの過程で作成されたサービス プリンシパル に RBAC を付与する ④ までを解説します。

最初に、Azure VM が ARM に対して 「マネージド ID が欲しい」と要求をし、ARM 側がしかとその要求を受け取ります。
えっ、ARM って何？って思った方は、こちらの記事が参考になると思います。

-参考情報
[Microsoft のクラウド Azure の入門講座を和訳した (後編) Azure について - どんなサービスがあるの？ #MSIgniteTheTour](https://qiita.com/chomado/items/439eeea4b3ce318fb5a8#04azure-%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%83%9E%E3%83%8D%E3%83%BC%E3%82%B8%E3%83%A3%E3%83%BC-resource-manager-arm)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/38fa3548-3460-8894-4c3c-888ad7a5488e.png)

次に ARM が Azure AD に対してマネージド ID を作成したいから Azure AD 上にサービス プリンシパルを作ってよ、と要求をします。
ここのポイントとしては、無作為に Azure AD テナントを選別するのではなく、Azure サブスクリプションに紐づけがされた Azure AD テナントを対象に要求するということです。

そもそも Azure サブスクリプションと Azure AD の関係性よく分からん、という人はこちらの Microsoft の Blog が参考になると思います。

-参考情報
[Azure サブスクリプションと Azure AD の管理者](https://jpazureid.github.io/blog/azure-active-directory/subscription-azure-ad-relationship/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/5968cdc3-c722-8c36-ae8d-742807431100.png)

次に Azure AD がサービス プリンシパルを自身の Azure AD テナント内に作成します。
ここで注目なのが ***用語*** にも出てきた ***プリンシパル ID (オブジェクト ID)*** と ***アプリケーション ID (クライアント ID)*** になります。

サービス プリンシパルの実体はプリンシパル ID  (オブジェクト ID) の方になりますが、アプリケーションを一意に識別するために必要な アプリケーション ID (クライアント ID) も必要な情報になります。

サービス プリンシパルに対して後述する RBAC のロールを付与して、アプリケーションの方がマネージド ID の作成やアクセス トークンを取得する際に必要なアプリケーション ID (クライアント ID) と証明書情報を格納しています。
それぞれが別々の役割を担っているということになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/cf337c61-9672-2b83-ae76-e6329684be9b.png)

次に、 ARM が IMDS エンドポイントに対して Azure AD が作成したアプリケーション ID (クライアント ID) と証明書情報を更新することによってマネージド ID が最初に要求した Azure VM 上にマネージド ID が有効化されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/aa4975be-2a2b-3047-124e-ab23e22e8f93.png)

次に、Azure AD が作成したサービス プリンシパルに対して RBAC を利用し Azure VM に対して許可をさせたいロール (権限) を付与します。
ここまでが Microsoft の公開情報に書かれている ④ までの流れになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/3113341c-bfe7-bff9-6f10-70df98103653.png)

#システム割り当てマネージド ID がアクセス トークンを取得して SQL DB にアクセスするまでの流れ

残りの ⑤ から ⑦ も少しだけフォーマットを変えて説明していきます。
目的はバックエンドにある SQL DB にアクセスして DB 内の情報を取得することでしたね。

アクセス トークンを発行するのは Azure AD になりますので、Azure AD 側にアクセス トークンの要求する必要がありますが、マネージド ID がアクセス トークンを要求する先は下記絵にあるとおり IMDS になります。

IMDS は仮想マシン インスタンスに関するメタデータ情報を格納している REST 型のエンドポイントになっています。
この IMDS は [押さえておきたい用語](https://qiita.com/drafts/edd75f7ee47471a98670/edit#%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84%E7%94%A8%E8%AA%9E) の箇所でもふれたようにリンクローカル アドレスとなるため、実行中の仮想マシンからのみアクセスが可能です。


内部的には以下のようなパラメータを指定して (今回の場合 SQL DB をリソース パラメーターに指定) アクセス トークンの要求を行っています。

| 用語|    設定値(例) | 
|:-----------------|:------------------|
|  エンドポイント   |  http://169.254.169.254/metadata/identity/oauth2/token |    
|  パラメーター   |api-version=2018-02-01 |  
| ヘッダー  | "Metadata"="true" |  
|リソース |resource=https://database.windows.net/|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/851bf58a-ccfc-76e9-16fb-231e99f33428.png)

今回の例では SQL DB に対してアクセスしたいのでアクセス トークンをください、という要求を受けて IMDS から Azure AD に対してアクセス トークンの要求を行い、Azure AD から発行されたアクセス トークン を IMDS が受けて、Azure VM に紐づいているマネージド ID に渡します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/15732887-327f-084a-f225-bfbc62a1d858.png)

晴れてアクセス トークンを取得したマネージド ID はサービス プリンシパルに割り当てられた RBAC の権限内の範囲で SQL DB にアクセスできる、という動作になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/dd6d07c3-6e6e-e545-8c22-30c2f11fdfba.png)

以上がシステム割り当てマネージド ID がアクセス トークンを取得して SQL DB にアクセスするまでの流れになります。

#システム割り当てマネージド ID とユーザー割り当てマネージド ID の違い
最後に 2 つのマネージド ID ***システム割り当てマネージド ID*** と ***ユーザー割り当てマネージド ID*** について触れたいと思います。

この違いはさきほどから紹介している Microsoft の公開情報の下記情報が分かりやすいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/23088f53-857b-a86a-e3e7-153132f65120.png)

端的に言うと、システム割り当てマネージド ID は Azure リソースとの間で ***一対一*** の関係で紐づきます。
絵にするとこんな感じです。

例えば Azure VM を作成するとき、もしくは作成済みの VM に対してシステム割り当てマネージド ID を有効 (状態をオン) にすることで自動で当該の Azure VM に紐づく形でシステム割り当てマネージド ID が作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/0f3eabea-6a46-a38b-ec69-8c3e99c9bee1.png)

一方、ユーザー割り当てマネージド ID は個別で作成する必要がありますが、下記絵のように 1 つのユーザー割り当てマネージド ID を複数の Azure VM に対して共有させることが可能です。

メリットとしては、1 つのユーザー割り当てマネージド ID に割り当てた RBAC のロールを複数のフロントエンド サーバーに対して展開したい場合に有効な選択になります。まさに今回の絵のように １つの DB に対してフロントエンドのサーバーが複数ある場合にはシステム割り当てマネージド ID のように 1 つ 1 つマネージド ID を払い出す必要もないので、利便性が高いと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/623a1250-ce00-4f7d-ebb4-e9377f5727dd.png)

もう 1 つこの 2 つのマネージド ID の違いの特徴をあげるとすると、マネージド ID を割り当てた Azure リソースを削除する際の動作が異なります。
システム割り当てマネージド ID に紐づいている Azure VM を削除すると、下記絵のように紐づいているシステム割り当てマネージド ID も一緒に削除してくれます。

これによりシステム割り当てマネージド ID だけが宙に浮くようなこともないので、運用がとても楽になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/8a55470b-34b8-3116-780a-e4eba8e94585.png)

一方、ユーザー割り当てマネージド ID については、紐づいている Azure VM を削除しても削除がされません。
理由は下記絵を見て分かるとおり、ユーザー割り当てマネージド ID は複数の Azure リソースに対して共有して利用するため、逆に 1 つの Azure リソースを削除した際にユーザー割り当てマネージド ID も一緒に削除されてしまうと、その他の Azure リソースに影響が出てしまいます。

そうならなようにするために自動的には削除されないよう設計されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/f9dd9b58-f2f9-c806-303b-83a9e42f92a6.png)

#マネージド ID が利用できる Azure リソース、マネージド ID を利用したクライアントからの Azure AD 認証をサポートしているサービス

ここまで読んできた方は、それなら全部 Azure 上のサービスでマネージド ID 使えば便利じゃん、と思うかもしれません。
確かにそのとおりなのですが、マネージド ID を利用できるシーンというのが今のところ限られています。

まず前提としてマネージド ID は ***Azure リソース*** を対象にしているので、オンプレミス環境上で構成したアプリケーションを Azure AD に登録してもマネージド ID を有効化することができません。

次に、Azure サービスの中でもマネージド ID を有効化できるサービスとバックエンド サイドとして、マネージド ID を割り当てたクライアントからの Azure AD 認証をサポートできるサービスが限られています。

それぞれどの Azure サービスがサポートしているのかについては下記 Microsoft の公開情報で最新の内容を確認することをおすすめします。

-参考情報
Azure リソースのマネージド ID をサポートする Azure サービス
URL:https://docs.microsoft.com/ja-jp/azure/active-directory/managed-identities-azure-resources/services-support-managed-identities#azure-services-that-support-managed-identities-for-azure-resources

Azure AD 認証をサポートしている Azure サービス
URL:https://docs.microsoft.com/ja-jp/azure/active-directory/managed-identities-azure-resources/services-support-managed-identities#azure-services-that-support-azure-ad-authentication

#まとめ
今回はマネージド ID の概要編としてマネージド ID を使うと何がうれしいのか、マネージド ID はどんな感じで構成されどのようにアクセス トークンを取得するのかなど絵を交えながら説明しました。

最後にここまでの内容を簡単に箇条書きでまとめました。

- バックエンドのアプリケーションにアクセスするためにフロント エンド側の接続構成ファイル内に資格情報をハード コーディングする必要がなくなる。
	
- サービス プリンシパルに対して必要最低限のロールを付与することでバックエンドのアプリケーションへの権限を管理できる。

- マネージド ID の資格情報は Azure のバックグラウンド側で自動でローテーションされる。つまりサービス プリンシパルを利用したシークレットや証明書の有効期限を気にする必要がない、まさにマネージド。

- システム割り当てマネージド ID の場合は紐づいている Azure リソースを削除すると自動的にマネージド ID も削除してくれる。宙に浮いたままマネージド ID が Azure AD 上に存在し続けるということがなくなる。
	
- Azure AD が提供している無料の機能である。(実は無料の機能)

今回は概要だけで結構なボリュームになってしまいましたが、次回は (しつこいですがやるとは言っていない) 実際にマネージド ID を有効化してバックエンドのアプリケーションにマネージド ID を使って何らかのデータを取ってくる内容を書きたいと思っています。

今回の記事が少しでもマネージド ID 利用検討の参考になれば幸いです。