🎰

【Terraform】ECSスロットリング検知とSlackへの自動通知(AWS CloudWatchとChatbotの活用)〜実装修正〜

2024/04/18に公開

はじめに

本シリーズのご紹介

このシリーズでは、AWSとSlackを連携させる方法や、Terraformを用いた自動化技術の基本について詳しく解説します。前回の記事の内容を踏まえつつ、さらに実用的なスキルを身につけることができるよう、具体的な手順やコード例を交えて進めていきます。

https://zenn.dev/take_tech/articles/04707c6594e3fb

https://zenn.dev/take_tech/articles/5029460000a0ed

Slackの設定

Workspace IDとChannel IDの取得

以下をもとにWorkspace_id と channel_idを取得します。
https://slack.com/intl/ja-jp/help/articles/221769328-Slack-URL-または-ID-を確認する#フリー、プロ、ビジネスプラスプラン-2

workspace_idは、ウェブブラウザからSlackへログインすると、そのURLに表示されます。
「T」で始まる文字列が、参加中のworkspace_idに該当します。

Webhook URLの取得方法

以下の手順でWebhook URLを取得します。

  1. Slackにログインして、左サイドバーの下にある「アプリを追加する」をクリック
  2. Slack Appディレクトリページで、「Incoming Webhooks」を検索
  3. 「Incoming Webhooks」アプリを見つけたら、それをクリックして「アプリを追加」ボタンを選択
  4. Webhookを送信したいSlackチャンネルを選択
  5. 「Webhook URLの追加」ボタンをクリックして、生成されたWebhook URLをコピー

こちらを参考
https://media-radar.jp/contents/meditsubu/slack_incoming_webhook/

AWSの設定

ECSのクラスター名とサービス名の確認

スロットリングが発生するおそれのあるECSのクラスター名とサービス名を確認してTerraformに記載します。
▼クラスター名とサービス名とはどこのこと?

(画像引用)
https://dev.classmethod.jp/articles/ecs-console-v2-executes-create-service-by-cfn/

Terraformでのクラスター名とサービス名の追加

↑上記で取得したクラスター名とサービス名をcloudwatch_alarm.tfに追加します。

resource "aws_cloudwatch_metric_alarm" "ecs_throttling_alarm" {
  alarm_name          = "ecs-throttling-alarm-staging"
  (省略)
  alarm_description   = "ECSスロットリング発生時のアラーム"
  dimensions = {
    ClusterName = "************-stg"       # 追加
    ServiceName = "************-datadog"      # 追加
  }
}

IAMの設定

IAMロールのポリシー取得方法

以下の手順でAWSのIAM管理コンソールから取得します。

  1. AWSマネジメントコンソールにログイン
  2. 「サービス」から「IAM」を選択
  3. 左のナビゲーションバーから「ポリシー」をクリック
  4. 必要なポリシーを検索し、そのポリシーのARNを取得
  5. ポリシーをクリックすると、その詳細ページでARNを見ることができる

こちらを参考
https://docs.aws.amazon.com/ja_jp/kms/latest/developerguide/determining-access-iam-policies.html

IAMの基本と重要性

そもそもIAMとは何か?
なぜIAMが必要になるのか?
IAMポリシーとは何か?

こちらを参考
https://dev.classmethod.jp/articles/aws-iam-beginner/

IAMが必要な理由は、主にセキュリティとアクセス制御の強化のためです。1個のAWSアカウントを複数人で使い回すのではなく、複数のAWSアカウントを作成して個別のIAMユーザーを作成することが推奨されています。

IAMポリシーの効果的な管理

IAMポリシーを利用して、AWSサービスへのアクセス権を精密に管理します。具体的には、各AWSサービスに対して、閲覧のみ、編集、決済などの権限レベルを割り当て可能です。また、IAMロールに関する情報も詳細に説明しています。

CloudWatchFullAccessの非推奨化

https://dev.classmethod.jp/articles/aws-managed-policy-is-deprecating-cloudwatchfullaccess/


https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/auth-and-access-control-cw.html

上記の理由により、CloudWatchFullAccessV2へupdateしました

chatbot_slack_config.tf

managed_policy_arns = [
    "arn:aws:iam::aws:policy/CloudWatchFullAccessV2",
    "arn:aws:iam::aws:policy/AmazonSNSFullAccess"
  ]

Terraformでmanaged_policy_arns属性の設定を行うことで、自動的にポリシーがロールに割り当てられるそうです。つまり、AWSコンソールで手動でこれらのポリシーを設定する必要はなさそう。

Terrafromの修正

Chatbotの設定の見直し

主に3点、Chatbotの設定についてチームからフィードバックを頂きましたので共有です。

  1. SNSトピックの明確化
    chatbotがSNSから受け取るsns_topicを指定するために、sns_topic_arnsを指定する必要がある

  2. セキュリティの向上
    defaultではadmin権限になるので、guardrail_policiesでセキュリティを強化する

guardrail_policies = ["arn:aws:iam::aws:policy/ReadOnlyAccess"]
  1. 不要なIAMポリシーの削除
    IAM ロールの managed_policy_arns は不要とのこと。(CloudWatchFullAccessV2を設定しましたがすみません🙏)
  • AWS Chatbot が直接 CloudWatch と紐づいているわけではないため
  • また、Chatbot が SNS トピックをサブスクライブするために特定のIAMポリシーを必要としないため

上記3点を修正したコード

resource "awscc_chatbot_slack_channel_configuration" "ecs_throttling_alert_config" {
  configuration_name = "ecs-throttling-alert-config"
  iam_role_arn       = awscc_iam_role.ecs_throttling_alert_role.arn
  slack_channel_id   = "***********"
  slack_workspace_id = "***********"
  sns_topic_arns     = [aws_sns_topic.ecs_throttling_notifications.arn] # 修正
  guardrail_policies = ["arn:aws:iam::aws:policy/ReadOnlyAccess"] # 修正
}

resource "awscc_iam_role" "ecs_throttling_alert_role" {
  role_name = "ECS-Throttling-Alert-Role"
  assume_role_policy_document = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "chatbot.amazonaws.com"
        }
      },
    ]
  })
  managed_policy_arns = [] # 削除
}

実装していて迷った部分

sns_topic_arnsの書き方について、以下の2つで迷いました。


https://github.com/vinycoolguy2015/awslambda/blob/d2a2543c060634d38bd2ecd41dff05d36bba680c/terraform_slack_aws_chatbot.tf#L200


https://docs.aws.amazon.com/ja_jp/sns/latest/dg/sns-message-and-json-formats.html

結論

上記1番を選択しました。

理由

依存関係を考慮する必要があるためです。
上記2番のようにリソースのarnを直接書き込んでも動きますが、もしリソース名が変更された際に、依存関係を保てなくなるおそれがあるためです。また、sns_topic.tfにてsns topicをすでに作成しているため、そのリソースのarnを受け取れるように書いてあげればOKです。(画像青枠の部分)

これらの修正を通じて、依存関係を考慮したTerraformの設定が実現できました。

次回(セキュリティ面)

(すでにお気づきの方もいらっしゃると思いますが)次回の記事では、現在のセットアップにおける大きなセキュリティリスクに焦点を当てます。特に、SlackのWebhook URLやチャンネルIDなどがコードに直書きされており、これらのセキュリティリスクをどのように緩和するかについての具体的な手順と実践した方法を紹介します。セキュリティを強化するための詳細なガイドラインを提供し、より安全なインフラストラクチャの構築方法を学べる内容となる予定です。次回の更新もお楽しみに!

以上です。
今回もご精読いただきありがとうございました!

追記

前回までの記事とセキュリティ編の最新記事です!特にセキュリティ面は知っていて損はない内容になっていますので、ぜひご一読ください!

https://zenn.dev/take_tech/articles/04707c6594e3fb

https://zenn.dev/take_tech/articles/5029460000a0ed

https://zenn.dev/take_tech/articles/4f728035d166b1

Discussion