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

IAMポリシーの許可と拒否

要求に一致したStatementを示しながら、許可不足と明示的拒否、同一アカウントと別アカウントの違いを説明します。

説明

IAMの評価では、誰が、どの操作を、どの資源へ要求したかに対してポリシーを照合します。許可文が見つからない場合の暗黙的拒否と、Deny文に一致する明示的拒否は、調べるべき箇所が異なります。

IAMユーザーanalystとS3オブジェクトの固定ポリシーを使います。同一アカウント内でidentity-based policyとresource-based policyを照合し、読取り、書込み、private配下の拒否を確認します。最後に別アカウントの資源へ切り替え、双方の許可が必要なケースを調べます。この例ではboundaryや組織制限は設けていません。

要求に一致したStatementを示しながら、許可不足と明示的拒否、同一アカウントと別アカウントの違いを説明します。

1主体・操作・資源をそろえる

identity.jsonはユーザー側の許可、resource.jsonは対象側の許可です。Actionは操作、ResourceはARN、EffectはAllowまたはDeny、Sidは文を識別する名前です。

cat context.json主体とアカウント関係を読む cat identity.jsonユーザー側の許可文を読む cat resource.json対象側の許可文を読む

ユーザー側にはtraining-reports配下へのGetObjectがあり、対象側のStatementは空です。S3のオブジェクトARNにはregionやaccountの欄がなく、所有アカウントはこの演習のcontextで別に指定しています。

2読取りに一致する許可文

public/a.csvへのGetObjectを評価します。

python3 evaluate.py --action s3:GetObject --key public/a.csv公開用プレフィックス内の読取り要求を照合する

identityのReadReports:Allowに一致してallowedです。同一アカウントのこのケースでは、対象側の許可文がなくても、ユーザー側の許可が成立しています。

3許可されていない書込み

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

python3 evaluate.py --action s3:PutObject同じ資源への書込み要求に替える --key public/a.csv

両方ともmatches=noneでimplicitDenyです。Deny文が見つかったのではなく、書込みを許可する文がありません。読取りの許可を持つことは、書込みの許可を持つことではありません。

4リソースポリシーでユーザーに許可を与える

resource-write.jsonはPrincipalにanalystのARNを指定し、PutObjectを許可する案です。反映して再評価します。

cat resource-write.json主体を指定した対象側の許可を読む cp resource-write.json resource.json書込み許可を対象側へ反映する python3 evaluate.py --action s3:PutObject --key public/a.csv同じ書込みを再評価する

ユーザー側は一致なしでも、対象側のWriteByAnalyst:Allowでallowedになります。この例は同一アカウントのIAMユーザーに直接許可する条件であり、あらゆるロールや制限の組合せへそのまま当てはめるものではありません。

5private配下だけを明示的に拒否する

書込み許可に加えて、private/*へのPutObjectをDenyする文を反映します。

cat resource-deny.json許可と拒否が共存する案を読む cp resource-deny.json resource.jsonprivate配下の拒否を加える python3 evaluate.py --action s3:PutObject --key private/a.csv拒否対象のオブジェクトへ書込みを要求する

WriteByAnalyst:AllowとProtectPrivate:Denyの両方に一致しますが、結果はexplicitDenyです。許可があることだけを確認せず、同じ要求へ一致する拒否文まで確認します。

6拒否条件の範囲を確認する

publicへの書込みとprivateからの読取りを評価します。

python3 evaluate.py --action s3:PutObject --key public/a.csv拒否対象外への書込みを確認する python3 evaluate.py --action s3:GetObject --key private/a.csv同じprivate配下でも異なる操作を確認する

どちらもallowedです。Deny文はprivate配下へのPutObjectにだけ一致します。「private」という名前自体が読取りを禁止するのではなく、ActionとResourceの条件が評価されています。

7別アカウントの対象側だけが許可した場合

partner-reportsは別アカウント所有のバケットです。対象側はanalystに読取りを許可していますが、ユーザー側の許可はtraining-reportsだけです。

cat partner-resource.json別アカウントの対象側の許可を読む python3 evaluate.py --partner対象をpartner-reportsへ変更する --action s3:GetObject --key public/a.csv

resourceにはPartnerRead:Allowがある一方、identityは一致せずimplicitDenyです。この別アカウントのケースでは、要求元と対象側の双方で許可が必要です。

8要求元にも対象資源への許可を加える

identity-partner.jsonはpartner-reportsへのGetObjectも許可する案です。対象側の許可はそのままで、要求元へ追加します。

cp identity-partner.json identity.json要求元にもpartnerの読取りを許可する python3 evaluate.py --partner --action s3:GetObject同じ別アカウントの要求を再評価する --key public/a.csv

ReadPartner:AllowとPartnerRead:Allowがそろい、allowedになります。片側の変更だけで判断せず、要求が通るために必要な双方の文を照合しました。

9追加許可で既存の拒否が消えないことを確認

元のtraining-reportsのprivate配下へ書込みを要求します。

python3 evaluate.py --action s3:PutObject --key private/a.csv既存の拒否条件を同じ要求で再確認する

ProtectPrivate:DenyでexplicitDenyのままです。別の資源への許可を増やしても、この要求に一致する明示的拒否は消えません。

まとめ

ActionとResource、必要ならPrincipalをそろえて、一致する文を確認します。

許可文がない暗黙的拒否と、Deny文に一致する明示的拒否を分けて調べます。

別アカウントのこのケースでは双方の許可が必要で、明示的拒否は許可より優先されます。

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

シェル / Python 3

1
cat context.json cat identity.json cat resource.json
{
  "principal": "arn:aws:iam::111111111111:user/analyst",
  "principal_account": "111111111111",
  "resource_account": "111111111111",
  "scope": "IAM user, no boundary/session/SCP/RCP restrictions in this case"
}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadReports",
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::training-reports/*"
    }
  ]
}
{
  "Version": "2012-10-17",
  "Statement": []
}
2
python3 evaluate.py --action s3:GetObject --key public/a.csv
identity matches=ReadReports:Allow
resource matches=none
account_relation=same-account decision=allowed
3
python3 evaluate.py --action s3:PutObject --key public/a.csv
identity matches=none
resource matches=none
account_relation=same-account decision=implicitDeny
4
cat resource-write.json cp resource-write.json resource.json python3 evaluate.py --action s3:PutObject --key public/a.csv
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "WriteByAnalyst",
      "Effect": "Allow",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::training-reports/*",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:user/analyst"
      }
    }
  ]
}
identity matches=none
resource matches=WriteByAnalyst:Allow
account_relation=same-account decision=allowed
5
cat resource-deny.json cp resource-deny.json resource.json python3 evaluate.py --action s3:PutObject --key private/a.csv
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "WriteByAnalyst",
      "Effect": "Allow",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::training-reports/*",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:user/analyst"
      }
    },
    {
      "Sid": "ProtectPrivate",
      "Effect": "Deny",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::training-reports/private/*",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:user/analyst"
      }
    }
  ]
}
identity matches=none
resource matches=WriteByAnalyst:Allow,ProtectPrivate:Deny
account_relation=same-account decision=explicitDeny
6
python3 evaluate.py --action s3:PutObject --key public/a.csv python3 evaluate.py --action s3:GetObject --key private/a.csv
identity matches=none
resource matches=WriteByAnalyst:Allow
account_relation=same-account decision=allowed
identity matches=ReadReports:Allow
resource matches=none
account_relation=same-account decision=allowed
7
cat partner-resource.json python3 evaluate.py --partner --action s3:GetObject --key public/a.csv
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PartnerRead",
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::partner-reports/*",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:user/analyst"
      }
    }
  ]
}
identity matches=none
resource matches=PartnerRead:Allow
account_relation=cross-account decision=implicitDeny
8
cp identity-partner.json identity.json python3 evaluate.py --partner --action s3:GetObject --key public/a.csv
identity matches=ReadPartner:Allow
resource matches=PartnerRead:Allow
account_relation=cross-account decision=allowed
9
python3 evaluate.py --action s3:PutObject --key private/a.csv
identity matches=none
resource matches=WriteByAnalyst:Allow,ProtectPrivate:Deny
account_relation=same-account decision=explicitDeny

演習完了