AWSTemplateFormatVersion: '2010-09-09' Description: > Script to create S3 bucket, DNS (Route53) and Cloudfront distribution. ############################################################################### Parameters: ############################################################################### DomainName: Type: String Description: The domain name. Default: 'ordbok.aws.uib.no' AllowedPattern: (?!-)[a-zA-Z0-9-.]{1,63}(?<!-) ConstraintDescription: must be a valid DNS zone name DomainPrefix: Type: String Default: beta PriceClass: Type: String Description: The CloudFront distribution price class Default: 'PriceClass_100' AllowedValues: - 'PriceClass_100' #- 'PriceClass_200' #- 'PriceClass_All' SecretArn: Type: String CertificateArn: Type: String Default: '' Conditions: UseDomain: !Not [!Or [!Equals [!Ref DomainName, ''], !Equals [!Ref CertificateArn, '']]] ############################################################################### Resources: ############################################################################### DNS: Type: "AWS::Route53::RecordSet" Condition: UseDomain Properties: HostedZoneConfig: Comment: !Join ['', ['Hosted zone for ', !Ref 'DomainName']] HostedZoneName: !Join ['.', [!Ref DomainName, '']] Name: !Join ['.', [!Ref DomainPrefix, !Ref DomainName, '']] Type: A AliasTarget: HostedZoneId: xxxxxxxxxxx DNSName: !GetAtt Distribution.DomainName HostedZoneTags: - Key: Application Value: beta.ordbok.uib.no WebBucket: Type: "AWS::S3::Bucket" Properties: BucketName: !Sub "${AWS::StackName}.aws.uib.no" VersioningConfiguration: Status: Enabled AccessControl: !If - UseDomain - !Ref "AWS::NoValue" - "PublicRead" WebsiteConfiguration: !If - UseDomain - !Ref "AWS::NoValue" - IndexDocument: index.html Tags: - Key: Application Value: !Ref DomainName BucketPolicy: Type: "AWS::S3::BucketPolicy" Properties: PolicyDocument: Id: MyPolicy Version: 2012-10-17 Statement: - Sid: PublicReadForGetBucketObjects Effect: Allow Principal: !If - UseDomain - CanonicalUser: !GetAtt CloudFrontOriginIdentity.S3CanonicalUserId - "*" Action: !If - UseDomain - 's3:*' - 's3:GetObject' Resource: !Join - '' - - 'arn:aws:s3:::' - !Ref WebBucket - /* Bucket: !Ref WebBucket ItaIpSet: Type: "AWS::WAF::IPSet" Condition: UseDomain Properties: IPSetDescriptors: - Type: "IPV4" Value: "129.177.0.0/16" Name: "allowed IPs" ITARule: Type: "AWS::WAF::Rule" Condition: UseDomain Properties: MetricName: "ITARule" Name: "ITARule" Predicates: - Type: "IPMatch" Negated: false DataId: !Ref ItaIpSet ACL: Type: "AWS::WAF::WebACL" Condition: UseDomain Properties: DefaultAction: Type: "BLOCK" Name: "intern ITA" MetricName: "WebACL" Rules: - Action: Type: "ALLOW" Priority: 1 RuleId: !Ref ITARule Distribution: Type: "AWS::CloudFront::Distribution" Condition: UseDomain Properties: DistributionConfig: Enabled: true HttpVersion: http2 PriceClass: !Ref PriceClass Enabled: 'true' DefaultRootObject: index.html Origins: - DomainName: !Sub "${WebBucket}.s3-${AWS::Region}.amazonaws.com" Id: s3ProductionBucket S3OriginConfig: OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${CloudFrontOriginIdentity}" Aliases: - !Join ['.', [!Ref DomainPrefix, !Ref DomainName]] CustomErrorResponses: - ErrorCachingMinTTL: 300 ErrorCode: 403 ResponseCode: 200 ResponsePagePath: /index.html - ErrorCachingMinTTL: 300 ErrorCode: 404 ResponseCode: 200 ResponsePagePath: /index.html DefaultCacheBehavior: AllowedMethods: - GET - HEAD Compress: true TargetOriginId: s3ProductionBucket ForwardedValues: QueryString: 'false' Cookies: Forward: none ViewerProtocolPolicy: redirect-to-https ViewerCertificate: AcmCertificateArn: !Ref CertificateArn MinimumProtocolVersion: TLSv1.1_2016 SslSupportMethod: sni-only WebACLId: !If - UseDomain - !Ref ACL - !Ref "AWS::NoValue" CloudFrontOriginIdentity: Type: "AWS::CloudFront::CloudFrontOriginAccessIdentity" Properties: CloudFrontOriginAccessIdentityConfig: Comment: "origin identity" XRayPolicy: Type: 'AWS::IAM::ManagedPolicy' Properties: ManagedPolicyName: !Sub "${AWS::StackName}-XRayPolicy" PolicyDocument: Version: 2012-10-17 Statement: - Action: - 'xray:PutTelemetryRecords' - 'xray:PutTraceSegments' Effect: Allow Resource: '*' S3LambdaRole: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: - "lambda.amazonaws.com" Action: - "sts:AssumeRole" ManagedPolicyArns: - "arn:aws:iam::aws:policy/AmazonS3FullAccess" - !Ref XRayPolicy Policies: - PolicyName: !Sub "${AWS::StackName}-SecretsPolicy" PolicyDocument: Version: 2012-10-17 Statement: - Action: 'secretsmanager:GetSecretValue' Effect: Allow Resource: !Ref SecretArn RoleName: !Sub "${AWS::StackName}-S3LambdaRole"