AWS Config RulesとLambdaによる非準拠リソースの自動修復

目次

概要

AWS Configを使えばリソースの設定がセキュリティポリシーに準拠しているかを継続的に監視できますが、非準拠リソースを検出した後の対応は手動で行う必要があります。運用チームが対応するまでの間、非準拠の状態が放置されるリスクがあります。

この問題を解決するのが、Config RulesとLambda関数を組み合わせた 自動修復(Auto Remediation) です。非準拠リソースを検出した時点でLambda関数が自動的に呼び出され、設定を修正します。

ただし、自動修復を構成する際には Lambda の実行ロールに適切な権限を付与する必要があり、権限不足によって修復が失敗するケースが頻繁に発生します。本記事では、S3バケットのサーバーアクセスログ設定を題材に、Config RulesとLambdaによる自動修復の仕組みと、IAMロールの権限設定のポイントを解説します。

AWS Configの基本的な使い方についてはAWS Configによるリソース設定の監視で解説しています。本記事ではその知識を前提に、自動修復にフォーカスします。

Config Ruleが非準拠を検出し、Lambda関数が自動的にS3バケットのログ設定を修復する全体構成図
Config Ruleが非準拠を検出し、Lambda関数が自動的にS3バケットのログ設定を修復する全体構成図
クラウドおさる

非準拠を見つけたら、人の手を待たずに Lambda で直してしまう自動修復を確かめる記事でござる。ログ設定をわざと無効にして、勝手に元へ戻るところまで見届けるのでござるな。

この記事のメリット

  • AWS Config Rulesの自動修復アーキテクチャ(SSM Automation方式とカスタムLambda方式)の違いを理解できる
  • Lambda関数による自動修復を構築する際に必要なIAMロールの権限設計を習得できる
  • Lambda実行ロールの信頼ポリシー(Trust Relationship)の設定方法を把握できる
  • 「Lambdaが呼び出されたが修復に失敗する」というよくあるトラブルの原因と対処法を理解できる
  • S3バケットのサーバーアクセスログ設定の自動修復をハンズオンで体験できる
  • SCS試験の「Config Rulesによる自動修復」「Lambda実行ロールの権限」に関する問いに正確に答えられるようになる

執筆者とキャラクター紹介

執筆者:土肥(とひ)

株式会社ジェニュインの代表であり元エンジニア。これまでオンプレミスと AWS 環境のインフラ業務を担当。AWS 認定資格の学習で得た知識を、ハンズオンとともに解説するのが得意。直近では新人の教育も行っており、これから技術を学ぶ方が納得できる解説を心がけています。基礎編・Cloud Practitioner の記事では、解説役としても登場します。

土肥

クラウドおさる

クラウドおさる

はじめましてでござる。弊猿はクラウドおさる。IT インフラが異常に発達した猿山から、雲に乗って地上の AWS を学びに降りてきたのでござる。

クラウドおさる

基礎編や Cloud Practitioner の記事では、とひさんに素朴な疑問をぶつける役でござるな。Security - Specialty などの記事では、要所でワンポイントや注意点をひとこと添えるでござる。

クラウドおさる

猿山にもデータセンターや監視当番があって、地上で起きることはだいたい猿山にも同じ仕組みがあるのでござる。例え話がつい猿山に寄るのは、弊猿の癖でござる。

技術解説

Config Rulesの自動修復方式

AWS Configで非準拠リソースを検出した後の修復方式は、大きく2つに分かれます。

方式実装方法特徴ユースケース
SSM AutomationConfig Rulesの修復アクションとしてSSM Automationドキュメントを指定AWSが用意した修復ドキュメントを利用でき、実装が容易S3バケットのパブリックアクセスブロック有効化など、定型的な修復
カスタムLambdaConfig Rulesの変更トリガーでLambda関数を呼び出す複雑な修復ロジックや条件分岐が可能修復前の条件判定、複数リソースにまたがる修復、通知との連携

SSM Automation方式は設定が簡単ですが、修復ロジックのカスタマイズには限界があります。カスタムLambda方式はコードを書く必要がありますが、修復前のチェックや例外処理など柔軟な対応が可能です。

マネージドルールとカスタムルール

Config Rulesには2種類あります。

種類説明例
マネージドルールAWSが提供する事前定義されたルール。設定パラメータを指定するだけで利用できるs3-bucket-logging-enabled、s3-bucket-public-write-prohibited
カスタムルールLambda関数を使って独自の評価ロジックを実装するルール特定のタグが付与されているか、命名規則に準拠しているか等

本記事では、マネージドルール s3-bucket-logging-enabled を使ってS3バケットのサーバーアクセスログ設定を監視し、非準拠の場合にカスタムLambda関数で修復を行います。

カスタムLambdaによる自動修復のアーキテクチャ

カスタムLambdaによる自動修復は、以下の流れで動作します。

  1. S3バケットの設定が変更される
  2. AWS Configが設定変更を検出し、Config Ruleで評価する
  3. 評価結果が「非準拠(NON_COMPLIANT)」の場合、Amazon EventBridgeルールがトリガーされる
  4. EventBridgeルールのターゲットとして設定されたLambda関数が呼び出される
  5. Lambda関数がS3 APIを呼び出し、バケットのログ設定を修復する
Config Rule → EventBridge → Lambda → S3 API という自動修復の処理フロー図
Config Rule → EventBridge → Lambda → S3 API という自動修復の処理フロー図

Lambda実行ロールの権限設計

自動修復でよくある失敗パターンは、Lambda関数は正常に呼び出されるが、修復対象のAWSリソースに対する権限が不足しているケースです。

Lambda関数の実行ロールには、以下の3種類の権限が必要です。

権限の種類内容例
Lambda基本実行権限CloudWatch Logsへのログ出力logs:CreateLogGroup、logs:CreateLogStream、logs:PutLogEvents
修復対象リソースの操作権限修復に必要なAPI呼び出しs3:PutBucketLogging、s3:GetBucketLogging
Config への結果報告権限(任意)評価結果をConfigに報告config:PutEvaluations

S3バケットのサーバーアクセスログを再有効化する場合、Lambda関数は s3:PutBucketLogging を呼び出してログ設定を書き込み、s3:GetBucketLogging で現在の設定を確認します。これらの権限がLambda実行ロールに付与されていないと、Lambda関数は実行されるもののAPI呼び出しが AccessDenied で失敗します。

クラウドおさる

Lambda が呼ばれているのに直らないときは、まず実行ロールの権限を疑うのでござる。s3:PutBucketLogging が無ければ、関数は動いても AccessDenied で止まるのでござるぞ。猿山でも、当番を起こしただけで倉庫の鍵を渡し忘れたら、バナナは一本も動かぬでござる。

Lambda実行ロールの信頼ポリシー

Lambda関数の実行ロールには、Lambdaサービスがそのロールを引き受けられるよう信頼ポリシー(Trust Relationship)を設定する必要があります。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

この信頼ポリシーがないと、Lambda関数はロールを引き受けることができず、実行自体が失敗します。信頼ポリシーはロールが「誰に使わせるか」を定義するものであり、許可ポリシーが「何ができるか」を定義するのとは役割が異なります。

フリーランス案件
クラウドおさる
クラウドキャリアフリーランス

AWS の実務経験があるなら、単価を上げにいく

AWS に特化したフリーランスエージェントです。以下は取り扱い案件の一例です。設計・SRE・セキュリティ・生成 AI の領域で、専門を掛け合わせるほど単価が上がります。

横にスクロールできます。掲載時点の情報のため、募集が終了している場合があります。条件の近い案件をご紹介しますので、お気軽にご相談ください。

実践

前提条件

以下のリソースが作成済みであること。

リソース種別リソース名用途
S3バケットconfig-remediation-target-bucket(任意の名前)修復対象のバケット
S3バケットconfig-remediation-log-bucket(任意の名前)アクセスログの保存先バケット
AWS ConfigConfiguration Recorderリソースの設定記録(有効化済み)
  • リージョン: ap-northeast-1(東京)
  • バケット名は全世界で一意である必要があるため、実際にはアカウントIDなどを付けた名前にします
  • ログ保存先バケットには、S3サーバーアクセスログの配信を許可するバケットポリシー(プリンシパル logging.s3.amazonaws.com に s3:PutObject を許可)が設定済みであること
  • 修復対象バケットには、あらかじめサーバーアクセスのログ記録を有効にしておきます(準拠している状態から始めます)
  • 修復対象バケットにタグ Purpose = config-remediation-demo を付けておきます(Config Ruleの評価対象をこのバケットだけに絞るため)

重要: s3-bucket-logging-enabled を絞り込みなしで作成すると、アカウント内のすべてのS3バケットが評価対象になります。この記事の構成では非準拠と判定されたバケットのログ設定をLambdaが自動的に書き換えるため、検証用でないバケットまで変更してしまいます。評価対象は必ずタグなどで絞り込んでください。

作成するリソース一覧

リソース種別リソース名用途
Config Rules3-bucket-logging-enabledS3バケットのログ設定を評価するマネージドルール
IAMロールConfigRemediationLambdaRoleLambda関数の実行ロール
IAMポリシーConfigRemediationLambdaPolicyLambda関数に必要な権限をまとめたポリシー
Lambda関数ConfigRemediateS3LoggingS3バケットのログ設定を修復する関数
EventBridgeルールconfig-s3-logging-noncompliantConfig Ruleの非準拠イベントをキャッチするルール

ステップ1: Config Ruleの作成

S3バケットのサーバーアクセスログが有効になっているかを評価するマネージドルールを追加します。

  • AWSマネジメントコンソールにログインし、リージョンがap-northeast-1(東京)であることを確認します
  • 上部の検索バーにConfigと入力し、表示された「Config」を選択します
  • 左側ナビゲーションの「ルール」を選択します
  • 「ルールを追加」をクリックします
  • 3ステップのウィザード(ルールタイプの指定 / ルールの設定 / 確認と作成)が開きます
  • ステップ1で「AWS によって管理されるルールの追加」を選択します
  • 検索ボックスにloggingと入力してEnterを押し、ページを送ってs3-bucket-logging-enabledのラジオボタンを選択します

検索ボックスは1単語での絞り込みしかできません。s3-bucket-logging-enabled のようにハイフンでつないだ名前をそのまま入力すると「一致が見つかりません」になります。logging のような単語で絞り込み、ページ送りで目的のルールを探してください。

マネージドルール選択画面(s3-bucket-logging-enabled が選択された状態)
マネージドルール選択画面(s3-bucket-logging-enabled が選択された状態)
  • 「次へ」をクリックします
  • ステップ2「ルールの設定」で、「変更範囲」を「タグ」にして以下を入力します
  • タグキー: Purpose
  • タグの値: config-remediation-demo
  • パラメータ(targetBucket / targetPrefix)は空のままにします(空のままなら、ログ記録が有効かどうかだけを評価します)
  • 「次へ」をクリックし、確認画面で「保存」をクリックします
ルール一覧(s3-bucket-logging-enabled が追加された状態)
ルール一覧(s3-bucket-logging-enabled が追加された状態)
クラウドおさる

変更範囲をタグで絞ったのがここの肝でござる。絞らずに作ると、アカウント内のすべてのバケットが評価対象になり、検証用でないバケットのログ設定まで Lambda が書き換えてしまうのでござるな。

ステップ2: Lambda実行ロールの作成

Lambda関数がS3バケットのログ設定を修復するために必要なIAMロールを作成します。

  • 上部の検索バーにIAMと入力し、「IAM」を選択します
  • 左側ナビゲーションの「ポリシー」を選択します
  • 「ポリシーの作成」をクリックします
  • 「JSON」タブを選択し、以下のポリシーを入力します
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "CloudWatchLogs",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
            "Sid": "S3BucketLogging",
            "Effect": "Allow",
            "Action": [
                "s3:GetBucketLogging",
                "s3:PutBucketLogging"
            ],
            "Resource": "arn:aws:s3:::config-remediation-target-bucket"
        }
    ]
}
IAMポリシーのJSONエディタ画面(ConfigRemediationLambdaPolicyのJSON全体が入力された状態)
IAMポリシーのJSONエディタ画面(ConfigRemediationLambdaPolicyのJSON全体が入力された状態)

Resource をワイルドカード(arn:aws:s3:::*)にすると、この関数はアカウント内のどのバケットのログ設定も書き換えられるようになります。修復対象のバケットに限定しておくのが安全です。

  • 「次へ」をクリックします
  • ポリシー名にConfigRemediationLambdaPolicyと入力します
  • 説明にPermissions for the Config remediation Lambda functionと入力します

説明欄に日本語を入れると「無効な文字です。英数字と『+=,.@-』の文字を使用してください」というエラーになります。説明は英数字で書きます。

  • 「ポリシーの作成」をクリックします

続いてIAMロールを作成します。

  • 左側ナビゲーションの「ロール」を選択します
  • 「ロールを作成」をクリックします
  • 信頼されたエンティティタイプで「AWSのサービス」を選択します
  • ユースケースで「Lambda」を選択します
ロール作成画面の信頼されたエンティティ選択(Lambda が選択された状態)
ロール作成画面の信頼されたエンティティ選択(Lambda が選択された状態)
  • 「次へ」をクリックします
  • 検索バーにConfigRemediationLambdaPolicyと入力し、表示されたポリシーにチェックを入れます
  • 「次へ」をクリックします
  • ロール名にConfigRemediationLambdaRoleと入力します
  • 「ロールを作成」をクリックします
ConfigRemediationLambdaRole の詳細画面(ConfigRemediationLambdaPolicy がアタッチされている状態)
ConfigRemediationLambdaRole の詳細画面(ConfigRemediationLambdaPolicy がアタッチされている状態)

作成されたロールの信頼ポリシーを確認します。

  • ロール一覧からConfigRemediationLambdaRoleをクリックします
  • 「信頼関係」タブを選択します

以下の信頼ポリシーが自動的に設定されていることを確認します。Lambdaをユースケースとして選択したため、lambda.amazonaws.comがプリンシパルに設定されています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
ConfigRemediationLambdaRole の信頼関係タブ(lambda.amazonaws.com がプリンシパルに表示されている状態)
ConfigRemediationLambdaRole の信頼関係タブ(lambda.amazonaws.com がプリンシパルに表示されている状態)

ステップ3: Lambda関数の作成

S3バケットのサーバーアクセスログを再有効化するLambda関数を作成します。

  • 上部の検索バーにLambdaと入力し、「Lambda」を選択します
  • 左側ナビゲーションの「関数」を選択します
  • 「関数の作成」をクリックします
  • 「一から作成」を選択します
  • 以下を入力します
  • 関数名: ConfigRemediateS3Logging
  • ランタイム: Python 3.13
  • 「カスタム設定」の「その他の設定」を展開します
  • 「全般」の「カスタム実行ロール」をオンにします
  • 開いた「カスタム実行ロールを設定」で「既存のロールを選択」を選び、ConfigRemediationLambdaRoleを選択して「保存」をクリックします
Lambda関数の作成画面(関数名、ランタイム、既存ロールの設定が入力された状態)
Lambda関数の作成画面(関数名、ランタイム、既存ロールの設定が入力された状態)
  • 「関数の作成」をクリックします

関数が作成されたら、コードソースに以下のコードを入力します。

import json
import boto3

s3 = boto3.client('s3')

# ログの保存先バケット名を設定してください
LOG_BUCKET = 'config-remediation-log-bucket'

def lambda_handler(event, context):
    print(json.dumps(event))

    detail = event.get('detail', {})
    resource_id = detail.get('resourceId', '')
    compliance_type = detail.get('newEvaluationResult', {}).get('complianceType', '')

    if compliance_type != 'NON_COMPLIANT':
        print(f'Resource {resource_id} is {compliance_type}. No action needed.')
        return

    bucket_name = resource_id
    print(f'Remediating S3 bucket logging for: {bucket_name}')

    try:
        s3.put_bucket_logging(
            Bucket=bucket_name,
            BucketLoggingStatus={
                'LoggingEnabled': {
                    'TargetBucket': LOG_BUCKET,
                    'TargetPrefix': f'{bucket_name}/'
                }
            }
        )
        print(f'Successfully enabled logging for bucket: {bucket_name}')
    except Exception as e:
        print(f'Error enabling logging for bucket {bucket_name}: {str(e)}')
        raise

    return {
        'statusCode': 200,
        'body': json.dumps(f'Logging enabled for {bucket_name}')
    }

注意: LOG_BUCKETの値は、ご自身のログ保存先バケット名に置き換えてください。

Lambda関数のコードソース画面(上記Pythonコードが入力された状態)
Lambda関数のコードソース画面(上記Pythonコードが入力された状態)
  • 「Deploy」をクリックしてコードをデプロイします

ステップ4: EventBridgeルールの作成

Config Ruleが非準拠を検出した際にLambda関数を自動的に呼び出すEventBridgeルールを作成します。

  • 上部の検索バーにEventBridgeと入力し、「EventBridge」を選択します
  • 左側ナビゲーションの「ルール」を選択します
  • 「ルールを作成」をクリックします

ルール作成画面には「強化ビルダー」(ドラッグアンドドロップのビジュアルビルダー)と「アドバンストビルダー」(ステップバイステップ)の2つのモードがあります。既定は強化ビルダーで、キャンバスにイベントとターゲットを置き、右側の「イベントパターン (フィルター)」のJSONエディタでパターンを直接書けます。

  • 名前をconfig-s3-logging-noncompliant、イベントバスをdefaultにします
  • イベントパターンに以下を入力します
{
    "source": ["aws.config"],
    "detail-type": ["Config Rules Compliance Change"],
    "detail": {
        "messageType": ["ComplianceChangeNotification"],
        "configRuleName": ["s3-bucket-logging-enabled"],
        "newEvaluationResult": {
            "complianceType": ["NON_COMPLIANT"]
        }
    }
}
EventBridgeルールの詳細画面(イベントパターンのJSONが表示されている状態)
EventBridgeルールの詳細画面(イベントパターンのJSONが表示されている状態)
  • ターゲットに「Lambda 関数」を選び、関数としてConfigRemediateS3Loggingを指定します
  • 内容を確認して「作成」をクリックします

作成後、ルールの詳細画面の「ターゲット」タブで、Lambda関数がターゲットになっていることを確認します。

EventBridgeルールのターゲットタブ(Lambda関数 ConfigRemediateS3Logging が設定された状態)
EventBridgeルールのターゲットタブ(Lambda関数 ConfigRemediateS3Logging が設定された状態)

ステップ5: 動作確認(ログ設定の無効化と自動修復)

構成が正しく動作するかを確認します。対象バケットのサーバーアクセスログを手動で無効化し、自動的に再有効化されることを確認します。

ログ設定の無効化

  • 上部の検索バーにS3と入力し、「S3」を選択します
  • バケット一覧からconfig-remediation-target-bucketをクリックします
  • 「プロパティ」タブを選択します
  • 「サーバーアクセスのログ記録」セクションまでスクロールし、「編集」をクリックします
  • 「サーバーアクセスのログ記録」を「無効にする」に変更します
S3バケットのサーバーアクセスログ記録の編集画面(無効にするが選択された状態)
S3バケットのサーバーアクセスログ記録の編集画面(無効にするが選択された状態)
  • 「変更の保存」をクリックします

自動修復の確認

ログ設定の無効化後、AWS Configが設定変更を検出し、Config Ruleの評価が行われます。非準拠と判定されると、EventBridge経由でLambda関数が呼び出され、ログ設定が自動的に再有効化されます。

  • 上部の検索バーにConfigと入力し、「Config」を選択します
  • 左側ナビゲーションの「ルール」を選択します
  • s3-bucket-logging-enabledをクリックします
  • 「対象範囲内のリソース」セクションで、対象バケットのコンプライアンスステータスが「非準拠」に変化することを確認します(このセクションは既定で「非準拠」だけを表示します)

注意: Config Ruleの評価には数分かかる場合があります。

Config Ruleの詳細画面(対象バケットが NON_COMPLIANT と表示されている状態)
Config Ruleの詳細画面(対象バケットが NON_COMPLIANT と表示されている状態)

Lambda関数の実行ログを確認します。

  • 上部の検索バーにCloudWatchと入力し、「CloudWatch」を選択します
  • 左側ナビゲーションの「ログ」→「ログ管理」を選択します
  • /aws/lambda/ConfigRemediateS3Loggingをクリックします
  • 最新のログストリームをクリックします
  • Successfully enabled logging for bucketというメッセージが出力されていることを確認します
CloudWatch Logsの画面(Lambda関数が正常に実行され、ログ設定が修復された旨のログが表示されている状態)
CloudWatch Logsの画面(Lambda関数が正常に実行され、ログ設定が修復された旨のログが表示されている状態)

最後に、S3バケットのログ設定が再有効化されていることを確認します。

  • 上部の検索バーにS3と入力し、「S3」を選択します
  • バケット一覧からconfig-remediation-target-bucketをクリックします
  • 「プロパティ」タブを選択します
  • 「サーバーアクセスのログ記録」セクションで、ログ記録が「有効」に戻っていることを確認します
S3バケットのプロパティ画面(サーバーアクセスのログ記録が有効に戻っている状態)
S3バケットのプロパティ画面(サーバーアクセスのログ記録が有効に戻っている状態)

権限不足による修復失敗のトラブルシューティング

Lambda実行ロールにs3:PutBucketLogging権限が付与されていない場合、CloudWatch Logsに以下のようなエラーが記録されます。

An error occurred (AccessDenied) when calling the PutBucketLogging operation: Access Denied

この場合の対処手順は以下のとおりです。

  • IAMコンソールでConfigRemediationLambdaRoleのポリシーを確認します
  • ConfigRemediationLambdaPolicyにs3:PutBucketLoggingとs3:GetBucketLoggingが含まれていることを確認します
  • 権限が不足している場合はポリシーを編集して必要な権限を追加します
  • Lambda関数を再度テスト実行し、修復が成功することを確認します
クラウドおさる

問われるのは、修復が失敗したときに信頼ポリシーと許可ポリシーのどちらが足りないのかを見分ける観点でござる。定型の修復なら SSM Automation、柔軟なロジックならカスタム Lambda、という使い分けも取り違えやすいところでござるな。

まとめ

本記事のポイントを整理します。

  • Config Rulesの自動修復には2つの方式がある: SSM Automationは定型的な修復に適し、カスタムLambdaは柔軟な修復ロジックの実装に適しています
  • カスタムLambda方式の構成: Config Rule → EventBridge → Lambda関数の流れで非準拠リソースを自動修復します
  • Lambda実行ロールには修復対象の権限が必要: Lambda基本実行権限に加えて、修復に必要なAPI権限(s3:PutBucketLogging等)を付与する必要があります
  • 信頼ポリシーの設定: Lambda実行ロールにはlambda.amazonaws.comをプリンシパルとする信頼ポリシーが必要です
  • よくある失敗パターン: Lambda関数は呼び出されるが、IAMロールの権限不足により修復APIの呼び出しがAccessDeniedで失敗するケースに注意が必要です
  • マネージドルールとカスタムルール: マネージドルールはAWSが提供する定義済みルール、カスタムルールはLambda関数で独自の評価ロジックを実装するルールです

参照先

フリーランス案件
クラウドおさる
クラウドキャリアフリーランス

AWS の実務経験があるなら、単価を上げにいく

AWS に特化したフリーランスエージェントです。以下は取り扱い案件の一例です。設計・SRE・セキュリティ・生成 AI の領域で、専門を掛け合わせるほど単価が上がります。

横にスクロールできます。掲載時点の情報のため、募集が終了している場合があります。条件の近い案件をご紹介しますので、お気軽にご相談ください。

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

株式会社ジェニュイン(https://genuine-pt.jp)の代表取締役.

2018年〜インフラエンジニアとしてキャリアをスタートし、オンプレミスのネットワーク・サーバ環境で3年半、クラウド環境で4年半の8年間エンジニアとして従事。
2021年に佐藤氏の創業した株式会社Luxyを引き継ぎ、代表に就任。
その後アガルートグループ内の株式会社ジェニュインと合併。
合併後同社代表に就任。

目次