1
votes

I'm using AWS CDK to setup S3 and CloudFront static website hosting. All works well until I want to redirect "http[s]//:www.mydomain.com" to "https ://mydomain.com". I do not want to make the S3 repositories public rather provide bucket permission for the CloudFront "Origin Access Identity". The relevant snippet of my CDK code is as follows:

const wwwbucket = new s3.Bucket(this, "www." + domainName, {
    websiteRedirect: {
    hostName: domainName,
    protocol: s3.RedirectProtocol.HTTPS },
    blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL
})

const oaiWWW = new cloudfront.OriginAccessIdentity(this, 'CloudFront-OriginAccessIdentity-WWW', {
    comment: 'Allows CloudFront to access the bucket'
})
wwwbucket.grantRead(oaiWWW)

const cloudFrontRedirect = new cloudfront.CloudFrontWebDistribution(this, 'https://www.' + domainname + '.com redirect', {
    aliasConfiguration: {
        acmCertRef: certificateArn,
        names: [ "www." + domainName ],
        sslMethod: cloudfront.SSLMethod.SNI,
        securityPolicy: cloudfront.SecurityPolicyProtocol.TLS_V1_1_2016,
    },
    defaultRootObject: "",
    originConfigs: [
        // {
        //   customOriginSource: {
        //     domainName: wwwbucket.bucketWebsiteDomainName
        //   },
        //   behaviors : [ {isDefaultBehavior: true}],
        // },
        {
        s3OriginSource: {
            s3BucketSource: wwwbucket,
            originAccessIdentity: oaiWWW
        },
        behaviors : [ {isDefaultBehavior: true}],
        }
    ]
});

Unfortunately the result is that rather than redirecting, browsing to www.mydomain.com results in the browser showing an S3 XML bucket listing result. I can fix the problem manually by using the AWS console to edit CloudFront's "Origin Domain Name" within "origin settings" from:

bucketname.s3.eu-west-2.amazonaws.com

to:

bucketname.s3-website.eu-west-2.amazonaws.com

Then all works as expected. I have tried changing my CDK script to use a customOriginSource rather than s3OriginSource (commented-out code above) which results in the correct address in CloudFront's "Origin Domain Name" but then the CloudFront distribution does not have a "Origin Access Identity" and so can't access the S3 bucket.

Does anyone know a way to achieve the redirect without having to make the redirect bucket public or edit the "Origin Domain Name" manually via the AWS console?

1

1 Answers

1
votes

I thought I'd found an answer using a CDK escape hatch. After creating the CloudFront distribution for my redirect I modified the CloudFormation JSON behind the CDK class as (in typescript):

type ChangeDomainName = {
    origins: {
      domainName: string
    }[]
}

const cfnCloudFrontRedirect = cloudFrontRedirect.node.defaultChild as cloudfront.CfnDistribution
var distributionConfig = cfnCloudFrontRedirect.distributionConfig as cloudfront.CfnDistribution.DistributionConfigProperty & ChangeDomainName
distributionConfig.origins[0].domainName = wwwbucket.bucketWebsiteDomainName
cfnCloudFrontRedirect.distributionConfig = distributionConfig

Unfortunately although this appeared to generate the CloudFormation template I was aiming for (checked using cdk synthesize) when deploying (cdk deploy) the following error was generated by CloudFormation:

UPDATE_FAILED | AWS::CloudFront::Distribution | The parameter Origin DomainName does not refer to a valid S3 bucket.

It appears that even though it's possible to set a website endpoint of the form - ${bucketname}.s3-website.${region}.amazonaws.com - manually in the field Origin Domain Name within the CloudFront console this isn't possible using CloudFormation. This leads me to conclude either:

  1. This is a bug with CloudFormation.
  2. It's a bug in the console, in that the console shouldn't allow this setup.

However although currently modifying Origin Domain Name in console works, I don't know if this is a "legal" configuration that could be changed in the future in which case my code might stop working. The current solutions are:

  1. Make the redirect bucket public in which case the customOriginSource will work.
  2. Rather than using a redirect bucket instead use a Lambda to perform the redirect and deploy within CloudFront using "Lambda@Edge".

I would prefer not to make my redirect bucket public as it results in warnings when using security checking tools. The option of deploying "Lambda@Edge" using the cdk outside of us-east-1 currently looks painful so for the moment I'll continue manually editing Origin Domain Name in the console.

For reference the AWS documentation appears to imply that the API prohibits this use, though the console permits it, see: Using Amazon S3 Buckets Configured as Website Endpoints for Your Origin. See also: