diff --git a/.env.example b/.env.example index eaa8ac1..c83bdf0 100644 --- a/.env.example +++ b/.env.example @@ -27,3 +27,6 @@ ALEXA_AMAZON_CLIENT_SECRET = secret LARA_SECRET = secret STAGE = dev + +FRONTEND_CERTIFICATE_ARN = arn:aws:acm:eu-west-1:123456789012:certificate/12345678-1234-1234-1234-123456789012 +BACKEND_CERTIFICATE_ARN = arn:aws:acm:eu-west-1:123456789012:certificate/12345678-1234-1234-1234-123456789012 diff --git a/.github/workflows/reusable-deploy-job.yml b/.github/workflows/reusable-deploy-job.yml index a59aa33..f91644b 100644 --- a/.github/workflows/reusable-deploy-job.yml +++ b/.github/workflows/reusable-deploy-job.yml @@ -47,6 +47,9 @@ jobs: SES_REGION: ${{ secrets.SES_REGION }} FRONTEND_URL: ${{ secrets.FRONTEND_URL }} BACKEND_URL: ${{ secrets.BACKEND_URL }} + HOSTED_ZONE_ID: ${{ secrets.HOSTED_ZONE_ID }} + FRONTEND_CERTIFICATE_ARN: ${{ secrets.FRONTEND_CERTIFICATE_ARN }} + BACKEND_CERTIFICATE_ARN: ${{ secrets.BACKEND_CERTIFICATE_ARN }} steps: - uses: actions/checkout@v4 @@ -78,6 +81,11 @@ jobs: role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-deploy-user role-session-name: github-deployment + - name: Set environment variables without https + run: | + echo "FRONTEND_URL_WITHOUT_HTTPS=$(echo ${{ secrets.FRONTEND_URL }} | sed 's/^https:\/\///')" >> $GITHUB_ENV + echo "BACKEND_URL_WITHOUT_HTTPS=$(echo ${{ secrets.BACKEND_URL }} | sed 's/^https:\/\///')" >> $GITHUB_ENV + - name: Deploy Frontend run: serverless s3sync bucket --bucket ${{ secrets.COMPANY_ABBREVIATION }}-lara-frontend-${{ inputs.target }} diff --git a/serverless.yml b/serverless.yml index 5cb29c4..d16de42 100644 --- a/serverless.yml +++ b/serverless.yml @@ -250,6 +250,16 @@ functions: - 'packages/alexa' resources: + Conditions: + IsProductionOrStaging: + Fn::Or: + - Fn::Equals: + - ${self:custom.stage} + - production + - Fn::Equals: + - ${self:custom.stage} + - staging + Resources: UserTable: Type: 'AWS::DynamoDB::Table' @@ -370,7 +380,6 @@ resources: Properties: DistributionConfig: PriceClass: PriceClass_100 - #CNAMEs: [ ${self:provider.environment.PRODUCTION_FE_URL} ] IPV6Enabled: true Enabled: true Comment: Frontend @@ -401,13 +410,22 @@ resources: ViewerProtocolPolicy: redirect-to-https ForwardedValues: QueryString: true + ResponseHeadersPolicyId: e61eb60c-9c35-4d20-a928-2b84e02af89c + Aliases: + - ${env:FRONTEND_URL_WITHOUT_HTTPS} + ViewerCertificate: + Fn::If: + - IsProductionOrStaging + - AcmCertificateArn: ${self:provider.environment.FRONTEND_CERTIFICATE_ARN} + SslSupportMethod: sni-only + MinimumProtocolVersion: TLSv1.2_2021 + - Ref: AWS::NoValue BackendDistribution: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: PriceClass: PriceClass_100 - #CNAMEs: [ ${self:provider.environment.PRODUCTION_FE_URL} ] IPV6Enabled: true Enabled: true Comment: Backend @@ -418,7 +436,8 @@ resources: HTTPSPort: 443 OriginProtocolPolicy: https-only OriginSSLProtocols: - - TLSv1 + - TLSv1.2 + OriginPath: '/${self:custom.stage}' HttpVersion: http2 DefaultCacheBehavior: AllowedMethods: @@ -433,6 +452,36 @@ resources: ViewerProtocolPolicy: redirect-to-https ForwardedValues: QueryString: true + ResponseHeadersPolicyId: e61eb60c-9c35-4d20-a928-2b84e02af89c + Aliases: + - ${env:BACKEND_URL_WITHOUT_HTTPS} + ViewerCertificate: + Fn::If: + - IsProductionOrStaging + - AcmCertificateArn: ${self:provider.environment.BACKEND_CERTIFICATE_ARN} + SslSupportMethod: sni-only + MinimumProtocolVersion: TLSv1.2_2021 + - Ref: AWS::NoValue + + FrontendAliasRecord: + Type: AWS::Route53::RecordSet + Properties: + HostedZoneId: ${env:HOSTED_ZONE_ID} + Name: ${env:FRONTEND_URL_WITHOUT_HTTPS} + Type: A + AliasTarget: + DNSName: !GetAtt FrontendDistribution.DomainName + HostedZoneId: Z2FDTNDATAQYW2 + + BackendAliasRecord: + Type: AWS::Route53::RecordSet + Properties: + HostedZoneId: ${env:HOSTED_ZONE_ID} + Name: ${env:BACKEND_URL_WITHOUT_HTTPS} + Type: A + AliasTarget: + DNSName: !GetAtt BackendDistribution.DomainName + HostedZoneId: Z2FDTNDATAQYW2 OAC: Type: AWS::CloudFront::OriginAccessControl @@ -443,8 +492,8 @@ resources: SigningBehavior: no-override SigningProtocol: sigv4 - PolicyForCloudFrontPrivateContent: - Type: 'AWS::S3::BucketPolicy' + FrontendBucketPolicy: + Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref FrontendBucket PolicyDocument: @@ -460,14 +509,6 @@ resources: Condition: StringEquals: aws:SourceArn: !Sub 'arn:aws:cloudfront::${AWS::AccountId}:distribution/${FrontendDistribution.Id}' - - FrontendBucketPolicy: - Type: AWS::S3::BucketPolicy - Properties: - Bucket: !Ref FrontendBucket - PolicyDocument: - Version: '2012-10-17' - Statement: - Sid: 'AllowSSLRequestsOnly' Effect: Deny Principal: '*'