[Terraform] AWS Lambdaを構築し、EventBridgeとSubscription Filterでトリガーする方法

## はじめに
AWS Lambda を Terraform で構築し、 EventBridge や CloudWatch Logs の Subscription Filter を使ってトリガーする方法について解説します。

・EventBridge を利用して Lambda を実行する 
　→ カスタムイベントをトリガーにする場合に適用

・Subscription Filter を利用して Lambda を実行する 
　→ CloudWatch Logs のログパターンを検知して実行する場合に適用

 それぞれの Terraform コードを交えながら解説していきます。

 ## 1. EventBridge から Lambda を起動する
 EventBridge のルールを作成し、指定したイベントが発生した際に Lambda をトリガーする構成を作成します。

 ### 構成の概要
・aws_lambda_function で Lambda 関数を作成
・aws_cloudwatch_event_rule でカスタムイベントのルールを定義
・aws_cloudwatch_event_target でルールと Lambda を紐付け
・aws_lambda_permission で EventBridge からの実行を許可

### Terraform コード
```terraform main.tf
provider "aws" {
  region = "us-east-1"
}

resource "aws_lambda_function" "eventbridge_lambda" {
  function_name = "eventbridge_lambda"
  handler       = "index.handler"
  runtime       = "python3.9"
  filename      = "lambda.zip"
  role          = aws_iam_role.lambda_exec.arn
}

resource "aws_cloudwatch_event_rule" "eventbridge_rule" {
  name        = "eventbridge_rule"
  description = "Trigger Lambda on custom event"
  event_pattern = jsonencode({
    source = ["custom.myapp"]
  })
}

resource "aws_cloudwatch_event_target" "lambda_target" {
  rule      = aws_cloudwatch_event_rule.eventbridge_rule.name
  arn       = aws_lambda_function.eventbridge_lambda.arn
}

resource "aws_lambda_permission" "allow_eventbridge" {
  statement_id  = "AllowExecutionFromEventBridge"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.eventbridge_lambda.function_name
  principal     = "events.amazonaws.com"
  source_arn    = aws_cloudwatch_event_rule.eventbridge_rule.arn
}
```
 principal     = "events.amazonaws.com"
 ⇅
 principal     = "logs.amazonaws.com"
 結構間違いやすいので、ご注意ください。
 Eventbridgeの場合は"events.amazonaws.com"です。

### IAM Role
```terraform role.tf
resource "aws_iam_role" "lambda_exec" {
  name = "lambda_exec_role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = {
        Service = "lambda.amazonaws.com"
      }
    }]
  })
}

resource "aws_iam_policy_attachment" "lambda_logs" {
  name       = "lambda_logs"
  roles      = [aws_iam_role.lambda_exec.name]
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
```
※ 必要に応じてポリシーを追加してください。

## 2. Subscription Filter から Lambda を起動する
CloudWatch Logs の特定のログパターンを検知し、Lambda をトリガーする構成を作成します。

### 構成の概要
・aws_lambda_function で Lambda 関数を作成
・aws_cloudwatch_log_group を作成（ログが出力されるグループ）
・aws_cloudwatch_log_subscription_filter でログフィルターを定義
・aws_lambda_permission で CloudWatch Logs からの実行を許可

### Terraform コード
```terraform main.tf
provider "aws" {
  region = "us-east-1"
}

resource "aws_lambda_function" "subscription_lambda" {
  function_name = "subscription_lambda"
  handler       = "index.handler"
  runtime       = "python3.9"
  filename      = "lambda.zip"
  role          = aws_iam_role.lambda_exec.arn
}

resource "aws_cloudwatch_log_group" "example_log_group" {
  name = "/aws/lambda/example_log_group"
}

resource "aws_cloudwatch_log_subscription_filter" "subscription_filter" {
  name            = "log_subscription_filter"
  log_group_name  = aws_cloudwatch_log_group.example_log_group.name
  filter_pattern  = ""
  destination_arn = aws_lambda_function.subscription_lambda.arn
}

resource "aws_lambda_permission" "allow_logs" {
  statement_id  = "AllowExecutionFromLogs"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.subscription_lambda.function_name
  principal     = "logs.amazonaws.com"
  source_arn    = aws_cloudwatch_log_group.example_log_group.arn
}
```
principal     = "logs.amazonaws.com"
 ⇅
principal     = "events.amazonaws.com"
結構間違いやすいので、ご注意ください。
Subscription Filterの場合は"logs.amazonaws.com"です。

### IAM Role
```terraform role.tf
resource "aws_iam_role" "lambda_exec" {
  name = "lambda_exec_role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = {
        Service = "lambda.amazonaws.com"
      }
    }]
  })
}

resource "aws_iam_policy_attachment" "lambda_logs" {
  name       = "lambda_logs"
  roles      = [aws_iam_role.lambda_exec.name]
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
```
※ 必要に応じてポリシーを追加してください。

## まとめ
本記事では、Terraform を使用して AWS Lambda を構築し、 EventBridge と CloudWatch Logs の Subscription Filter を用いてトリガーする方法を解説しました。
・EventBridge: カスタムイベントをトリガーに Lambda を実行
・Subscription Filter: CloudWatch Logs の特定パターンを検知して Lambda を実行
どちらの方法もユースケースによって使い分けることが重要です。お役に立てれば幸いです。