Resources: # Set-up an S3 bucket to store the site WebsiteS3Bucket: Type: AWS::S3::Bucket Properties: AccessControl: BucketOwnerFullControl BucketName: ${self:custom.domain.domainname} PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true # Set-up a policy on the bucket so it can be used as a website WebsiteBucketPolicy: Type: AWS::S3::BucketPolicy Properties: PolicyDocument: Id: Fn::Join: - "" - - ${self:service.name} - BucketPolicy Statement: - Sid: CloudFrontForGetBucketObjects Effect: Allow Principal: CanonicalUser: Fn::GetAtt: - CloudFrontIdentity - S3CanonicalUserId Action: 's3:GetObject' Resource: Fn::Join: - '' - - 'arn:aws:s3:::' - Ref: WebsiteS3Bucket - /* Bucket: Ref: WebsiteS3Bucket # Configure CloudFront to get all content from S3 WebsiteCloudFrontDistribution: Type: 'AWS::CloudFront::Distribution' Properties: DistributionConfig: WebACLId: Ref: CustomAuthorizationHeaderRestriction Aliases: - ${self:custom.domain.domainname} - www.${self:custom.domain.domainname} CustomErrorResponses: - ErrorCode: '404' ResponsePagePath: "/error.html" ResponseCode: '200' ErrorCachingMinTTL: '30' DefaultCacheBehavior: Compress: true ForwardedValues: QueryString: false Cookies: Forward: all SmoothStreaming: false TargetOriginId: defaultOrigin ViewerProtocolPolicy: redirect-to-https DefaultRootObject: index.html Enabled: true Origins: - DomainName: Fn::GetAtt: - WebsiteS3Bucket - DomainName Id: defaultOrigin S3OriginConfig: OriginAccessIdentity: Fn::Join: - "/" - - origin-access-identity - cloudfront - Ref: CloudFrontIdentity PriceClass: PriceClass_All ViewerCertificate: AcmCertificateArn: ${self:custom.domain.sslCertificateARN} SslSupportMethod: sni-only # DNS Record for the domain WebsiteDNSRecord: Type: "AWS::Route53::RecordSet" Properties: AliasTarget: DNSName: Fn::GetAtt: - WebsiteCloudFrontDistribution - DomainName HostedZoneId: Z2FDTNDATAQYW2 HostedZoneName: ${self:custom.domain.domain}. Name: ${self:custom.domain.domainname} Type: 'A' # DNS Record for www.domain WebsiteWWWDNSRecord: Type: "AWS::Route53::RecordSet" Properties: AliasTarget: DNSName: Fn::GetAtt: - WebsiteCloudFrontDistribution - DomainName HostedZoneId: Z2FDTNDATAQYW2 HostedZoneName: ${self:custom.domain.domain}. Name: www.${self:custom.domain.domainname} Type: 'A' # Predicate to match the authorization header CustomAuthorizationHeader: Type: AWS::WAF::ByteMatchSet Properties: ByteMatchTuples: - FieldToMatch: Type: HEADER Data: Authorization TargetString: Fn::Join: - " " - - Custom - "**Password**" TextTransformation: NONE PositionalConstraint: EXACTLY Name: Fn::Join: - "_" - - ${self:custom.domain.domainname} - Authorization - Header CustomAuthorizationHeaderRule: Type: AWS::WAF::Rule Properties: Name: Fn::Join: - "_" - - ${self:custom.domain.domainname} - Authorization - Header - Rule MetricName: Fn::Join: - "" - - ${self:custom.stage} - ${self:service.name} - Authorization - Header - Rule Predicates: - DataId: Ref: CustomAuthorizationHeader Negated: false Type: ByteMatch CustomUserAgentHeader: Type: AWS::WAF::ByteMatchSet Properties: ByteMatchTuples: - FieldToMatch: Type: HEADER Data: User-Agent TargetString: Fn::Join: - " " - - ${self:custom.security.passwords.development} - "Tester" TextTransformation: NONE PositionalConstraint: EXACTLY Name: Fn::Join: - "_" - - ${self:custom.domain.domainname} - UserAgent - Header CustomUserAgentHeaderRule: Type: AWS::WAF::Rule Properties: Name: Fn::Join: - "_" - - ${self:custom.domain.domainname} - UserAgent - Header - Rule MetricName: Fn::Join: - "" - - ${self:custom.domain.domain} - ${self:custom.stage} - UserrAgent - Header - Rule Predicates: - DataId: Ref: CustomUserAgentHeader Negated: false Type: ByteMatch