IAM Permission Boundary (許可の境界)で開発者のロール作成時に権限昇格を防止する方法

目次

概要

開発チームにIAMロールの作成権限を委任したい場面は多くあります。Lambda関数やECSタスクには専用のIAMロールが必要であり、開発のたびにセキュリティチームにロール作成を依頼するのは効率的ではありません。

しかし、IAMロールの作成権限をそのまま委任すると、開発者が自分自身よりも強い権限を持つロールを作成する「権限昇格」が可能になってしまいます。この問題を解決するのが Permissions Boundary(アクセス許可の境界) です。

本記事では、Permissions Boundaryの仕組みを理解し、実際にPermissions Boundaryを使って開発者の権限昇格を防止する設定を行います。

 この記事のメリット

  • Permissions Boundaryの概念と、IDベースポリシーとの関係を正確に理解できる
  • 「有効な権限 = IDベースポリシー ∩ Permissions Boundary」という評価ロジックを把握できる
  • 開発者がIAMロールを作成する際にPermissions Boundaryの付与を強制するポリシーの書き方を習得できる
  • Permissions Boundaryなしではロールを作成できないことをハンズオンで確認できる
  • SCS試験の「IAM権限委任・権限昇格防止」に関する問いに正確に答えられるようになる

 技術解説

 権限昇格の問題

IAMロールの作成権限(iam:CreateRoleiam:AttachRolePolicy)を持つユーザーは、AdministratorAccessを持つロールを作成し、そのロールを引き受ける(AssumeRole)ことで、自分に付与された権限を超えた操作が可能になります。これが権限昇格です。

例えば、S3とEC2の操作権限のみを持つ開発者が、AdministratorAccessポリシーを付与したIAMロールを作成し、そのロールをLambda関数に割り当てれば、Lambda経由であらゆるAWSリソースを操作できてしまいます。

 Permissions Boundaryとは

Permissions Boundaryは、IAMユーザーまたはIAMロールに設定できる 権限の上限 です。AWSマネージドポリシーまたはカスタマー管理ポリシーを使って定義します。

重要なのは、Permissions Boundary自体は権限を付与しないという点です。Permissions Boundaryはあくまで「ここまでの権限なら許可してよい」という上限を設定するものであり、実際に権限を付与するのはIDベースポリシーです。

 有効な権限の決定方法

Permissions Boundaryが設定されたエンティティの有効な権限は、IDベースポリシーとPermissions Boundaryの 共通部分(交差) になります。

有効な権限 = IDベースポリシー ∩ Permissions Boundary

以下の表で具体例を示します。

IDベースポリシーPermissions Boundary有効な権限
S3, EC2, IAMS3, EC2, CloudWatchS3, EC2
AdministratorAccessS3, EC2S3, EC2
S3 のみS3, EC2, CloudWatchS3 のみ

IDベースポリシーでAdministratorAccessを付与しても、Permissions Boundaryで許可されていないサービスは利用できません。逆に、Permissions Boundaryで広く許可していても、IDベースポリシーで付与されていない権限は有効になりません。

 Permissions Boundaryで権限昇格を防止する仕組み

Permissions Boundaryを使った権限昇格の防止は、以下の2つの設定を組み合わせることで実現します。

  1. Permissions Boundaryポリシーの作成: 開発者が作成するロールに付与可能な権限の上限を定義する
  2. ロール作成時のPermissions Boundary付与の強制: 開発者がロールを作成する際に、必ず指定のPermissions Boundaryを付与することを条件にする

2つ目の設定が特に重要です。iam:CreateRoleiam:AttachRolePolicyのアクションに対して、iam:PermissionsBoundary条件キーを使い、指定されたPermissions Boundaryポリシーが付与されている場合のみ操作を許可します。

{
    "Sid": "CreateRoleOnlyWithBoundary",
    "Effect": "Allow",
    "Action": [
        "iam:CreateRole",
        "iam:AttachRolePolicy"
    ],
    "Resource": "*",
    "Condition": {
        "StringEquals": {
            "iam:PermissionsBoundary": "arn:aws:iam::123456789012:policy/AppBoundaryPolicy"
        }
    }
}

この条件により、開発者はPermissions Boundaryを付けずにロールを作成することができなくなります。作成するロールには必ずAppBoundaryPolicyが適用されるため、たとえAdministratorAccessをアタッチしても、実際に有効な権限はBoundaryの範囲内に制限されます。

 他の選択肢との比較

冒頭のシナリオで挙げられた他の選択肢と比較します。

アプローチ種別管理オーバーヘッド権限昇格の防止
Permissions Boundary予防的低い確実に防止
CloudTrail + Lambda監視検知的高い(Lambda関数の開発・運用が必要)事後検知のみ
Organizations SCP予防的中程度(Organizations導入が前提)防止可能だがスコープが広すぎる
IAM操作拒否 + チケット制予防的高い(チケット運用が必要)防止可能だが開発速度が低下

Permissions Boundaryは権限委任と権限制限を両立でき、管理オーバーヘッドも最小限に抑えられるため、このシナリオに最も適しています。

 実践

 前提条件

  • リージョン: ap-northeast-1(東京)
  • IAMユーザーが1つ作成済みであること(本記事ではdeveloper-userとします)
  • developer-userにはマネジメントコンソールへのログインが可能なパスワードが設定済みであること

 作成するリソース一覧

リソース種別リソース名用途
IAMポリシーAppPermissionsBoundaryロールに設定するPermissions Boundary
IAMポリシーDeveloperPolicy開発者ユーザーに付与するポリシー
IAMロールLambdaAppRole(実践中に作成)Lambda用ロール(Boundary付き)

 ステップ1: Permissions Boundaryポリシーの作成

開発者が作成するロールの権限上限を定義するポリシーを作成します。ここではLambdaとECSのアプリケーションに必要なS3、DynamoDB、CloudWatch Logsへのアクセスのみを許可します。

  • AWSマネジメントコンソールにログインし、リージョンがap-northeast-1(東京)であることを確認します
  • 上部の検索バーにIAMと入力し、表示された「IAM」を選択します
  • 左側ナビゲーションの「ポリシー」を選択します
  • 「ポリシーの作成」をクリックします
  • 「JSON」タブを選択し、以下のポリシーを入力します
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowAppServices",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:ListBucket",
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "dynamodb:Query",
                "dynamodb:Scan",
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "*"
        }
    ]
}
  • 「次へ」をクリックします
  • ポリシー名にAppPermissionsBoundaryと入力します
  • 「ポリシーの作成」をクリックします

 ステップ2: 開発者用ポリシーの作成

開発者ユーザーに付与するポリシーを作成します。このポリシーにはアプリケーションに必要な権限に加えて、Permissions Boundaryの付与を条件としたIAMロール作成権限を含めます。

  • IAMコンソールの「ポリシー」画面で「ポリシーの作成」をクリックします
  • 「JSON」タブを選択し、以下のポリシーを入力します
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowAppDevelopment",
            "Effect": "Allow",
            "Action": [
                "s3:*",
                "dynamodb:*",
                "logs:*",
                "lambda:*",
                "ecs:*",
                "ecr:*"
            ],
            "Resource": "*"
        },
        {
            "Sid": "AllowCreateRoleWithBoundary",
            "Effect": "Allow",
            "Action": [
                "iam:CreateRole",
                "iam:AttachRolePolicy",
                "iam:DetachRolePolicy",
                "iam:PutRolePermissionsBoundary"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "iam:PermissionsBoundary": "arn:aws:iam::ACCOUNT_ID:policy/AppPermissionsBoundary"
                }
            }
        },
        {
            "Sid": "AllowRoleManagement",
            "Effect": "Allow",
            "Action": [
                "iam:GetRole",
                "iam:ListRoles",
                "iam:ListRolePolicies",
                "iam:ListAttachedRolePolicies",
                "iam:PassRole",
                "iam:CreatePolicy",
                "iam:GetPolicy",
                "iam:ListPolicies"
            ],
            "Resource": "*"
        },
        {
            "Sid": "DenyBoundaryPolicyModification",
            "Effect": "Deny",
            "Action": [
                "iam:DeletePolicy",
                "iam:CreatePolicyVersion",
                "iam:DeletePolicyVersion",
                "iam:SetDefaultPolicyVersion"
            ],
            "Resource": "arn:aws:iam::ACCOUNT_ID:policy/AppPermissionsBoundary"
        },
        {
            "Sid": "DenyRemoveBoundary",
            "Effect": "Deny",
            "Action": "iam:DeleteRolePermissionsBoundary",
            "Resource": "*"
        }
    ]
}

注意ACCOUNT_IDの部分は、ご自身のAWSアカウントIDに置き換えてください。アカウントIDはコンソール右上のアカウント名をクリックすると確認できます。

各ステートメントの役割を説明します。

  • AllowAppDevelopment: アプリケーション開発に必要なサービス(S3、DynamoDB、Lambda、ECS等)の操作を許可します
  • AllowCreateRoleWithBoundaryAppPermissionsBoundaryをPermissions Boundaryとして付与する場合に限り、IAMロールの作成とポリシーのアタッチを許可します。iam:PermissionsBoundary条件キーがこの制御の要です
  • AllowRoleManagement: ロールの参照やPassRoleなど、ロール管理に必要な補助的な操作を許可します
  • DenyBoundaryPolicyModificationAppPermissionsBoundaryポリシー自体の変更・削除を明示的に拒否します。これにより、開発者がBoundaryの内容を書き換えて権限を拡大することを防止します
  • DenyRemoveBoundary: ロールからPermissions Boundaryを削除する操作を拒否します。Boundaryを外して権限昇格することを防止します
  1. 「次へ」をクリックします
  2. ポリシー名にDeveloperPolicyと入力します
  3. 「ポリシーの作成」をクリックします

 ステップ3: 開発者ユーザーにポリシーを付与する

  1. 左側ナビゲーションの「ユーザー」を選択します
  2. ユーザー一覧からdeveloper-userをクリックします
  3. 「許可」タブの「許可を追加」をクリックし、「ポリシーを直接アタッチする」を選択します
  4. 検索バーにDeveloperPolicyと入力し、表示されたポリシーにチェックを入れます
  5. 「次へ」→「許可を追加」をクリックします

 ステップ4: Permissions Boundaryなしでのロール作成を試みる(失敗の確認)

developer-userでログインし、Permissions Boundaryを付けずにロールを作成できないことを確認します。

  • 現在のセッションからサインアウトし、developer-userでマネジメントコンソールにログインします
  • 上部の検索バーにIAMと入力し、「IAM」を選択します
  • 左側ナビゲーションの「ロール」を選択します
  • 「ロールを作成」をクリックします
  • 信頼されたエンティティタイプで「AWSのサービス」を選択し、ユースケースで「Lambda」を選択します
  • 「次へ」をクリックします
  • 検索バーにAmazonS3FullAccessと入力し、表示されたポリシーにチェックを入れます
  • 「次へ」をクリックします
  • ロール名にTestRoleWithoutBoundaryと入力します
  • Permissions Boundaryは設定せずに「ロールを作成」をクリックします

結果: 権限が不足している旨のエラーメッセージが表示され、ロールの作成に失敗します。DeveloperPolicyAllowCreateRoleWithBoundaryステートメントの条件(iam:PermissionsBoundary)が満たされないため、iam:CreateRoleの実行が許可されません。

 ステップ5: Permissions Boundaryを付けてロールを作成する(成功の確認)

続いて、Permissions Boundaryを付けてロールを作成できることを確認します。

  • 再度「ロールを作成」をクリックします
  • 信頼されたエンティティタイプで「AWSのサービス」を選択し、ユースケースで「Lambda」を選択します
  • 「次へ」をクリックします
  • 検索バーにAmazonS3FullAccessと入力し、チェックを入れます
  • 「Permissions Boundary」セクションの「Permissions Boundaryを使用してアクセス許可の上限を設定する」を展開します
  • 検索バーにAppPermissionsBoundaryと入力し、表示されたポリシーを選択します
  • 「次へ」をクリックします
  • ロール名にLambdaAppRoleと入力します
  • 「ロールを作成」をクリックします

結果: ロールの作成に成功します。条件キーiam:PermissionsBoundaryが指定したAppPermissionsBoundaryと一致するため、操作が許可されました。

 ステップ6: 作成されたロールの有効な権限を確認する

作成したLambdaAppRoleの有効な権限を確認し、Permissions Boundaryが正しく機能していることを確かめます。

  1. 左側ナビゲーションの「ロール」を選択し、LambdaAppRoleをクリックします
  2. 「許可」タブを確認すると、以下の2つが表示されています。
    • 許可ポリシーAmazonS3FullAccess
    • 許可の境界AppPermissionsBoundary
  3. このロールの有効な権限を整理すると以下のようになります。
操作IDベースポリシー(S3FullAccess)Permissions Boundary有効な権限
s3:GetObject許可許可許可
s3:PutObject許可許可許可
s3:ListBucket許可許可許可
s3:DeleteObject許可許可されていない拒否
s3:DeleteBucket許可許可されていない拒否
ec2:*許可されていない許可されていない拒否
iam:*許可されていない許可されていない拒否

IDベースポリシーでAmazonS3FullAccess(S3の全操作を許可)がアタッチされていますが、Permissions Boundary側で許可されているのはs3:GetObjects3:PutObjects3:ListBucketのみです。そのため、s3:DeleteObjectなどBoundaryで許可されていない操作は拒否されます。

このように、たとえ広い権限のポリシーをアタッチしても、Permissions Boundaryで定義した範囲内の操作しか実行できないことが確認できました。

 まとめ

本記事のポイントを整理します。

  • Permissions Boundaryは権限の上限を設定する仕組み です。権限を付与するのではなく、IDベースポリシーで付与できる権限の最大範囲を定義します
  • 有効な権限はIDベースポリシーとPermissions Boundaryの共通部分 です。どちらか一方でも許可していない操作は実行できません
  • iam:PermissionsBoundary条件キー を使うことで、ロール作成時にPermissions Boundaryの付与を強制できます。これにより権限昇格を確実に防止できます
  • Boundaryポリシーの変更・削除の拒否 を組み合わせることで、開発者がBoundaryを回避することを防止します
  • Permissions Boundaryは、CloudTrailによる事後検知やチケット制による運用と比べて、予防的かつ低オーバーヘッド なアプローチです

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

株式会社Luxy(https://luxy-inc.com)の代表取締役.

2018年〜インフラエンジニアとしてキャリアをスタートし、オンプレミスのネットワーク・サーバ環境で3年半、クラウド環境で4年半の8年間エンジニアとして従事。
2021年に佐藤氏の創業した会社を引き継ぎ、代表に就任。

目次