0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS Configで「非準拠」を自動検知・自動修復する

0
Posted at

前回の記事では、X-RayやVPCフローログを使った「非侵襲的な監視」について整理しました。今回は視点を変えて、「そもそもリソースの設定が正しい状態を保っているか」を継続的にチェックし、崩れていたら自動で直すAWS Configについて整理します。


なぜ設定はズレていくのか

CloudFormationやTerraformでリソースを厳格に管理していても、実際の運用では設定が意図せずズレていくことがよくあります。典型的なのは、緊急対応の場面です。

本来の運用:
  変更したい → IaCのテンプレート更新 → デプロイ → 反映

実際に起きること:
  障害対応のため、運用チームがコンソールから直接変更
    ↓
  応急処置として一時的にセキュリティグループを緩めた
    ↓
  そのまま戻し忘れる
    ↓
  IaCのテンプレートと実際の設定が乖離する

コンソールから直接いじれる人がいる限り、IaCでどれだけ厳格に管理していても「実物の設定」がテンプレートからズレる可能性は残ります。このズレを**「非準拠(non-compliant)」**と呼び、継続的に監視して検知・修正する仕組みが必要になります。


「非準拠」の具体例

非準拠とは、「組織が決めたセキュリティ基準に、実際のリソース設定が違反している状態」のことです。

リソース あるべき状態(準拠) 非準拠の例
S3バケット パブリックアクセスブロック有効 誰かがコンソールから「パブリック読み取り許可」に変更した
EBSボリューム 暗号化必須 暗号化なしでボリュームを作成した
セキュリティグループ SSH(22番)は特定IPのみ許可 0.0.0.0/0(全世界)からSSH許可に変更された
RDSインスタンス 削除保護が有効 削除保護がOFFになっている
CloudTrail 全リージョンで有効 特定リージョンだけ無効化された

AWS Configの土台: 「記録」の仕組み

非準拠を検知するには、まず「リソースが今どんな設定になっているか」を継続的に把握する必要があります。これを担うのがConfigレコーダーです。

Configレコーダーを有効にすると、対象リソースの設定が変わるたびに、その時点の設定内容を丸ごと1つの記録として保存します。この記録単位を**Configuration Item(設定項目、通称CI)**と呼びます。

{
  "resourceType": "AWS::EC2::SecurityGroup",
  "resourceId": "sg-0123456789",
  "configuration": {
    "ipPermissions": [
      { "fromPort": 22, "toPort": 22, "cidrIp": "0.0.0.0/0" }
    ]
  },
  "configurationItemCaptureTime": "2026-07-26T10:15:00Z"
}

このConfiguration Itemには、リソースの詳細設定・変更が発生した時刻(タイムスタンプ)・他リソースとの関連性が含まれます。このタイムスタンプ付きの記録こそが、Configの全機能(検知・自動修復・追跡・ダッシュボード表示)の土台となるデータです。記録がなければ、それ以降の非準拠判定も自動修復も何もできません。


ルールは自作しない ― ベストプラクティスの優先順位

「非準拠かどうかを判定するルール」は、ゼロから自作する必要はほとんどありません。AWSやコミュニティが用意した既製のルールセットを使うのが基本です。優先順位をつけて整理すると次のようになります。

1. AWS Configマネージドルール(まずこれ)
2. コンフォーマンスパック(業界標準の既製テンプレート)
3. Security Hub Security Standards(さらに手軽)
4. カスタムルール(Guardポリシー、組織固有の要件のみ)
5. Lambdaカスタムルール(最終手段)

1. マネージドルール

AWSが最初から200個以上用意している、よくあるベストプラクティスのルールです。有効化するだけで動きます。

resource "aws_config_config_rule" "encrypted_volumes" {
  name = "encrypted-volumes"

  source {
    owner             = "AWS"
    source_identifier = "ENCRYPTED_VOLUMES"
  }
}

自作するのは「ルールのロジック」ではなく、「どのマネージドルールを有効化するか選ぶ」だけで済みます。

2. コンフォーマンスパック

マネージドルールを1個ずつ有効化するのではなく、用途別にパッケージ化されたテンプレートをAWSが公式サンプルとして配布しています。

  • Operational-Best-Practices-for-Amazon-S3
  • Operational-Best-Practices-for-CIS-AWS-v1.4-Level1/2
  • Operational-Best-Practices-for-PCI-DSS
  • Operational-Best-Practices-for-HIPAA-Security
resource "aws_config_conformance_pack" "cis" {
  name          = "cis-benchmark-pack"
  template_body = file("Operational-Best-Practices-for-CIS-AWS-v1.4-Level1.yaml")
}

これらのYAMLテンプレートはAWS公式のGitHubリポジトリ(awslabs/aws-config-rules)にサンプルが公開されており、そのまま使えます。

3. Security Hub Security Standards

Security Hubを有効化すると、以下の標準ベンチマークがワンクリックで使えます。

  • AWS Foundational Security Best Practices (FSBP)
  • CIS AWS Foundations Benchmark
  • PCI DSS / NIST 800-53

裏側では実質的にConfigルール群が動いていますが、意識する必要すらなく、オン/オフの切り替えだけで済みます。

4. どうしても必要な場合のみカスタムルール

「タグに特定のキーが必須」のような組織固有のルールは、既製品には存在しません。この場合もLambdaをフルスクラッチで書くより、宣言的なポリシー言語(Guard)を使うCUSTOM_POLICYの方が労力が少なく済みます。

resource "aws_config_config_rule" "cost_center_tag" {
  name = "required-tag-costcenter"

  source {
    owner = "CUSTOM_POLICY"
    custom_policy_details {
      policy_runtime = "guard-2.x.x"
      policy_text    = <<-EOT
        rule tagged_correctly when resourceType == "AWS::S3::Bucket" {
          configuration.tags[*].key == "CostCenter"
        }
      EOT
    }
  }
}

判断軸: 「まず既製品で足りないかを先に検討する」のが鉄則です。Lambdaでの独自実装は最後の手段であり、「開発労力が大きい」という点で、要件を満たすアプローチとしては劣後しがちです。


検知だけでなく「自動修復」まで

コンフォーマンスパックには、ルールとセットで**自動修復(Remediation)**を組み込めます。

resource "aws_config_remediation_configuration" "s3_public_read" {
  config_rule_name = aws_config_config_rule.s3_public_read.name
  resource_type    = "AWS::S3::Bucket"
  target_type      = "SSM_DOCUMENT"
  target_id        = "AWS-DisableS3BucketPublicReadWrite"

  parameter {
    name         = "AutomationAssumeRole"
    static_value = aws_iam_role.config_remediation.arn
  }

  automatic                  = true
  maximum_automatic_attempts = 3
}

非準拠を検知すると、SSM Automationドキュメントが自動的に実行され、リソースを準拠状態へ戻します。「即座に検知して自動で修正する」という要件は、この仕組みで実現します。


マルチアカウント環境での可視化: Security Hub

複数のアプリチームがそれぞれ個別のAWSアカウントを持つ組織(AWS Organizations配下)では、Config単体だと非準拠状況がアカウントごとに分断されてしまいます。

Configだけの場合:
  Aアカウント: Configが非準拠を検出 → そのアカウント内でしか見えない
  Bアカウント: Configが非準拠を検出 → そのアカウント内でしか見えない
  Cアカウント: Configが非準拠を検出 → そのアカウント内でしか見えない

  → 組織全体を把握するには、アカウントを1つずつ開いて確認する必要がある

Security Hubは、Config・GuardDuty・Inspector・Macie等、複数のセキュリティサービスや複数アカウントの検出結果を、1つの管理アカウントに自動集約するサービスです。

[Security Hub 管理アカウント]
        ↑ 検出結果を自動集約
   ┌────┼────┐
Aアカウント  Bアカウント  Cアカウント
 Config      Config      Config

各Finding(検出結果)にはCreatedAtUpdatedAt等のタイムスタンプが標準で付与されるため、「正確なタイムスタンプ付きで追跡できる中央ダッシュボード」という要件もそのまま満たせます。

Configが「各現場の警備員」だとすると、Security Hubは「全拠点の警備状況が一目で分かる本部の監視モニター」というイメージです。

resource "aws_securityhub_account" "this" {}

resource "aws_securityhub_standards_subscription" "fsbp" {
  standards_arn = "arn:aws:securityhub:ap-northeast-1::standards/aws-foundational-security-best-practices/v/1.0.0"
  depends_on     = [aws_securityhub_account.this]
}

組織全体に展開する場合は、委任管理者アカウント側で組織対応版のリソースを使います。

resource "aws_config_organization_managed_rule" "encrypted_volumes" {
  name            = "org-encrypted-volumes"
  rule_identifier = "ENCRYPTED_VOLUMES"
}

resource "aws_securityhub_organization_admin_account" "this" {
  admin_account_id = var.security_tooling_account_id
}

非準拠の通知: EventBridge + Input Transformer

Config自体には通知機能がなく、検知した非準拠情報は、放置すれば誰にも気づかれません。これを解決するのがEventBridgeとSNSの組み合わせです。

Configは非準拠を検知すると、Config Rules Compliance ChangeというイベントをEventBridgeに自動送出します。これをルールで拾ってSNSに流します。

resource "aws_cloudwatch_event_rule" "restricted_ssh_violation" {
  name = "restricted-ssh-noncompliant"

  event_pattern = jsonencode({
    source      = ["aws.config"]
    detail-type = ["Config Rules Compliance Change"]
    detail = {
      configRuleName = ["restricted-ssh"]
      newEvaluationResult = {
        complianceType = ["NON_COMPLIANT"]
      }
    }
  })
}

resource "aws_cloudwatch_event_target" "sns" {
  rule = aws_cloudwatch_event_rule.restricted_ssh_violation.name
  arn  = aws_sns_topic.security_alert.arn

  input_transformer {
    input_paths = {
      sg_id   = "$.detail.resourceId"
      sg_name = "$.detail.resourceName"
    }
    input_template = "\"restricted-sshルール違反を検知: SG名=<sg_name>, ID=<sg_id>\""
  }
}

ここでのポイントは、通知に含めたい情報(セキュリティグループの名前やID)は、Configのイベント自体が既に持っているという点です。この程度の加工であれば、Lambdaを挟まずEventBridgeのInput Transformerだけで完結します。Lambdaが必要になるのは、複数のAPIを追加で呼び出して詳細情報を付加したり、Slack等の外部サービスに直接連携したりする、より複雑な加工が必要な場合に限られます。


Configのコスト構造

AWS Configの課金は2階建てです。

① Configレコーダーのコスト(記録自体)

課金対象は、記録された「Configuration Item」の数です。recording_groupで対象リソースタイプを絞ることで抑えられます。

② ルール評価のコスト

課金対象は、「1つのルールが1つのリソースを評価した回数」です。

コスト ≈ Σ(各ルール) [ そのルールが適用されるリソース数 × 評価回数 ]

コンフォーマンスパックの数がそのままコストになるわけではなく、各ルールが実際に対象とするリソースタイプと、評価トリガーの頻度(設定変更のたびに評価する「Configuration Changes」型か、一定間隔で評価する「Periodic」型か)によって決まります。

デプロイの失敗による再起動ループのように、短時間で設定変更が連発する状況では、Configuration Itemの記録とルール評価の両方が連鎖的に増えます。監視対象のシステムが不安定な状態にあるときほど、Configのコストも一緒に膨らみやすいという点は覚えておく価値があります。


まとめ

AWS Configによる非準拠管理の要点は次の3つです。

  1. ルールは自作しない。マネージドルール → コンフォーマンスパック → Security Hub標準の順に既製品を優先し、どうしても足りない場合のみカスタムルール(Guard)を使う
  2. 検知だけでなく自動修復までセットで構成する。コンフォーマンスパックにRemediationを組み込むことで、非準拠から復旧までを自動化できる
  3. マルチアカウントの可視化はSecurity Hubに任せる。個別のダッシュボードを自作する必要はない
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?