こんにちは。X(クロス)イノベーション本部 ソフトウェアデザインセンター セキュリティグループの耿です。
IAM の Permissions Boundary(アクセス許可境界)についてもやもやしていました。効果はわかるものの、どうして IAM ポリシーだけではダメで Permissions Boundary が必要なのかよくわかりませんでした。この記事では IAM のポリシードキュメントと API の仕様から、 Permissions Boundary が導入された本質的な理由を考えてみます。
結論から先に述べると、Permissions Boundary を使うことで特定の権限を超えて IAM ユーザー/ロールが作成されるのを防ぐ効果があり、これは IAM ポリシーだけでは実現できません。Permissions Boundary は、特定のユーザーが IAM ユーザー/ロールを作成するのを許可しつつ、権限昇格を防止する目的などに使用できます。
- 権限昇格の例
- Permissions Boundary とは
- 権限昇格を防ぐ例
- 本質1: IAM ポリシードキュメントに iam:PermissionsBoundary 条件キーが使える
- 本質2: Permissions Boundary は CreateUser / CreateRole 時に追加できる
- さいごに
権限昇格の例
まずは IAM の権限昇格を簡単な例で見てみます。
- 以下の IAM ポリシーを持つ IAM ユーザーがあるとします。
iam:CreateRole
(IAM ロールを作成する権限) とiam:PutRolePolicy
(IAM ロールにインラインポリシーを追加する権限)、さらにはsts:AssumeRole
が許可されています。他の権限については省略します。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iam:CreateRole", "iam:PutRolePolicy" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "sts:AssumeRole" ], "Resource": "*" } ] }
iam:CreateRole
が許可されているので、以下の信頼ポリシーを持つ IAM ロールを作ることができます。(同じアカウント内のプリンシパルであれば、 AssumeRole を許可)
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::000000000000:root" }, "Action": "sts:AssumeRole" } ] }
- 先の IAM ユーザーは
iam:PutRolePolicy
が許可されているので、作ったロールに任意のインラインポリシーを追加できます。例えば以下のような全てを許可するポリシーをエラーなく追加できます。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "*", "Resource": "*" } ] }
- 先の IAM ユーザーは
sts:AssumeRole
が許可されているので、作ったロールを AssumeRole し、アクセスキーID、シークレットアクセスキー、セッショントークンを獲得することで、全ての操作が許可される権限を手に入れることができます。元のユーザーにはできなかった操作ができるようになるので、権限昇格されています。
(以上の例は「IAM ユーザー」が「IAM ロールを経由して」権限昇格する例でしたが、権限昇格する主体が「IAM ロール」の場合や、「IAM ユーザーを経由して」権限昇格する場合もあります。)
Permissions Boundary とは
Permissions Boundary の実態は IAM 管理ポリシーです。他の IAM 管理ポリシーと同じように作成します。
一つの IAM ユーザー/ロールには最大で1つの IAM 管理ポリシーを、 Permissions Boundary として追加できます。また、Permissions Boundary にインラインポリシーを指定することはできません。
IAM ユーザー/ロールに Permissions Boundary が追加されている場合、そのユーザー/ロールに許可される権限は「アイデンティティベースのポリシー」と「Permissions Boundary」の AND 条件になります。Permissions Boundary で明示的に許可されていない権限は、アイデンティティベースのポリシーで許可されていても最終的にユーザー/ロールには許可されません。
(https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_boundaries.html より)
権限昇格を防ぐ例
Permissions Boundary を使うことで、どのように権限昇格を防ぐことができるのか見てみます。
- 以下の IAM 管理ポリシーを
my-permissions-boundary
という名前で作成します。iam:CreateRole
iam:PutRolePolicy
sts:AssumeRole
の3つの権限しか許可していません。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iam:CreateRole", "iam:PutRolePolicy", "sts:AssumeRole" ], "Resource": "*" } ] }
- 対象の IAM ユーザーに作成した
my-permissions-boundary
を Permissions Boundary として追加します。
- 対象の IAM ユーザーのポリシーを以下のように変更します。
Condition
句を追加し、Permissions Boundary としてmy-permissions-boudary
が指定された場合のみiam:CreateRole
iam:PutRolePolicy
できるようにしています。(この例では自身のポリシーを変更する権限を持っていないこともポイントです。)
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iam:CreateRole", "iam:PutRolePolicy" ], "Resource": "*", "Condition": { "StringEquals": { "iam:PermissionsBoundary": "arn:aws:iam::000000000000:policy/my-permissions-boudary" } } }, { "Effect": "Allow", "Action": [ "sts:AssumeRole" ], "Resource": "*" } ] }
以上が準備段階で、この状態で IAM ロールを経由して権限昇格を試みても次のような結果になります。
my-permissions-boudary
を付与しないと、IAM ロールを作ることに失敗します。my-permissions-boudary
を付与すれば、IAM ロールを作成できます。
- Admin 権限相当のインラインポリシーを作成した IAM ロールにつけ、AssumeRole をすることはできますが、Permissions Boundary で明示的に許可された以上の権限を持ちません。
以上はよくある Permissions Boundary の説明でした。このように権限昇格の防止を実現できるのは、2つの仕様上の本質があるためだと考えています。
本質1: IAM ポリシードキュメントに iam:PermissionsBoundary 条件キーが使える
権限昇格を防ぎたい IAM ユーザー/ロールのポリシーに iam:PermissionsBoundary 条件キーが使えるのが第一のポイントです。これによって、Permissions Boundary に特定のポリシーが存在する場合に限って特定の操作を許す、といった書き方ができるようになりました。
"Condition": { "StringEquals": { "iam:PermissionsBoundary": "arn:aws:iam::000000000000:policy/my-permissions-boudary" } }
本質2: Permissions Boundary は CreateUser / CreateRole 時に追加できる
こちらはより重要です。CreateUser と CreateRole の API 仕様を確認すると、これらの API を呼びだす時のパラメータで Permissions Boundary を追加できることがわかります。
一方で、通常のポリシーについては CreateUser と CreateRole の呼び出し時に追加することはできず、後から AttachUserPolicy、PutUserPolicy、AttachRolePolicy、PutRolePolicy など別 API で付与しなければなりません。すなわち、IAM ユーザー/ロールを作成した瞬間にはポリシーが何もついていない状態にどうしてもなってしまい、最初から特定の IAM ポリシーを持つように制限できません。Permissions Boundary であれば作成と同時に付与できるので、iam:PermissionsBoundary
条件キーと併用することで特定の Permissions Boundary を持つ場合に限って ユーザー/ロールの作成を許可する、といった書き方ができます。
推測ですが、作成時からポリシーを付与できるように従来の CreateUser
/ CreateRole
の API 仕様を変更するよりも、新しく Permissions Boundary という機能を追加した方が望ましいと判断したのではないかと思います。
さいごに
理解していても IAM の権限は複雑で、Permissions Boundary を使いこなすのは慎重な設定が必要な印象です。公式ドキュメントの例にも目を通すと、さらに理解の助けになるのではないかと思います。
お読みいただいてありがとうございました。
私たちは同じチームで働いてくれる仲間を大募集しています!たくさんのご応募をお待ちしています。
セキュリティエンジニア(セキュリティ設計)執筆:@kou.kinyo、レビュー:@nakamura.toshihiro
(Shodoで執筆されました)