Select your cookie preferences

We use cookies and similar tools to enhance your experience, provide our services, deliver relevant advertising, and make improvements. Approved third parties also use these tools to help us deliver advertising and provide certain site features.

Lambda to S3 via a custom resource

Created with SnapCloudFormationAWS LambdaAmazon S3

Creates a Lambda function that writes to an S3 bucket during deployment.

This pattern creates an Amazon S3 object by using an AWS CloudFormation custom resource and an AWS Lambda function. Custom resources enable you to write custom provisioning logic in templates that CloudFormation runs anytime you create, update (if you changed the custom resource), or delete stacks.
This pattern deploys a Lambda function that is responsible for creating (and deleting) S3 objects. The function is given CRUD permissions on objects in the S3 bucket. When the stack is first created, CloudFormation sends a create request to the function. When the stack is deleted, CloudFormation sends a delete request to the function. The function ARN is stored as a CloudFormation Export named "function-s3-create".

AWSTemplateFormatVersion: 2010-09-09
Transform: 'AWS::Serverless-2016-10-31'
Description: A CloudFormation Custom Resource and a Lambda function to create an S3 object. (uksb-1tthgi812) (tag:cfn-custom-resource-s3-create)

# Global values that are applied to all applicable resources in this template
Globals:
  Function:
    CodeUri: ./src
    Runtime: nodejs20.x
    MemorySize: 128
    Timeout: 15

Parameters:
  ExistingS3Bucket:
    Description: Name of an existing S3 bucket, or leave blank to create a new S3 bucket.
    Type: String
    MaxLength: 63
    AllowedPattern: ^[a-z0-9.-]*$

Conditions: 
  CreateS3Bucket: !Equals [!Ref ExistingS3Bucket, ""]

Resources:
  # If an exsiting S3 bucket name was not provided a new S3 bucket will be created
  NewS3Bucket:
    Type: 'AWS::S3::Bucket'
    Condition: CreateS3Bucket
    Properties:
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

  # Lambda function to create an S3 object:
  #   This function would normally be deployed in a separate CloudFormation template.
  #   Then the function Arn would be referenced in other CloudFormation templates
  #   as a custom resource whenever an S3 object needs to be created.
  FunctionS3Create:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: app.handler
      Policies:
        - S3CrudPolicy:
            BucketName: !If [CreateS3Bucket, !Ref NewS3Bucket, !Ref ExistingS3Bucket]

  # Example use of a CloudFormation custom resource:
  #   This custom resource can be used in other CloudFormation templates after the function above is deployed.
  #   If the CloudFormation stack is deleted, the S3 object will also be deleted.
  #   More info: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cfn-customresource.html
  CustomResourceS3Create:
    Type: 'Custom::S3Create'
    Properties:
      # If this custom resource is used in another CloudFormation template: 
      #   Modify the ServiceToken property to retrieve the function Arn from CloudFormation Exports.
      #   For example:  ServiceToken: !ImportValue function-s3-create
      #   However for this example, the function Arn is retrieved from a resource within this template:
      ServiceToken: !GetAtt FunctionS3Create.Arn
      
      # Define the resource properties that the function requires to create the S3 object:
      #   The Body property defines the content of the S3 object.
      #   In this example, an html document named "index.html" is being created.
      #   The html document includes a variable value that equals the S3 bucket name.
      Bucket: !If [CreateS3Bucket, !Ref NewS3Bucket, !Ref ExistingS3Bucket]
      Key: index.html
      ContentType: text/html # application/json, text/css, text/html, text/plain
      Body: !Sub
        - | 
          
          
            Index
          
          
            This object was created by using a CloudFormation custom resource.
            The S3 bucket name is: ${varS3Bucket}
          
          
        - varS3Bucket: !If [CreateS3Bucket, !Ref NewS3Bucket, !Ref ExistingS3Bucket]

Outputs:
  S3BucketName:
    Description: Name of the S3 bucket
    Value: !If [CreateS3Bucket, !Ref NewS3Bucket, !Ref ExistingS3Bucket]
  FunctionS3CreateArn:
    Description: Arn of the Lambda function to create an S3 object
    Value: !GetAtt FunctionS3Create.Arn
    # The name used to reference the function Arn in CloudFormation Exports:
    Export:
      Name: function-s3-create
  ResponseObjectKey:
    Description: ObjectKey from Lambda function response
    Value: !GetAtt CustomResourceS3Create.ObjectKey

< Back to all patterns


GitHub icon Visit the GitHub repo for this pattern.

Launch Stack

Download

git clone https://github.com/aws-samples/serverless-patterns/ cd serverless-patterns/cfn-custom-resource-s3-create

Deploy

sam deploy --guided


Testing

See the GitHub repo for detailed testing notes.

Cleanup

1. Delete the stack: sam delete --stack-name STACK_NAME.
2. Confirm the stack has been deleted: aws cloudformation list-stacks --query "StackSummaries[?contains(StackName,'STACK_NAME')].StackStatus"

Greg Davis

Presented by Greg Davis

I am a Principal Solutions Architect, Serverless Developer, Database Engineer, and Data Integration Architect. I specialize in architecting and developing Serverless, event-driven solutions.

Follow on LinkedIn