Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

S3 Bucket Lambda notifications in Cloudformation for an Existing Bucket #1020

Open
vemulagopal opened this issue Jul 10, 2019 · 5 comments
Open

Comments

@vemulagopal
Copy link

vemulagopal commented Jul 10, 2019

I am trying to add an S3 event to Lambda for an existing bucket using Cloudformation, but it is not working and says "S3 events must reference an S3 bucket in the same template". I checked few blogs but looks like this functionality is not supported via cloud formation. Would you please take it as a feature enhancement to allow the pre-existing s3 bucket as a trigger to Lambda using the Cloudformation.

Here is the CF script

LAMBDSample:
    Type: "AWS::Serverless::Function"
    Properties:
      FunctionName: LambdaSAMPLE
      CodeUri: "../lambda/lambda_function_Sample"
      Handler: "lambda_function.lambda_handler"
      MemorySize: 1200
      Role:
        Fn::GetAtt:
          - "ROLELAMBDASAMPLE"
          - "Arn"
      Runtime: "python3.6"
      Timeout: 900
      Events:
        SampleFileUpload:
          Type: S3
          Properties:
            Bucket: !FindInMap
              - AccountMap
              - !Ref "AWS::AccountId"
              - Bucket
            Events: s3:ObjectCreated:*
            Filter:
              S3Key:
                Rules:
                  - Name: prefix
                    Value: sample_files/
                  - Name: suffix
                    Value: .xml
      VpcConfig:
        SubnetIds:
          - !FindInMap
            - AccountMap
            - !Ref "AWS::AccountId"
            - PrivateSubnetAZa
          - !FindInMap
            - AccountMap
            - !Ref "AWS::AccountId"
            - PrivateSubnetAZb
        SecurityGroupIds:
          - !Ref SGLAMBDASAMPLE
    DependsOn:
      - SGLAMBDASAMPLE
      - ROLELAMBDASAMPLE
@keetonian
Copy link
Contributor

This is similar to #124. I agree that this would be a nice feature; it would require either a change to how events work with the CFN S3 bucket resource, or using a custom resource to add the event to an existing resource.

@roelvandenbranddvc
Copy link

roelvandenbranddvc commented Aug 29, 2019

This seems familiar. We work with different stages of cloudformation in which buckets are created in a different CF than the Lambda functions.
We created a workaround with a Lambda to fix a notification from S3 to SQS. This works for Lambdas as well if you change the NotificationConfiguration (CloudFunctionConfiguration) in the BucketConfiguration resource.

BucketConfiguration:
  Type: Custom::S3BucketConfiguration
  DependsOn:
  - ImportEventLambdaPermissionSortEventSQS
  - NotificationBucketPolicy
  Properties:
    ServiceToken: !GetAtt S3BucketConfiguration.Arn
    Bucket: {"Fn::ImportValue" : {"Fn::Sub" : "a-bucket-name"}}
    NotificationConfiguration:
      QueueConfigurations:
      - Events: ['s3:ObjectCreated:*']
        QueueArn: {"Fn::ImportValue" : {"Fn::Sub" : "a-sqs-arn"}}


S3BucketConfiguration:
    Type: AWS::Lambda::Function
    Properties:
        Description: Event S3 SQS Linker
        Runtime: nodejs8.10
        MemorySize: 128
        Timeout: 30
        Role: !GetAtt LambdaExecutionRole.Arn
        Handler: index.handler
        Code:
          ZipFile: !Sub |
            var response = require('cfn-response');
            var AWS = require('aws-sdk');
            var s3 = new AWS.S3();
            exports.handler = function(event, context) {
              var respond = (e) => response.send(event, context, e ? response.FAILED : response.SUCCESS, e ? e : {});
              process.on('uncaughtException', e=>failed(e));
              var params = event.ResourceProperties;
              delete params.ServiceToken;
              if (event.RequestType === 'Delete') {
                params.NotificationConfiguration = {};
                s3.putBucketNotificationConfiguration(params).promise()
                  .then((data)=>respond())
                  .catch((e)=>respond());
              } else {
                s3.putBucketNotificationConfiguration(params).promise()
                  .then((data)=>respond())
                  .catch((e)=>respond(e));
              }
            };

@keetonian
Copy link
Contributor

@pam81
Copy link

pam81 commented Dec 11, 2020

+1

@roelvandenbranddvc
Copy link

roelvandenbranddvc commented Dec 11, 2020

I think i need to update the workaround in nodejs 10.x

the BucketConfiguration is still the same, updated the runtime and "cfn-response" is still supported.
(seem to have lost the indentation required for yml)

S3BucketConfiguration:
Type: AWS::Lambda::Function
Properties:
Description: PLI DGI Orchestrator S3 Event to SQS Linker Lambda
Runtime: nodejs10.x
MemorySize: 128
Timeout: 30
Role: !GetAtt MyRole.Arn
Handler: index.handler
Code:
ZipFile: !Sub |
var response = require('./cfn-response');
var AWS = require('aws-sdk');
var s3 = new AWS.S3();
exports.handler = function(event, context) {
var respond = (e) => response.send(event, context, e ? response.FAILED : response.SUCCESS, e ? e : {});
process.on('uncaughtException', e=>failed(e));
var params = event.ResourceProperties;
delete params.ServiceToken;
if (event.RequestType === 'Delete') {
params.NotificationConfiguration = {};
s3.putBucketNotificationConfiguration(params).promise()
.then((data)=>respond())
.catch((e)=>respond());
} else {
s3.putBucketNotificationConfiguration(params).promise()
.then((data)=>respond())
.catch((e)=>respond(e));
}
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants