一覧CL-03-2 · クラウドIAM

IAMロールと一時的なアクセス権限

引受けの成立、引受け後の権限、時刻による有効性を別々に確認し、どの条件で要求が拒否されたか説明します。

説明

ロールの信頼ポリシーは誰が引き受けられるかを定め、権限ポリシーは引受け後に何ができるかを定めます。一時的なセッションには有効期限があり、セッションポリシーやpermissions boundaryで許可範囲がさらに狭まる場合があります。

アカウント111111111111のanalystが、別アカウントのReportReaderを引き受ける固定条件を使います。主体・MFA・期限を確認し、引受け後の要求をrole、boundary、session policy、組織制限へ順に照合します。対象側ポリシーからの追加許可は使わない条件で進めます。

引受けの成立、引受け後の権限、時刻による有効性を別々に確認し、どの条件で要求が拒否されたか説明します。

1ロールを引き受けられる条件

callerは要求元のAssumeRole許可、trustは引受け先が信頼する主体とMFA条件です。MFAは複数要素での認証を表します。

cat scope.txt主体・対象・評価範囲を読む cat caller.json要求元の引受け許可を読む cat trust.json対象roleの信頼条件を読む

要求元には対象roleへのAssumeRole許可があり、信頼側ではanalystとMFA=trueを指定しています。別アカウントの引受けなので、要求元の許可と信頼側の条件の両方を確認します。

2MFA条件を満たさない引受け

MFA=falseとして固定の条件を評価します。

python3 session.py assume --mfa falseMFA条件を満たさない引受けを評価する

caller_allowed=Trueでもtrust_condition=Falseなので拒否されます。AssumeRoleの許可を要求元に付けるだけでは、信頼側に指定された追加条件を満たしません。

3条件を満たすセッション記録

MFA=trueで評価し、成立したセッションの主体と有効期限を記録します。

python3 session.py assume --mfa true信頼条件を満たすセッションの記録を作る

主体はIAM userから、ReportReader/lessonというassumed-roleのセッションへ変わります。有効期間は09:00以上10:00未満です。引受け成立は、その後のすべての操作を許可する意味ではありません。

4引受け後の四つのポリシー

roleは読取りと書込み、boundaryは読取り、session policyはreports配下の読取りを許可します。組織制限はprivate配下の読取りを拒否します。

cat role.jsonroleの権限を読む cat boundary.json最大許可範囲を読む cat session-policy.json今回のセッションの範囲を読む cat organization.json組織の許可と明示的拒否を読む

この例では四つの許可範囲が重なる要求だけが候補になり、どこかに一致するDenyがあれば拒否されます。boundaryとsession policyを広くしても、role自身の許可を超えて権限を付与できません。

5四つのポリシーが許可する読み取り

09:10にreports/public/a.csvのGetObjectを評価します。時刻を省略した場合の固定値が09:10です。

python3 session.py request --action s3:GetObject --key reports/public/a.csv有効期間内の公開用帳票の読取りを照合する

role、boundary、session、organizationのすべてでAllowに一致し、allowedです。どの文がこの要求に対応したかを一行ずつ確認できます。

6roleが許可しても書込みは通らない

同じオブジェクトへのPutObjectを評価します。

python3 session.py request --action s3:PutObjectroleが許可する書込みを他の範囲へ照合する --key reports/public/a.csv

roleはReadAndWrite:Allowですが、boundaryとsessionは一致せずimplicitDenyです。roleの許可だけを見て書込みできると判断すると、実効範囲を読み違えます。

7プレフィックス制限と明示的拒否

reports外のarchiveへの読取りと、reports/privateへの読取りを続けて確認します。

python3 session.py request --action s3:GetObject --key archive/a.csvセッションの許可範囲外を確認する python3 session.py request --action s3:GetObject --key reports/private/a.csv組織が明示的に拒否する範囲を確認する

archiveはsessionの許可がなくimplicitDenyです。privateは各Allowに一致しても、組織のPrivateDenied:DenyでexplicitDenyになります。両者は拒否されていますが、原因となる文が異なります。

8セッションポリシーを広げた場合の権限の上限

s3:*を指定した広いセッションポリシーで、新しいセッション記録を作ります。旧セッションの変更ではなく、別の引受け条件として評価します。

cat session-wide.json広い許可を指定したセッション案を読む python3 session.py assume --mfa true --policy session-wide.json別のセッションポリシーで引受けを評価する python3 session.py request --action s3:PutObject --key reports/public/a.csv書込みの実効範囲を再確認する

sessionはAttemptExpansion:Allowになりますが、boundaryに書込みの許可がなくimplicitDenyです。セッションポリシーの広い指定によって、boundaryの上限を越えることはできません。

9有効期限の直前と期限到達時の違い

同じ読取りを09:59:59と10:00:00で評価します。後者は有効期限そのものです。

python3 session.py request --action s3:GetObject --key reports/public/a.csv --at 2026-11-01T09:59:59+00:00期限の1秒前で確認する python3 session.py request --action s3:GetObject --key reports/public/a.csv --at 2026-11-01T10:00:00+00:00期限と同時刻で確認する

直前はallowedですが、期限と同時刻ではexpired_or_not_yet_validです。ポリシーが同じでもセッションの有効期間を過ぎれば、その記録では要求を通せません。

まとめ

信頼条件は引受ける主体を、権限ポリシーは引受け後の操作を定めます。

この条件ではrole・boundary・session・組織制限の重なりを評価し、明示的拒否を優先します。

セッションの範囲を広げても上位の上限を越えられず、有効期限の確認も必要です。

操作履歴と解説を振り返れます。

シェル / Python 3

1
cat scope.txt cat caller.json cat trust.json
要求者: account 111111111111のIAM user analyst
対象role: account 222222222222のReportReader
引受け条件: callerのAssumeRole許可と、roleのtrustにある主体・MFA条件を両方満たす。
引受け後: role・boundary・session policy・組織制限を評価。
この例ではresource-based policyによる追加許可は使わず、RCP等の追加制限も設けない。
sessionの有効期間: 2026-11-01 09:00 UTC以上、10:00 UTC未満。
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AssumeReportRole",
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "arn:aws:iam::222222222222:role/ReportReader"
    }
  ]
}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AnalystWithMFA",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:user/analyst"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "true"
        }
      }
    }
  ]
}
2
python3 session.py assume --mfa false
caller_allowed=True trust_condition=False
AssumeRole denied
3
python3 session.py assume --mfa true
caller_allowed=True trust_condition=True
session recorded principal=arn:aws:sts::222222222222:assumed-role/ReportReader/lesson expires=2026-11-01T10:00:00+00:00
4
cat role.json cat boundary.json cat session-policy.json cat organization.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadAndWrite",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::training-reports/*"
    }
  ]
}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadOnly",
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::training-reports/*"
    }
  ]
}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReportsPrefix",
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::training-reports/reports/*"
    }
  ]
}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowBase",
      "Effect": "Allow",
      "Action": "*",
      "Resource": "*"
    },
    {
      "Sid": "PrivateDenied",
      "Effect": "Deny",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::training-reports/reports/private/*"
    }
  ]
}
5
python3 session.py request --action s3:GetObject --key reports/public/a.csv
role matches=ReadAndWrite:Allow
boundary matches=ReadOnly:Allow
session matches=ReportsPrefix:Allow
organization matches=AllowBase:Allow
decision=allowed
6
python3 session.py request --action s3:PutObject --key reports/public/a.csv
role matches=ReadAndWrite:Allow
boundary matches=none
session matches=none
organization matches=AllowBase:Allow
decision=implicitDeny
7
python3 session.py request --action s3:GetObject --key archive/a.csv python3 session.py request --action s3:GetObject --key reports/private/a.csv
role matches=ReadAndWrite:Allow
boundary matches=ReadOnly:Allow
session matches=none
organization matches=AllowBase:Allow
decision=implicitDeny
role matches=ReadAndWrite:Allow
boundary matches=ReadOnly:Allow
session matches=ReportsPrefix:Allow
organization matches=AllowBase:Allow,PrivateDenied:Deny
decision=explicitDeny
8
cat session-wide.json python3 session.py assume --mfa true --policy session-wide.json python3 session.py request --action s3:PutObject --key reports/public/a.csv
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AttemptExpansion",
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::training-reports/*"
    }
  ]
}
caller_allowed=True trust_condition=True
session recorded principal=arn:aws:sts::222222222222:assumed-role/ReportReader/lesson expires=2026-11-01T10:00:00+00:00
role matches=ReadAndWrite:Allow
boundary matches=none
session matches=AttemptExpansion:Allow
organization matches=AllowBase:Allow
decision=implicitDeny
9
python3 session.py request --action s3:GetObject --key reports/public/a.csv --at 2026-11-01T09:59:59+00:00 python3 session.py request --action s3:GetObject --key reports/public/a.csv --at 2026-11-01T10:00:00+00:00
role matches=ReadAndWrite:Allow
boundary matches=ReadOnly:Allow
session matches=AttemptExpansion:Allow
organization matches=AllowBase:Allow
decision=allowed
decision=expired_or_not_yet_valid

演習完了