概要
いまさらだけども理解しているつもりできちんと理解していなかったIAMについて、改めて勉強したので忘れないようにまとめる。
参考にした資料:
【AWS Black Belt Online Seminar】AWS Identity and Access Management (AWS IAM) Part1
【AWS Black Belt Online Seminar】AWS Identity and Access Management (AWS IAM) Part2
※この記事で利用しているSSは上記資料内のものです。詳しく知りたい方は直接元の動画を見てください。
IAMに登場する主な要素
- IAMユーザ
- IAMグループ
- IAMロール
- ポリシー
IAMユーザ
- マネジメントコンソールやCLIで利用するユーザ、あるいはSDKでAWSリソースへアクセスするアプリケーションの単位(EC2等で実行するアプリケーションの場合ユーザではなくロールを利用)で作成する。
- **ID+パスワード(+MFA)もしくはアクセスキー(認証用に生成された文字列)**で認証される。
- 複数の人やアプリケーションで使いまわしてはいけない。
IAMグループ
- 複数のユーザに同一のポリシーのセットを付与するのに使える。
- グループとユーザは0...10対N(1ユーザの所属できるグループは10まで、グループに所属させないことも可)
例)開発チームリーダーAさんはDevグループとLeaderグループに所属させる、開発チームメンバーBさんにはDevグループにだけ所属させる
IAMロール
- AWSサービスやEC2インスタンス内のアプリケーション、別のAWSアカウントのIAMユーザ/ロール、OIDCなど外部認証で認証されたユーザに権限を付与するための仕組み。
- IAMユーザやグループには紐付かない。
IAMロールの主なユースケース
- EC2上のアプリケーションへの権限付与
- クロスアカウントアクセス
- 一時的な権限昇格(Switch Role)
- 外部IdPによる認証
EC2上のアプリケーションへの権限付与
EC2上で動作するアプリケーションは通常のローカルPCやオンプレサーバ同様、EC2インスタンス内に保存されたアクセスキーによるAWSの操作を行うこともできるが、アクセスキーの漏洩などの危険性があるため、必ずIAMロールを利用する。
EC2インスタンスの作成時にIAMロールを指定する箇所があるのでそこで事前に作成したIAMロールを指定するだけ。
クロスアカウントアクセス
ロールは異なるAWSアカウントへの権限を移譲にも利用できる。
AWSでは環境やシステムごとにアカウントを分離することを推奨しており、エンタープライズでは一人のユーザが複数アカウントを利用することは珍しくない。このため、ユーザと権限の管理コストを下げるためにも、IAMロールを利用する。
アカウント間でアクセスキーなどのセキュリティ情報の共有をしてはいけない、権限の分離のためにアカウントを分けている意味がなくなってしまう。
一時的な権限昇格(Switch Role)
クロスアカウントだけでなく、同じアカウント内でもIAMロールの切り替えによる権限の切り替えが可能。
マネジメントコンソールから簡単に切り替えができるので、クロスアカウントでもこの仕組を使うと操作が楽になる。
外部IdPによる認証(SSO)
IAMロールを用いて外部のIdPによるSSOも可能。
社内システムなどの場合、社内のActiveDirectoryで管理された社員情報で認証を行わせることでユーザの二重管理を防げる。
ここで利用できるIdPにはGoogle,Facebook,Amazon,twitterなどのOIDC準拠のものも含まれる。
これを利用し、モバイルアプリに対しこれらのOIDCで認証を行い、AWSの操作権限を与えることもできる。
バックエンドにアプリケーションサーバを置かずとも、認証されたユーザのみにクライアントから直接DB操作をさせることができる、すごい。
ポリシー
IAMユーザ、IAMグループ、IAMロール、あるいはAWSリソースそのものに付与する権限の内容を定義するもの。JSONで記述する。
IAMユーザ、IAMグループ、IAMロールに付与するポリシーを「アイデンティティベースポリシー」、AWSリソースに付与するポリシーを「リソースベースポリシー」という。
ポリシーに記述する主な要素
他にもいくつか存在するが、基本はこれを覚えておくけばいい。
参考(公式ホワイトペーパー):https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements.html
Version
このポリシーのバージョンではなく、ポリシー言語のバージョン。
現在(2020/02時点)でのバージョンは
- 2008-10-17
- 2012-10-17
の2つしか存在しない。
指定しないと旧バージョンのドキュメントとして読み込まれ、ポリシー変数が有効にならなかったりするので必ず最新を指定する。
参考:https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_version.html
{
"Version": "2012-10-17", ←これ
"Statement": [
︙
]
}
Statement
Effect、Principal、Action、Resource、Conditionなどの子属性をまとめる親属性、配列。
この中身の1要素のことをステートメントブロックという。
{
"Version": "2012-10-17",
"Statement": [ ←これ
{ ←ここから
"Sid": "FirstStatement",
"Effect": "Allow",
"Action": ["iam:ChangePassword"],
"Resource": "*"
}, ←ここまでが1ステートメントブロック
{
"Sid": "ThirdStatement",
"Effect": "Allow",
"Action": [
"s3:List*",
"s3:Get*"
],
"Resource": [
"arn:aws:s3:::confidential-data",
"arn:aws:s3:::confidential-data/*"
],
"Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
}
]
}
Effect
そのステートメントは許可なのか拒否なのか。
"Allow"or"Deny"
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "FirstStatement",
"Effect": "Allow", ←これ
"Action": ["iam:ChangePassword"],
"Resource": "*"
}
]
}
Principal
そのステートメントはどのIAMエンティティ(IAMユーザやIAMロールなど)に対する定義なのか。
リソースベースポリシーにのみ必要、アイデンティティベースポリシーの場合暗黙で付与先のIAMエンティティ(IAMユーザやIAMロールなど)が対象となる。
指定したもの"以外"を対象とするNotPrincipal
もある。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "FirstStatement",
"Effect": "Allow",
"Principal": { ←これ
"AWS": [ ←複数のIAMエンティティを配列で指定可能
"arn:aws:iam::AWS-account-ID:user/user-name-1",
"arn:aws:iam::AWS-account-ID:user/UserName2"
]
}
"Action": ["iam:ChangePassword"],
"Resource": "*"
}
]
}
Action
そのステートメントはどのアクション(AWSリソースへの操作)を許可もしくは拒否するのか。
サービス名:アクション名
で事前定義されているものから選択し指定する。
指定したもの"以外"を対象とするNotAction
もある。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "FirstStatement",
"Effect": "Allow",
"Action": [ ←これ
"ec2:StartInstances", ←複数指定可能
"sqs:*Message", ←ワイルドカードも利用可能
"iam:ChangePassword",
"s3:GetObject" ]
"Resource": "*"
}
]
}
Resource
そのステートメントはどのリソースに対する定義なのか。
Describe~
などのリスト系の場合、"*"
しか使えない。
書き込み系等のレベルの高い権限はできるだけResource
を具体的に指定し、最小権限になるようにする。
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "dynamodb:*", ↓これ
"Resource": "arn:aws:dynamodb:us-east-2:AWS-account-ID:table/${aws:username}"
} ポリシー変数(後述)が利用可能↑
}
Condition
このポリシーを適用する条件。
特定のIPからのアクセスのみ許可、やS3バケット内の特定文字列から始まるオブジェクトへのアクセスのみ許可、EC2の特定のインスタンスタイプのみ起動を許可、など。
ANDとORをまとめて1つのCondition
に定義可能。
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "iam:*AccessKey*",
"Resource": "arn:aws:iam::AWS-account-ID:user/*",
"Condition": { ←これ
"IpAddress": {
"aws:SourceIp": [
"203.0.113.0/24",
"2001:DB8:1234:5678::/64"
]
}
}
}
}
その他ポリシーに関する予備知識
ポリシー変数
リソースとコンディションには${aws:username}
や${aws:SourceIp}
などの変数を利用することができる。
アクセス時に実際にログインしているIAMユーザやアクセス元のIPなどが動的にはめ込まれる。
例1:各ユーザに自分のユーザ名のついたS3バケットやDynamoDBのテーブルのみ操作可能にする
例2:VPNを経由しているとき(特定IPからのアクセス時)のみ対象の操作を許可する
参考:https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_variables.html#policy-vars-infotouse
カスタマー管理ポリシーとインラインポリシーの使い分け
カスタマー管理ポリシーのほうがあとからできたらしい、AWSはできるだけインラインポリシーではなくカスタマー管理ポリシーを使用することを推奨している。
IAMユーザ/ロール再作成時などの注意
プリンシパルに指定されたIAMユーザやIAMロールを再作成したときはロールの再編集が必要。
ロール保存時に内部ではユーザ名/ロール名ではなくIDで紐付けされているため。
アクセス許可の境界(Permission Boundary)
IAMポリシーはホワイトリストなので、後から許可を付与することで権限の範囲を広げることができる。
この追加に対して「これ以上は追加されたくない」という"境界"を事前に定義するのに利用する。
「ここまでは許可」と「これは拒否」を指定できる。
詳しくは↓が解りやすい。
https://dev.classmethod.jp/articles/iam-permissions-boundary/
AWS OrganizationのSCPもほぼ同じ、違いはアカウントをまたぐことができるかどうか
権限決定のロジック
IAMではアイデンティティベースポリシーやリソースベースポリシーなど複数の許可・拒否定義要素があるため、これらがどういった流れで適用されるのかを知らないと、正しい設定を行うことができない。
DenyとAllowの優先順位
全体の決定ロジック
SCPでもアクセス許可の境界でも拒否されていない、かつアイデンティティベースまたはリソースベースポリシーで許可されていれば許可。
ただし、クロスアカウントの場合、アイデンティティベースとリソースベースポリシー両方で許可されていないといけない。
(アイデンティティベースは自アカウント側、リソースベースは相手アカウント側なので当然といえば当然)
リソースベースポリシーとアイデンティティベースポリシー
リソースベースポリシーとアイデンティティベースポリシーはOR条件、どちらかに定義されていれば有効。
管理ポリシーとインラインポリシー
管理ポリシーとインラインポリシーもOR条件、どちらかに定義されていれば有効。
その他予備知識
STS
権限の移譲を行うサービス、IAMと深く関わってくる。
Switch Role
やAssume Role
に利用。
アクセスアドバイザー
IAMエンティティへのアクセス状況を確認できる機能、不審なアクセスや不要なユーザ・ロールが存在しないか確認するのに利用する。
ポリシージェネレータ
GUIでIAMポリシーを生成できる。
https://awspolicygen.s3.amazonaws.com/policygen.html