リソースグループタグ付けAPIで自分が作成したリソースのみを定期的にメール通知してみた

リソースグループタグ付けAPIで自分が作成したリソースのみを定期的にメール通知してみた

リソースグループタグ付けAPIで自分が作成したリソースのみをLambda関数で取得し、定期的にメールへ通知してみました
Clock Icon2024.10.01

はじめに

こんにちは、アノテーションのなかたです。
今回は、複数人にIAMロールが払い出されている検証アカウントでの環境において、自分のリソースのみを把握したいというのが背景になります。
リソースタグに自分の名前を付与し、Lambdaの定期実行でリソース情報をメール送信することで実現してみました。
今回の構成図はこちらになります。
image.png

背景

私のチームでは、検証アカウントでの環境において複数人にIAMロールが払い出されています。
つまり、他の人が作成したリソースが混在しています。
そのため、自分のリソースを把握するのが少し手間になっていました。

しかし、自分のリソースのみを把握する方法について、同期の岩橋さんが以下の運用方法を提案してくださいました。

  1. 作成したリソースに自分の名前が含まれたタグを付与する
  2. CLIで以下のコマンドを実行することで、サービスを横断的に検索し、指定されたタグのリソースを検出できる
bash
aws resourcegroupstaggingapi get-resources --tag-filters Key=Owner,Values=自分の名前

こちらのコマンドを実行すると、以下のようにJSON形式でリソース情報が出力されます。
image.png

JSON以外の出力形式について

以上のコマンドでは、大量のリソースが表示された際に見づらく、他の形式の方が見やすいと思います。
そのため、他の形式でどのように出力されるかいくつかご紹介したいと思います。
こちらも岩橋さんから情報を提供して頂きました。

--output table
テキストでテーブル表記に出力することができます。

-------------------------------------------------------------------------------------
|                                   GetResources                                    |
+-----------------------------------------------------------------------------------+
||                             ResourceTagMappingList                              ||
|+---------------------------------------------------------------------------------+|
||                                   ResourceARN                                   ||
|+---------------------------------------------------------------------------------+|
||  arn:aws:sns:ap-northeast-1:AWSアカウントID:aaaaaaaaaaaaaaaaaaaaaaaaaa             ||
|+---------------------------------------------------------------------------------+|
|||                                     Tags                                      |||
||+------------------------------------+------------------------------------------+||
|||                 Key                |                  Value                   |||
||+------------------------------------+------------------------------------------+||
|||  Owner                             |  自分の名前                                |||
||+------------------------------------+------------------------------------------+||

--output text
単純なテキスト形式の出力になります。

RESOURCETAGMAPPINGLIST  arn:aws:ec2:ap-northeast-1:AWSアカウントID:launch-template/lt-111aaa222bbb333cc
TAGS    Owner   自分の名前

--output yaml
yamlでの出力形式です。

ResourceTagMappingList:
- ResourceARN: arn:aws:sns:ap-northeast-1:AWSアカウントID:aaaaa
  Tags:
  - Key: Owner
    Value: 自分の名前

jqコマンドを使用した色付け
出力されたテキストに対して、jqコマンドを使用して色付けができるようです。
image.png

この運用方法により自分のリソースを把握できるだけでなく、今まで記憶に頼って行っていたリソース削除の負担が軽減されました!
従来では、リソース作成とともにサービス名を記憶して、検証が終わったタイミングでそれらを思い出して削除していました。
現在は、リソース作成時にタグを付与し、検証が終わったタイミングでCLIコマンドを実行するだけで、削除するべきリソースを把握することができます。
そのため、検証のみに脳のリソースを割くことができ、楽に検証を行えるようになりました!

今回は、こちらを定期実行することでリソース検出の自動化を行い、より楽できないかと考えて検証してみた記事になります。

やってみる

1. SNSトピックの作成

  1. SNSトピックを作成します
  2. 自分のメールアドレスをサブスクリプションに登録します
  3. 受信したメールからメールアドレスの認証を行います
  4. 作成したSNSトピックのARNをコピーします

2. Lambda関数の作成

  1. 以下のコードをデプロイします、こちらのスクリプトは、Claude 3.5 Sonnetを使用して作成しました。
lambda_function.py
import boto3
import json
import os
from datetime import datetime

# グローバル変数として設定情報を保持
OWNER_NAME = os.environ.get('OWNER_NAME')
SNS_TOPIC_ARN = os.environ.get('SNS_TOPIC_ARN')

def lambda_handler(event: dict, context: dict) -> dict:
    if not OWNER_NAME or not SNS_TOPIC_ARN:
        raise ValueError("OWNER_NAME and SNS_TOPIC_ARN must be set in environment variables")

    # 1. リソース情報の取得
    resources = get_tagged_resources(OWNER_NAME)

    # 2. メッセージの作成
    message = format_message(resources)

    # 3. SNSトピックにメッセージを送信
    send_sns_message(SNS_TOPIC_ARN, message)

    return {"statusCode": 200, "body": "メッセージが正常に送信されました"}

def get_tagged_resources(owner_name: str) -> list[dict]:
    client = boto3.client('resourcegroupstaggingapi')

    response = client.get_resources(
        TagFilters=[
            {
                'Key': 'Owner',
                'Values': [owner_name]
            }
        ]
    )

    return [
        {
            'name': resource.get('ResourceARN').split(':')[-1],
            'service': resource.get('ResourceARN').split(':')[2],
            'url': f"https://console.aws.amazon.com/resource-groups/resources/{resource.get('ResourceARN')}"
        }
        for resource in response.get('ResourceTagMappingList', [])
    ]

def format_message(resources: list[dict]) -> str:
    message = f"🚀 こんにちは、{OWNER_NAME}さん!\n\n"
    message += "現在、あなたが管理しているAWSリソースの最新情報をお届けします。\n"
    message += "タグ付けされたリソース一覧:\n\n"
    for resource in resources:
        message += f"サービス: {resource['service']}\n"
        message += f"名前: {resource['name']}\n"
        message += f"URL: {resource['url']}\n\n"
    return message

def send_sns_message(topic_arn: str, message: str) -> None:
    sns_client = boto3.client('sns')
    sns_client.publish(
        TopicArn=topic_arn,
        Message=message,
        Subject="あなたのAWSリソース管理レポート"
    )
  1. 環境変数を設定します
    OWNER_NAME: Ownerタグに付与している名前
    SNS_TOPIC_ARN: 先ほど作成したSNSトピックのARN
  2. Lambdaのロールに以下のポリシーを追加します
  • AWSResourceGroupsReadOnlyAccess
  • sns:Publishを許可するインラインポリシー
json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sns:Publish",
            "Resource": "arn:aws:sns:region:account-id:topic-name"
        }
    ]
}
  1. テストを実行し、メールの受信確認を行います

3. メールの確認

以下のようなメールを受信できました!
スクリーンショット 2024-09-27 19.52.25

4. EventBridgeスケジュールの作成

無事メールを受信できたため、Lambda関数を定期実行させます。
退勤時間の少し前くらいに通知するのが適切かなと考えたので、平日のみ毎日1回ずつ、17時ごろにスケジュールします。
image.png
次にcronでスケジュールを設定します。
スクリーンショット 2024-09-29 0.52.37.png
EventBridge Schedulerのcron式は少し癖があり、ハマりました。
公式ドキュメントを参照しながら作成するのがおすすめです。
https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-scheduled-rule-pattern.html#eb-cron-expressions
ターゲットAPIでAWS Lambda Invokeを選択します。
image.png
作成したLambda関数を指定します。

ペイロード

コードが引数に依存していないため、適当なJSONを指定します。

json
{
  "key1": "value1",
  "key2": "value2",
  "key3": "value3"
}

スクリーンショット 2024-10-01 17.50.49.png
オプションを設定します。
スクリーンショット 2024-09-29 0.59.01.png
スケジュール完了後のアクションDELETEを選択すると、最後の呼び出しが完了した際にスケジュールを削除することができます。
今回は、特にそのような要件はないのでNONEにしました。
また、必ず実行してほしいタスクではないので再試行ポリシーをオフにしました。

設定情報を確認し、スケジュールを作成ボタンを選択します。
スクリーンショット 2024-09-29 1.03.48.png
スケジュールが作成されました!
スクリーンショット 2024-09-29 1.05.13.png
こちらのスケジュールからLambda関数の実行も確認できました。
image.png

おわりに

EventBridge Schedulerについて、初めて使用しました。cron式の指定に苦労しましたが、Lambda関数の実行や様々なAWSサービスのAPI実行に対応していて、使いやすい印象がありました。
また、同期のかつまたさんが先日EventBridge Schedulerについて投稿されていたため、そちらもご覧ください。
https://dev.classmethod.jp/articles/EventBridge-Scheduler-ec2-ks/

参考

https://docs.aws.amazon.com/cli/latest/reference/resourcegroupstaggingapi/
https://dev.classmethod.jp/articles/resource-groups-tagging-api-launches-resourcearnlist-parameter-getresources-operation/
https://dev.classmethod.jp/articles/amazon-eventbridge-scheduler-new-way-to-launch-tasks/
https://dev.classmethod.jp/articles/notify-ec2-scheduled-events-from-lambda/

アノテーション株式会社について

アノテーション株式会社はクラスメソッドグループのオペレーション専門特化企業です。サポート・運用・開発保守・情シス・バックオフィスの専門チームが、最新 IT テクノロジー、高い技術力、蓄積されたノウハウをフル活用し、お客様の課題解決を行っています。当社は様々な職種でメンバーを募集しています。「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、アノテーション株式会社 採用サイトをぜひご覧ください。

この記事をシェアする

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.