⛳
【Terraform】AWS/ChatBotを使用し、EC2の状態が変わったらSlackへ通知する
はじめに
しばらくSNS・Lambdaを使ってメール通知を試していたのですが、
今回はSlackへの通知を試すため、AWSのChatBotを使用します。
EventBridge→SNS→ChatBot
のような構成です。
通知するイベントはEC2の状態変化にします。
構成図
どんな通知が届く?
こんな感じです
環境
Terraform 1.4.6
前提
- プロビジョニングにはTerraformを使用します
- 通知するイベントはEC2の
EC2 Instance State-change Notification
です - あらかじめslackワークスペースを登録しておく
- 既存のチャネルとの重複が不可であるため、通知するチャネルを事前に確認する
- チャネルIDはチャネルのリンクから取得可能
https://xxxxxxxxx-xxxxxxxx.slack.com/archives/<チャネルID>
Terraformコード
プロバイダ
awsプロバイダだとChatBotを管理出来ないため、awscc
プロバイダを使用します。
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.65.0"
}
awscc = {
source = "hashicorp/awscc"
version = "~> 0.54.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
default_tags {
tags = {
env = "test"
provision = "terraform"
}
}
}
provider "awscc" {
region = "ap-northeast-1"
}
Cloud Control API を利用する事で、作成、参照、変更、削除 基本的なリソース操作が共通で使えるようになるらしいです。
その操作をTerraform上でできるみたいです。
慣れていないため、今度改めて使ってみましょう。
EventBridge
EC2 Instance State-change Notification
イベントを飛ばすようにします。
resource "aws_cloudwatch_event_rule" "rule" {
name = "ec2-state-rule"
event_bus_name = "default"
tags = {
Name = "ec2-state-rule"
}
event_pattern = <<EOF
{
"source": ["aws.ec2"],
"detail-type": ["EC2 Instance State-change Notification"]
}
EOF
}
resource "aws_cloudwatch_event_target" "sns" {
rule = aws_cloudwatch_event_rule.rule.name
arn = aws_sns_topic.topic.arn
}
SNS
アクセスポリシーを適切に設定し、EventBridgeからアクセス出来るようにします。
今回はaws_sns_topic_subscription
でのサブスクリプションの作成は不要です。
resource "aws_sns_topic" "topic" {
name = "topic"
fifo_topic = false
}
resource "aws_sns_topic_policy" "policy" {
arn = aws_sns_topic.topic.arn
policy = data.aws_iam_policy_document.sns_topic_policy.json
}
data "aws_iam_policy_document" "sns_topic_policy" {
statement {
effect = "Allow"
actions = ["SNS:Publish"]
principals {
type = "Service"
identifiers = ["events.amazonaws.com"]
}
resources = [aws_sns_topic.topic.arn]
}
}
ChatBotとそのIAMロール
IAMロールにポリシーをアタッチしなくても動作しますね...
後日調べてみましょう
variable "slack_channel_id" {}
variable "slack_workspace_id" {}
resource "awscc_chatbot_slack_channel_configuration" "slack_channel" {
provider = awscc
configuration_name = "slack-test"
iam_role_arn = aws_iam_role.slack_role.arn
slack_channel_id = var.slack_channel_id
slack_workspace_id = var.slack_workspace_id
sns_topic_arns = [aws_sns_topic.topic.arn]
}
resource "aws_iam_role" "slack_role" {
name = "slack_role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = { Service = "chatbot.amazonaws.com" }
Action = "sts:AssumeRole"
}
]
})
}
ガードレールは?
今回はguardrail_policies
を設定しませんでした。
その場合、AdministratorAccess
が選択されました。
data
を使う場合)
ChatBot(既存チャネルをterraformで使用する場合はこちら
id
にはチャネルのArn
を入れればOKです
variable "slack_configration_id" {}
data "awscc_chatbot_slack_channel_configuration" "slack_channel" {
id = var.slack_configration_id
}
動作確認
EC2を起動します。
$ aws ec2 start-instances --instance-ids i-035df68f105b21780
通知が届けばOK
停止もしてみましょう。
$ aws ec2 stop-instances --instance-ids i-035df68f105b21780
しばらくまってSTOPPED
に遷移します。OKですね
おわりに
Slackに通知が飛ぶのは便利です。
IAMポリシー周りの理解が追いついていないため、これから固めていきます。
参考
ChatBotを使った通知
ガードレール
Discussion