AWSTemplateFormatVersion: '2010-09-09' Description: > Script to create S3 bucket, DNS (Route53) and Cloudfront distribution. ############################################################################### Parameters: ############################################################################### DomainName: Type: String Description: The domain name. Default: 'beta.ordbok.aws.uib.no' AllowedPattern: (?!-)[a-zA-Z0-9-.]{1,63}(?<!-) ConstraintDescription: must be a valid DNS zone name AltDomainName: Type: String Description: The domain name. Default: 'beta.ordbok.uib.no' AllowedPattern: (?!-)[a-zA-Z0-9-.]{1,63}(?<!-) ConstraintDescription: must be a valid DNS zone name PriceClass: Type: String Description: The CloudFront distribution price class Default: 'PriceClass_100' AllowedValues: - 'PriceClass_100' #- 'PriceClass_200' #- 'PriceClass_All' CertificateArn: Type: String ############################################################################### Resources: ############################################################################### LambdaRole: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: - "lambda.amazonaws.com" - "edgelambda.amazonaws.com" Action: - "sts:AssumeRole" RewriteLambda: Type: "AWS::Lambda::Function" Properties: Code: ZipFile: !Sub | 'use strict'; // lambda@edge Origin Request trigger to remove the first path element // compatible with either Node.js 6.10 or 8.10 Lambda runtime environment exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; // extract the request object request.uri = request.uri.replace(/^\/[^\/]+\//,'/'); // modify the URI return callback(null, request); // return control to CloudFront }; Handler: index.handler Role: !GetAtt LambdaRole.Arn Runtime: nodejs12.x DNS: Type: "AWS::Route53::RecordSet" Properties: HostedZoneName: !Sub "${DomainName}." Name: !Ref DomainName Type: A AliasTarget: HostedZoneId: Z2FDTNDATAQYW2 DNSName: !GetAtt Distribution.DomainName WebBucket: Type: "AWS::S3::Bucket" Properties: BucketName: !Sub "${AWS::StackName}.aws.uib.no" VersioningConfiguration: Status: Enabled Tags: - Key: Application Value: !Ref DomainName BucketPolicy: Type: "AWS::S3::BucketPolicy" Properties: Bucket: !Ref WebBucket PolicyDocument: Id: MyPolicy Version: 2012-10-17 Statement: - Sid: PublicReadForGetBucketObjects Effect: Allow Action: s3:* Resource: !Join ['', ['arn:aws:s3:::', !Ref 'WebBucket', /*]] Principal: CanonicalUser: !GetAtt CloudFrontOriginIdentity.S3CanonicalUserId ITAIpSet: Type: "AWS::WAF::IPSet" Properties: IPSetDescriptors: - Type: "IPV4" Value: "129.177.0.0/16" - Type: "IPV4" Value: "82.134.66.114/32" Name: "allowed IPs" ITARule: Type: "AWS::WAF::Rule" Properties: MetricName: "ITARule" Name: "ITARule" Predicates: - Type: "IPMatch" Negated: false DataId: !Ref ITAIpSet ACL: Type: "AWS::WAF::WebACL" Properties: DefaultAction: Type: "BLOCK" Name: "intern ITA" MetricName: "WebACL" Rules: - Action: Type: "ALLOW" Priority: 1 RuleId: !Ref ITARule Distribution: Type: "AWS::CloudFront::Distribution" Properties: DistributionConfig: Enabled: true HttpVersion: http2 PriceClass: !Ref PriceClass DefaultRootObject: index.html Origins: - DomainName: !Sub "${WebBucket}.s3-${AWS::Region}.amazonaws.com" Id: s3ProductionBucket S3OriginConfig: OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${CloudFrontOriginIdentity}" - Id: OrdbokCache DomainName: "ycyevfqwnk.execute-api.eu-west-1.amazonaws.com" OriginPath: "/DEV/cache" CustomOriginConfig: OriginProtocolPolicy: https-only OriginKeepaliveTimeout: 60 Aliases: - !Ref DomainName - !Ref AltDomainName 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 CacheBehaviors: - PathPattern: "/api/*/*" AllowedMethods: - HEAD - DELETE - POST - GET - OPTIONS - PUT - PATCH MaxTTL: 0 DefaultTTL: 0 MinTTL: 0 TargetOriginId: OrdbokCache LambdaFunctionAssociations: - EventType: viewer-request IncludeBody: false LambdaFunctionARN: !Sub "${RewriteLambda.Arn}:1" ForwardedValues: QueryString: true Cookies: Forward: all ViewerProtocolPolicy: redirect-to-https ViewerCertificate: AcmCertificateArn: !Ref CertificateArn MinimumProtocolVersion: TLSv1.1_2016 SslSupportMethod: sni-only WebACLId: !Ref ACL Tags: - Key: Application Value: !Ref DomainName CloudFrontOriginIdentity: Type: "AWS::CloudFront::CloudFrontOriginAccessIdentity" Properties: CloudFrontOriginAccessIdentityConfig: Comment: "origin identity"