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.csvroleは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
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"
}
}
}
]
}python3 session.py assume --mfa falsecaller_allowed=True trust_condition=False AssumeRole denied
python3 session.py assume --mfa truecaller_allowed=True trust_condition=True session recorded principal=arn:aws:sts::222222222222:assumed-role/ReportReader/lesson expires=2026-11-01T10:00:00+00:00
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/*"
}
]
}python3 session.py request --action s3:GetObject --key reports/public/a.csvrole matches=ReadAndWrite:Allow boundary matches=ReadOnly:Allow session matches=ReportsPrefix:Allow organization matches=AllowBase:Allow decision=allowed
python3 session.py request --action s3:PutObject --key reports/public/a.csvrole matches=ReadAndWrite:Allow boundary matches=none session matches=none organization matches=AllowBase:Allow decision=implicitDeny
python3 session.py request --action s3:GetObject --key archive/a.csv
python3 session.py request --action s3:GetObject --key reports/private/a.csvrole 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
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=implicitDenypython3 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:00role matches=ReadAndWrite:Allow boundary matches=ReadOnly:Allow session matches=AttemptExpansion:Allow organization matches=AllowBase:Allow decision=allowed decision=expired_or_not_yet_valid
演習完了