S3バージョニング自動修復システムから学ぶSOAサービス連携

S3バージョニング自動修復システムから学ぶSOAサービス連携

Clock Icon2025.07.15

はじめに

こんにちは。現在、AWS Certified SysOps Administrator – Associate(SOA)資格の学習に取り組んでいる八亀です。SOAの学習を進める中で、AWS Config、EventBridge、Systems Manager など多数のサービスが登場しますが、「どう連携させるのかイメージが湧かない…」という課題に直面しました。
そこで今回は、サービス間連携を理解するため、S3バケットの構成逸脱を自動で検知・修復する小規模なシステムを構築し、SOA試験頻出サービスの実践的な使い方を学んでいきます。

今回作るもの

本記事では、AWS CloudFormationで定義されたS3バケットの構成(バージョニング設定) が手動で変更された場合に、逸脱を検知→自動で修復処理を実行→処理結果をログ記録という一連の流れを自動化した「構成の自己修復システム」を構築します。

以下が本システムのアーキテクチャ図です
archi.drawio

このシステムを通して、SOA試験でも頻出の以下のサービスを学ぶことができます:

  • AWS CloudFormation
  • AWS Config
  • Amazon EventBridge
  • AWS Systems Manager Automation
  • Amazon CloudWatch Logs

やってみた

Step1 CloudFormation

本システムの対象となるリソース、S3バケットをCloudFormationで作成します。学習のため、S3バケット以外のリソース(AWS Config、EventBridge、SSM Automationなど)はマネジメントコンソールから作成していきます。

まず、CloudFormationテンプレートに使用する以下のYAMLファイルを準備します。ファイル名は self-healing-s3 など、わかりやすい名前で保存してください。

self-healing-s3.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: Learning - S3 Bucket for Self-Healing Practice

Parameters:
  ForceUpdateTimestamp:
    Type: String
    Default: "2025-01-01-00:00:00"
    Description: Force update parameter

Resources:
  MonitoredS3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub self-healing-demo-${AWS::AccountId}-${AWS::Region}
      VersioningConfiguration:
        Status: Enabled
      Tags:
        - Key: SelfHealingTarget
          Value: "true"
        - Key: LastUpdate
          Value: !Ref ForceUpdateTimestamp

重要なポイント:

  • VersioningConfiguration:S3バケットのバージョニングを有効化
  • SelfHealingTarget タグ:Config Rule の監視対象を限定し、既存のS3バケットに影響を与えないようスコープを制御

テンプレートの準備ができたら、AWSマネジメントコンソールから「AWS CloudFormation」にアクセスし、スタックの作成→新しいリソースを使用をクリックします。

スタックの作成
「テンプレートの準備」で「テンプレートファイルをアップロード」を選択し、先ほど準備したテンプレートファイルをアップロードします。「次へ」を押します。
スクリーンショット 2025-07-09 13.28.10

スタックの詳細を指定
スタック名を分かりやすい名前で入力します。今回は「yakame-self-healing-s3-stack」と付けています。パラメータはそのままで、「次へ」をクリックします。
スクリーンショット 2025-07-09 13.34.42

スタックオプションの設定
自分のIAMユーザーにS3の作成・管理権限がある場合は、そのまま進めて問題ありません。権限不足の場合のみ適切なIAMロールを指定します。「次へ」をクリックします。
スクリーンショット 2025-07-09 13.35.28

確認して作成
設定に問題がなければ「送信」をクリックし、以下を確認しましょう。

  1. CloudFormationコンソールでスタックステータスが CREATE_COMPLETE になっていること
  2. S3コンソールで新しいバケットが作成されていること
  3. バケットのプロパティでバージョニングが「有効」になっていること
  4. タグ「SelfHealingTarget=true」が付与されていること
    stack

S3_m4

Step2 AWS Config

次に、AWS Configのルールを作成します。
今回の目的は、S3バケットのバージョニング設定が無効化された場合に逸脱を検知することです。そのために、AWSが提供するマネージドルールである「s3-bucket-versioning-enabled」を使います。

AWSマネジメントコンソールから「AWS Config」にアクセスし、「ルール」タブを開きます。「ルールの追加」ボタンをクリックして、ルール名にs3-bucket-versioning-enabledを入力し検索します。該当のルールが表示されたら「追加」をクリックします。
Config1

ルールの設定
ルール名をわかりやすい名前に変更します。今回は、「yakame-s3-bucket-versioning-enabled」としています。
また、評価対象のリソースを絞り込むために「タグ」スコープを使用します。
CloudFormationでS3バケットに付与したタグと一致するように、キーを「SelfHealingTarget」、値を「true」に設定します。
Config2
この設定により、既存のバケットには影響を与えずに、今回作成したバケットのみを監視対象とすることができます。
「次へ」をクリックします。

確認と作成
確認画面で設定に問題がなければ「保存」をクリックします。
作成が完了したら、以下を確認します。

  1. ルールが作成されていること
  2. 評価対象のリソースがCloudFormationで作成した1つのS3バケットのみであり、検出コンプライアンスが「準拠」と表示されていること
    Config3

Step3 IAMロール作成

AWS EventBridge と SSM Automation を連携させるため、適切な権限を持つIAMロールを事前に作成する必要があります。このロールは、EventBridge がSSM Automation を実行し、SSM が CloudFormation 更新や S3 操作、ログ出力を行うために使用されます。

具体的な操作手順はここでは省略しますが、以下の内容を満たすIAMロールを事前に作成しておきましょう:

IAMポリシー:SSMCloudFormationRemediationPolicy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cloudformation:UpdateStack",
                "cloudformation:DescribeStacks"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:DescribeLogGroups",
                "logs:PutLogEvents"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutBucketVersioning",
                "s3:PutBucketTagging",
                "s3:GetBucketTagging",
                "s3:GetBucketVersioning"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ssm:StartAutomationExecution",
                "ssm:GetAutomationExecution",
                "ssm:DescribeAutomationExecutions"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "iam:PassRole"
            ],
            "Resource": "arn:aws:iam::xxxxxxxxxxxx:role/SSMExecutionRoleForRemediation"
        }
    ]
}

注:iam:PassRoleの"Resource"に記載されているxxxxは自身のアカウントIDを入れてください。

IAMロールの信頼関係:SSMExecutionRoleForRemediation
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "ssm.amazonaws.com",
                    "events.amazonaws.com"
                ]
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

権限の説明:

  • CloudFormation: スタック更新と状態確認
  • CloudWatch Logs: 修復結果の記録とログ管理
  • S3: バケットのバージョニング設定操作
  • SSM: Automation実行状況の確認

Step4 AWS Systems Manager

次に、EventBridge から呼び出される修復処理を定義するカスタム SSM Automation ドキュメントを作成します。このドキュメントが、実際の修復ロジックを実行する中核部分となります。

理想的には CloudFormation の再適用だけで S3 バージョニングを SuspendedEnabled に修復できるはずですが、実際にテストしてみると、CloudFormation ではバージョニングの状態変更が期待通りに動作しない場合があることが分かりました。

そこで今回は、以下のハイブリッドプロセスで自動修復を実現しています:

  1. まず CloudFormation 再適用による修復を試行
  2. 修復後にS3の実際の状態を確認
  3. まだ修復されていない場合は S3 API で直接修復

AWSマネジメントコンソールから「AWS Systems Manager」にアクセスし、左メニューの「ドキュメント」から、「ドキュメントの作成」→「オートメーション」を選択します。
左上からドキュメント名を任意の名前に変更します。今回は「Custom-UpdateCloudFormationStack」としています。
「コード」に、以下のYAML形式のコードを貼り付けます。

Custom-UpdateCloudFormationStack
schemaVersion: '0.3'
description: S3 Self-Healing with Auto-Created Logs (Minimal)
assumeRole: '{{ AutomationAssumeRole }}'
parameters:
  BucketName:
    type: String
    description: S3 bucket name to heal
  StackName:
    type: String
    description: CloudFormation stack name
  AutomationAssumeRole:
    type: String
    description: IAM role for execution
mainSteps:
  - name: UpdateStack
    action: aws:executeAwsApi
    nextStep: WaitAndFix
    isEnd: false
    inputs:
      Service: cloudformation
      Api: UpdateStack
      StackName: '{{ StackName }}'
      UsePreviousTemplate: true
      Parameters:
        - ParameterKey: ForceUpdateTimestamp
          ParameterValue: '{{ global:DATE_TIME }}'
  - name: WaitAndFix
    action: aws:sleep
    nextStep: FixAndLog
    isEnd: false
    inputs:
      Duration: PT30S
  - name: FixAndLog
    action: aws:executeScript
    isEnd: true
    inputs:
      Runtime: python3.9
      Handler: fix_and_log
      Script: |
        import boto3
        import json
        from datetime import datetime

        def fix_and_log(events, context):
            s3 = boto3.client('s3')
            logs = boto3.client('logs')

            bucket = events['BucketName']
            log_group = '/aws/s3-self-healing/audit'
            log_stream = f"fix-{datetime.now().strftime('%Y%m%d-%H%M%S')}"

            # ロググループ自動作成
            try:
                logs.create_log_group(logGroupName=log_group)
                print(f"Created log group: {log_group}")
            except logs.exceptions.ResourceAlreadyExistsException:
                print("Log group already exists")

            # ログストリーム作成
            try:
                logs.create_log_stream(logGroupName=log_group, logStreamName=log_stream)
            except:
                pass

            # バージョニング確認
            response = s3.get_bucket_versioning(Bucket=bucket)
            status = response.get('Status', 'Unversioned')

            # 修復処理
            if status != 'Enabled':
                s3.put_bucket_versioning(
                    Bucket=bucket,
                    VersioningConfiguration={'Status': 'Enabled'}
                )
                method = 'direct_api'
                print("Fixed by direct API")
            else:
                method = 'cloudformation'
                print("Fixed by CloudFormation")

            # ログ出力
            log_data = {
                "timestamp": datetime.now().isoformat(),
                "bucket": bucket,
                "remediation_method": method,
                "initial_status": status,
                "final_status": "Enabled"
            }

            logs.put_log_events(
                logGroupName=log_group,
                logStreamName=log_stream,
                logEvents=[{
                    'timestamp': int(datetime.now().timestamp() * 1000),
                    'message': json.dumps(log_data)
                }]
            )

            print(f"Logged to: {log_group}/{log_stream}")
            return {"method": method, "status": "success"}
      InputPayload:
        BucketName: '{{ BucketName }}'
        StackName: '{{ StackName }}'
    outputs:
      - Name: Result
        Selector: $.Payload
        Type: StringMap
outputs:
  - FixAndLog.Result

マネージドサービスのドキュメントとして用意されている「AWS-UpdateCloudFormationStack」ではスタックの更新しかできずS3 APIの適用ができない為、カスタムドキュメントを使用しています。
ドキュメントの作成には Claude Sonnet 4 を活用しています。
SSMdoc

SSM Automation の処理概要:

  1. CloudFormation 更新
  2. 待機: CloudFormation 処理完了を待つ(30秒)
  3. ハイブリッド修復: バージョニング状態を確認し、必要に応じて S3 API で直接修復
  4. ログ記録: 修復結果を CloudWatch Logs に詳細記録

設定が完了したら「ランブックを作成」をクリックします。

Step5 AWS EventBridge

次に、AWS Configから発行される「非準拠イベント」を検知するために、EventBridgeのルールを作成します。このルールにより、構成の逸脱が発生した際に、自動的にSSM Automationが起動し、CloudFormationスタックの再適用を実行することができます。

AWSマネジメントコンソールから「Amazon EventBridge」にアクセスし、左メニューの「ルール」から「ルールの作成」をクリックします。

ルールの詳細を定義
ルール名と説明欄は任意のもので構いません。今回は以下のように設定しました:

  • ルール名:yakame-s3-versioning-noncompliant-rule
  • 説明:Rule for detecting non-compliance events from AWS Config rules
    EventBridge1

イベントパターンを構成
イベントパターンはカスタムパターンを使用し、以下の内容を入力します。

カスタムパターン(JSONエディタ)
{
  "source": ["aws.config"],
  "detail-type": ["Config Rules Compliance Change"],
  "detail": {
    "configRuleName": ["yakame-s3-bucket-versioning-enabled"],
    "newEvaluationResult": {
      "complianceType": ["NON_COMPLIANT"]
    }
  }
}

configRuleNameには自身で作成したConfigRule名を入れてください。
この設定により、作成したConfig Ruleが非準拠と評価した時のみ、イベントが発火します。
EventBridge2

ターゲットを選択
ターゲットには、「Systems Managerオートメーション」を選択します。
ドキュメント名は作成したSSMドキュメントを指定します。
今回は「Custom-UpdateCloudFormationStack」を指定します。

入力パラメータは以下の通りです:

  • S3バケット名(self-healing-demo-xxxxxxxxxxxx-ap-northeast-1)
  • CloudFormation Stack名
  • 作成済みのIAMロールのARN
  • 実行ロールでは「既存ロールを使用」を選択し、作成したロールを適用しましょう。
    EventBridge3_m

タグの設定
タグは任意です。必要でなければ、何も入力せずにスキップして問題ありません。

ルールの作成
最後に「レビューと作成」画面で内容を確認し、「ルールの作成」をクリックします。
作成が完了すると、以下のようにルールが一覧に表示され、有効になっていることが確認できます。
EventBridge4_m

確認してみた

実際にシステムを動作させて、自己修復の一連の流れを確認していきます。

バージョニングの停止
S3バケットのプロパティタブから、手動でバージョニングを「停止」に変更します
S3check_m

Configの確認
AWS Config が構成変更を検知し、コンプライアンス状態が「非準拠」に変わったことを確認します。
Config_check

EventBridgeの確認
Config の非準拠イベントをトリガーとして、EventBridge ルールが発火したことを確認します。
※表示まで5分程度かかるため飛ばしても可
Evnet_m

SSM Automationの確認
EventBridge により起動された SSM Automation の実行状況を確認します。各ステップの成功/失敗や実行時間を詳細に確認できます。
AWSマネジメントコンソールから「AWS Systems Manager」にアクセスし、左メニューの「自動化」から確認できます。

SSMcheck_m

CloudFormationの確認
SSM Automation により CloudFormation スタックが更新されたことを確認します。
ステータスが「UPDATE_COMPLETE」になっていればOKです
CloudFormation_check

CloudWatch logsの確認
修復処理の詳細な実行ログが CloudWatch Logs に記録されていることを確認します。
AWSマネジメントコンソールから「CloudWatch」にアクセスし、左メニューの「ロググループ」から確認できます。

logs1

logs2_m

やはり、バージョニングに関してはStackの再適用だけではEnabled状態にならず、direct_apiで修復したことが分かりますね…なぜだろう?

S3バージョンの修復確認
最後に、S3のバージョニング状態を見ていきます。
システムにより自動修復され、S3 バケットのバージョニングが「有効」に戻っていることを確認できました。
LastUpdateタグが更新されており、Stackの再適用も一部できていることも確認できます。
s3_endM

おわりに

本記事では、S3バージョニング自動修復システムの構築を通じて、SOA試験頻出サービスの実践的な連携方法を解説しました。

AWS Config による構成監視から始まり、EventBridge でのイベント駆動、SSM Automation による修復処理、そして CloudWatch Logs での結果記録まで、一連の自動化フローを掴んでいただけたのではないでしょうか。

SOA学習をさらに深めるには、今回使用した各サービスの他の機能も確認してみることをお勧めします。Systems Manager であれば Parameter Store や Session Manager、CloudWatch であればカスタムメトリクスやアラーム機能など、実際のコンソールで様々なメニューを触ってみることで、SOA試験で問われる幅広い知識を身につけることができます。

アノテーション株式会社について

アノテーション株式会社はクラスメソッドグループのオペレーション専門特化企業です。サポート・運用・開発保守・情シス・バックオフィスの専門チームが、最新 IT テクノロジー、高い技術力、蓄積されたノウハウをフル活用し、お客様の課題解決を行っています。当社は様々な職種でメンバーを募集しています。「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、アノテーション株式会社 採用サイトをぜひご覧ください。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.