CT.S3.PV.5
コントロールの説明
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.txt2. 有効化前の確認
コントロール有効化前は、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-testAn 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.comAn 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 policyHTTP PutObject(拒否)
echo "test" | aws s3 cp - s3://ct-s3-pv5-test/test2.txt \
--endpoint-url http://s3.ap-northeast-1.amazonaws.comupload 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 policyHTTPS 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.txtHTTP アクセスのみが拒否され、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 を参照。