简体   繁体   中英

sns unable to trigger lambda when created using cloudformation

I have gone through many blogs but none of them solves my issue. SNS created by cloudformation is unable to trigger the lambda created by the same cloudformation, I see the trigger as sns in lambda but it didn't trigger it, below is the code.

Tried all solution suggested like using only SourceArn in lambda permission instead of SourceAccountId and all

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

It appears that you are wanting to trigger an AWS Lambda function when the CloudFormation stack deploys.

You can do this with an AWS Lambda-backed Custom Resource .

The template should include:

  • The Lambda function
  • A Custom:: entry to trigger your Lambda function

The Lambda function will need to signal back when it is complete. There is a cfn-response Module provided to assist with this. It is available for Node.js and Python.

Here is a basic CloudFormation template that deploys and runs a Custom Resource:

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

I have AWS::Serverless::Function and there's Events attribute in the its properties. If you had that, then your configuration would be something like this:

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: |
        My code


    Environment:
      Variables: 
        env: !Ref Environment
        kmsid: !Ref kmsKeyIIS
    Events:
      SNSTopicMessage:
        Type: SNS
        Properties:
          Topic:
            Fn::Join:
              - ':'
              - - arn
                - Ref: AWS::Partition
                - sns
                - Ref: AWS::Region
                - Ref: AWS::AccountId
                - SNSTopicLambdaInvoke
  DependsOn: LambdaBasicExecutionRole

I am checking about your use case having AWS::Lambda::Function .

You can check this example .

About the difference between a Serverless Function, and a Lambda Function you can check in this answer: What is the difference between a Serverless Function, and a Lambda Function

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM