[Azure] az ad sp create-for-rbac は何をやっているのか

## はじめに
`az ad sp create-for-rbac` は何をやっているのでしょうか。
答えは、サービスプリンシパルを作成している、です。

それは分かるし、表示された ID とパスワードを使えばスクリプトを動かすことができる。
だけど、このコマンドの裏でどういったことが行われているのかはわからない。

この記事はそんな経験を持つ昔の自分に向けて、このコマンドで何が実行されているのかを記したものです。

## az ad sp create-for-rbac がやっていることを Azure Portal で確認してみる
以下のドキュメントは、Azure Portal からサービスプリンシパルを作成する手順が示されています。
https://docs.microsoft.com/ja-jp/azure/active-directory/develop/howto-create-service-principal-portal

このドキュメントの手順を簡単にまとめると、サービスプリンシパルの作成は次の 4 工程に分かれます。(今回はキーコンテナの使用がないと仮定し、アクセスポリシーの構成手順は省略します。)

- アプリの登録によるサービスプリンシパルの作成
- サービスプリンシパルにロール割り当て
- テナント ID とアプリ ID 値の確認
- 認証設定

`az ad sp create-for-rbac` はこれら 4 工程を、 1 コマンドで実行していることになります。

ここからは以下のコマンドで作成してみたサービスプリンシパルを、各工程に沿って Portal 上から確認してみます。

```bash

$ az ad sp create-for-rbac --name testsp001
{
  "appId": "cb799f99-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "displayName": "testsp001",
  "name": "http://testsp001",
  "password": "kCxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "tenant": "c4xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
```

### アプリの登録によるサービスプリンシパルの作成
Azure Portal からサービスプリンシパルを作成する際には、Azure Active Directory の `アプリの登録` メニューから作成します。
そこで、上記コマンド実行後に `アプリの登録` メニューに遷移してみると、確かに指定した名前のオブジェクトが作成されています。
![2020-11-24_11h43_35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423135/ccf80fcd-2e88-f849-bb8a-52698b267aa0.png)

実はこのとき、もう一つオブジェクトが作成されています。
Azure Active Directory の `エンタープライズアプリケーション` メニューを選択し、アプリケーションの種類をすべてのアプリケーションに変更して確認してみると、こちらにも同じ名前のオブジェクトがあることが分かります。
![2020-11-24_11h53_47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423135/b841d729-6176-9130-c6ab-4fd6107b091d.png)




Azure Portal の `アプリの登録` や今回のように `az ad sp create-for-rbac` コマンドを実行した場合、以下 2 種類のオブジェクトが作成されます。

- `アプリの登録` から確認できる**アプリケーションオブジェクト**
- `エンタープライズアプリケーション` から確認できる**サービスプリンシパルオブジェクト**

アプリケーションオブジェクトはサービスプリンシパルの鋳型のような存在であり、サービスプリンシパルオブジェクトはその鋳型を元に作成されたサービスプリンシパルの実体となります。
アプリケーションオブジェクトとサービスプリンシパルオブジェクトについては、下記ドキュメントが詳しいです。
https://docs.microsoft.com/ja-jp/azure/active-directory/develop/app-objects-and-service-principals

### ロール割り当て
続いて、作成したサービスプリンシパルに割り当てられているロールを確認します。
`サブスクリプション > アクセス制御 (IAM) > ロールの割り当て` から確認できます。
![2020-11-24_13h08_22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423135/29b6ea2e-48af-51be-e40c-5272339b0bda.png)



`az ad sp create-for-rbac` で作成したサービスプリンシパルは、デフォルトで共同作成者ロールが割り当てられています。
共同作成者ロールの権限：https://docs.microsoft.com/ja-jp/azure/role-based-access-control/built-in-roles#contributor

もちろん、ロールの割り当てには必要最小権限が推奨されます。
別のロールを割り当てる場合は、サービスプリンシパル作成時に `--role` オプションを使うことでロール指定ができます。

```
# ロールの一覧を表示する
$ az role definition list -o table

# サービスプリンシパル作成時にロールを指定する
$ az ad sp create-for-rbac --name <サービスプリンシパル名> --role <ロール名>
```

### テナント ID とアプリ ID 値の確認
`az ad sp create-for-rbac` を実行するとテナント ID とアプリ ID が出力されます。
これらの情報は、`アプリの登録` から見ることができるアプリケーションオブジェクトでも確認できます。
![2020-11-24_13h33_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423135/d0562f6e-9365-a5fc-d2c7-3f95876c3c32.png)


### 認証設定
サービスプリンシパルの認証方式は 2 種類あります。

- 証明書ベースの認証
- パスワード (クライアントシークレット) ベースの認証

`az ad sp create-for-rbac` では、デフォルトでクライアントシークレットによる認証が適用されます。
Azure Portal から確認してみます。
`アプリの登録` > 該当のアプリケーションオブジェクトにて `証明書とシークレット` を選択します。
![2020-11-24_13h45_56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423135/29e193ae-c6b4-3223-eea9-50eb255c0ed9.png)
画面下部に、作成されたクライアントシークレットが確認できます。
作成済みのクライアントシークレットの値 (パスワード) については、確認することができません。
値を忘れてしまった場合は `+ 新しいクライアントシークレット` から再作成しましょう。

なお、クライアントシークレットの有効期限はデフォルトで 1 年となっているので注意しましょう。
コマンド実行時に `--year` オプションを使用することで、期限を指定することができます。

```
$ az ad sp create-for-rbac --name <サービスプリンシパル名> --year 3
```

※ 以下のページによると、`--year` の指定は最大 `9999 - <現在の西暦>`まで指定できるようです。
https://github.com/Azure/azure-cli/issues/12412

また、公式の推奨は証明書ベースの認証です。
`--cert` オプションを使用することで、証明書ベースの認証方式によるサービスプリンシパルを作成できます。
使用方法は以下ドキュメントを参考にしてください。
https://docs.microsoft.com/ja-jp/cli/azure/create-an-azure-service-principal-azure-cli#certificate-based-authentication

## おわりに
`az ad sp create-for-rbac` は上記 4 工程を一度に実行して、すぐに使えるサービスプリンシパルを作成できる便利なコマンドでした。
ただし、ロールの指定や認証設定など注意すべき点もあり、コマンドが何を実行しているのかを理解することは大切なことだと改めて実感しました。

## 参考資料
- Azure CLI によるサービスプリンシパルの作成：https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli

- Azure Portal によるサービスプリンシパルの作成：https://docs.microsoft.com/ja-jp/azure/active-directory/develop/howto-create-service-principal-portal

- Azure Active Directory のアプリケーション オブジェクトとサービス プリンシパル オブジェクト：https://docs.microsoft.com/ja-jp/azure/active-directory/develop/app-objects-and-service-principals

- az ad sp create-for-rbac コマンド：https://docs.microsoft.com/en-us/cli/azure/ad/sp?view=azure-cli-latest#az_ad_sp_create_for_rbac

- az role definition list コマンド：https://docs.microsoft.com/en-us/cli/azure/role/definition?view=azure-cli-latest#az_role_definition_list