アプリ登録 でも最小権限の原則を適用しよう

この記事は、[Office 365 Advent Calendar 2021](https://adventar.org/calendars/6679) の20日目の記事です。

# はじめに
O365, AADの管理者をしていると、「〇〇がやりたいので、グローバル管理者の権限ください」という依頼がよく来ます。まあ、普通の管理者なら「おととい来やがれ」って断りますよね。

しかし、「✖✖がやりたいので、Mail.Readのアプリケーションのアクセス許可の管理者の同意お願いします」なんて依頼が来たらどうしますか? 「同意すればいいんですね。わかりましたー」っていうことしてませんか。

この記事では大きな規模のテナントでアプリ登録をする場合に気をつけなければならない権限についての注意点を述べます。

# 何が危ないのか?
[Microsoftのアクセス許可のリファレンス](https://docs.microsoft.com/ja-jp/graph/permissions-reference#mail-permissions) を見てみます。アプリケーションのアクセス許可では 
> サインインしているユーザーなしで、すべてのメールボックス内のメールをアプリで読み取れるようにします。

と書かれています。(ここで、委任されたアクセス許可の権限と間違わないように気をつけてください。)
ということは、最初の依頼は 「✖✖がやりたいので、テナント全体のユーザ(社長も役員も上司も部下も全員)のメールボックスを読めるようにしてください」と言い換えることができます。これは最小権限でしょうか?

アプリの動作などを根掘り葉掘り聞いてみると、実際にはアプリを呼び出したユーザのメールの読み込みだけで良かったりします。

# アプリ登録とは何か?
AAD には2種類のIDがあります。ユーザプリンシパルとサービスプリンシパルです。
簡単に言うと、アプリ登録とはサービスプリンシパルを追加するということです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215014/50b1ccc1-6457-87a1-44b6-0d61d02afbc5.png)

azure ポータルの「ユーザー」はユーザプリンシパルを管理するブレードで、「エンタープライズアプリケーション」と「アプリの登録」がサービスプリンシパルを管理するブレードです。この画面からもユーザプリンシパルとサービスプリンシパル、そしてデバイスがAADにとっては並列の概念であることがわかります。

### ユーザプリンシパル
ユーザプリンシパルは一般的なユーザIDを指します。いわゆる人間がAzureやO365をインタラクティブに操作するためのIDです。
### サービスプリンシパル
サービスプリンシパルは人間ではなく、AzureやO365をサービスやアプリケーションから操作するためのIDです。シークレットや証明書で認証ができ、プログラムから利用しやすい一方で、ポータルや、GUI での操作はできなくなっています。

ここでよく起きる間違いは、サービスプリンシパルを知らない人がアプリケーションを作ると、ユーザプリンシパルを使ってアプリケーションを作ろうとすることです。アプリケーションが作りにくい上、アプリケーションには必要がない操作ができてしまいます。最小権限ではないのでやめましょう。実を言うと、ユーザプリンシパルでアプリを作っても管理者側からはわからないことが多いのですが、私の経験では、「MFAを除外してください」という依頼で発覚することが多いです。

# サービスプリンシパルに権限を追加する
アプリケーションとそれに紐づくサービスプリンシパルに権限を追加しないと、Azureのリソース、O365のリソースには何もできません。いわゆる認可の管理をしなければいけません。権限の付け方としてはユーザプリンシパル同様にロールを割当をする必要があります。またサービスプリンシパルではAPIのアクセス許可を追加できます。APIのアクセス許可には「委任されたアクセス許可」と「アプリケーションのアクセス許可」の2種類があります。

### 委任されたアクセス許可
委任されたアクセス許可では、ユーザに同意され、代わりにアプリが、そのユーザと同じ権限で動作する方法です。委任されたアクセス許可の Mail.Read は同意したユーザ個人のメールにのみアクセスできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215014/fb1899bd-343e-ba32-bfdb-325a29f6a8ea.png)

ほとんどの場合委任されたアクセス権限で動作するアプリケーションはAAD, O365の管理者の視点から見ると、機密性、完全性に影響がある範囲を限定でき最小権限なので安全です。

### アプリケーションのアクセス許可
アプリケーションのアクセス許可は、ユーザとは関係なくアプリが独自に認証してAzureの全体リソース、O365の全体リソースにアクセスします。特に「管理者の同意が必要」な権限は **とてつもなくヤバい権限** であると認識してください。アプリケーションのアクセス許可の Mail.Read は管理者の同意が必要な権限です。管理者が同意した場合、サービスプリンパルおよびそれに紐づくアプリケーションからテナント全体のメールを読み込みが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215014/6d10faf7-2a20-bbd7-449d-5495e48a1229.png)

アプリケーションのアクセス権限で動作するアプリケーションはAAD, O365の管理者の視点から見ると、テナント全体の機密性、完全性に影響するので非常に注意が必要です。例えば、そのアプリケーションに log4j の脆弱性があったらどうなりますか?



# アプリの登録を依頼されたら
端的に言うと、委任されたアクセス許可は容認して、アプリケーションのアクセス許可は否認しましょう。アプリケーションのアクセス許可はそのアプリの目的、権限の範囲などをよく調査した上で、特例的に容認しましょう。

## 特例としてもいいもの
### 全ユーザが使うもの
例えば、全テナントユーザが利用するアプリケーションの場合はアプリケーションのアクセス権限でも問題ないと考えます。委任されたアクセス許可だとしても影響範囲は同じです。

### スコープを絞れる権限を使うもの
アプリケーションのアクセス許可の Sites.Read.All は sharepoint のすべてのサイトコレクションに含まれるアイテムの読み取りができます。一方で、アプリケーションのアクセス許可の Sites.Selected を使えば、選択したサイトコレクションのみにアクセス範囲を絞ることが可能です。ほとんどのsharepointを利用するアプリケーションは、この権限で問題ないはずです。

この方法であれば、全ユーザが使わないアプリだとしても、最小権限にすることができます。

# 要望
### O365, AAD の管理者の方へ
アプリの登録は、ユーザに対するロールの追加と同様に必要性を検討した上で設定しましょう。
特に、「管理者の同意」はテナント全体のデータに影響するので、[アクセス許可のリファレンス](https://docs.microsoft.com/ja-jp/graph/permissions-reference)を読んで確認しましょう。

サービスプリンシパルについては、ぶっちゃけ概念が難しいので、[Identity and Access Administrator Associate](https://docs.microsoft.com/ja-jp/learn/certifications/identity-and-access-administrator/) や [Azure Solutions Architect Expert](https://docs.microsoft.com/ja-jp/learn/certifications/azure-solutions-architect/) の勉強やトレーニングを受けることをおすすめします。


### アプリ開発をする人、会社へ
構想設計段階から最小権限で動かすことを前提にアプリ開発をしてください。アプリの登録をする段階になって、必要とする権限が大きすぎて、全部作り直すということになりかねません。

よくある間違いとしては、自分たちが作るアプリは安全なので、権限が広くても大丈夫という慢心です。信用してほしいなら ISO27001, 27017, 27018, SOC2, SOC3 の認証や報告書を見せてください。


### Microsoft へ
リソースのスコープを絞れる api をより多く提供してください。最近になって、[sharepoint は Site.Selected](https://docs.microsoft.com/ja-jp/graph/permissions-reference#sites-permissions)、[Teams でもリソース固有の同意](https://docs.microsoft.com/ja-jp/microsoftteams/platform/graph-api/rsc/resource-specific-consent) が提供されましたが、他のリソースでも同様の機能がほしいです。例えば AAD の特定のアトリビュートのみ readwrite できるとか。

# まとめ
アプリ登録という作業はユーザ作成するよりも注意の必要があることがおわかりいただけたでしょうか。ユーザ同様に最小権限にすることを目指しましょう。