VPC Reachability Analyzer + Lambda 関数でセキュリティグループ変更を監視~通知する仕組みを実装してみた
はじめに
テクニカルサポートの 片方 です。
セキュリティグループの設定変更により、疎通ができなくなる可能性があります。
本ブログではこの課題を解決する仕組みとして、VPC Reachability Analyzer と Lambda、SNS、EventBridge を組み合わせ、自動で疎通チェックと通知を行う仕組みを紹介します。
「意図しないセキュリティグループ変更により通信が遮断される事態を即座に検知できる」 ようになります。
想定シナリオ
例として、システムが必ず 443 番ポート(HTTPS)でインターネット疎通できることが必須というケースを考えます。
手動作業時にルールを誤って削除・変更しても、自動で検知と通知が入るため安全です。
実装してみた
実装の手順としては、以下が想定されます。
- VPC Reachability Analyzer で Path を作成
- SNS トピック作成
- Lambda 関数作成 (疎通チェック実行・通知処理)
- EventBridge ルールでセキュリティグループ変更をトリガー化
2.の SNS トピック作成は省略しますが、通知先メールアドレスを登録してください。
VPC Reachability Analyzer の Path 作成
Network Manager コンソール を開きます。
左ペインの Reachability Analyzer を選択します。
「パスの作成と分析」をクリックし設定を進めます。
設定ポイント
- ソース : 検証対象の EC2 インスタンス
- 宛先 : インターネットゲートウェイ
- プロトコル : TCP
あとは、そのまま作成を進めてください。
作成後に表示される 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
処理が遅い場合は Lambda のタイムアウト値やメモリを調整してください。
EventBridge ルール作成
セキュリティグループ変更をトリガーするルールを作成します。
EventBridge でルール作成します。ルールタイプは、イベントパターンを持つルールを選択します。
カスタムパターン (JSON エディタ) を選択後、以下を貼り付けてください。
※ イベントパターン例
{
"source": ["aws.ec2"],
"detail-type": ["AWS API Call via CloudTrail"],
"detail": {
"eventSource": ["ec2.amazonaws.com"],
"eventName": ["AuthorizeSecurityGroupIngress", "RevokeSecurityGroupIngress", "AuthorizeSecurityGroupEgress", "RevokeSecurityGroupEgress"]
}
}
ターゲット選択では、Lambda 関数を選択します。
関数には、先ほど作成した関数名を選択します。
その他の設定はデフォルトで問題ないので、ルール作成を完了してください。
これで実装は終了です。お疲れ様でした!
検証してみた
EC2 にアタッチしている セキュリティグループのルール追加と削除を行いました。
その後、CloudTrail を確認したところ、問題なく実行されていました。
Reachability Analyzer 側でも実行されていることを確認してます。
もし、Reachability Analyzer 側 で到達不可能である場合、SNS より以下のような通知が来ます。
=== Reachability check failed (unreachable) ===
Path ID: nip-xxxxxxxxxxxx
Analysis ID: nia-xxxxxxxxxxxxx
Status: succeeded
NetworkPathFound: False
期待通りの動作を確認しました、成功です!
まとめ
本ブログよりヒューマンエラーによるシステム障害を抑止できます。本ブログが誰かの参考になれば幸いです。
参考資料
- Reachability Analyzer を使用した到達可能性に関する問題のトラブルシューティング - Amazon Virtual Private Cloud
- Lambda 関数呼び出しのタイムアウトエラーをトラブルシューティングする | AWS re:Post
- Actions - Amazon Elastic Compute Cloud
アノテーション株式会社について
アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。「らしく働く、らしく生きる」のスローガンを掲げ、様々な背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。