VPC Reachability Analyzer + Lambda 関数でセキュリティグループ変更を監視~通知する仕組みを実装してみた

VPC Reachability Analyzer + Lambda 関数でセキュリティグループ変更を監視~通知する仕組みを実装してみた

2025.09.05

はじめに

テクニカルサポートの 片方 です。
セキュリティグループの設定変更により、疎通ができなくなる可能性があります。
本ブログではこの課題を解決する仕組みとして、VPC Reachability Analyzer と Lambda、SNS、EventBridge を組み合わせ、自動で疎通チェックと通知を行う仕組みを紹介します。
「意図しないセキュリティグループ変更により通信が遮断される事態を即座に検知できる」 ようになります。

想定シナリオ

例として、システムが必ず 443 番ポート(HTTPS)でインターネット疎通できることが必須というケースを考えます。
手動作業時にルールを誤って削除・変更しても、自動で検知と通知が入るため安全です。

実装してみた

実装の手順としては、以下が想定されます。

  1. VPC Reachability Analyzer で Path を作成
  2. SNS トピック作成
  3. Lambda 関数作成 (疎通チェック実行・通知処理)
  4. EventBridge ルールでセキュリティグループ変更をトリガー化

2.の SNS トピック作成は省略しますが、通知先メールアドレスを登録してください。

VPC Reachability Analyzer の Path 作成

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/reachability-analyzer.html

Network Manager コンソール を開きます。
左ペインの Reachability Analyzer を選択します。
「パスの作成と分析」をクリックし設定を進めます。

02
03

設定ポイント

  • ソース : 検証対象の EC2 インスタンス
  • 宛先 : インターネットゲートウェイ
  • プロトコル : TCP

04

あとは、そのまま作成を進めてください。

05

作成後に表示される Path ID (nip-xxxx) を控えてください。後ほど Lambda 関数で使用します。
これで、終了です。

Lambda 関数作成

実行ロール作成

信頼されたエンティティタイプ ⇒ AWS のサービス ⇒ Lambda で作成します。
または、以下の信頼関係 (信頼ポリシー) で進めます。

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

AmazonVPCReachabilityAnalyzerFullAccess の AWS 管理ポリシーをアタッチ
さらに SNS 通知・ログ出力用のカスタマー管理ポリシーを作成~追加します

アタッチするポリシー例
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "SNSPublish",
      "Effect": "Allow",
      "Action": "sns:Publish",
      "Resource": "arn:aws:sns:ap-northeast-1:123456789012:xxxxxxxxxxxxx"
    },
    {
      "Sid": "CloudWatchLogs",
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "*"
    }
  ]
}

※ 適宜修正してください。
特に、SNS トピックに通知するための arn 修正を忘れずに。
"Resource": "arn:aws:sns:ap-northeast-1:123456789012:sg-change-alert"

Lambda 関数

Python 3.13 で作成しました。
実行ロールでは、既存のロールを使用するを選択し先ほど作成したロールを指定します。

import boto3
import os
import time

def lambda_handler(event, context):
    ec2 = boto3.client('ec2')
    sns = boto3.client('sns')

    # 環境変数から設定値を取得
    analyzer_path_id = os.environ['NETWORK_INSIGHTS_PATH_ID']
    sns_topic_arn = os.environ['SNS_TOPIC_ARN']

    # Reachability Analysis 実行
    response = ec2.start_network_insights_analysis(
        NetworkInsightsPathId=analyzer_path_id
    )
    analysis_id = response['NetworkInsightsAnalysis']['NetworkInsightsAnalysisId']

    print(f"Started Reachability Analysis: {analysis_id}")

    # 結果が出るまでポーリング
    while True:
        result = ec2.describe_network_insights_analyses(
            NetworkInsightsAnalysisIds=[analysis_id]
        )
        analysis = result['NetworkInsightsAnalyses'][0]
        status = analysis['Status']

        print(f"Status: {status}")

        if status in ['succeeded', 'failed']:
            break
        time.sleep(5)

    # 判定結果を評価
    if status == 'succeeded':
        path_found = analysis.get('NetworkPathFound', False)

        if not path_found:
            # 到達不可ケース → SNS 通知
            message = (
                "=== Reachability check failed (unreachable) ===\n"
                f"Path ID: {analyzer_path_id}\n"
                f"Analysis ID: {analysis_id}\n"
                f"Status: {status}\n"
                f"NetworkPathFound: {path_found}"
            )
            sns.publish(
                TopicArn=sns_topic_arn,
                Subject="[ALERT] Security Group change caused connectivity issue",
                Message=message
            )
            print("Unreachable notification sent.")
        else:
            print("Connectivity succeeded. No notification sent.")

    else:
        # 解析自体が失敗したケース
        message = (
            "=== Reachability analysis execution error ===\n"
            f"Path ID: {analyzer_path_id}\n"
            f"Analysis ID: {analysis_id}\n"
            f"Status: {status}"
        )
        sns.publish(
            TopicArn=sns_topic_arn,
            Subject="[ERROR] Reachability Analyzer failed to run",
            Message=message
        )
        print("Execution error notification sent.")

環境変数を利用しているため、以下を設定してください。

キー: NETWORK_INSIGHTS_PATH_ID
キー: SNS_TOPIC_ARN

06

処理が遅い場合は Lambda のタイムアウト値やメモリを調整してください。

https://repost.aws/ja/knowledge-center/lambda-troubleshoot-invocation-timeouts

EventBridge ルール作成

セキュリティグループ変更をトリガーするルールを作成します。
EventBridge でルール作成します。ルールタイプは、イベントパターンを持つルールを選択します。
カスタムパターン (JSON エディタ) を選択後、以下を貼り付けてください。

※ イベントパターン例

{
  "source": ["aws.ec2"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {
    "eventSource": ["ec2.amazonaws.com"],
    "eventName": ["AuthorizeSecurityGroupIngress", "RevokeSecurityGroupIngress", "AuthorizeSecurityGroupEgress", "RevokeSecurityGroupEgress"]
  }
}

07

ターゲット選択では、Lambda 関数を選択します。
関数には、先ほど作成した関数名を選択します。
その他の設定はデフォルトで問題ないので、ルール作成を完了してください。

08

これで実装は終了です。お疲れ様でした!

検証してみた

EC2 にアタッチしている セキュリティグループのルール追加と削除を行いました。
その後、CloudTrail を確認したところ、問題なく実行されていました。

09

Reachability Analyzer 側でも実行されていることを確認してます。

010

もし、Reachability Analyzer 側 で到達不可能である場合、SNS より以下のような通知が来ます。

=== Reachability check failed (unreachable) ===
Path ID: nip-xxxxxxxxxxxx
Analysis ID: nia-xxxxxxxxxxxxx
Status: succeeded
NetworkPathFound: False

期待通りの動作を確認しました、成功です!

まとめ

本ブログよりヒューマンエラーによるシステム障害を抑止できます。本ブログが誰かの参考になれば幸いです。

参考資料

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

アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。「らしく働く、らしく生きる」のスローガンを掲げ、様々な背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。

この記事をシェアする

facebookのロゴhatenaのロゴtwitterのロゴ

© Classmethod, Inc. All rights reserved.