9

I want to use Cloudformation to create an S3 bucket that will trigger Lambda function whenever an S3 event occurs such as file creation, file deletion, etc.

From my research, I have my AWS::Lambda::Function and AWS::S3::Bucket setup,

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  HandleFileCreation: 
    Type: "AWS::Lambda::Function"
    Properties: 
      ...

  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      ManagedPolicyArns:
      - arn:aws:iam::aws:policy/AmazonS3FullAccess
      - arn:aws:iam::aws:policy/AWSLambdaFullAccess
      AssumeRolePolicyDocument:
        ...

  ReportsBucket:
    Type: AWS::S3::Bucket

  BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref ReportsBucket
      PolicyDocument:
        ...

I was looking at the AWS::Events::Rule, but the example is only for EC2 and I can't find examples for S3

  EventRule: 
    Type: "AWS::Events::Rule"
    Properties: 
      Description: "EventRule"
      EventPattern: 
        source: 
          - "aws.ec2"
        detail-type: 
          - "EC2 Instance State-change Notification"
        detail: 
          state: 
            - "stopping"
      State: "ENABLED"
      Targets: 
        - 
          Arn: 
            Fn::GetAtt: 
              - HandleFileCreation
              - Arn
          Id: TargetFunctionV1
  PermissionForEventsToInvokeLambda: 
    Type: AWS::Lambda::Permission
    Properties: 
      FunctionName: 
        Ref: HandleFileCreation
      Action: "lambda:InvokeFunction"
      Principal: "events.amazonaws.com"
      SourceArn: 
        Fn::GetAtt: 
          - "EventRule"
          - "Arn"

How do I write the template to trigger on S3 events?

5 Answers 5

10

Here is an example covered,

http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-notificationconfig-lambdaconfig.html

EncryptionServiceBucket:
  Type: "AWS::S3::Bucket"
  Properties:
    BucketName: !Sub ${User}-encryption-service
    NotificationConfiguration:
      LambdaConfigurations:
        -
          Function: !Ref LambdaDeploymentArn
          Event: "s3:ObjectCreated:*"
          Filter:
            S3Key:
              Rules:
                -
                  Name: suffix
                  Value: zip

One issue I have noticed is, you need to create the function before you assign a trigger to it. If you are doing with CF, make sure you create lambda function before you create trigger for it.

Hope it helps.

Sign up to request clarification or add additional context in comments.

2 Comments

I am getting an error AWS::S3::Bucket ReportsBucket The ARN is not well formed Physical ID:some-prefix-us-west-2-test-43a8dcf which references my bucket name BucketName: !Join ['-', ['some-prefix', !Ref Region, !Ref Stage]]
This works, I just had to add a dependency or else you'll get an error. DependsOn: MyBucketPermission
2

I found the answer in one of the Visual Studio example projects with the Amazon Toolkit:

"myBucketName": {
    "Type": "AWS::S3::Bucket",
    "Properties": { }
},
"csvProcessor" : {
  "Type" : "AWS::Serverless::Function",
  "Properties": {
    "Handler": "appli::appli.csvProcessor::FunctionHandler",
    "Runtime": "dotnetcore2.1",
    "CodeUri": "",
    "Description": "Function processing files when they're dropped in s3 bucket",
    "MemorySize": 256,
    "Timeout": 30,
    "Role": null,
    "Policies": [ "AWSLambdaFullAccess" ],
    "Events": {
        "madeUpEventName" : {
            "Type" : "S3",
            "Properties" : {
                "Bucket" : { "Ref" : "myBucketName" },
                "Events" : [
                    "s3:ObjectCreated:*"
                ]
            }
        }
    }
  }
}

Comments

2

I have created the below code and it is working with CloudFormation ########################################################################### Trigger Lambda function whenever an S3 event

  Type: AWS::S3::Bucket
  Properties:
    BucketName: !Sub '${EnvironmentNameShorthand}.product'
    NotificationConfiguration:
      LambdaConfigurations:
      - 
        Function: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:function name'
        Event: "s3:ObjectCreated:*"
        Filter:
          S3Key:
            Rules:
            - 
              Name: suffix
              Value: .json

LambdaInvokePermission:
  Type: AWS::Lambda::Permission
  Properties:
    FunctionName: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:function name '
    Action: "lambda:InvokeFunction"
    Principal: "s3.amazonaws.com"
    SourceArn: !Sub 'arn:aws:s3:::${EnvironmentNameShorthand}.product'

1 Comment

Yes, it will do.. But It will trigger the lambda function on each and every object creation notification. If you want to trigger the lambda based on s3 key prefix or suffix filter, you need to follow the answer posted by Kanniyan in the above
1

Here is a detailed answer (from https://medium.com/@windix/s3-bucket-notification-to-lambda-in-cloudformation-without-circular-reference-f8f56ec5342c)

AWSTemplateFormatVersion: '2010-09-09'
Description: Example Stack

Parameters:
  BucketName:
    Type: String
    Default: unique-bucket-name

Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Ref BucketName
      ...
      NotificationConfiguration:
        LambdaConfigurations:
          - Event: 's3:ObjectCreated:*'
            Filter:
              S3Key:
                Rules:
                  - Name: prefix
                    Value: test/
                  - Name: suffix
                    Value: .txt
            Function: !GetAtt Lambda.Arn
  
  Lambda:
    Type: AWS::Lambda::Function
    ...

  S3InvokeLambdaPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !Ref Lambda
      Principal: s3.amazonaws.com
      SourceArn: !Sub arn:aws:s3:::${BucketName}

  LambdaRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal:
            Service: lambda.amazonaws.com
          Action:
          - sts:AssumeRole
      Path: '/'
      Policies:
      - PolicyName: s3
        PolicyDocument:
          Statement:
          - Effect: Allow
            Action:
              - s3:Get*
            Resource:
              - !Sub arn:aws:s3:::${BucketName}
              - !Sub arn:aws:s3:::${BucketName}/*

Comments

1

The stack.json file in the github location below, implements lambda triggering based on s3, codecommit events and much more. Please refer to the same. Hope this helps.

https://github.com/sudheendrantl/aws-cloudformation-stack

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.