[レポート]AWS Configを使ったリソースのコンプライアンスチェックと自動修復に挑戦する #AWSreInforce #GRC357

[レポート]AWS Configを使ったリソースのコンプライアンスチェックと自動修復に挑戦する #AWSreInforce #GRC357

Clock Icon2025.06.23

はじめに

こんにちは、コンサルティング部の神野です。

米国東海岸で開催されているAWS re:Inforce 2025に現地参加していました。
先日無事日本に帰国しました!

今回の記事では、re:Inforce 2025のBuilders' sessionの1つ、「GRC357: Evaluate risk and automate remediation in your AWS environment」についてレポートします。

本セッションではAWS Configを使ったコンプライアンスチェックと自動修復について、実際に手を動かしながら学びました。

セッション概要

セッション番号: GRC357
セッションタイトル: Evaluate risk and automate remediation in your AWS environment
レベル: 300 - Advanced
セッションタイプ: Builders' session
トラック: Governance, Risk, and Compliance
関連エリア: Culture of Security, DevSecOps

Security teams face increasing challenges when evaluating and remediating risks across their AWS environments. This session demonstrates how to automate continuous security using AWS Config and AWS Systems Manager. Learn to streamline security analysis and response using predefined rules and automated workflows. Through practical examples, discover how to leverage Config rules and Systems Manager runbooks to assess your compliance posture, remediate violations, and maintain security standards at scale. You must bring your laptop to participate.

スピーカー:

  • Senior Delivery Consultant, Amazon Web Services (AWS)
  • WW CloudOps Principal PSA, Amazon Web Services
  • Senior Solutions Architect, Amazon Web Services
  • Sr TAM, Amazon Web Services

概要を読むと、AWS環境のリスクを全体的に洗い出して、横断的に対応できるようなシナリオかと思いましたが、AWS Configのルールを活用したコンプライアンスチェックと、その自動修復に対して基本的な内容を押さえていくセッションでした。

セッション内容

ワークショップシナリオ

今回のワークショップでは、開発者がデプロイしたWebアプリケーションのセキュリティ問題を発見し、修復するというシナリオで進めました。

具体的には、us-west-2(Oregon)とus-east-1(N. Virginia)の2つのリージョンにデプロイされたEC2インスタンスのセキュリティグループが、0.0.0.0/0からのSSHアクセス(ポート22)を許可している状態を発見し、これを自動的に検出・修復する仕組みを構築しました。

Architecture with warnings

AWS Configでのルールとコンプライアンスチェックの実装

最初のステップでは、AWS Configを使ってセキュリティ違反を検出する仕組みを構築します。

restricted-sshルールの設定

AWS Configのマネージドルールである「restricted-ssh」を使って、SSHアクセスが制限されていないセキュリティグループを検出してみました。

AWS Configコンソールからマネージドルールを検索し、「restricted-ssh」を選択するだけです。パラメータも特に変更せず、デフォルトのまま保存しました。

config-rule-restrict-ssh-enable

設定自体は本当にシンプルで、数クリックで完了しました。ルールを設定すると、AWS Configが自動的にリソースを評価し、違反しているリソースを識別してくれます。

config-rules-created

ただし、新しいルールの評価には数分かかることがあります。
ワークショップでは時間短縮のため、ルールを選択して手動で評価をトリガーしました。実際の環境では評価を待つことになりますが、すぐに結果を確認したい場合はこの方法がいいかと思います。

re-evaluate-rule

コンプライアンス状況の詳細確認

ルールが評価されたら、Dashboardから違反しているリソースの詳細を確認できます。インベントリページでセキュリティグループの詳細を見ることができました。特に便利だったのがタイムラインです。

config-resource-timeline

タイムラインでは、コンプライアンス状態の変更履歴、設定変更の履歴、関連するCloudTrail イベントが時系列で確認できます。

CleanShot 2025-06-18 at 23.08.14@2x

いつ、誰が、どのような変更を行ったかを追跡できるため、セキュリティインシデントの調査にも役立ちます。パッとリソースの変更を調べるときに視覚的にも見やすくて便利ですね!

Advanced Queriesによる高度な検索

AWS ConfigのAdvanced Queries機能を試してみました。3つの方法でクエリを実行できて、それぞれ違った使い道がありそうです。

まずは既存のクエリテンプレートから「Currently running EC2 Instances」を選んで実行してみました。ユースケースを選択すると自動的にクエリが生成されるので、SQLを一から書く必要がなくて便利です。

query-1

ただし、このままだとus-west-2リージョンの結果しか表示されません。そこでQuery scopeを「My-Aggregator」に変更し、accountIdとawsRegionカラムを追加してマルチリージョン対応にしました。

SELECT
  accountId, -- 追加
  awsRegion, -- 追加 
  resourceId,
  resourceName,
  resourceType,
  configuration.instanceType,
  tags,
  availabilityZone,
  configuration.state.name
WHERE
  resourceType = 'AWS::EC2::Instance'
  AND configuration.state.name = 'running'

これで両リージョンのインスタンスが一覧表示されました。

output-2

すごいなと思ったのがNatural Language Query Processorです。自然言語で「List security groups allowing SSH inbound, ordered by account and region」と書くだけで、以下のようなクエリを自動生成してくれました。

nql-prompt

「Generate」→「Populate to editor」をクリックすると、SSH関連のセキュリティグループを検索するクエリが生成されました。

SELECT
    accountId,
    awsRegion,
    resourceId,
    resourceName,
    configuration.ipPermissions,
    configuration
WHERE
    resourceType = 'AWS::EC2::SecurityGroup'
    AND configuration.ipPermissions.fromPort = 22
    AND configuration.ipPermissions.toPort = 22
ORDER BY
    accountId,
    awsRegion

実行結果では「View configuration」でセキュリティグループの詳細設定をJSON形式で確認することもできました。

CleanShot 2025-06-18 at 23.10.35@2x-0606930

修正せずに一発でクエリを実行できたので、構文に慣れていない場合や、どのフィールドが使えるか分からない時に、自然言語でクエリが作成できるのは便利だと思いました。

自動修復の実装

次に、検出した違反を自動的に修復する仕組みを実装しました。

Systems Manager Runbookとの連携

AWS ConfigとSystems Manager Automation Runbookを連携させて、違反が検出されたときの自動修復を設定してみました。

restricted-sshルールの「Actions」から「Manage remediation」を選び、自動修復をONにします。修復アクションには、AWSが提供済みの「AWS-DisableIncomingSSHOnPort22」Runbookを指定するだけです。あとは自分のアカウントIDを含むIAMロールのARNを設定すれば準備完了です。

ssh-1

ssh-2

アカウントIDの取得は、右上のユーザー名をクリックして「Account ID」の横にあるコピーアイコンから簡単にできます。

この設定により、違反が検出されると自動的にSSHルールが削除されます。MaximumAutomaticAttempts: 5RetryAttemptSeconds: 60の設定により、一時的な障害があっても最大5回まで60秒間隔でリトライされる設定となります。

修復結果の確認

修復が実行されたかを確認してみました。restricted-sshルールのページで「Resources in scope」から「All」を選択すると、セキュリティグループのStatusが「Action executed successfully」に変わっていました。セキュリティグループIDをクリックして、実際のリソースの画面まで遷移すると「インバウンドルール」タブでSSHルール(ポート22)が完全に削除されていることが確認できました。

CleanShot 2025-06-18 at 23.14.27@2x

CleanShot 2025-06-18 at 23.14.56@2x

さらに、Systems Manager Automationコンソールで実行履歴を確認することもできます。
正常に実行されたか?実行がうまくいったか?を確認するのにいいですね。

  1. Systems Managerコンソールの「Automation」を選択
  2. 「AWS-DisableIncomingSSHOnPort22」のExecution IDをクリック(何回かボタンを押した影響か複数回実行されていますね・・・)
    CleanShot 2025-06-18 at 23.15.54@2x
  3. 「Executed steps」セクションで、どのようにSSHルールが削除されたかの詳細を確認
    CleanShot 2025-06-18 at 23.16.03@2x

この一連の流れを見て、違反検出から修復までが対応されていることを実感できました。
手動で対応するケースと比べると時間短縮になりますね。

ただ、どこまでこの設定を入れるのか、自動修復を入れたいルールが多いと若干大変そうにも思えました。

カスタムルールとカスタム修復の作成(Optional Lab)

AWS提供のマネージドルールだけでなく、独自のコンプライアンスルールを作成することも可能です。今回は、EC2インスタンスの非ルートEBSボリュームが終了時に保持される設定になっているかをチェックするカスタムルールを作成しました。

Guardを使ったカスタムルール作成

AWS Config GuardというPolicy as Codeフレームワークを使って、Lambda関数を書くことなくカスタムルールを作成できます。

Lambda関数を書かずに済むGuard言語でカスタムルールを作成してみました。「Create custom rule using Guard」を選択し、ルール名を「ec2-preserve-data-on-termination」として、EC2インスタンスの非ルートEBSボリュームが終了時に保持される設定になっているかをチェックするルールを作ります。

add-guard-rule

Guard言語では以下のようなコードで、ルートデバイス以外のボリュームのdeleteOnTermination設定をチェックできます。

rule check_non_root_volume_preservation when
    resourceType == "AWS::EC2::Instance" {
    let root_volume_name = configuration.rootDeviceName
    # Identify all non-root volumes by filtering out the root device
    let non_root_volumes = configuration.blockDeviceMappings.*[ deviceName != %root_volume_name ]
    # Only evaluate the rule if there are non-root volumes
    when %non_root_volumes !empty {
        %non_root_volumes {
            # Ensure volume is preserved on instance termination
            ebs.deleteOnTermination == false
        }
    }
}

このルールは、ルートデバイス以外のEBSボリュームがdeleteOnTermination: falseに設定されているかをチェックします。データ損失を防ぐための重要な設定が適切に行われているかを継続的に監視できます。

ルール作成後、EC2コンソールで確認すると、実際に/dev/sdb(非ルートボリューム)の「削除時に終了」が「はい」になっており、ルールが正しく検出されていました。

CleanShot 2025-06-18 at 23.20.40@2x

CleanShot 2025-06-18 at 23.19.27@2x

カスタムSystems Manager Runbook作成

修復アクションもカスタマイズ可能です。違反したEC2インスタンスのEBSボリューム設定を自動的に修正するRunbookを作成しました。

修復アクション用のカスタムRunbookも作成してみました。Systems Managerの「Documents」から「Create document」→「Automation」を選び、ドキュメント名を「EC2-EnableNonRootVolumesRetention」として、「Code」ビューで以下のYAMLを入力します。

schemaVersion: '0.3'
assumeRole: '{{AutomationAssumeRole}}'
description: Enables volume retention for all the non-root EBS volumes of an EC2 instance
parameters:
  InstanceId:
    type: String
    description: (Required) The ID of the EC2 instance
    allowedPattern: i-[a-z0-9]{8,17}$
  AutomationAssumeRole:
    type: String
    description: (Optional) The ARN of the role that allows Automation to perform the actions on your behalf.
    default: ''
    allowedPattern: ^arn:aws(-cn|-us-gov)?:iam::\d{12}:role\/[\w+=,.@_\/-]+|^$
mainSteps:
  - name: GetInstanceInfo
    action: aws:executeAwsApi
    nextStep: ProcessVolumes
    isEnd: false
    inputs:
      Service: ec2
      Api: DescribeInstances
      InstanceIds:
        - '{{ InstanceId }}'
    outputs:
      - Name: RootDeviceName
        Selector: $.Reservations[0].Instances[0].RootDeviceName
        Type: String
      - Name: BlockDeviceNames
        Selector: $.Reservations[0].Instances[0].BlockDeviceMappings[?(@.Ebs.DeleteOnTermination == true)].DeviceName
        Type: StringList
  - name: ProcessVolumes
    action: aws:loop
    isEnd: true
    inputs:
      Iterators: '{{ GetInstanceInfo.BlockDeviceNames }}'
      IteratorDataType: String
      Steps:
        - name: CheckIfNonRootVolume
          action: aws:branch
          isEnd: true
          inputs:
            Choices:
              - NextStep: EnableVolumeRetention
                Not:
                  Variable: '{{ ProcessVolumes.CurrentIteratorValue }}'
                  StringEquals: '{{ GetInstanceInfo.RootDeviceName }}'
        - name: EnableVolumeRetention
          action: aws:executeAwsApi
          isEnd: true
          inputs:
            Service: ec2
            Api: ModifyInstanceAttribute
            InstanceId: '{{ InstanceId }}'
            BlockDeviceMappings:
              - DeviceName: '{{ ProcessVolumes.CurrentIteratorValue }}'
                Ebs:
                  DeleteOnTermination: false

CleanShot 2025-06-18 at 23.22.05@2x

このRunbookは、Systems Manager Automationの豊富なアクション(aws:executeAwsApi、aws:loop、aws:branch)を活用して、ルートデバイス以外のボリュームを自動的に識別し、保持設定を有効化します。

カスタム修復の設定と確認

カスタムルールにカスタム修復を設定してみました。
ec2-preserve-data-on-terminationルールのページで「Actions」→「Manage remediation」を選び、自動修復をONにして、作成したカスタムRunbook「EC2-EnableNonRootVolumesRetention」を指定します。
Resource ID parameterにはInstanceIdを選択し、AutomationAssumeRoleには自分のアカウントIDを含むIAMロールのARNを入力して、作成し修復を実行しました。

修復実行後、EC2コンソールで確認すると、/dev/sdbの「削除時に終了」が「いいえ」に変更されており、データ保護が適切に設定されたことを確認できました。

CleanShot 2025-06-18 at 23.25.50@2x

Lambda関数を書かずに、宣言的な記述だけで複雑なロジックを実装できるのは、運用負荷を考えると大きなメリットだと感じました。

こちらも今回は1個の設定なのでそこまで大変に思わなかったのですが、複数大量にカスタムルールを入れたいとなると大変な可能性はあるかと思いました。

マルチリージョン展開(Optional Lab)

最後に、適合パックとCloudFormation StackSetsを使って、複数リージョンに一括でコンプライアンスルールを展開する方法を学びました。

適合パックの活用

Conformance Packsは、複数のConfig rulesとremediationをパッケージ化したYAMLテンプレートです。AWSはGitHubで様々なサンプルを提供しており、そのまま使うことも、カスタマイズすることも可能です。

今回は、CIS AWS Foundations Benchmark Level 2をベースにしたConformance Packを使用しました。このパックには、先ほど作成したカスタムルールも含め、60以上のセキュリティルールが含まれています。一個一個ルールを作成するのと比べて、一括で設定できるのは非常に便利ですね。

適合パック自体の説明は下記ブログが大変わかりやすいので、参考になります!

https://dev.classmethod.jp/articles/aws-config-conformance-packs-understand/

StackSetを使った初回デプロイ手順

CloudFormation StackSetsを使って、Conformance Packを複数リージョンに一括展開してみました。提供されたテンプレートファイルをアップロードし、StackSet名を「Multiregion-Conformance-Pack」として、デプロイ先にus-east-1とus-west-2の両リージョンを指定します。Region concurrencyを「Parallel」に設定することで、並行デプロイによる時間短縮も可能です。

stackset-create-1

例として、restricted-sshルールは以下のように定義されていました。

IncomingSshDisabled:
    Properties:
      ConfigRuleName: restricted-ssh
      Scope:
        ComplianceResourceTypes:
          - AWS::EC2::SecurityGroup
      Source:
        Owner: AWS
        SourceIdentifier: INCOMING_SSH_DISABLED
    Type: AWS::Config::ConfigRule

Architecture

修復機能の追加

次に、ルールだけでなく修復機能も含むConformance Packに更新してみました。RULES_AND_REMEDIATIONS_cloudformation.yamlをダウンロードし、既存のStackSet「Multiregion-Conformance-Pack」に対して「Replace current template」で新しいテンプレートに更新します。Region concurrencyを再度「Parallel」に設定して更新を開始しました。

更新されたテンプレートには、例として、restricted-sshに対して以下のような修復設定が追加されていました。

DisableIncomingSSHRemediationConfig:
  Type: AWS::Config::RemediationConfiguration
  DependsOn: IncomingSshDisabled
  Properties:
    ConfigRuleName: restricted-ssh
    TargetId: AWS-DisableIncomingSSHOnPort22
    TargetType: SSM_DOCUMENT
    Parameters:
      AutomationAssumeRole:
        StaticValue:
          Values:
            - 'arn:aws:iam::${AWS::AccountId}:role/DisableSSHAutomationRole'
      SecurityGroupIds:
        ResourceValue:
          Value: RESOURCE_ID
    Automatic: true
    MaximumAutomaticAttempts: 5
    RetryAttemptSeconds: 60

マルチリージョンでの確認

Config Aggregatorを使って、両リージョンのコンプライアンス状況を確認してみました。us-west-2のConfigコンソールで「Aggregators」→「Conformance packs」を選択すると、us-east-1リージョンの方がus-west-2より多くの違反を表示していました(us-west-2は既に修復済みのため)。

conformance-pack-rules-overview

us-east-1の「CIS-Conformance-Pack」をクリックしてrestricted-sshルールを検索し、セキュリティグループのリンクを選択してみました。

修復が完了しても、Configが再評価している間はコンプライアンスステータスが数分間非準拠のままになることがありました。
セキュリティグループの画面に遷移すると、下記のようにus-east-1のインスタンスでもSSHが適切に削除されており、マルチリージョンでの自動修復が正常に機能していることが確認できました。

sgs-rule-executed

sg-manage-resource

sg-console

この仕組みにより、単一のStackSetで複数リージョンを管理し、各リージョンにConformance Packを展開して、Config Aggregatorで全リージョンのコンプライアンス状況を一元管理できる構成を実現できます。

最後のセクションは自分自身で手でやったことがなかったので、若干難しくは感じつつも実際に組織単位でガバナンスを効かせるとなるとこういった方法が有効なんだなと勉強になりました。推奨されている設定を各リージョン毎に1つずつ設定しなくていいのは大変魅力的でいいですね。

まとめ

本Builder's Sessionを通じて、AWS Configによるコンプライアンス自動化を学びました。
マネージドルールから始まり、カスタムルール作成、自動修復の設定、そしてマルチリージョン展開へと、段階的に難易度が上がっていく構成で、ステップバイステップで理解を深められたのが良かったです。
特に印象的だったのは以下の点です。

  • 検出から修復までの自動化
    ルール違反を検出するだけでなく、自動的に修復まで行える点が実用的です。
  • カスタマイズ性の高さ
    マネージドルールに加えて、組織固有の要件に応じたカスタムルールを簡単に作成可能です。
  • スケーラビリティ
    Conformance PacksとStackSetsを使えば、数百のルールを複数リージョン・アカウントに一括展開できる点がいいですね。

今回のセッションで学んだ内容は、すぐにでも実際のプロジェクトで実践できる内容かなと思いました。
特に自動修復まで実装することで、セキュリティ自動化を実現できることを学びました。

AWS Configを使ったことがない方も、まずはrestricted-sshのような基本的なルールから始めて、徐々に要件やポリシーに応じたカスタムルールや自動修復を追加していくことで、段階的にコンプライアンス自動化を学ぶのにいいコンテンツかなと思いました!

本記事が少しでも役に立ったら幸いです!
最後までご覧いただきありがとうございました!

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.