0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【AWS S3】リソースタグを使ってオブジェクト単位のアクセス制御を実現する方法

Posted at

🧩 背景

Amazon S3では、バケット単位のアクセス制御が一般的ですが、「同じバケット内でもオブジェクトごとにアクセスを分けたい」 というケースも少なくありません。

例えば:

  • 機密ファイル(Confidential)だけ特定ロールに限定したい
  • タグのないオブジェクトはアップロードも禁止したい
  • データ分類(Public / Confidential)をタグで管理したい

といった要件です。

この記事では、S3のオブジェクトタグを使ってアクセスを制御するIAMポリシーの実装例を紹介します。

🎯 ポリシー概要

このポリシーは、以下のルールでS3を制御します。

# 内容 効果
1 全バケット一覧取得を許可 s3:ListAllMyBuckets
2 各バケットの中身を一覧表示可能 s3:ListBucket
3 DataClass=Confidential のタグを持つオブジェクトのみ全操作許可 s3:*Object + タグ条件
4 アップロード(PutObject)時には必ず DataClass=Confidential タグが必要 s3:RequestObjectTag 条件付きで許可
5 タグを付けずにアップロードを試みた場合は拒否 Deny ルール

🧠 実装ポリシー全文

Policy(S3ConfidentialObjectTagAccess)
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ListAllBuckets",
            "Effect": "Allow",
            "Action": "s3:ListAllMyBuckets",
            "Resource": "*"
        },
        {
            "Sid": "ListEachBucket",
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::*"
        },
        {
            "Sid": "AllowAllOpsOnTaggedObjects",
            "Effect": "Allow",
            "Action": "s3:*Object",
            "Resource": "arn:aws:s3:::*/*",
            "Condition": {
                "StringEquals": {
                    "s3:ExistingObjectTag/DataClass": "Confidential"
                }
            }
        },
        {
            "Sid": "RequireTagOnPut",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:PutObjectTagging"
            ],
            "Resource": "arn:aws:s3:::*/*",
            "Condition": {
                "StringEquals": {
                    "s3:RequestObjectTag/DataClass": "Confidential"
                }
            }
        },
        {
            "Sid": "DenyPutWithoutRequiredTag",
            "Effect": "Deny",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::*/*",
            "Condition": {
                "Null": {
                    "s3:RequestObjectTag/DataClass": "true"
                }
            }
        },
        {
            "Sid": "DenyTagMutationAfterSet",
            "Effect": "Deny",
            "Action": [
                "s3:PutObjectTagging",
                "s3:DeleteObjectTagging"
            ],
            "Resource": "arn:aws:s3:::*/*",
            "Condition": {
                "Null": {
                    "s3:ExistingObjectTag/DataClass": "false"
                }
            }
        }
    ]
}

🖼️ 図で理解する:タグベース制御の流れ

1️⃣ オブジェクト操作時(Get / Delete / Tagging など)

🔹 評価ポイント

  • アップロード時には必ず DataClass=Confidential をタグとして同梱する必要がある
  • 値は "Confidential" に完全一致している必要あり(大文字小文字も含む)
  • タグを省略したアップロードは Deny により拒否される

2️⃣ アップロード(PutObject)時のタグ強制フロー

🔹 評価ポイント

  • アップロード時には必ず DataClass=Confidential をタグとして付与する必要がある
  • 値は "Confidential" に完全一致している必要あり(大文字小文字も含む)
  • タグを省略したアップロードは Deny により拒否される

✅ アクション整理

操作 タグ条件評価 制御方法
GetObject ✅ 可能 (s3:ExistingObjectTag/DataClass) タグ Confidential のみ許可
PutObject ✅ 可能 (s3:RequestObjectTag/DataClass) タグを付与しないアップロードを拒否
DeleteObject ❌ 不可 MFA・ロール・プレフィックスなどで別制御
PutObjectTagging / DeleteObjectTagging ✅ 初回付与のみ許可、以降拒否 DenyTagMutationAfterSet で後付け変更禁止

💻 CLIでのアップロード例

高レベルコマンド aws s3 cp には --tagging オプションがありません。
そのため s3api put-object を使用する必要があります。

✅ タグ付きでアップロード(許可される)

アップロード(OK)
aws s3api put-object \
  --bucket my-secure-bucket \
  --key uploads/sample.txt \
  --body ./sample.txt \
  --tagging "DataClass=Confidential"

❌ タグなしでアップロード(拒否される)

アップロード(NG)
aws s3api put-object \
  --bucket my-secure-bucket \
  --key uploads/untagged.txt \
  --body ./untagged.txt

出力例:

output
An error occurred (AccessDenied) when calling the PutObject operation: Access Denied

🧩 既存オブジェクトへのタグ付与

後からタグを設定したい場合は以下のようにします。

タグ付与
aws s3api put-object-tagging \
  --bucket my-secure-bucket \
  --key uploads/sample.txt \
  --tagging 'TagSet=[{Key=DataClass,Value=Confidential}]'

🧩 動作イメージ

  1. オブジェクトに DataClass=Confidential タグがある場合のみアクセス可能
  2. タグがないオブジェクトは GetObject / PutObject / DeleteObject 全て拒否
  3. 新規アップロード時もタグ必須

⚠️ 注意点

項目 説明
評価対象 ポリシーはIAMポリシー用(バケットポリシーではない)
タグの単位 判定はオブジェクトタグのみでバケットタグは不可
既存オブジェクト タグがない場合はアクセスが拒否される
暗号化バケット SSE-KMS利用時はkms:Decrypt権限も必要
アップロード運用 原則「アップロード時にタグ付与」がおすすめ

🧪 応用例

📘 複数タグ値を許可

複数タグ
"Condition": {
  "StringEquals": {
    "s3:ExistingObjectTag/DataClass": ["Confidential", "Secret"]
  }
}

🧾 まとめ

目的 方法
タグベースでアクセス制御 s3:ExistingObjectTag / s3:RequestObjectTag を利用
タグなしアップロードを禁止 Deny + Null 条件で強制
データ分類を明確化 タグ値を「Public」「Confidential」などに統一
運用のコツ アップロード時に必ず --tagging 付きで実行

🧰 おわりに

S3タグを 「データ分類ラベル」 として活用することで、バケットを分けなくても 機密・公開を明確に区別できる柔軟な権限設計 が可能になります。
また、S3タグは、単なるメタデータではなく 「ポリシーのキー」 として活用できる強力な仕組みです。
組織的な情報管理・機密区分にもおすすめです。

🔍 参考ドキュメント

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?