S3汎用バケットのDeleteBucketをタグ条件でDenyできるのか試してみた

S3汎用バケットのDeleteBucketをタグ条件でDenyできるのか試してみた

S3汎用バケットを誤削除から守りたい。その一環として、バケットのタグを条件に`s3:DeleteBucket`をDenyできるか検証してみました。最初は期待通りにいきませんでしたが、S3汎用バケットでABACを有効化することで解決できます。その検証過程を紹介します。
2026.06.04

はじめに

クラウド事業本部コンサルティング部の山﨑です。

AWS リソースを、マネジメントコンソールや AWS CLI から誤って削除されないようにしたい、というケースがあります。

今回はその一環として、S3 汎用バケットに付与したタグを条件にして、s3:DeleteBucket を Deny できるのか検証してみました。

最初は「バケットにタグを付けて aws:ResourceTag 条件で Deny すれば削除を防げるのでは」と考えていたのですが、実際に試すと ABAC 無効状態では期待通りに Deny されず、少しハマりました。

この記事では、その検証過程と、S3 汎用バケットの ABAC を有効化することでタグ条件 Deny が効くようになるまでを紹介します。

結論

  • S3 汎用バケットでは、タグを付けるだけでは s3:DeleteBucket のタグ条件 Deny は効きませんでした。
  • S3 汎用バケットの ABAC を有効化すると、バケットタグを条件に s3:DeleteBucket を Deny できました。
  • ABAC 有効化後は、バケットタグの追加・削除に使用する API が TagResource / UntagResource に変わります。

やりたかったこと

やりたかったことはシンプルです。

管理している S3 汎用バケットに、特定のタグを付与します。

今回は検証として、以下のタグを使用します。

ManagedBy=iac

このタグが付いている S3 汎用バケットは削除できないようにしたいです。

イメージとしては以下です。

バケットタグ 期待する動作
ManagedBy=iac あり 削除できない
ManagedBy=iac なし 削除できる

検証したポリシー

まずは、検証用 IAM ロールに以下のようなポリシーを付与しました。

検証用 IAM ロールのポリシー
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowS3Baseline",
      "Effect": "Allow",
      "Action": [
        "s3:DeleteBucket",
        "s3:DeleteObject",
        "s3:ListAllMyBuckets",
        "s3:ListBucket",
        "s3:GetBucketTagging",
        "s3:GetObjectTagging",
        "s3:GetBucketAbac",
        "s3:PutBucketAbac",
        "s3:ListTagsForResource",
        "s3:TagResource",
        "s3:UntagResource",
        "s3:PutBucketTagging"
      ],
      "Resource": "*"
    },
    {
      "Sid": "DenyDeleteBucketIfIac",
      "Effect": "Deny",
      "Action": "s3:DeleteBucket",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:ResourceTag/ManagedBy": "iac"
        }
      }
    }
  ]
}

ManagedBy=iac タグが付いている S3 汎用バケットに対して、s3:DeleteBucket を明示的に Deny するポリシーです。

検証環境

検証用に、以下の 2 つの S3 汎用バケットを用意しました。

バケット タグ 期待結果
example-abac-bucket-iac-001 ManagedBy=iac 削除失敗
example-abac-bucket-notag-001 なし 削除成功

なお、今回の検証では s3:DeleteBucket の動作結果を確認するため、検証用バケットはいずれも空の状態にしています。

バケットのタグ状態を確認します。

タグ付きバケットのタグ確認
aws s3api get-bucket-tagging \
  --bucket example-abac-bucket-iac-001

実行結果です。

{
  "TagSet": [
    {
      "Key": "ManagedBy",
      "Value": "iac"
    }
  ]
}

タグなしバケットでは、タグが存在しないことを確認します。

タグなしバケットのタグ確認
aws s3api get-bucket-tagging \
  --bucket example-abac-bucket-notag-001

実行結果です。

An error occurred (NoSuchTagSet) when calling the GetBucketTagging operation: The TagSet does not exist

ABAC 無効状態で DeleteBucket してみる

まず、S3 汎用バケットの ABAC を有効化していない状態で試します。

ManagedBy=iac タグ付きのバケットを削除してみます。

ABAC 無効状態でタグ付きバケットを削除
aws s3api delete-bucket \
  --bucket example-abac-bucket-iac-001 \
  --region ap-northeast-1

期待としては、明示的 Deny により AccessDenied になるはずでした。

しかし、結果は 削除成功 でした。

存在確認をすると、バケットは削除されています。

削除後の存在確認
aws s3api head-bucket \
  --bucket example-abac-bucket-iac-001

実行結果です。

An error occurred (404) when calling the HeadBucket operation: Not Found

つまり、ManagedBy=iac タグが付いているにもかかわらず、aws:ResourceTag/ManagedBy を条件にした Deny は効きませんでした。

なぜ Deny できなかったのか

調べてみると、S3 汎用バケットでは ABAC がデフォルトで無効であることが分かりました。

S3 汎用バケットで、タグベースのアクセス制御を行うには、対象バケットで ABAC を有効化する必要があります。

つまり、最初の検証で Deny が効かなかった理由は、ポリシーの構文ミスではなく、対象バケットで ABAC が有効化されておらず、バケットタグが認可条件として評価されなかったことでした。

ポイントは以下です。

  • バケットにタグが付いていること
  • そのタグをアクセス制御の条件として評価できること

この 2 つは別です。

今回のケースでは、バケットに ManagedBy=iac タグは付いていましたが、ABAC が無効だったため、aws:ResourceTag/ManagedBy 条件が期待通り評価されませんでした。

S3 汎用バケットの ABAC を有効化する

以降の検証では、ABAC 無効状態の検証で削除された example-abac-bucket-iac-001 を再作成し、再度 ManagedBy=iac タグを付与した状態から進めます。

対象バケットで ABAC を有効化します。

タグ付きバケットで ABAC を有効化
aws s3api put-bucket-abac \
  --bucket example-abac-bucket-iac-001 \
  --abac-status Status=Enabled \
  --region ap-northeast-1

タグなしバケット側も比較用に ABAC を有効化します。

タグなしバケットで ABAC を有効化
aws s3api put-bucket-abac \
  --bucket example-abac-bucket-notag-001 \
  --abac-status Status=Enabled \
  --region ap-northeast-1

ABAC の状態を確認します。

ABAC 状態確認
aws s3api get-bucket-abac \
  --bucket example-abac-bucket-iac-001 \
  --region ap-northeast-1

実行結果です。

{
  "AbacStatus": {
    "Status": "Enabled"
  }
}

これで、対象バケットの ABAC が有効化されました。

ABAC 有効化後に再度 DeleteBucket してみる

ABAC 有効化後、改めて ManagedBy=iac タグ付きバケットを削除してみます。

ABAC 有効状態でタグ付きバケットを削除
aws s3api delete-bucket \
  --bucket example-abac-bucket-iac-001 \
  --region ap-northeast-1

結果は以下です。

An error occurred (AccessDenied) when calling the DeleteBucket operation:
User: arn:aws:sts::123456789012:assumed-role/example-role/example-session
is not authorized to perform: s3:DeleteBucket
on resource: "arn:aws:s3:::example-abac-bucket-iac-001"
with an explicit deny in an identity-based policy

期待通り、ManagedBy=iac タグ付きバケットの削除が Deny されました。

エラーメッセージにも、explicit deny in an identity-based policy と出ています。

つまり、以下の Deny ステートメントが期待通り評価されたと言えます。

{
  "Sid": "DenyDeleteBucketIfIac",
  "Effect": "Deny",
  "Action": "s3:DeleteBucket",
  "Resource": "*",
  "Condition": {
    "StringEquals": {
      "aws:ResourceTag/ManagedBy": "iac"
    }
  }
}

タグなしバケットでは削除できるか

次に、ManagedBy=iac タグが付いていないバケットを削除します。

ABAC 有効状態でタグなしバケットを削除
aws s3api delete-bucket \
  --bucket example-abac-bucket-notag-001 \
  --region ap-northeast-1

こちらは成功しました。

存在確認をすると、バケットが削除されていることが分かります。

削除後の存在確認
aws s3api head-bucket \
  --bucket example-abac-bucket-notag-001

実行結果です。

An error occurred (404) when calling the HeadBucket operation: Not Found

期待通り、タグなしバケットは Deny 条件に一致しないため削除できました。

検証結果

検証結果をまとめると以下のとおりです。

ABAC 状態 バケットタグ 期待結果 実際の結果
無効 ManagedBy=iac 削除失敗 削除成功
有効 ManagedBy=iac 削除失敗 削除失敗
有効 タグなし 削除成功 削除成功

S3 汎用バケットのタグを条件に s3:DeleteBucket を制御したい場合は、対象バケットで ABAC の有効化が必要でした。

分かったこと

今回の検証で分かったことは以下です。

  • S3 汎用バケットで ABAC が無効な状態だと、バケットタグを条件にした Deny ポリシーだけではバケット削除を制御できなかった
  • S3 汎用バケットでは、バケットタグをアクセス制御に使うために ABAC の有効化が必要
  • ABAC 有効化後は、aws:ResourceTag/ManagedBy を条件に s3:DeleteBucket を Deny できた
  • タグなしバケットは Deny 条件に一致しないため、削除できた

特に重要なのは、タグが付いていることと、そのタグを認可条件として評価できることは別という点です。

注意点:ABAC 有効化後はタグ操作 API が変わる

S3 汎用バケットの ABAC を有効化する場合、タグ操作 API に注意が必要です。

ABAC 有効化後は、対象バケットに対して従来の PutBucketTaggingDeleteBucketTagging は使えなくなり、代わりに TagResourceUntagResource を使ってバケットタグを管理する必要があります。

AWS CLI で ABAC 有効化後にタグを付与する場合は、以下のように aws s3control tag-resource を使います。

ABAC 有効化後にタグを付与
aws s3control tag-resource \
  --account-id 123456789012 \
  --resource-arn arn:aws:s3:::example-abac-bucket-iac-001 \
  --tags '[{"Key":"ManagedBy","Value":"iac"}]' \
  --region ap-northeast-1

AWS CLI でタグを削除する場合は、以下のように aws s3control untag-resource を使います。

ABAC 有効化後にタグを削除
aws s3control untag-resource \
  --account-id 123456789012 \
  --resource-arn arn:aws:s3:::example-abac-bucket-iac-001 \
  --tag-keys '["ManagedBy"]' \
  --region ap-northeast-1

既存の IaC や運用スクリプトで PutBucketTagging / DeleteBucketTagging、または AWS CLI の aws s3api put-bucket-tagging / aws s3api delete-bucket-tagging を使っている場合は、ABAC 有効化前に影響確認が必要です。

参考

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事