15

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
MLu
  • 23,798
  • 5
  • 54
  • 81
Ayushi Garg
  • 153
  • 1
  • 1
  • 4

2 Answers2

22

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}
Michael Hampton
  • 237,123
  • 42
  • 477
  • 940
Alan Ivey
  • 1,699
  • 12
  • 16
  • 1
    Weird that this is not a native type. Config files are very easily populated with the template's data. – Manatax Sep 04 '19 at 03:01
5

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.
030
  • 5,731
  • 12
  • 61
  • 107
MLu
  • 23,798
  • 5
  • 54
  • 81
  • 2
    See other answer, it's perfectly doable. Also one can define a Lambda function inside the template which can be executed and do whatever you want. Using custom resources anyhow. Also see https://aws.amazon.com/premiumsupport/knowledge-center/cloudformation-s3-custom-resources/ – scravy Nov 17 '20 at 04:22
  • I use custom lambda resource too for anything outside of CF capabilities. No dependency on any 3rd party this way. – Lukas Liesis Oct 03 '21 at 09:43