web-dev-qa-db-ja.com

Terraform:CloudWatch Logサブスクリプション配信をラムダに設定しますか?

クラウドウォッチのログをログ分析サービスに出荷する必要があります。

私はこれらの記事 here および here を追って説明しましたが、手作業で問題なく動作しました。

今、私はこれをすべてTerraform(ロール/ポリシー、セキュリティグループ、クラウドウォッチロググループ、ラムダ、ロググループからラムダをトリガー)で自動化しようとしています。

ただし、TFを使用してAWSを構成し、cloudwatchログからラムダをトリガーする方法はわかりません。

2つのTFリソースを手動でリンクするには、次の手順を実行します(Lambda WebコンソールUIで):

  • ラムダ関数の「トリガー」セクションに入る
  • 「トリガーの追加」をクリックします
  • トリガータイプのリストから「cloudwatch logs」を選択します
  • ラムダをトリガーするロググループを選択します
  • フィルター名を入力してください
  • フィルターパターンを空のままにします(すべてのログストリームに対するトリガーを意味します)
  • 「トリガーを有効にする」が選択されていることを確認してください
  • 送信ボタンをクリックします

それが完了すると、ラムダはサブスクリプション列のクラウドウォッチログコンソールに表示されます-「Lambda(cloudwatch-sumologic-lambda)」として表示されます。

次のTFリソースを使用してサブスクリプションを作成しようとしました。

resource "aws_cloudwatch_log_subscription_filter" "cloudwatch-sumologic-lambda-subscription" {
  name            = "cloudwatch-sumologic-lambda-subscription"
  role_arn        = "${aws_iam_role.jordi-waf-cloudwatch-lambda-role.arn}"
  log_group_name  = "${aws_cloudwatch_log_group.jordi-waf-int-app-loggroup.name}"
  filter_pattern  = "logtype test"
  destination_arn = "${aws_lambda_function.cloudwatch-sumologic-lambda.arn}"
}

しかし、次のように失敗します。

aws_cloudwatch_log_subscription_filter.cloudwatch-sumologic-lambda-subscription:InvalidParameterException:ベンダーlambdaのdestinationArnはroleArnで使用できません

私は この回答 スケジュールされたイベントに同様のものを設定することについて見つけましたが、それは上記で説明したコンソールアクションが行うこととは異なるようです(コンソールUIメソッドは私が見ることができるイベント/ルール)。

誰かが私が間違っていることについてのポインタを教えてもらえますか?

22
Shorn

aws_cloudwatch_log_subscription_filterリソースが正しく定義されていません-この状況では、role_arn引数を指定しないでください。

また、aws_lambda_permissionリソースを追加する必要があります(フィルターにdepends_on関係が定義されているか、TFが間違った順序でそれを行う場合があります)。

AWSラムダコンソールUIはラムダアクセス許可を目に見えないように追加するので、コンソールUIで同じアクションを実行したことがある場合、aws_cloudwatch_log_subscription_filterはアクセス許可リソースなしで機能することに注意してください。

必要なTF設定は次のようになります(最後の2つのリソースは、実際のcloudwatch->lambdaトリガーの設定に関連するものです):

// intended for application logs (access logs, modsec, etc.)
resource "aws_cloudwatch_log_group" "test-app-loggroup" {
  name              = "test-app"
  retention_in_days = 90
}

resource "aws_security_group" "cloudwatch-sumologic-lambda-sg" {
  name = "cloudwatch-sumologic-lambda-sg"

  tags {
    Name = "cloudwatch-sumologic-lambda-sg"
  }

  description = "Security group for lambda to move logs from CWL to SumoLogic"
  vpc_id      = "${aws_vpc.dev-vpc.id}"
}

resource "aws_security_group_rule" "https-egress-cloudwatch-sumologic-to-internet" {
  type              = "egress"
  from_port         = 443
  to_port           = 443
  protocol          = "tcp"
  security_group_id = "${aws_security_group.cloudwatch-sumologic-lambda-sg.id}"
  cidr_blocks       = ["0.0.0.0/0"]
}

resource "aws_iam_role" "test-cloudwatch-lambda-role" {
  name = "test-cloudwatch-lambda-role"

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

resource "aws_iam_role_policy" "test-cloudwatch-lambda-policy" {
  name = "test-cloudwatch-lambda-policy"
  role = "${aws_iam_role.test-cloudwatch-lambda-role.id}"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "CopiedFromTemplateAWSLambdaVPCAccessExecutionRole1",
      "Effect": "Allow",
      "Action": [
        "ec2:CreateNetworkInterface"
      ],
      "Resource": "*"
    },
    {
      "Sid": "CopiedFromTemplateAWSLambdaVPCAccessExecutionRole2",
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeNetworkInterfaces",
        "ec2:DeleteNetworkInterface"
      ],
      "Resource": "arn:aws:ec2:ap-southeast-2:${var.dev_vpc_account_id}:network-interface/*"
    },

    {
      "Sid": "CopiedFromTemplateAWSLambdaBasicExecutionRole1",
      "Effect": "Allow",
      "Action": "logs:CreateLogGroup",
      "Resource": "arn:aws:logs:ap-southeast-2:${var.dev_vpc_account_id}:*"
    },
    {
      "Sid": "CopiedFromTemplateAWSLambdaBasicExecutionRole2",
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": [
    "arn:aws:logs:ap-southeast-2:${var.dev_vpc_account_id}:log-group:/aws/lambda/*"
      ]
    },

    {
      "Sid": "CopiedFromTemplateAWSLambdaAMIExecutionRole",
      "Effect": "Allow",
      "Action": [
         "ec2:DescribeImages"
      ],
      "Resource": "*"
    }


  ]
}
EOF
}

resource "aws_lambda_function" "cloudwatch-sumologic-lambda" {
  function_name    = "cloudwatch-sumologic-lambda"
  filename         = "${var.lambda_dir}/cloudwatchSumologicLambda.Zip"
  source_code_hash = "${base64sha256(file("${var.lambda_dir}/cloudwatchSumologicLambda.Zip"))}"
  handler          = "cloudwatchSumologic.handler"

  role        = "${aws_iam_role.test-cloudwatch-lambda-role.arn}"
  memory_size = "128"
  runtime     = "nodejs4.3"

  // set low because I'm concerned about cost-blowout in the case of mis-configuration
  timeout = "15"

  vpc_config = {
    subnet_ids         = ["${aws_subnet.dev-private-subnet.id}"]
    security_group_ids = ["${aws_security_group.cloudwatch-sumologic-lambda-sg.id}"]
  }
}

resource "aws_lambda_permission" "test-app-allow-cloudwatch" {
  statement_id  = "test-app-allow-cloudwatch"
  action        = "lambda:InvokeFunction"
  function_name = "${aws_lambda_function.cloudwatch-sumologic-lambda.arn}"
  principal     = "logs.ap-southeast-2.amazonaws.com"
  source_arn    = "${aws_cloudwatch_log_group.test-app-loggroup.arn}"
}

resource "aws_cloudwatch_log_subscription_filter" "test-app-cloudwatch-sumologic-lambda-subscription" {
  depends_on      = ["aws_lambda_permission.test-app-allow-cloudwatch"]
  name            = "cloudwatch-sumologic-lambda-subscription"
  log_group_name  = "${aws_cloudwatch_log_group.test-app-loggroup.name}"
  filter_pattern  = ""
  destination_arn = "${aws_lambda_function.cloudwatch-sumologic-lambda.arn}"
}

[〜#〜] edit [〜#〜]:上記のTFコードは数年前にバージョン0.11.xを使用して書かれていることに注意してください-それはまだ機能するはずですが、物事を行うより良い方法があるかもしれません。具体的には、必要な場合を除き、このようなインラインポリシーを使用せず、代わりに aws_iam_policy_document を使用します。これらは、時間の経過とともに維持するのがずっと簡単です。

41
Shorn