はじめに
認可って、実際にはどういう仕組みで実現されているのか
理解するべく、
そんな中でAWSの権限管理について調べてみると、
- 誰が
- 何を
- 何に対して
- どんな条件で
実行してよいのかを判定する仕組みが、かなり具体的に見えてきました。
普段AWSを使っていても、
- 権限申請をする
- Roleを切り替える
- 権限が足りずAccessDeniedになる
といったことはよくあります。
ただ、
権限を付けてもらったから使えるようになった
で終わるのではなく、
なぜ権限を付けると操作できるようになるのか
AWSは何を見て、操作を許可・拒否しているのか
まで少し踏み込んでみると、IAM RoleやPolicyが、「認可」 という考え方そのものにつながっていることが分かります。
この記事では、AWSの権限管理を題材にしながら、認可の仕組みをざっくり整理していきます。
認証と認可の違い
まず、認証と認可の違いから整理します。
認証
認証は、
あなたは誰ですか?
を確認する仕組みです。
例えば、
- ID / パスワード
- SSO
- SAML
- MFA
などによって、ユーザーやサービスの身元を確認します。
イメージとしては、
ログイン情報を送る
↓
本人確認
↓
「このユーザーである」と特定する
という流れです。
認証についてはAuth0を題材にこちらの記事で整理しています
認可
一方で認可は、
あなたは何をしてよいですか?
を判断する仕組みです。
例えば、
- 管理者だけユーザーを削除できる
- 一般ユーザーは閲覧だけできる
- 自分の所属企業のデータだけ編集できる
といった制御です。
基本的には、
認証
「あなたは誰?」
↓
認可
「あなたは何をしていい?」
という流れになります。
認可は何を見て判断するのか
認可をかなり単純化すると、
誰が
何を
何に対して
を見て判断します。
例えば、
誰が = User A
何を = 更新する
何に対して = Project X
です。
さらに必要に応じて、
どんな条件で
という情報も加わります。
例えば、
- 特定のIPからのみ許可
- 特定の部署のみ許可
- 特定の時間帯のみ許可
といった条件です。
つまり、認可はざっくり、
誰が
× 何を
× 何に対して
× どんな条件で
を評価して、
許可する / 拒否する
を決める仕組みだと考えられます。
アプリケーションではどう認可するのか
例えばRailsで、管理者だけユーザーを削除できるようにするとします。
かなり単純化すると、以下のように書けます。
def destroy
return head :forbidden unless current_user.admin?
@user.destroy
end
やっていることは、
current_user
↓
adminか?
↓
YES → 削除可能
NO → 403 Forbidden
です。
これも認可です。
RBACという考え方
認可の代表的な方式の一つに、
Role-Based Access Control(RBAC)
があります。
例えば、
User
↓
Role
↓
Permission
という形で権限を管理します。
具体的には、
admin
- 閲覧可能
- 編集可能
- 削除可能
member
- 閲覧可能
のようにRoleごとに権限を定義し、
Aさん → admin
Bさん → member
のようにユーザーへRoleを割り当てます。
ユーザー一人ひとりに権限を直接設定するのではなく、Role単位で管理できるのがメリットです。
認可をかなり抽象化すると、
authorize(user, action, resource)
のようなイメージになります。
つまり、
このユーザーが、このリソースに、この操作をしてよいか?
を判定しているということです。
AWSの認可も基本は同じ
ここからAWSの話に入ります。
AWSでも、認可の考え方自体は大きく変わりません。
AWSでは主に、
Principal
Action
Resource
Condition
を見て認可を判断します。
Principal
「誰が」操作するのかです。
例えば、
- IAM User
- IAM Role
- AWS Service
などです。
Action
「何を」するのかです。
例えば、
s3:GetObject
s3:PutObject
ec2:StartInstances
などです。
Resource
「何に対して」操作するのかです。
例えばS3なら、
arn:aws:s3:::my-bucket/*
のようなリソースです。
Condition
「どんな条件で」許可するのかです。
例えば、
- 特定IPからのみ
- 特定VPCからのみ
- MFAありの場合のみ
- 特定タグがある場合のみ
といった条件を指定できます。
つまりAWSでも、
誰が
× 何を
× 何に対して
× どんな条件で
を見ているわけです。
IAM Policyで認可ルールを定義する
AWSでは、IAM Policyを使って認可ルールを表現します。
例えば、
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}
というPolicyがあったとします。
これはざっくり、
my-bucket内のオブジェクトに対して、GetObjectを実行してよい
という意味です。
主に見るのは、
Effect
Action
Resource
Condition
です。
AWSでは、何も許可されていなければDeny
AWSでは基本的に、
何も許可されていない
↓
Deny
です。
つまり、
書いていない操作も何となくできる
ということはなく、基本的には明示的に許可される必要があります。
さらに、明示的にDenyされている場合は、AllowよりもDenyが優先されます。
Allow
+
Explicit Deny
↓
Deny
かなりざっくり覚えるなら、
何もなければDeny
Allowがあれば許可候補
明示的なDenyがあればDeny
です。
IAM Roleとは何か
ここは最初かなり混乱しやすいところでした。
IAM Roleは、単純に「権限そのもの」ではありません。
ざっくり言うと、
AWS上で誰として振る舞うか
を表すものです。
そのRoleにIAM Policyを紐づけることで、
そのRoleとして何をしてよいか
を決めます。
つまり、
IAM Role
→ 誰として動くか
IAM Policy
→ そのRoleで何をしてよいか
です。
AssumeRoleとは何か
別のIAM RoleとしてAWSを操作したい場合、そのRoleをAssumeします。
例えば、
自分
↓
Developer RoleをAssume
↓
Developer RoleとしてAWSを操作
という形です。
RoleをAssumeすると、そのRoleとしてAWS APIを呼ぶための一時的な認証情報が発行されます。
その状態でAWSを操作すると、
Developer Roleとして、この操作をしてよいか?
という認可が行われます。
ここでは、
Trust Policy
→ 誰がこのRoleを使ってよいか
Permissions Policy
→ このRoleで何をしてよいか
と分けて考えると理解しやすいです。
「AWSの権限申請をすると使えるようになる」とは何が起きているのか
普段AWSを使っていると、
この環境を使いたいので権限申請をする
ということがあります。
その結果、
自分
↓
権限申請
↓
Developer Roleを利用できるようになる
↓
そのRoleでAWSを操作できる
という状態になります。
認可の観点で見ると、
自分
↓
このRoleを利用してよい
↓
Roleに設定されたPolicyの範囲で
AWSを操作してよい
ということが起きています。
つまり、
権限を付けてもらったから使えるようになった
というより、
自分が使えるRoleが増え、そのRoleに設定されたPolicyの範囲で操作できるようになった
と考えると、少し仕組みが見えやすくなります。
ECSを例にもう少し具体的に見る
ここからはECSを例に、実際にどのRoleが使われるのかを見ていきます。
ECS Taskとは
ECS Taskは、
ECS上で動くアプリケーションの実行単位
です。
ざっくり、
という関係になります。
- ECS ServiceがTaskを管理する
- Taskの中でContainerが動く
- Containerの中でRailsなどのアプリケーションが動く
というイメージです。
Task Roleとは何か
Task Roleは、
ECS Task内のアプリケーションがAWSサービスを利用するときに使うIAM Role
です。
例えばRailsアプリケーションからS3を読みたい場合、
というイメージになります。
ここでも認可の基本は同じです。
誰が
→ Task Role
何を
→ s3:GetObject
何に対して
→ S3のObject
という情報を見て、AWS側が許可・拒否を判断します。
コンテナに入る権限と、中で使う権限は別
ここが今回、一番理解が深まった部分でした。
例えばECS Execを使ってECS Task内のコンテナへ入るとします。
このとき、
自分がECS Taskへ接続できるか
と、
ECS Task内のアプリケーションがS3などを操作できるか
では、認可に使われるRoleが異なります。
自分がECS Taskに入れるか
まず、自分がECS Taskへ接続するときです。
ここでは、
自分が、このECS Taskに接続してよいか?
が判断されます。
認可に使われるのは、自分が現在利用しているIAM Roleです。
ECS内のアプリケーションがAWSを操作できるか
一方で、コンテナに入った後や、アプリケーションからAWS APIを呼ぶ場合は別です。
ここでは、
このECS Taskは、S3を操作してよいか?
が判断されています。
使われるのは、ECS Task Roleです。
つまり、
| やりたいこと | 主に使われるRole |
|---|---|
| 自分がECS Taskに入る | 自分が利用しているIAM Role |
| ECS内のアプリがAWSサービスを操作する | ECS Task Role |
という違いがあります。
全体像
ここまでを一枚にすると、以下のようになります。
この図で重要なのは、
自分 → ECS Task
と、
ECS Task内のアプリ → S3
では、
認可される主体が異なる
ということです。
前者では自分が利用しているIAM Role。
後者ではECS Task Roleです。
つまり、
ECSの中に入れる = AWS上で何でも操作できる
というわけではありません。
ECS Execでコンテナに入る権限があっても、Task RoleにS3への権限がなければ、コンテナ内からS3を操作しようとしてもAccessDeniedになります。
AccessDeniedが出たら「誰が・何を・何に対して」で考える
AWSを使っていると、
AccessDenied
に遭遇することがあります。
このとき、
なんか権限が足りない
だけで終わらせず、認可の基本に戻って、
誰が
何を
何に対して
に分解すると、原因を追いやすくなります。
例えばS3へのアクセスであれば、
誰が
→ どのIAM Role?
何を
→ s3:GetObject?
→ s3:ListBucket?
何に対して
→ どのBucket?
→ どのObject?
どんな条件で
→ Conditionに引っかかっていない?
Policyは
→ Allowされている?
→ Explicit Denyはない?
という形で確認できます。
特にECS上のアプリケーションであれば、
このTaskはどのTask Roleを使っているのか?
を見るところから始めると、権限周りの問題をかなり切り分けやすくなります。
まとめ
認証と認可は、
認証
→ あなたは誰か
認可
→ あなたは何をしてよいか
という違いがあります。
そして認可は基本的に、
誰が
何を
何に対して
どんな条件で
を見て判断しています。
アプリケーションでは、
ユーザー
× 操作
× リソース
AWSでは、
Principal
× Action
× Resource
× Condition
という形で考えると分かりやすいです。
またAWSでは、
IAM Role
→ 誰として動くか
IAM Policy
→ そのRoleで何をしてよいか
と考えると整理しやすくなります。
普段AWSを使う中で行っている、
- 権限申請
- Switch Role
- AssumeRole
- ECS Exec
- Task Role
- IAM Policy
も、すべて、
誰が、何を、何に対して実行してよいのか
を制御する認可の仕組みにつながっています。
これまでは「権限を付けてもらったから使える」とだけ捉えていましたが、その裏でどのRoleが使われ、どのPolicyによって操作が許可されているのかまで見てみると、AWSの権限管理と「認可」という概念がかなりつながって理解できました。
認可を考えるときは、まず、
誰が
何を
何に対して
に分解してみる。
この見方を持っておくだけでも、アプリケーションの権限設計や、AWSでAccessDeniedが出たときの調査がかなりしやすくなると思います。
参考
文献
動画
