Gemcook Tech Blog
💫

Lambdaで複数のEventBridgeのステータスを一括変更する

2025/02/12に公開

はじめに

こんにちは!株式会社Gemcookのバックエンドエンジニアのshunです。

早速ですが今回は複数のEventBridgeのステータスを一括で変更してみます!

どのようなケースで活用できるのか?

例えばEventBridgeとAWS Batchでバッチ処理を作成[1][2]している場合など、DBのメンテナンス作業中などは一時的にデータ更新用のバッチ処理を停止させたい場面があるかと思います。今回紹介するのはそのような場面で、複数のEventBridgeのステータス(無効化/有効化)を一括で変更する方法です。

バッチ処理の本数自体が少なければAWSコンソール上で手動で変更しても問題ないと思いますが、バッチ処理の本数が10本~20本と増えるほど工数の削減、ヒューマンエラーの防止、手順書へ落とせるなど、自動化するメリットは大きいと思いますので是非参考になればと思います👍

対象読者

  • 複数のEventBridgeに対して、一括で設定変更する処理を検討している人

構成図

グレーで囲った範囲がこの記事のメインとなります。

EventBridgeの設定を一括で変更する機会は多くないため、Lambda関数を実行するだけのシンプルでわかりやすい構成にします。

前置き

【1】EventBridgeを作成する

まずはステータスを一括変更する対象のEventBridgeのルールを作成していきます。

ターゲットを用意

先にEventBridge用の簡単なターゲットを作成しておきます。今回はメールを送信するSNSトピックをtest_topicという名前で作成します。

入力
aws sns create-topic --name test_topic
出力
{
    "TopicArn": "arn:aws:sns:ap-northeast-1:[AWSアカウントID]:test_topic"
}

SNSトピックのARNに対してメールアドレスをサブスクライブします。

入力
aws sns subscribe \
--topic-arn arn:aws:sns:ap-northeast-1:[AWSアカウントID]:test_topic \
--protocol email \
--notification-endpoint [送信先のメールアドレス]
出力
{
    "SubscriptionArn": "pending confirmation"
}

メールが届くので承認します。

念のためSNSトピックを発行して実際にメールが届くか確認してみます。

入力
aws sns publish \
--topic-arn arn:aws:sns:ap-northeast-1:[AWSアカウントID]:test_topic \
--subject "test_topic mail" \
--message "Hello World!"
出力
{
    "MessageId": "21c748d4-e394-54e0-aa48-28d1af9a0060"
}

メールが届いていればOKです。

https://qiita.com/wktq/items/ea57e5eeba35139f3f8e

EventBridgeを作成

今回ステータスを一括変更する対象のEventBridge本体を作成します。test_event_publish_email__{A...C}という名前で複数個作成します

1. ルールを作成

検証用なのでcronの値は何でもOKです。

入力
aws events put-rule \
--name "test_event_publish_email__A" \
--schedule-expression "cron(0 9 * * ? *)"
出力
{
    "RuleArn": "arn:aws:events:ap-northeast-1:[AWSアカウントID]:rule/test_event_publish_email__A"
}

2. ターゲットを指定

  • 今回作成する3つのEventBridgeのルールにはそれぞれ、1つのターゲットしか設定しないので"Id"の値は全て1でOKです。
  • "Arn"には「ターゲットを用意する」セクションで出力されたSNSトピックのARNの値を指定します。
入力
aws events put-targets \
--rule "test_event_publish_email__A" \
--targets "Id"="1","Arn"="arn:aws:sns:ap-northeast-1:[AWSアカウントID]:test_topic"
出力
{
    "FailedEntryCount": 0,
    "FailedEntries": []
}

AWSコンソール上でも、ステータスが有効状態の3つのEventBridgeのルールが出来上がります。

https://docs.aws.amazon.com/ja_jp/cli/v1/userguide/cli_eventbridge_code_examples.html

【2】Lambda関数を作成する

最終的にこのLambda関数を実行することで、対象のEventBridgeのステータスを有効化もしくは無効化に変更することができます。

実行ロールを作成

Lambda関数の実行ロールを作成し、必要なポリシーをアタッチします。

ロール名
LambdaToSwitchEventBridgeActionRoleとします
入力
aws iam create-role \
--role-name LambdaToSwitchEventBridgeActionRole \
--assume-role-policy-document '{"Version": "2012-10-17","Statement": [{ "Effect": "Allow", "Principal": {"Service": "lambda.amazonaws.com"}, "Action": "sts:AssumeRole"}]}'
出力はこちら
出力
{
    "Role": {
        "Path": "/",
        "RoleName": "LambdaToSwitchEventBridgeActionRole",
        "RoleId": "AROAZKDICZDC5L44XUVKF",
        "Arn": "arn:aws:iam::[AWSアカウントID]:role/LambdaToSwitchEventBridgeActionRole",
        "CreateDate": "2025-01-18T08:55:28+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "lambda.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        }
    }
}

ポリシーを2つアタッチします。

ポリシー名 説明
AWSLambdaBasicExecutionRole 主にCloudWatch Logsへの書き込み権限を提供[3]
AmazonEventBridgeFullAccess Amazon EventBridge へのフルアクセス権を提供[4]
(今回は検証用なのでフルアクセス)
入力
aws iam attach-role-policy \
--role-name LambdaToSwitchEventBridgeActionRole \ 
--policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
入力
aws iam attach-role-policy \
--role-name LambdaToSwitchEventBridgeActionRole \
--policy-arn "arn:aws:iam::aws:policy/AmazonEventBridgeFullAccess"

AWSコンソール上で、LambdaToSwitchEventBridgeActionRoleが出来上がります。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-intro-execution-role.html

デプロイコードを作成

ローカルでLambda関数のファイルを作成します。

今回はLambda関数の作成やコードのデプロイをAWS CLIで行うため、作成したLambda関数のファイルはzip化しておきます。

ローカルでデプロイコードを作成し、zip化

以下2ファイルを作成します。

  • target_eventbridge_rules.txt
  • lambda_main.py
Lambda関数の概要説明はこちら

lambda_handlerが実行され、以下の流れで処理が進みます。

  1. load_rules関数が実行され引数のtxtファイルからEventBridgeのルール名をリストで返す
  2. Lambda関数実行時のペイロード(引数)のactionの値(enabledisable)に応じてEventBridgeのステータスを有効化もしくは無効化に変更する
  3. EventBridgeのルール名ごとに「成功」「存在しないルール」「失敗」の3パターンのメッセージをjson形式でレスポンス
target_eventbridge_rules.txt
test_event_publish_email__A
test_event_publish_email__B
test_event_publish_email__C
lambda_main.py
# 【目的】
# EventBridgeのルールのステータスを一括変更する。(有効化/無効化)
#
# 【使い方】
# 1. 更新対象のEventBridgeのルールをtarget_eventbridge_rules.txtファイルに記載する。
# 2. Lambda関数を実行する。
#
# target_eventbridge_rules.txtの例
# test_event_publish_email__A
# test_event_publish_email__B
# test_event_publish_email__C

import boto3
import logging

# ログの設定
def setup_logger():
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    return logger

# EventBridgeクライアントの設定
def create_eventbridge_client():
    return boto3.client('events')

# 更新対象のEventBridgeのルール名リストを取得
def load_rules(file_path):
    try:
        with open(file_path, 'r') as f:
            rule_names = [line.strip() for line in f if line.strip()]
        return rule_names
    except Exception as e:
        logger.error(f"Failed to load rules from {file_path}: {e}")
        return []

def lambda_handler(event, context):
    logger = setup_logger()
    eventbridge_client = create_eventbridge_client()

    logger.info("Lambda function started.")

    action = event.get("action")

    if not action:
        return {
            "statusCode": 400,
            "body": "Missing 'action' parameter. Use 'enable' or 'disable'."
        }

    if action not in ["enable", "disable"]:
        return {
            "statusCode": 400,
            "body": f"Invalid action: {action}. Use 'enable' or 'disable'."
        }

    rule_list = load_rules('target_eventbridge_rules.txt')
    update_rule_method = eventbridge_client.enable_rule if action == "enable" else eventbridge_client.disable_rule

    results = {}
    for rule in rule_list:
        try:
            update_rule_method(Name=rule)
            results[rule] = f"Successfully {action}d."
        except eventbridge_client.exceptions.ResourceNotFoundException:
            logger.warning(f"Rule not found: {rule}")
            results[rule] = "Rule not found."
        except Exception as e:
            logger.error(f"Failed to {action} {rule}: {e}")
            results[rule] = f"Failed to {action}: {e}"

    response = {
        "statusCode": 200,
        "body": results
    }

    logger.info(f"Response: {response}")
    logger.info("Lambda function completed.")

    return response

zip化します。

入力
zip -r lambda_function.zip lambda_main.py target_eventbridge_rules.txt
ls | grep lambda_function
出力
lambda_function.zip

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/python-package.html#python-package-create-update

デプロイ

先に、先程作成したLambda関数の実行ロールのARNを確認します。

入力
aws iam get-role --role-name LambdaToSwitchEventBridgeActionRole --query "Role.Arn"
出力
"arn:aws:iam::[AWSアカウントID]:role/LambdaToSwitchEventBridgeActionRole"

Lambda関数をデプロイします。

入力
aws lambda create-function \
--function-name switch-eventbridge-action-function \
--runtime python3.13 \
--role "arn:aws:iam::[AWSアカウントID]:role/LambdaToSwitchEventBridgeActionRole" \
--handler lambda_main.lambda_handler \
--zip-file fileb://lambda_function.zip
出力はこちら
出力
{
    "FunctionName": "switch-eventbridge-action-function",
    "FunctionArn": "arn:aws:lambda:ap-northeast-1:[AWSアカウントID]:function:switch-eventbridge-action-function",
    "Runtime": "python3.13",
    "Role": "arn:aws:iam::[AWSアカウントID]:role/LambdaToSwitchEventBridgeActionRole",
    "Handler": "lambda_main.lambda_handler",
    "CodeSize": 1652,
    "Description": "",
    "Timeout": 3,
    "MemorySize": 128,
    "LastModified": "2025-01-18T10:10:47.277+0000",
    "CodeSha256": "xuwaW9yk0oFauVJDl7nFOtI+sH0OSH6rlAODBjGGUmE=",
    "Version": "$LATEST",
    "TracingConfig": {
        "Mode": "PassThrough"
    },
    "RevisionId": "98a7eec5-9a76-4812-8dcd-19015f3406a0",
    "State": "Pending",
    "StateReason": "The function is being created.",
    "StateReasonCode": "Creating",
    "PackageType": "Zip",
    "Architectures": [
        "x86_64"
    ],
    "EphemeralStorage": {
        "Size": 512
    },
    "SnapStart": {
        "ApplyOn": "None",
        "OptimizationStatus": "Off"
    },
    "RuntimeVersionConfig": {
        "RuntimeVersionArn": "arn:aws:lambda:ap-northeast-1::runtime:b881cbc9a10a8bcb3def9d9e9fe38f922bb36510a1d92d4ce85cf2a899eeabd8"
    },
    "LoggingConfig": {
        "LogFormat": "Text",
        "LogGroup": "/aws/lambda/switch-eventbridge-action-function"
    }
}

AWSコンソール上に、Lambda関数が出来上がります。

【3】Lambda関数を実行しEventBridgeのステータスを変更する

Lambda関数を実行

aws lambda invokeコマンドでLambda関数を実行し、EventBridgeのステータスを切り替えます。今回は{ "action": "disable" }を指定し、EventBridgeのステータスを無効化してみます。

入力
aws lambda invoke \
--function-name switch-eventbridge-action-function \
--cli-binary-format raw-in-base64-out \
--payload '{ "action": "disable" }' \
response.json
オプション 説明
--cli-binary-format ペイロード(引数)をエンコード (AWS CLI v2の場合は必須[5])
--payload enabledisableを指定する
response.json レスポンス結果のファイル名
出力
{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}

https://docs.aws.amazon.com/ja_jp/cli/v1/userguide/cli_lambda_code_examples.html

https://docs.aws.amazon.com/cli/latest/reference/lambda/invoke.html

レスポンス結果を確認

response.jsonの中身を確認します。

入力
cat response.json
出力
{"statusCode": 200, "body": {"test_event_publish_email__A": "Successfully disabled.", "test_event_publish_email__B": "Successfully disabled.", "test_event_publish_email__C": "Successfully disabled."}}%

無事target_eventbridge_rules.txtで指定したEventBridgeのステータスが無効化されました!成功です!!

レスポンス結果を見やすくする

response.json見やすくフォーマットするため、ローカルPCや踏み台サーバなどで実行する場合はjqコマンド[6]をインストールしておくことをお勧めします。

jqコマンドをインストールした上で、先ほどのaws lambda invokeコマンドに&&で続けてresponse.jsonを出力してみます。

OS installコマンド
macOS brew install jq
Linux(Ubuntu) sudo apt-get install jq
入力
aws lambda invoke \
--function-name switch-eventbridge-action-function \
--cli-binary-format raw-in-base64-out \
--payload '{ "action": "disable" }' \
response.json && cat response.json | jq
出力
{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}
{
  "statusCode": 200,
  "body": {
    "test_event_publish_email__A": "Successfully disabled.",
    "test_event_publish_email__B": "Successfully disabled.",
    "test_event_publish_email__C": "Successfully disabled."
  }
}

非常に見やすくなりました🎉!

指定のEventBridgeのルールが存在しない場合は..?

仮にtest_event_publish_email__Dという存在しないEventBridgeのルールが指定された場合は以下のような出力になります。

出力
{
  "statusCode": 200,
  "body": {
    "test_event_publish_email__A": "Successfully disabled.",
    "test_event_publish_email__B": "Successfully disabled.",
    "test_event_publish_email__C": "Successfully disabled.",
    "test_event_publish_email__D": "Rule not found."
  }

処理が中断されることなく、メッセージでわかるようになっています。

運用例

ささっとEventBridgeのステータスを変更したい

仮に実行回数も年に数回だけかつ対象のEventBridgeの数も膨大でない場合はAWSコンソールのLambdaのコードエディタ上で「target_eventbridge_rules.txtの中身を変更」 & 「Lambda関数を実行」すると非常にシンプルでコンパクトですね。

(lambda関数の処理内ではtarget_eventbridge_rules.txtは引数のようなファイルなため、状況に応じて対象のEventBridgeを変更できるように空ファイルでデプロイしといも良いかもですね。)

Lanbdaのコードエディタ上で実行する手順

  1. target_eventbridge_rules.txtの中身を変更し、Deployボタンを押下

  1. Testボタンからテストを作成し、invokeボタンを押下して実行

実行結果もコードエディタのプロンプトで確認できます。

まとめ

今回は自動化に関するテーマでした。プロジェクトコード上での自動化といえば「Makeコマンドやシェルスクリプトを手動で実行する」という工程で対応することも多いと思いますが、AWSリソースの設定変更に関してもそれと近い感じで「Lambda関数を手動で実行する」というちょうど良い手軽さで構成できたのは保守面でもコストが低いためメリットに感じました!

脚注
  1. EventBridge ターゲットとしての AWS Batch ジョブ ↩︎

  2. チュートリアル: スケジュールされた AWS Batch ジョブを作成する ↩︎

  3. AWSLambdaBasicExecutionRole ↩︎

  4. AmazonEventBridgeFullAccess ↩︎

  5. AWS Lambda関数の呼び出しがAWS CLI v2にアップデートすると失敗する ↩︎

  6. jqコマンド ↩︎

Gemcook Tech Blog
Gemcook Tech Blog

Discussion