AWS Config で S3 バケットのコンプライアンスチェックを CloudFormation と一緒にやってみた

AWS Config で S3 バケットのコンプライアンスチェックを CloudFormation と一緒にやってみた

CloudFormationでS3バケットとAWS Configを同時にデプロイし、ガバナンスチェックの仕組みを組み込んでみました。想定と異なる結果になった検証結果と、最近のS3仕様変更についてまとめています。
2026.07.22

はじめに

こんにちは、クラスメソッドオペレーションズの目取眞です。

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 が有効化済みであることが必要です。今回のテンプレートには ConfigurationRecorderDeliveryChannel を含めていないため、まだ 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 コンソールで「既存のテンプレートを選択」を選び、テンプレートファイルをアップロードしてスタックを作成します。

テンプレート指定画面

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

Config ルールの評価完了を待つタイムライン

想定外の結果:まさかの「準拠」判定

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 のデフォルト仕様の変化を考慮した上でテンプレートを設計する必要がある、というのが今回の一番の学びです。

参考

クラスメソッドオペレーションズ株式会社について

クラスメソッドグループのオペレーション企業です。
運用・保守開発・サポート・情シス・バックオフィスの専門チームが、 IT・AI をフル活用した「しくみ」を通じて、お客様の業務代行から課題解決や高付加価値サービスまでを提供するエキスパート集団です。
当社は様々な職種でメンバーを募集しています。
「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、クラスメソッドオペレーションズ株式会社 コーポレートサイトをぜひご覧ください。
※2026 年 1 月 アノテーション㈱から社名変更しました。

この記事をシェアする

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

関連記事