AWS Config で S3 バケットのコンプライアンスチェックを CloudFormation と一緒にやってみた
はじめに
こんにちは、クラスメソッドオペレーションズの目取眞です。
CloudFormation は「リソースを作る」ためのものだと思われがちですが、今回はリソースの作成と同時にガバナンスチェックの仕組みまで組み込んでみました。
具体的には、S3 バケットを作成すると同時に AWS Config のマネージドルールでそのバケットを自動的にチェックする構成を CloudFormation で組んでみます。
どちらも非準拠になることを狙って作ったのですが、実際にやってみると想定と違う結果になったものもあり、その経緯も含めてまとめてみました。
今回のゴール
- CloudFormation で S3 バケットと AWS Config マネージドルールを同時にデプロイする
- 意図的に非準拠な設定を作り、AWS Config が正しく検知するか確認する
- あわせて、最近の S3 の仕様変更についても触れる
構成
今回作成したのは、次の 2 パターンです。
| パターン | AWS Config マネージドルール | チェック内容 | 想定結果 |
|---|---|---|---|
| ① | S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED | S3 バケットのサーバー側の暗号化が有効か | 非準拠になるはず |
| ② | S3_BUCKET_LEVEL_PUBLIC_ACCESS_PROHIBITED | S3 バケットのパブリックアクセスブロックが有効か | 非準拠になるはず |
前提条件として、検証するアカウントで AWS Config が有効化済みであることが必要です。今回のテンプレートには ConfigurationRecorder や DeliveryChannel を含めていないため、まだ AWS Config を有効化していないアカウントの場合は、先にコンソールから有効化しておいてください。
パターン① 暗号化チェック
まずは S3 バケットと、暗号化の有無をチェックする AWS Config マネージドルール(S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED)を作成する CloudFormation テンプレートを用意しました。
TargetBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "${TestBucketNamePrefix}-${AWS::AccountId}"
# あえて BucketEncryption を設定しない
# → AWS Config マネージドルールで「非準拠」判定させるための検証用リソース
S3EncryptionRule:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: s3-bucket-server-side-encryption-enabled-handson
Description: S3 バケットにサーバー側の暗号化が設定されているかをチェックする(ハンズオン用)
Source:
Owner: AWS
SourceIdentifier: S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED
Scope:
ComplianceResourceTypes:
- AWS::S3::Bucket
ComplianceResourceId: !Ref TargetBucket
テンプレート全文はこちら
AWSTemplateFormatVersion: '2010-09-09'
Description: |
既に AWS Config が有効なアカウント向けのハンズオン用テンプレート。
検証用の S3 バケットを作成し、AWS Config マネージドルールで「サーバー側の暗号化が有効かどうか」を自動チェックする。
ConfigurationRecorder / DeliveryChannel は既存のものをそのまま利用する想定のため、このテンプレートには含めない。
Parameters:
TestBucketNamePrefix:
Type: String
Default: config-handson-target
Description: 検証対象とする S3 バケット名のプレフィックス(末尾に AccountId を付与してユニークにします)
Resources:
#########################
# 検証対象の S3 バケット(わざと暗号化なしで作成)
#########################
TargetBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "${TestBucketNamePrefix}-${AWS::AccountId}"
# あえて BucketEncryption を設定しない
# → AWS Config マネージドルールで「非準拠」判定させるための検証用リソース
#########################
# AWS Config マネージドルール
#########################
S3EncryptionRule:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: s3-bucket-server-side-encryption-enabled-handson
Description: S3 バケットにサーバー側の暗号化が設定されているかをチェックする(ハンズオン用)
Source:
Owner: AWS
SourceIdentifier: S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED
Scope:
ComplianceResourceTypes:
- AWS::S3::Bucket
ComplianceResourceId: !Ref TargetBucket
Outputs:
TargetBucketName:
Description: 検証対象の S3 バケット(暗号化なしで作成、AWS Config で非準拠判定される想定)
Value: !Ref TargetBucket
ConfigRuleName:
Description: 作成された AWS Config マネージドルールの名前
Value: !Ref S3EncryptionRule
意図としては「暗号化設定を書かなければ、当然非準拠になるはず」というものでした。
CloudFormation コンソールで「既存のテンプレートを選択」を選び、テンプレートファイルをアップロードしてスタックを作成します。

スタックの作成が完了すると、タイムライン上で TargetBucket と S3EncryptionRule の両方が緑色(完了)になります。

想定外の結果:まさかの「準拠」判定
AWS Config のルール一覧画面を見てみると、s3-bucket-server-side-encryption-enabled-handson は予想に反して 準拠 と判定されていました。

原因を調べたところ、2023 年 1 月 5 日以降、S3 はデフォルト暗号化が設定されていないすべてのバケット(新規・既存を問わず)に対して、新しくアップロードされるオブジェクトにサーバー側の暗号化(SSE-S3)を自動的に適用する仕様になっていることがわかりました。
つまり、以前であれば「明示的に暗号化を設定しないと非準拠になる」構成だったものが、今の S3 では何も指定しなくても自動的に暗号化されるため、意図した非準拠を再現できなかった、というわけです。
これは失敗ではなく、むしろ「現在の AWS がデフォルトセキュリティをどこまで強化しているか」を体感できた貴重な気づきでした。
パターン② パブリックアクセスブロックチェック
暗号化チェックでは非準拠を再現できなかったので、今度は別のルールで試してみました。
S3_BUCKET_LEVEL_PUBLIC_ACCESS_PROHIBITED は、S3 バケットにバケットレベルのパブリックアクセスブロック設定が有効になっているかをチェックするルールです。
実は 2023 年 4 月 5 日に展開が始まり、同月 28 日までに全リージョンへの展開が完了した仕様変更により、S3 は新規作成されるすべてのバケットに対してパブリックアクセスブロックもデフォルトで有効になっています。
つまり、暗号化チェックと同じく「何もしなければ準拠になってしまう」状態です。そこで今回は、テンプレート側で PublicAccessBlockConfiguration を明示的に指定し、4 つの設定を false にしました。CloudFormation でプロパティを明示指定すると、S3 側のデフォルト値より指定値が優先されるため、これによりデフォルトの挙動を上書きし、確実に非準拠を再現できます。
NonCompliantBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "${NonCompliantBucketNamePrefix}-${AWS::AccountId}"
PublicAccessBlockConfiguration:
BlockPublicAcls: false
BlockPublicPolicy: false
IgnorePublicAcls: false
RestrictPublicBuckets: false
# 4 つの設定をすべて `false` にすることで、
# S3_BUCKET_LEVEL_PUBLIC_ACCESS_PROHIBITED ルールで確実に非準拠判定させる
S3PublicAccessRule:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: s3-bucket-level-public-access-prohibited-handson
Description: S3 バケットレベルでパブリックアクセスがブロックされているかチェックする(ハンズオン用)
Source:
Owner: AWS
SourceIdentifier: S3_BUCKET_LEVEL_PUBLIC_ACCESS_PROHIBITED
Scope:
ComplianceResourceTypes:
- AWS::S3::Bucket
ComplianceResourceId: !Ref NonCompliantBucket
テンプレート全文はこちら
AWSTemplateFormatVersion: '2010-09-09'
Description: |
AWS Config で「非準拠」判定を確実に再現するためのハンズオン用テンプレート。
パブリックアクセスブロック設定を明示的に無効化した S3 バケットを作成し、
AWS Config マネージドルール(S3_BUCKET_LEVEL_PUBLIC_ACCESS_PROHIBITED)で非準拠判定させる。
Parameters:
NonCompliantBucketNamePrefix:
Type: String
Default: config-handson-noncompliant
Description: 非準拠検証用バケット名のプレフィックス(末尾に AccountId を付与してユニークにします)
Resources:
#########################
# 検証対象の S3 バケット(パブリックアクセスブロックをあえて無効化)
#########################
NonCompliantBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "${NonCompliantBucketNamePrefix}-${AWS::AccountId}"
PublicAccessBlockConfiguration:
BlockPublicAcls: false
BlockPublicPolicy: false
IgnorePublicAcls: false
RestrictPublicBuckets: false
# 4 つの設定をすべて `false` にすることで、
# S3_BUCKET_LEVEL_PUBLIC_ACCESS_PROHIBITED ルールで確実に非準拠判定させる
#########################
# AWS Config マネージドルール
#########################
S3PublicAccessRule:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: s3-bucket-level-public-access-prohibited-handson
Description: S3 バケットレベルでパブリックアクセスがブロックされているかチェックする(ハンズオン用)
Source:
Owner: AWS
SourceIdentifier: S3_BUCKET_LEVEL_PUBLIC_ACCESS_PROHIBITED
Scope:
ComplianceResourceTypes:
- AWS::S3::Bucket
ComplianceResourceId: !Ref NonCompliantBucket
Outputs:
NonCompliantBucketName:
Description: 検証対象の S3 バケット(パブリックアクセスブロック無効化、AWS Config で非準拠判定される想定)
Value: !Ref NonCompliantBucket
ConfigRuleName:
Description: 作成された AWS Config マネージドルールの名前
Value: !Ref S3PublicAccessRule
同様にテンプレートをアップロードしてスタックを作成します。

スタック作成完了後、S3PublicAccessRule の評価が進みます。

ルール一覧画面を確認すると、今度は狙い通り s3-bucket-level-public-access-prohibited-handson が 非準拠 と表示されました。

対象範囲内のリソースを確認すると、今回作成した非準拠バケットが PublicAccessBlockConfiguration の項目で非準拠と判定されていることがわかります。

まとめ
今回は CloudFormation で S3 バケットの作成と AWS Config によるガバナンスチェックを同時に組み込むハンズオンを行いました。
- 暗号化チェックは、S3 のデフォルト仕様変更により、想定に反して「準拠」と判定された
- パブリックアクセスブロックチェックは、狙い通り非準拠を再現できた
「リソースを作ると同時にチェックの仕組みも動かす」という構成は、実務でも意図しない設定ミスの早期発見に役立ちそうです。また、今回のように AWS のデフォルト仕様は年々セキュアな方向にアップデートされている ため、ルールの前提を定期的に見直す必要があることも実感しました。非準拠を意図的に再現したい場合は、こうした S3 のデフォルト仕様の変化を考慮した上でテンプレートを設計する必要がある、というのが今回の一番の学びです。
参考
- デフォルトの暗号化の設定 - Amazon Simple Storage Service
- サーバー側の暗号化によるデータの保護 - Amazon Simple Storage Service
- Amazon S3 の暗号化のベストプラクティス - AWS 規範ガイダンス
- お知らせ: Amazon S3 のセキュリティに関する変更が 2023 年 4 月に予定されています
- AWS Config マネージドルール一覧(s3-bucket-server-side-encryption-enabled ほか)
クラスメソッドオペレーションズ株式会社について
クラスメソッドグループのオペレーション企業です。
運用・保守開発・サポート・情シス・バックオフィスの専門チームが、 IT・AI をフル活用した「しくみ」を通じて、お客様の業務代行から課題解決や高付加価値サービスまでを提供するエキスパート集団です。
当社は様々な職種でメンバーを募集しています。
「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、クラスメソッドオペレーションズ株式会社 コーポレートサイトをぜひご覧ください。
※2026 年 1 月 アノテーション㈱から社名変更しました。







