【问题标题】:Lambda Function in AWS CloudFormationAWS CloudFormation 中的 Lambda 函数
【发布时间】:2017-10-14 01:12:43
【问题描述】:

能够在 Lambda 服务中成功创建 Lambda 函数。但它不会自动发送邮件。创建 Lambda 函数后,我手动单击测试。如何从 CloudFormation 执行此操作。

IAM 角色

"LambdaExecutionRole": {
"Type": "AWS::IAM::Role",
"Properties": {
    "AssumeRolePolicyDocument": {
        "Version": "2012-10-17",
        "Statement": [{ "Effect": "Allow", "Principal": {"Service": ["lambda.amazonaws.com"]}, "Action": ["sts:AssumeRole"] }]
    },          
    "Path": "/",
    "Policies": [{
        "PolicyName": "root",
        "PolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [{ "Effect": "Allow", "Action": ["ses:*"], "Resource": "*" }]
        }
    }]
} }

拉姆达函数

"SendEmailNotification" : {
  "Type": "AWS::Lambda::Function",
  "Properties": {
    "Handler": "index.handler",
    "Role": { "Fn::GetAtt" : ["LambdaExecutionRole", "Arn"] },
    "Code": {
      "ZipFile":  { "Fn::Join": ["", [
        "var response = require('cfn-response');\n",
        "var aws = require('aws-sdk');\n",
        "var ses = new aws.SES({\n",
        "region:'us-east-1'\n",
        "});\n",
        "exports.handler = function(event, context) {\n",
        "console.log('Incoming: ', event);\n",
        "var eParams = {\n",
        "Destination: {\n"  ,
        "ToAddresses: ['abc@example.com']\n",
        "},\n",
        "Message: {\n",
        "Body: {\n",
        "Text: {\n",
        {"Fn::Join" : ["",["Data: '", { "Fn::ImportValue" : "Route53DNSName" },"'\n"]]},
        "}\n",
        "},\n",
        "Subject: {\n",
        "Data: 'DNSName'\n",
        "}\n",
        "},\n",
        "Source: 'abc@example.com'\n",
        "};\n",
        "console.log('SENDING EMAIL');\n",
        "var email = ses.sendEmail(eParams, function(err, data){\n",
        "if(err) console.log(err);\n",
        "else {\n",
        "console.log('EMAIL SENT');\n",
        "console.log(data);\n",
        "console.log('EMAIL: ', email);\n",
        "context.succeed(event);\n",
        "}\n",
        "});\n",
        "};"
      ]]}
    },
    "Runtime": "nodejs6.10"
  }
}

【问题讨论】:

  • 无需过多查看代码,您希望何时调用 lambda 函数?您是否配置了触发器来调用该函数?
  • 如何获得 Route 53 DNS 的 SES 或 SNS 通知?

标签: node.js amazon-web-services aws-lambda amazon-cloudformation


【解决方案1】:

我了解到您希望发送 Lambda 函数以在您运行云形成模板时触发。

AWS::Lambda::Function 资源类型只创建 lambda 函数,它不执行它。如果您希望它与 cloudformation 一起运行,您需要一个自定义 Lambda 支持资源 (http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources-lambda.html)

这是一个在创建 cloudformation 时运行 lambda 的示例:

Resources:
  TestFunction:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: python2.7
      Handler: index.handler
      Role: !GetAtt TestRole.Arn
      Code:
        ZipFile: !Sub |
          from botocore.vendored import requests
          import json


          def send(event, context, responseStatus, responseData, physicalResourceId):
              responseUrl = event['ResponseURL']

              print responseUrl

              responseBody = {}
              responseBody['Status'] = responseStatus
              responseBody['Reason'] = 'See the details in CloudWatch Log Stream: ' + context.log_stream_name
              responseBody['PhysicalResourceId'] = physicalResourceId or context.log_stream_name
              responseBody['StackId'] = event['StackId']
              responseBody['RequestId'] = event['RequestId']
              responseBody['LogicalResourceId'] = event['LogicalResourceId']
              responseBody['Data'] = responseData

              json_responseBody = json.dumps(responseBody)

              print "Response body:\n" + json_responseBody

              headers = {
                  'content-type' : '',
                  'content-length' : str(len(json_responseBody))
              }

              try:
                  response = requests.put(responseUrl,
                                          data=json_responseBody,
                                          headers=headers)
                  print "Status code: " + response.reason
              except Exception as e:
                  print "send(..) failed executing requests.put(..): " + str(e)

          def handler(event, context):
              print event
              print context

              responseData = {}

              send(event, context, "SUCCESS", responseData, "CustomResourcePhysicalID")

  TestRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          -
            Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Policies:
        - PolicyName: AllowAccess
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - "logs:*"
                Resource: "arn:aws:logs:*:*:*"

  CustomResourceTest:
    Type: Custom::Demo
    Properties:
      ServiceToken: !GetAtt TestFunction.Arn

这只是运行函数,您可以在 CloudWatch 日志中看到。根据需要进行调整以发送电子邮件。

你必须注意几件事:

  • 只有在 CustomResource 更改时才会执行该函数。改变一个输入参数就可以了。在您的情况下,可能会将子网 ID 传递给自定义资源。
  • 另外,请考虑从 Cloudformation 发送电子邮件是否确实是一个好主意。在不确切了解您的用例的情况下很难说,但也许听 CloudTrail 中的配置更改会更好?还可以考虑向 SNS 发送通知,而不是直接发送电子邮件。

【讨论】:

  • 实际上我的目标是通过托管区域 DNS 获得通知。我正在使用 AWS CLI 创建堆栈(附加的托管区域应用程序负载均衡器)。因此,如果不检查 AWS 控制台,我应该会收到托管区域 DNS 名称的电子邮件通知。
  • 为什么创建自定义资源失败?
猜你喜欢
  • 2018-10-02
  • 2016-04-08
  • 2021-10-09
  • 2019-04-03
  • 2020-01-08
  • 2022-07-29
  • 1970-01-01
  • 2021-03-27
  • 1970-01-01
相关资源
最近更新 更多