コンテンツにスキップ

CT.S3.PV.5

検証日: 2026-03-15 / リージョン: ap-northeast-1

コントロールの説明

S3 バケットへの HTTP(非暗号化)アクセスを禁止する。

本コントロールは RCP(リソースコントロールポリシー)により、S3 バケットへの HTTP アクセスをブロックする。Control Tower で対象の OU を指定して有効化すると、その OU 配下の全アカウントの全 S3 バケットに適用される。各バケットにバケットポリシーを設定する必要はない。ただし、本コントロールはバケットポリシーを自動追加するわけではないため、Security Hub [S3.5] は引き続き FAILED として検出される。

S3 の HTTPS 強制には以下の方法がある。

方法内容スコープ
Security Hub S3.5バケットポリシーに HTTPS 強制条件があるかチェック検出のみ(ブロックしない)
バケットポリシー(手動)バケットごとに HTTP を拒否するポリシーを設定(補足1参照バケット単位
CT.S3.PV.5(本コントロール)OU 配下の全バケットで HTTP を自動的に拒否OU 単位

Security Hub [S3.5] はバケットポリシーの設定有無をチェックするだけで、HTTP アクセス自体はブロックしない。バケットポリシーによる手動設定はバケットごとに必要で、設定漏れのリスクがある。

検証の流れ

    flowchart LR
    A[1. 事前準備] --> B[2. HTTP/HTTPS<br>両方成功]
    B --> C[3. Security Hub S3.5<br>で検出を確認]
    C --> D[4. CT.S3.PV.5<br>有効化]
    D --> E[5. 既存設定<br>維持を確認]
    D --> F[6. HTTP 拒否<br>HTTPS 成功を確認]
    E & F --> G[7. CT.S3.PV.5<br>無効化]
    G --> H[8. HTTP アクセス<br>成功を確認]
  

結果

  • コントロールの有効化前、HTTP・HTTPS の両方で S3 オブジェクトにアクセスできることを確認できた。
  • Security Hub [S3.5] で「FAILED」として検出されることを確認できた。
  • コントロールの有効化後、既存のバケット設定(バケットポリシーなし)は維持されることを確認できた。
  • HTTP でのアクセス(GetObject、PutObject)が explicit deny in a resource control policy で拒否されることを確認できた。
  • HTTPS でのアクセスは正常に動作することを確認できた。
  • コントロールの無効化後、再び HTTP アクセスが可能になることを確認できた。

1. 事前準備

テスト用の S3 バケットを作成する。

aws s3api create-bucket \
  --bucket ct-s3-pv5-test \
  --create-bucket-configuration LocationConstraint=ap-northeast-1
{
    "Location": "http://ct-s3-pv5-test.s3.amazonaws.com/",
    "BucketArn": "arn:aws:s3:::ct-s3-pv5-test"
}

テスト用オブジェクトをアップロードする。

echo "test data" | aws s3 cp - s3://ct-s3-pv5-test/test.txt

2. 有効化前の確認

コントロール有効化前は、HTTP・HTTPS の両方でアクセスできることを確認する。

HTTPS でのアクセス(成功)

aws s3api get-object \
  --bucket ct-s3-pv5-test --key test.txt /dev/null
{
    "AcceptRanges": "bytes",
    "LastModified": "2026-03-15T13:25:04+00:00",
    "ContentLength": 10,
    "ETag": "\"39a870a194a787550b6b5d1f49629236\"",
    "ChecksumCRC64NVME": "lAOnrRKrjh8=",
    "ChecksumType": "FULL_OBJECT",
    "ContentType": "binary/octet-stream",
    "ServerSideEncryption": "AES256",
    "Metadata": {}
}

HTTP でのアクセス(成功)

aws s3api get-object \
  --bucket ct-s3-pv5-test --key test.txt /dev/null \
  --endpoint-url http://s3.ap-northeast-1.amazonaws.com
{
    "AcceptRanges": "bytes",
    "LastModified": "2026-03-15T13:25:04+00:00",
    "ContentLength": 10,
    "ETag": "\"39a870a194a787550b6b5d1f49629236\"",
    "ChecksumCRC64NVME": "lAOnrRKrjh8=",
    "ChecksumType": "FULL_OBJECT",
    "ContentType": "binary/octet-stream",
    "ServerSideEncryption": "AES256",
    "Metadata": {}
}

HTTP でも正常にオブジェクトを取得できた。

3. Security Hub S3.5 での検出確認

Security Hub の [S3.5] コントロールで、テスト用の S3 バケットのバケットポリシーに SSL 強制条件がないことが検出されているか確認する。

aws securityhub get-findings \
  --filters '{
    "GeneratorId": [{"Value": "security-control/S3.5", "Comparison": "PREFIX"}],
    "ResourceId": [{"Value": "arn:aws:s3:::ct-s3-pv5-test", "Comparison": "EQUALS"}]
  }' \
  --query 'Findings[0].{Compliance:Compliance.Status,Title:Title}' \
  --profile Audit
{
    "Compliance": "FAILED",
    "Title": "S3 general purpose buckets should require requests to use SSL"
}

バケットポリシーに aws:SecureTransport 条件がないため、FAILED として検出されている。

4. CT.S3.PV.5 の有効化

aws controltower enable-control \
  --control-identifier arn:aws:controlcatalog:::control/7mo7a2h2ebsq71l8k6uzr96ou \
  --target-identifier <OU の ARN>
{
    "arn": "arn:aws:controltower:ap-northeast-1:<管理アカウント ID>:enabledcontrol/<enabledcontrol ID>",
    "operationIdentifier": "<オペレーション ID>"
}

有効化が完了するまで待機する。

aws controltower get-control-operation \
  --operation-identifier <オペレーション ID>
{
    "controlOperation": {
        "operationType": "ENABLE_CONTROL",
        "status": "SUCCEEDED",
        "statusMessage": "Operation was successful."
    }
}

5. 既存設定の維持確認

RCP はバケットポリシーを変更するのではなく、アクセス制御のレイヤーとして機能する。バケットポリシーが自動的に追加されていないことを確認する。

aws s3api get-bucket-policy \
  --bucket ct-s3-pv5-test
An error occurred (NoSuchBucketPolicy) when calling the GetBucketPolicy operation: The bucket policy does not exist

バケットポリシーは追加されていない。RCP はバケットの設定を変更せず、独立したアクセス制御レイヤーとして HTTP アクセスをブロックする。

6. 拒否の確認

HTTP GetObject(拒否)

aws s3api get-object \
  --bucket ct-s3-pv5-test --key test.txt /dev/null \
  --endpoint-url http://s3.ap-northeast-1.amazonaws.com
An error occurred (AccessDenied) when calling the GetObject operation:
User: arn:aws:sts::<Workload のアカウント ID>:assumed-role/<ロール名>/<セッション名>
is not authorized to perform: s3:GetObject on resource:
"arn:aws:s3:::ct-s3-pv5-test/test.txt" with an explicit deny in a resource control policy

HTTP PutObject(拒否)

echo "test" | aws s3 cp - s3://ct-s3-pv5-test/test2.txt \
  --endpoint-url http://s3.ap-northeast-1.amazonaws.com
upload failed: - to s3://ct-s3-pv5-test/test2.txt An error occurred (AccessDenied) when calling the PutObject operation:
User: arn:aws:sts::<Workload のアカウント ID>:assumed-role/<ロール名>/<セッション名>
is not authorized to perform: s3:PutObject on resource:
"arn:aws:s3:::ct-s3-pv5-test/test2.txt" with an explicit deny in a resource control policy

HTTPS GetObject(成功)

aws s3api get-object \
  --bucket ct-s3-pv5-test --key test.txt /dev/null
{
    "AcceptRanges": "bytes",
    "LastModified": "2026-03-15T13:25:04+00:00",
    "ContentLength": 10,
    "ETag": "\"39a870a194a787550b6b5d1f49629236\"",
    "ChecksumCRC64NVME": "lAOnrRKrjh8=",
    "ChecksumType": "FULL_OBJECT",
    "ContentType": "binary/octet-stream",
    "ServerSideEncryption": "AES256",
    "Metadata": {}
}

HTTPS PutObject(成功)

echo "test https" | aws s3 cp - s3://ct-s3-pv5-test/test-https.txt

HTTP アクセスのみが拒否され、HTTPS アクセスは正常に動作している。エラーメッセージに explicit deny in a resource control policy と記載されており、RCP による拒否であることがわかる。

7. CT.S3.PV.5 の無効化

aws controltower disable-control \
  --control-identifier arn:aws:controlcatalog:::control/7mo7a2h2ebsq71l8k6uzr96ou \
  --target-identifier <OU の ARN>
{
    "operationIdentifier": "<オペレーション ID>"
}
aws controltower get-control-operation \
  --operation-identifier <オペレーション ID>
{
    "controlOperation": {
        "operationType": "DISABLE_CONTROL",
        "status": "SUCCEEDED",
        "statusMessage": "Operation was successful."
    }
}

8. 制限解除の確認

コントロール無効化後、HTTP アクセスが再び成功することを確認する。

aws s3api get-object \
  --bucket ct-s3-pv5-test --key test.txt /dev/null \
  --endpoint-url http://s3.ap-northeast-1.amazonaws.com
{
    "AcceptRanges": "bytes",
    "LastModified": "2026-03-15T13:25:04+00:00",
    "ContentLength": 10,
    "ETag": "\"39a870a194a787550b6b5d1f49629236\"",
    "ChecksumCRC64NVME": "lAOnrRKrjh8=",
    "ChecksumType": "FULL_OBJECT",
    "ContentType": "binary/octet-stream",
    "ServerSideEncryption": "AES256",
    "Metadata": {}
}

HTTP アクセスが再び成功した。コントロールを無効化すると即座に制限が解除される。

9. クリーンアップ

aws s3 rm s3://ct-s3-pv5-test/ --recursive
aws s3api delete-bucket --bucket ct-s3-pv5-test

補足1: バケットポリシーによる SSL 強制との比較

CT.S3.PV.5 を使わずにバケットポリシーで HTTP を拒否する場合は、以下のようなポリシーをバケットごとに設定する。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::<バケット名>",
                "arn:aws:s3:::<バケット名>/*"
            ],
            "Condition": {
                "Bool": {
                    "aws:SecureTransport": "false"
                }
            }
        }
    ]
}

バケットポリシーで拒否された場合と CT.S3.PV.5(RCP)で拒否された場合では、エラーメッセージが異なる。

拒否元エラーメッセージ
RCP(CT.S3.PV.5)explicit deny in a resource control policy
バケットポリシーexplicit deny in a resource-based policy

この違いにより、HTTP アクセスが拒否された際にどのレイヤーで拒否されたかを特定できる。

補足2: CloudTrail での確認について

SCP による拒否は CloudTrail の管理イベントとして記録されるため、CloudTrail のイベント履歴や CloudWatch Logs から確認できる。

一方、CT.S3.PV.5(RCP)の拒否対象である GetObject / PutObject 等は CloudTrail のデータイベントに分類される。データイベントはデフォルトでは記録されず、確認するには証跡でデータイベントの記録を明示的に有効化する必要がある。また、Organization Trail の CloudWatch Logs にはデータイベントは配信されない(S3 バケットにのみ配信される)。

補足3: 除外プリンシパル

CT.S3.PV.5 の有効化時にパラメータ ExemptedPrincipalArns で特定の IAM ロールの ARN を指定すると、そのロールのみ RCP の制限を回避(HTTP でのアクセスを許可)できる。例えば、レガシーシステムの IAM ロールがすぐに HTTPS へ移行できない場合に、移行期間中の互換性を維持するために使用する。

設定方法は Configure controls with parameters を参照。

Amazonアソシエイトリンク