Cloudformation and Cloudfront

with tags AWS Cloudformation S3 -

Since as I’m having fun (for a given value of fun) with Cloudformation at the moment, I thought I’d give trying to setup a hosting for a static website using Cloudformation with the intention being to eventually wind up with everything being automated right down to SSL certificates.

However I’m currently a bit stumped as to how to import my SSL certificate from LetsEncrypt into Cloudfront automatically. but heres how to do the rest.

S3

First off we need somewhere to host the files, S3 is an ideal candidate for this

and whipping up a bucket in Cloudformation is simples

  "WebBucket": {
    "Type": "AWS::S3::Bucket",
    "Properties": {
      "BucketName": "myuniquebucketname"
    }
Note since as we’re going to stick Cloudfront on top of this S3 bucket we don’t need to worry about matching your bucket name to your domain name.

Cloudfront

So the below sets up a bare bones CloudFront property pointing at the S3 bucket

{
"CDN": {
  "Type": "AWS::CloudFront::Distribution",
  "Properties": {
    "DistributionConfig": {
      "Origins": [
        {
          "DomainName": {
            "Fn::GetAtt": [
              "WebBucket",
              "DomainName"
            ]
          },
          "Id": "WebBucket",
          "S3OriginConfig": {}
        }
      ],
      "Enabled": "true",
      "Aliases": [
        "foo.bar",
        "www.foo.bar"
      ],
      "DefaultCacheBehavior": {
        "TargetOriginId": "WebBucket",
        "ForwardedValues": {
          "QueryString": "false"
        },
        "ViewerProtocolPolicy": "allow-all"
      },
      "ViewerCertificate": {
        "IamCertificateId" : "ASCAIR75318008XXX",
        "SslSupportMethod": "sni-only"
        },
      "PriceClass": "PriceClass_100"
    }
  }
}
}
Origins determines where the property looks for the source files you’ll need to use the an address in the format BucketName.s3.amazonaws.com for any bucket outside of the template, the ID is used further down the template in the DefaultCacheBehavior section

Enabled should be fairly self explanitory

Aliases allows you to specify which domain names you wish to be associated with this property

DefaultCacheBehavior setup a basic set of behavior in this case I set the origin to the S3 bucket referenced earlier drop all query strings to improve the cache efficiency and allow access via both HTTP and HTTPS

ViewerCertificate sets your custom SSL certificate that you’ve already uploaded (ID can be found by running aws iam list-server-certificates) and we set sni-only to save some money but disables support for ye olde browsers

Allowing CloudFront access to S3

Unfortunatly we have to either cheat and use the aws console to setup “origin access identity” in Cloudfront or set the bucket to be publicly readable

}
  "WebBucket": {
    "Type": "AWS::S3::Bucket",
    "Properties": {
      "AccessControl" : "PublicRead",
      "BucketName": "myuniquebucketname",
      "WebsiteConfiguration" : {
        "IndexDocument" : "index.html",
        "ErrorDocument" : "error.html"
      }
    }
  }
}

Putting it all together

Sticking it all together and we should get a template that looks like

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "CMS-API cloudformation template",
  "Resources": {
    "WebBucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "AccessControl" : "PublicRead",
        "BucketName": "myuniquebucketname",
        "WebsiteConfiguration" : {
          "IndexDocument" : "index.html",
          "ErrorDocument" : "error.html"
        }
      },
      "DeletionPolicy" : "Retain"
    },
    "CDN": {
      "Type": "AWS::CloudFront::Distribution",
      "Properties": {
        "DistributionConfig": {
          "Origins": [
            {
              "DomainName": {
                "Fn::GetAtt": [
                  "WebBucket",
                  "DomainName"
                ]
              },
              "Id": "WebBucket",
              "S3OriginConfig": {}
            }
          ],
          "Enabled": "true",
          "Aliases": [
            "foo.bar",
            "www.foo.bar"
          ],
          "DefaultCacheBehavior": {
            "TargetOriginId": "WebBucket",
            "ForwardedValues": {
              "QueryString": "false"
            },
            "ViewerProtocolPolicy": "allow-all"
          },
          "ViewerCertificate": {
            "IamCertificateId" : "ASCAIR75318008XXX",
            "SslSupportMethod": "sni-only"
          },
          "PriceClass": "PriceClass_100"
        }
      }
    }
  }
}

Note

Aws certificate manager now exists for provisioning SSL certs for use on aws services.

Written by
Later article
Compiling Textual
Older article
SSL and Transmission