AWS Cost Anomaly Detection を Chatbot で Slack 通知させる by Terraform
どうも、ちゃだいん(@chazuke4649)です。
AWS Cost Anomaly Detection を AWS Chatbot で Slack 通知させるリソース一式を Terraform で作りました。
ほぼ、以下ブログのTerraform版です。
手順
- AWS ChatbotにSlackワークスペースを登録する
- Terraformコードの適用する
- 通知テストする
1. AWS ChatbotにSlackワークスペースを登録する
まだ、AWS ChatbotにSlackワークスペースを登録していない場合は、Chatbotコンソールより実施します。
※詳細は割愛します
2. Terraformコードの適用する
メインとなるTerraoformコードは以下となります。
############################################################################### # Cost Anomaly Detection ############################################################################### resource "aws_ce_anomaly_monitor" "default" { name = "default" monitor_type = "DIMENSIONAL" monitor_dimension = "SERVICE" } resource "aws_ce_anomaly_subscription" "default" { name = "default" frequency = "IMMEDIATE" threshold_expression { dimension { key = "ANOMALY_TOTAL_IMPACT_PERCENTAGE" values = ["50.0"] match_options = ["GREATER_THAN_OR_EQUAL"] } } monitor_arn_list = [aws_ce_anomaly_monitor.default.arn] subscriber { type = "SNS" address = aws_sns_topic.cost_anomaly.arn } } ############################################################################### # SNS Topic ############################################################################### resource "aws_sns_topic" "cost_anomaly" { name = "cost_anomaly" } data "aws_iam_policy_document" "sns_cost_anomaly" { statement { effect = "Allow" resources = [aws_sns_topic.cost_anomaly.arn] actions = ["sns:Publish"] principals { type = "Service" identifiers = [ "costalerts.amazonaws.com", ] } } } resource "aws_sns_topic_policy" "sns_cost_anomaly" { arn = aws_sns_topic.cost_anomaly.arn policy = data.aws_iam_policy_document.sns_cost_anomaly.json } ############################################################################### # Chatbot ############################################################################### data "aws_iam_policy_document" "cloudwatch_access" { statement { effect = "Allow" resources = ["*"] actions = [ "cloudwatch:Describe*", "cloudwatch:Get*", "cloudwatch:List*", ] } } resource "aws_iam_policy" "chatbot_role" { name = "chatbot" policy = data.aws_iam_policy_document.cloudwatch_access.json } data "aws_iam_policy_document" "chatbot_role" { statement { actions = ["sts:AssumeRole"] principals { type = "Service" identifiers = ["chatbot.amazonaws.com"] } } } resource "aws_iam_role_policy_attachment" "chatbot_role" { role = aws_iam_role.chatbot_role.name policy_arn = aws_iam_policy.chatbot_role.arn } resource "aws_iam_role" "chatbot_role" { name = "chatbot" assume_role_policy = data.aws_iam_policy_document.chatbot_role.json } resource "aws_cloudformation_stack" "chatbot" { name = "chatbot" template_body = yamlencode({ Description = "Managed by Terraform" Resources = { AlertNotifications = { Type = "AWS::Chatbot::SlackChannelConfiguration" Properties = { ConfigurationName = "CostAlertNotifications" SlackWorkspaceId = "ABCDEFG123" ## SlackワークスペースID SlackChannelId = "HIJKLMN456" ## SlackチャンネルID IamRoleArn = aws_iam_role.chatbot_role.arn SnsTopicArns = [aws_sns_topic.cost_anomaly.arn] GuardrailPolicies = ["arn:aws:iam::aws:policy/ReadOnlyAccess"] LoggingLevel = "NONE" UserRoleRequired = false } } } }) }
一部を解説します。
Cost Anomaly Detection
############################################################################### # Cost Anomaly Detection ############################################################################### resource "aws_ce_anomaly_monitor" "default" { name = "default" monitor_type = "DIMENSIONAL" monitor_dimension = "SERVICE" } resource "aws_ce_anomaly_subscription" "default" { name = "default" frequency = "IMMEDIATE" threshold_expression { dimension { key = "ANOMALY_TOTAL_IMPACT_PERCENTAGE" values = ["50.0"] match_options = ["GREATER_THAN_OR_EQUAL"] } } monitor_arn_list = [aws_ce_anomaly_monitor.default.arn] subscriber { type = "SNS" address = aws_sns_topic.cost_anomaly.arn } }
基本的には以下ドキュメントのサンプルを参考にしています。
aws_ce_anomaly_monitor | Resources | hashicorp/aws | Terraform Registry
aws_ce_anomaly_subscription | Resources | hashicorp/aws | Terraform Registry
モニター側で注意点としては、組織にひもづかないAWSアカウントを2023年3月27日以降に開設すると、Cost Anomaly Detecitionモニターの「AWSサービス」タイプが自動作成されます。これは複数作ることができないので、すでに作成されている場合はすでに存在するため、上記コードだとエラーになります。
サブスクリプション側では、引数の threshold
が Depracated で、代わりに threshold_expression
で柔軟な設定が可能になっています。
今回は、ANOMALY_TOTAL_IMPACT_PERCENTAGE
(合計インパクト・パーセンテージ)を使用しており、異常と検出された金額が通常金額の何%かをしきい値とします。今回だと「50%以上」だと通知する設定にしています。
SNS
############################################################################### # SNS Topic ############################################################################### resource "aws_sns_topic" "cost_anomaly" { name = "cost_anomaly" } data "aws_iam_policy_document" "sns_cost_anomaly" { statement { effect = "Allow" resources = [aws_sns_topic.cost_anomaly.arn] actions = ["sns:Publish"] principals { type = "Service" identifiers = [ "costalerts.amazonaws.com", ] } } } resource "aws_sns_topic_policy" "sns_cost_anomaly" { arn = aws_sns_topic.cost_anomaly.arn policy = data.aws_iam_policy_document.sns_cost_anomaly.json }
普通のSNSトピックとリソースポリシーですが、特筆すると、トピックへのアクセスを許可しているAWSサービスの識別子として costalerts.amazonaws.com
を指定しています。
Creating an Amazon SNS topic for anomaly notifications - AWS Cost Management
Chatbot
############################################################################### # Chatbot ############################################################################### data "aws_iam_policy_document" "cloudwatch_access" { statement { effect = "Allow" resources = ["*"] actions = [ "cloudwatch:Describe*", "cloudwatch:Get*", "cloudwatch:List*", ] } } resource "aws_iam_policy" "chatbot_role" { name = "chatbot" policy = data.aws_iam_policy_document.cloudwatch_access.json } data "aws_iam_policy_document" "chatbot_role" { statement { actions = ["sts:AssumeRole"] principals { type = "Service" identifiers = ["chatbot.amazonaws.com"] } } } resource "aws_iam_role_policy_attachment" "chatbot_role" { role = aws_iam_role.chatbot_role.name policy_arn = aws_iam_policy.chatbot_role.arn } resource "aws_iam_role" "chatbot_role" { name = "chatbot" assume_role_policy = data.aws_iam_policy_document.chatbot_role.json } resource "aws_cloudformation_stack" "chatbot" { name = "chatbot" template_body = yamlencode({ Description = "Managed by Terraform" Resources = { AlertNotifications = { Type = "AWS::Chatbot::SlackChannelConfiguration" Properties = { ConfigurationName = "CostAlertNotifications" SlackWorkspaceId = "ABCDEFG123" ## SlackワークスペースID SlackChannelId = "HIJKLMN456" ## SlackチャンネルID IamRoleArn = aws_iam_role.chatbot_role.arn SnsTopicArns = [aws_sns_topic.cost_anomaly.arn] GuardrailPolicies = ["arn:aws:iam::aws:policy/ReadOnlyAccess"] LoggingLevel = "NONE" UserRoleRequired = false } } } }) }
こちらで紹介の方法を大変参考にさせていただいてます。ありがとうございます!
注意点としては、SlackワークスペースID と SlackチャンネルID はダミーなので差し替える必要があります。
ちなみに、TerraformがChatbotをサポートしていないのでCloudFormationをラップしていますが、今なら AWS Cloud Control Provider を使って直接作成する方法もあるようです、なるほど〜
3. 通知テストする
terraform apply後、Chatbotコンソールにて、テスト通知を行うと以下のような通知が届きました。
また、SNSトピックにて、Cost Anomaly Detectionのサンプルメッセージを送信すると、以下のような通知が届きました。
それでは今日はこの辺で。