May 20, 2020
Evolution of a S3 Bucket in CloudFormation
CloudFormation has changed a lot over the years. As new features and services become available, the way to define those resources in CloudFormation is expanded or sometimes changed.
In this blog, we’ll walk through setting up a S3 bucket with CloudFormation. We’ll start with a simple resource and work up to a more real-life example with support for versioning, encryption, and preventing any objects from becoming public.
Let’s get started with just about the simplest CloudFormation template we can write:
--- AWSTemplateFormatVersion: 2010-09-09 Resources: MyBucket: Type: AWS::S3::Bucket
Save this into a file (in my case I’ll use
s3-cfn-example.yaml) and then you can deploy it with the [aws cli](). I’m also going to use AWS Vault for managing my AWS profiles / credentials.
$ aws-vault exec oe-sandbox -- aws cloudformation deploy \ --no-fail-on-empty-changeset \ --template-file s3-cfn-example.yaml \ --stack-name s3-cfn-example-stack Waiting for changeset to be created.. Waiting for stack create/update to complete Successfully created/updated stack - s3-cfn-example-stack $
We can run this deploy command repeatedly (it is idempotent).
So after this initial deployment we can look in the console and we will see a CloudFormation stack with one resource - our bucket!
Note that CloudFormation generated a unique name for our bucket since we didn’t specify the
BucketName property. In general you shouldn’t explicitly specify a bucket name, because if you do then CloudFormation can’t perform updates that require replacement of this resource.
Let’s look at the basic features of our bucket:
Hmm - let’s enable versioning and default encryption - update your CloudFormation template to look like this:
--- AWSTemplateFormatVersion: 2010-09-09 Resources: MyBucket: Type: AWS::S3::Bucket Properties: BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: AES256 VersioningConfiguration: Status: Enabled
After we re-run our deploy command, we can check the properties of our bucket again and see that we now have versioning and default encryption enabled.
Let’s take a quick look at permissions. If we go back to the list of buckets, we see that our new bucket has been listed as ‘Objects can be public’…so while they aren’t public by default, they have the option of being public.
Update your template to match the below:
--- AWSTemplateFormatVersion: 2010-09-09 Resources: MyBucket: Type: AWS::S3::Bucket Properties: AccessControl: Private BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: AES256 PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true VersioningConfiguration: Status: Enabled
After we run our deploy command again, we see that our bucket access now says ‘Not Public’:
In this post, we started with the most basic representation of a CloudFormation resource possible (in our example a S3 bucket) and then progressively built out more features and functionality using CloudFormation. There are tons more we could do with this bucket, but I hope this simple example shows how you can build upon your resources with CloudFormation to iteratively create complex infrastructures.
Good luck & happy coding!