首页 > 解决方案 > sns 在使用 cloudformation 创建时无法触发 lambda

问题描述

我浏览了很多博客,但没有一个能解决我的问题。cloudformation 创建的 SNS 无法触发同一个 cloudformation 创建的 lambda,我在 lambda 中看到触发器为 sns 但它没有触发它,下面是代码。

尝试了所有建议的解决方案,例如在 lambda 权限中仅使用 SourceArn 而不是 SourceAccountId 和所有

LambdaBasicExecutionRole:
    Type: "AWS::IAM::Role"
    Properties:
      RoleName: "LambdaBasicExecutionRole"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          -
            Effect: "Allow"
            Principal:
              Service:
                - "lambda.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      Path: "/"
      Policies: 
        - 
          PolicyName: "LambdaPolicyEC2KeyPair"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              -
                Effect: "Allow"
                Action: 
                  - "kms:ListGrants"
                  - "kms:CreateGrant"
                  - "kms:Encrypt"
                  - "kms:Decrypt"
                Resource: "arn:aws:kms:*:*:*"
              - 
                Effect: "Allow"
                Action: 
                  - "logs:CreateLogGroup"
                  - "logs:CreateLogStream"
                  - "logs:PutLogEvents"
                Resource: "arn:aws:logs:*:*:*"
              - 
                Effect: "Allow"
                Action: "ec2:CreateKeyPair"
                Resource: "*"
              - 
                Effect: "Allow"
                Action: "ssm:PutParameter"
                Resource: "*"

  LambdaFunctionEC2KeyPair:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: LambdaFunctionEC2KeyPair
      Description: "Lambda Function to create EC2 KeyPair and storing it's private key securely to paramater store"
      Handler: index.handler
      Runtime: python3.6
      Role: !GetAtt LambdaBasicExecutionRole.Arn
      Code:
        ZipFile: |
          import boto3, os, botocore, cfnresponse

          client = boto3.client('ec2')
          ssm = boto3.client("ssm")

          def handler(event, context):
            ###############################
            # Variable Defination from CF #
            ###############################

            IIS = ['service', 'engine', 'micro']

            namespace = "IIS"
            keyid = os.environ['kmsid']
            env = os.environ['env']

            for iis_tier in IIS:
              keyname = 'IIS-EC2-KeyPair-'+iis_tier+'-'+env
              try:
                response = client.create_key_pair(
                  KeyName=keyname
                )

              except botocore.exceptions.ClientError as e:
                if e.response['Error']['Code'] == 'InvalidKeyPair':
                  print ("Invalid Key Pair Duplicate Error")
                  continue
                else:
                  continue

              try:
                ssm_response = ssm.put_parameter(
                  Name=f"/{namespace}/{env}/EC2-KeyPair/{iis_tier}",
                  Value=response['KeyMaterial'],
                  Type="SecureString",
                  KeyId=keyid,
                  Description='Private key for '+iis_tier+' '+env+' EC2 instance for ssh connection, one would need it for making ssh connection with the instance for administrative purposes'
                )
              except botocore.exceptions.ClientError as e:
                if e.response['Error']['Code'] == 'AccessDeniedException':
                  print ("Access Denied Error")
                  continue
                else:
                  continue
            cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, physicalResourceId )
            return



      Environment:
        Variables: 
          env: !Ref Environment
          kmsid: !Ref kmsKeyIIS
    DependsOn: LambdaBasicExecutionRole


  EC2KeyPair:
    Type: Custom::EC2KeyPairResource
    Properties:
      ServiceToken: !GetAtt LambdaFunctionEC2KeyPair.Arn

标签: pythonamazon-web-servicesaws-lambdaamazon-cloudformation

解决方案


您似乎希望在部署 CloudFormation 堆栈时触发 AWS Lambda 函数。

您可以使用AWS Lambda 支持的自定义资源来执行此操作。

模板应包括:

  • Lambda 函数
  • Custom::触发您的 Lambda 函数的条目

Lambda 函数在完成时需要返回信号。提供了一个cfn-response 模块来帮助解决这个问题。它适用于 Node.js 和 Python。

这是部署和运行自定义资源的基本 CloudFormation 模板:

AWSTemplateFormatVersion: 2010-09-09

Resources:

  LambdaBasicExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: MyLambdaRole
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          -
            Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

  LambdaFunctionTest:
    Type: AWS::Lambda::Function
    DependsOn: LambdaBasicExecutionRole
    Properties:
      FunctionName: LambdaFunctionTest
      Description: Lambda Function to test that Custom Resource works
      Handler: index.handler
      Runtime: python3.6
      Role: !GetAtt LambdaBasicExecutionRole.Arn
      Code:
        ZipFile: |
          import boto3
          import cfnresponse

          def handler(event, context):
            print('This is in the handler')

            responseData = {}
            cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData)
            return

  CustomFunctionTest:
    Type: Custom::CustomFunctionTest
    Properties:
      ServiceToken: !GetAtt LambdaFunctionTest.Arn

推荐阅读