AWSTemplateFormatVersion: 2010-09-09
Description: Cloudformation Template

Parameters:
  S3BucketParameter:
    Description: S3 Bucket
    Type: String

  AliasParameter:
    Description: CNAME (alternate domain names)
    Type: String
    Default: None

  AcmCertificateParameter:
    Description: ACM Certificate
    Type: String
    Default: None

Conditions:
  UseDefaultCertificate: !Equals [!Ref AcmCertificateParameter, None]
  UseAlias: !Not [!Equals [!Ref AliasParameter, None]]

Resources:
  CloudFrontOriginAccessIdentity:
    Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
    Properties:
      CloudFrontOriginAccessIdentityConfig:
        Comment: !Sub CloudFront origin access identity for ${S3BucketParameter}

  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Ref S3BucketParameter
      VersioningConfiguration:
        Status: Enabled
      WebsiteConfiguration:
        IndexDocument: index.html
        ErrorDocument: index.html

  S3BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref S3Bucket
      PolicyDocument:
        Statement:
          - Action:
              - s3:GetObject
            Effect: Allow
            Resource: !Sub arn:aws:s3:::${S3Bucket}/*
            Principal:
              CanonicalUser: !GetAtt CloudFrontOriginAccessIdentity.S3CanonicalUserId

  CloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Aliases:
          - !If [UseAlias, !Ref AliasParameter, !Ref "AWS::NoValue"]
        ViewerCertificate:
          AcmCertificateArn: !If [UseDefaultCertificate, !Ref "AWS::NoValue", !Ref AcmCertificateParameter]
          SslSupportMethod: !If [UseDefaultCertificate, !Ref "AWS::NoValue", sni-only]
          CloudFrontDefaultCertificate: !If [UseDefaultCertificate, true, !Ref "AWS::NoValue"]
        DefaultCacheBehavior:
          DefaultTTL: 300
          ForwardedValues:
            QueryString: true
          TargetOriginId: !Ref S3BucketParameter
          ViewerProtocolPolicy: redirect-to-https
        DefaultRootObject: index.html
        CustomErrorResponses:
          - ErrorCode: 403
            ResponseCode: 200
            ResponsePagePath: /
          - ErrorCode: 404
            ResponseCode: 200
            ResponsePagePath: /
        Enabled: true
        HttpVersion: http2
        Origins:
          - DomainName: !GetAtt S3Bucket.DomainName
            Id: !Ref S3BucketParameter
            S3OriginConfig:
              OriginAccessIdentity: !Sub origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}

Outputs:
  S3Bucket:
    Description:  S3 Bucket
    Value: !Ref S3BucketParameter

  S3BucketDomainName:
    Description:  S3 Bucket Url
    Value: !GetAtt S3Bucket.DomainName

  CloudFrontDistribution:
    Description:  CloudFront Distribtion Id
    Value: !Ref CloudFrontDistribution

  CloudFrontDomainName:
    Description:  CloudFront Distribtion Domain Name
    Value: !GetAtt CloudFrontDistribution.DomainName