How to upload a file into S3 bucket using CloudFormation script?

How do I upload a file into my AWS S3 bucket CloudFormation template?

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      AccessControl: PublicRead
      BucketName: s3bucketuser
      VersioningConfiguration:
        Status: Enabled

Solution 1:

You can't upload files through CloudFormation, that's not supported because CFN doesn't have access to your local filesystem.

What I usually do:

  • Call cloudformation task from Ansible
  • CFN creates the bucket and in the Outputs exports the bucket name
  • Ansible uploads the files using s3_sync in the next task once the CFN one is done.

Hope that helps :)

Solution 2:

AWS provides a sample Macro that may help, depending on your use case: https://github.com/awslabs/aws-cloudformation-templates/tree/a11722d/aws/services/CloudFormation/MacrosExamples/S3Objects.

  1. Create a separate CloudFormation stack with macro.template. This creates the Transform Macro "S3Objects" that will then be available to any other stack in the region. The README.md explains how to "package" the macro template prior to adding to CloudFormation (it will need to include a separate source file for a Lambda function).
  2. The file example.template provides sample usage. Note the top-level Transform section that refers to S3Objects, which allows the use of Type: AWS::S3::Object.

In the provided example, the Body property allows for entering text directly in the YAML or JSON template. To expand on that, one can use Fn::Sub to create a file with parameters or properties from other resources:

---
AWSTemplateFormatVersion: '2010-09-09'

Transform: S3Objects

Parameters:
  ANameField:
    Type: String

Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      AccessControl: PublicRead
      BucketName: s3bucketuser
      VersioningConfiguration:
        Status: Enabled

  S3Object:
    Type: AWS::S3::Object
    Properties:
      Target:
        Bucket: !Ref S3Bucket
        Key: README.md
        ContentType: text/markdown
      Body: !Sub |
        # My text file

        This is my text file for ${ANameField}.
        The region is ${AWS::Region} and my account ID is ${AWS::AccountId}.
        This file is in the ${S3Bucket} bucket. The bucket ARN is ${S3Bucket.Arn},
        and its website endpoint is ${S3Bucket.WebsiteURL}