こんにちは、ゲームソリューショングループのsoraです。
今回は、Trusted AdvisorレコメンデーションをEventBridge Schedulerを使って定期的に通知してみたことについて書いていきます。
構成
EventBridge Schedulerで指定した間隔で、Lambdaを呼び出して、Trusted Advisorのレコメンデーションを取得する構成です。
取得した後は、SNS経由でSlack通知するようにします。
Terraformで作成
Terraformを使って作成します。
Trusted Advisorのチェック結果はバージニア北部から取得する必要があります。
私だけかもしれませんが、aws_lambda_permissionでLambdaのトリガーを追加することは忘れがちなので注意してください。
main.tf
terraform {
#AWSプロバイダーのバージョン指定
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.51.0"
}
}
}
#AWSプロバイダーの定義
provider aws {
# Trusted Advisorのチェック結果はバージニア北部から取得する必要がある
region = "us-east-1"
}
#============ IAMロール作成 ============
##EventBridge Sheduler
data aws_iam_policy_document events_assume_role {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = ["scheduler.amazonaws.com"]
}
actions = ["sts:AssumeRole"]
}
}
resource aws_iam_role iam_for_events {
name = "EventBridge_TrustedAdvisor_Notification_Role"
assume_role_policy = data.aws_iam_policy_document.events_assume_role.json
managed_policy_arns = ["arn:aws:iam::aws:policy/service-role/AWSLambdaRole"]
}
##Lambda(Trusted Advisorからの情報取得用)
data aws_iam_policy_document lambda_assume_role {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
actions = ["sts:AssumeRole"]
}
}
resource aws_iam_role iam_for_lambda {
name = "Lambda_TrustedAdvisor_Notification_Role"
assume_role_policy = data.aws_iam_policy_document.lambda_assume_role.json
inline_policy {
name = "my_inline_policy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = ["support:DescribeTrustedAdvisorCheckResult"]
Effect = "Allow"
Resource = "*"
},
]
})
}
managed_policy_arns = [
"arn:aws:iam::aws:policy/AWSTrustedAdvisorPriorityReadOnlyAccess",
"arn:aws:iam::aws:policy/service-role/AWSIoTDeviceDefenderPublishFindingsToSNSMitigationAction"
]
}
#============ リソース作成 ============
##SNS(トピック)
###トピックの作成
resource aws_sns_topic trusted_advisor_topic {
name = "TrustedAdvisor-notification-topic"
}
##Lambda(Trusted Advisorからの情報取得用)
data archive_file lambda_trustedadvisor {
type = "zip"
source_file = "lambda/lambda_trustedadvisor.py"
output_path = "lambda_trustedadvisor.zip"
}
resource aws_lambda_function lambda_trustedadvisor {
filename = "lambda_trustedadvisor.zip"
function_name = "trusted-advisor-detection"
role = aws_iam_role.iam_for_lambda.arn
handler = "lambda_trustedadvisor.lambda_handler"
source_code_hash = data.archive_file.lambda_trustedadvisor.output_base64sha256
runtime = "python3.9"
environment {
variables = {
SNSTopicArn = aws_sns_topic.trusted_advisor_topic.arn
}
}
}
##Lambda(Slack通知用)
data archive_file lambda_slack {
type = "zip"
source_file = "lambda/lambda_slack.py"
output_path = "lambda_slack.zip"
}
resource aws_lambda_function lambda_slack {
filename = "lambda_slack.zip"
function_name = "trusted-advisor-notification-to-slack"
role = aws_iam_role.iam_for_lambda.arn
handler = "lambda_slack.lambda_handler"
source_code_hash = data.archive_file.lambda_slack.output_base64sha256
runtime = "python3.9"
environment {
variables = {
ChannelName = "<Slackのチャンネル名>",
HookURL = "<HookURL>"
}
}
}
resource aws_lambda_permission lambda_slack_permission {
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.lambda_slack.function_name
principal = "sns.amazonaws.com"
source_arn = aws_sns_topic.trusted_advisor_topic.arn
}
##EventBridge Sheduler
resource aws_scheduler_schedule eventbridge {
name = "trusted-advisor-notification-schedule"
description = "Trusted Advisor Notification"
flexible_time_window {
mode = "OFF"
}
schedule_expression = "cron(0 0 1 * ? *)"
schedule_expression_timezone = "Asia/Tokyo"
target {
arn = aws_lambda_function.lambda_trustedadvisor.arn
role_arn = aws_iam_role.iam_for_events.arn
}
}
##SNS(サブスクリプション)
###サブスクリプションの登録
resource aws_sns_topic_subscription slack_subscription {
topic_arn = aws_sns_topic.trusted_advisor_topic.arn
protocol = "lambda"
endpoint = aws_lambda_function.lambda_slack.arn
}
Lambdaコード
今回の構成では、Trusted Advisorから情報取得する用とSlack通知用の2つがあります。
Trusted Advisorから取得する用のLambdaについて、項目ごとに設定されているチェックIDを使用して情報を取得します。
チェックIDは以下から確認できます。
AWS Trusted Advisor チェックリファレンス
今回はセキュリティグループで無制限アクセスが可能になっているものを検知してみます。
Python SDKのリクエスト/レスポンスについては、以下をご参照ください。
describe_trusted_advisor_check_result
lambda_trustedadvisor.py
import boto3
import json
import os
SNSTopicArn = os.environ['SNSTopicArn']
def lambda_handler(event, context):
client = boto3.client('support', region_name='us-east-1')
message = []
response = client.describe_trusted_advisor_check_result(
checkId="1iG5NDGVre",
language='ja'
)
check_result = response['result']
# SNSに通知するメッセージを作成
message.append("セキュリティグループ — 無制限アクセス")
for flag in check_result['flaggedResources']:
if flag["status"] == "error":
message.append(f"Status: {flag['status']} ,Region: {flag['region']}, SecurtyGroupName: {flag['metadata'][1]}")
# メッセージをSNSに送信
sns_client = boto3.client('sns')
# 通知を送信するSNSトピックのARNを指定
sns_topic_arn = SNSTopicArn
sns_client.publish(
TopicArn=sns_topic_arn,
Message=json.dumps(message, indent=3, ensure_ascii=False)
)
Slack通知用のLambdaは色々なところで書かれているため割愛します。
実行結果
EventBridge Schedulerで指定したタイミングで通知がきました。
最後に
今回は、Trusted AdvisorレコメンデーションをEventBridge Schedulerを使って定期的に通知してみたことを記事にしました。
どなたかの参考になると幸いです。