Last active
October 24, 2021 14:19
-
-
Save reinhrst/6c10b2da47bda52d7ced4e87c0f00681 to your computer and use it in GitHub Desktop.
Cloudformation template for static website through S3 and CloudFront
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This stack accompanies an article on my blog: https://blog.claude.nl/tech/manual/create-a-static-https-site-on-aws-with-cloudformation/ | |
| AWSTemplateFormatVersion: 2010-09-09 | |
| Description: Creates an https website | |
| Metadata: {} | |
| Parameters: | |
| HostedZoneName: | |
| Description: The HostedZoneName of the zone that you want to host the website on. This has to be in the same account, and has to be active (i.e. used as the DNS server for this domain). | |
| Type: String | |
| HostedZoneId: | |
| Description: The ID for the HostedZoneName | |
| Type: String | |
| Hostname: | |
| Description: The hostname to host the website on (in the HostedZoneId). This should not exist yet within the HostedZoneId. | |
| Type: String | |
| AllowedPattern: ^[a-z0-9][a-z0-9-]*$ | |
| Default: www | |
| PriceClass: | |
| Type: String | |
| Description: The CloudFront distribution price class | |
| AllowedValues: | |
| - 'PriceClass_100' | |
| - 'PriceClass_200' | |
| - 'PriceClass_All' | |
| Mappings: {} | |
| Conditions: {} | |
| Resources: | |
| Certificate: | |
| Type: AWS::CertificateManager::Certificate | |
| Properties: | |
| DomainName: !Sub "${Hostname}.${HostedZoneName}" | |
| DomainValidationOptions: | |
| - DomainName: !Sub "${Hostname}.${HostedZoneName}" | |
| HostedZoneId: !Ref HostedZoneId | |
| ValidationMethod: DNS | |
| Bucket: | |
| Type: AWS::S3::Bucket | |
| DeletionPolicy: Retain | |
| Properties: | |
| AccessControl: Private | |
| BucketEncryption: | |
| ServerSideEncryptionConfiguration: | |
| - ServerSideEncryptionByDefault: | |
| SSEAlgorithm: AES256 | |
| BucketName: !Sub "${Hostname}.${HostedZoneName}" | |
| PublicAccessBlockConfiguration: | |
| BlockPublicAcls: true | |
| BlockPublicPolicy: true | |
| IgnorePublicAcls: true | |
| RestrictPublicBuckets: true | |
| VersioningConfiguration: | |
| Status: Enabled | |
| BucketPolicy: | |
| Type: AWS::S3::BucketPolicy | |
| Properties: | |
| Bucket: !Ref Bucket | |
| PolicyDocument: | |
| Statement: | |
| - Action: | |
| - s3:GetObject | |
| Effect: Allow | |
| Resource: !Sub "arn:aws:s3:::${Bucket}/website/*" | |
| Principal: | |
| CanonicalUser: !GetAtt CloudFrontOriginAccessIdentity.S3CanonicalUserId | |
| CloudFrontDistribution: | |
| Type: AWS::CloudFront::Distribution | |
| Properties: | |
| DistributionConfig: | |
| Aliases: | |
| - !Sub "${Hostname}.${HostedZoneName}" | |
| DefaultCacheBehavior: | |
| CachePolicyId: 4135ea2d-6df8-44a3-9df3-4b5a84be39ad # caching disabled | |
| Compress: true | |
| ForwardedValues: | |
| QueryString: false | |
| TargetOriginId: !Sub "S3-${Hostname}.${HostedZoneName}" | |
| ViewerProtocolPolicy: redirect-to-https | |
| DefaultRootObject: index.html | |
| CustomErrorResponses: | |
| - ErrorCachingMinTTL: 10 | |
| ErrorCode: 403 | |
| ResponseCode: 404 | |
| ResponsePagePath: /404.html | |
| - ErrorCachingMinTTL: 10 | |
| ErrorCode: 404 | |
| ResponseCode: 404 | |
| ResponsePagePath: /404.html | |
| Enabled: true | |
| HttpVersion: http2 | |
| Origins: | |
| - DomainName: !Sub "${Bucket}.s3.amazonaws.com" | |
| OriginPath: /website | |
| Id: !Sub "S3-${Hostname}.${HostedZoneName}" | |
| S3OriginConfig: | |
| OriginAccessIdentity: | |
| !Sub "origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}" | |
| Logging: | |
| Bucket: !Sub "${Bucket}.s3.amazonaws.com" | |
| IncludeCookies: False | |
| Prefix: cloudfront-logs/ | |
| PriceClass: !Ref PriceClass | |
| ViewerCertificate: | |
| AcmCertificateArn: !Ref Certificate | |
| MinimumProtocolVersion: TLSv1 | |
| SslSupportMethod: sni-only | |
| Tags: | |
| - Key: Domain | |
| Value: !Sub "${Hostname}.${HostedZoneName}" | |
| CloudFrontOriginAccessIdentity: | |
| Type: AWS::CloudFront::CloudFrontOriginAccessIdentity | |
| Properties: | |
| CloudFrontOriginAccessIdentityConfig: | |
| Comment: !Sub 'CloudFront OAI for ${Hostname}.${HostedZoneName}' | |
| DNSEntry: | |
| Type: AWS::Route53::RecordSet | |
| Properties: | |
| Name: !Sub "${Hostname}.${HostedZoneName}." | |
| Type: A | |
| AliasTarget: | |
| DNSName: !GetAtt CloudFrontDistribution.DomainName | |
| HostedZoneId: Z2FDTNDATAQYW2 # hardcoded CloudFront zone id | |
| HostedZoneName: !Sub "${HostedZoneName}." | |
| Outputs: | |
| {} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment