Terraform:通知 SNS 的 CloudWatch 事件

Posted

技术标签:

【中文标题】Terraform:通知 SNS 的 CloudWatch 事件【英文标题】:Terraform: CloudWatch Event that notifies SNS 【发布时间】:2020-03-20 18:18:52 【问题描述】:

我正在学习 TF 并尝试应用一种基础架构来创建:

    一个简单的 lambda 函数 一个 SNS 主题 让该 lambda 订阅 SNS 主题 每隔一段时间向主题发布消息的 Cloud Watch 事件 一个 Cloud Watch 日志组,用于检查 lambda 是否由 SNS 通知 允许来自 SNS 的调用的 lambda 权限

我能够成功应用它。基础设施看起来非常好(当我通过可视化 aws 控制台自己创建它时,它具有相同的方面)

但不会触发云监视事件(从 TF 构建时),因此不会向 SNS 发布任何消息,也不会调用 lambda。不知道为什么

有谁知道我该怎么做?咆哮我的 .tf 脚本:

provider "aws" 
  region = "us-east-1"


//lambda function handler & code file
resource "aws_lambda_function" "lambda-function" 
  function_name = "Function01"
  handler = "com.rafael.lambda.Function01"
  role = "arn:aws:iam::12345:role/LambdaRoleTest"
  runtime = "java8"
  s3_bucket = aws_s3_bucket.sns-test.id
  s3_key = aws_s3_bucket_object.file_upload.id
  source_code_hash = filebase64sha256("../target/sns-cw-lambda-poc.jar")


//allow sns to call lambda
resource "aws_lambda_permission" "allow-sns-to-lambda" 
  function_name = aws_lambda_function.lambda-function.function_name
  action = "lambda:InvokeFunction"
  principal = "sns.amazonaws.com"
  source_arn = aws_sns_topic.call-lambdas-topic.arn
  statement_id = "AllowExecutionFromSNS"


//app s3 repository
resource "aws_s3_bucket" "sns-test" 
  bucket = "app-bucket-12345"
  region = "us-east-1"


//app jar file
resource "aws_s3_bucket_object" "file_upload" 
  depends_on = [
    aws_s3_bucket.sns-test
  ]
  bucket = aws_s3_bucket.sns-test.id
  key = "sns-cw-lambda-poc.jar"
  source = "../target/sns-cw-lambda-poc.jar"
  server_side_encryption = "AES256"
  etag = filebase64sha256("../target/sns-cw-lambda-poc.jar")


//to check lambda exec logs
resource "aws_cloudwatch_log_group" "lambda-cloudwatch-logs" 
  name = "/aws/lambda/$aws_lambda_function.lambda-function.function_name"
  retention_in_days = 1


//rule to trigger SNS
resource "aws_cloudwatch_event_rule" "publish-sns-rule" 
  name = "publish-sns-rule"
  schedule_expression = "rate(1 minute)"


//cloud watch event targets SNS
resource "aws_cloudwatch_event_target" "sns-publish" 
  count = "1"
  rule = aws_cloudwatch_event_rule.publish-sns-rule.name
  target_id = aws_sns_topic.call-lambdas-topic.name
  arn = aws_sns_topic.call-lambdas-topic.arn


//SNS topic to subscribe
resource "aws_sns_topic" "call-lambdas-topic" 
  name = "call-lambdas-topic"


//lambda subscribes the topic, so it should be nofied when other resource publishes to the topic
resource "aws_sns_topic_subscription" "sns-lambda-subscritption" 
  topic_arn = aws_sns_topic.call-lambdas-topic.arn
  protocol = "lambda"
  endpoint = aws_lambda_function.lambda-function.arn

【问题讨论】:

使用 AWS 控制台创建资源时是否触发了 cloudwatch 事件? 是的,当我使用 AWS 控制台构建相同的基础设施时,会触发 CloudWatch 事件。 Lambda 在指定的时间间隔由 SNS 通知。我可以通过查看云监视日志组来确保这一点。 【参考方案1】:

我想通了,我忘了添加允许 CloudWatch 发布到 SNS 主题的 SNS 策略。要使上述脚本正常工作,只需添加以下内容:

resource "aws_sns_topic_policy" "default" 
  count  = 1
  arn    = aws_sns_topic.call-lambdas-topic.arn
  policy = "$data.aws_iam_policy_document.sns_topic_policy.0.json"


data "aws_iam_policy_document" "sns_topic_policy" 
  count = "1"
  statement 
    sid       = "Allow CloudwatchEvents"
    actions   = ["sns:Publish"]
    resources = [aws_sns_topic.call-lambdas-topic.arn]

    principals 
      type        = "Service"
      identifiers = ["events.amazonaws.com"]
    
  

【讨论】:

以上是关于Terraform:通知 SNS 的 CloudWatch 事件的主要内容,如果未能解决你的问题,请参考以下文章

OpsGenie 不会在 AWS 仪表板或 terraform 中自动确认 SNS 订阅

如果禁用 SNS 端点,为啥 SNS 无法发送推送通知?

SNS 通知调度

AWS Eventbridge 通知无法使用 SNS 主题

sns 推送通知发布到单个设备

使用 SNS 发送推送通知 - Expo App