@scloud/cdk-patterns
Version:
Serverless CDK patterns for common infrastructure needs
65 lines • 12.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebFrontend = void 0;
const aws_certificatemanager_1 = require("aws-cdk-lib/aws-certificatemanager");
const aws_cloudfront_1 = require("aws-cdk-lib/aws-cloudfront");
const aws_route53_1 = require("aws-cdk-lib/aws-route53");
const constructs_1 = require("constructs");
const aws_route53_targets_1 = require("aws-cdk-lib/aws-route53-targets");
const aws_cloudfront_origins_1 = require("aws-cdk-lib/aws-cloudfront-origins");
const GithubActions_1 = require("./GithubActions");
const PrivateBucket_1 = require("./PrivateBucket");
const RedirectWww_1 = require("./RedirectWww");
/**
* A Cloudfront distribution backed by an s3 bucket.
*
* The bucket and contents are treated as expendable on the basis they are assumed to be generated by a CI/CD process that can rebuild the content.
*
* NB us-east-1 is required for Cloudfront certificates:
* https://docs.aws.amazon.com/cdk/api/v1/docs/aws-cloudfront-readme.html
*/
class WebFrontend extends constructs_1.Construct {
constructor(scope, id, props) {
super(scope, `${id}WebFrontend`);
const domainName = props.domainName || props.zone.zoneName;
// We consider the objects in the bucket to be expendable because
// they're most likely static content we generate from source code (rather than user data).
this.bucket = PrivateBucket_1.PrivateBucket.expendable(scope, `${id}Static`);
(0, GithubActions_1.githubActions)(scope).addGhaBucket(id, this.bucket);
this.certificate = new aws_certificatemanager_1.DnsValidatedCertificate(scope, `${id}Certificate`, {
domainName,
hostedZone: props.zone,
region: 'us-east-1',
subjectAlternativeNames: props.redirectWww !== false ? [`www.${domainName}`] : undefined,
});
// This enables us to separate out the defaultBehavior props (if any) from the distributionProps (if provided)
// See https://stackoverflow.com/a/34710102/723506 for an explanation of this destructuring
const { defaultBehavior, ...distributionProps } = props.distributionProps || {};
this.distribution = new aws_cloudfront_1.Distribution(scope, `${id}Distribution`, {
domainNames: [domainName],
comment: domainName,
defaultRootObject: props.defaultIndex ? 'index.html' : undefined,
defaultBehavior: {
origin: aws_cloudfront_origins_1.S3BucketOrigin.withOriginAccessControl(this.bucket),
viewerProtocolPolicy: aws_cloudfront_1.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
...defaultBehavior,
},
certificate: this.certificate,
errorResponses: props.errorResponses,
...distributionProps,
});
(0, GithubActions_1.githubActions)(scope).addGhaDistribution(id, this.distribution);
// DNS record for the distribution
new aws_route53_1.ARecord(scope, `${id}ARecord`, {
zone: props.zone,
recordName: domainName,
target: aws_route53_1.RecordTarget.fromAlias(new aws_route53_targets_1.CloudFrontTarget(this.distribution)),
});
if (props.redirectWww !== false) {
// Redirect www -> zone root
new RedirectWww_1.RedirectWww(scope, id, { zone: props.zone, certificate: this.certificate, domainName });
}
}
}
exports.WebFrontend = WebFrontend;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiV2ViRnJvbnRlbmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvV2ViRnJvbnRlbmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsK0VBQTZFO0FBQzdFLCtEQUVvQztBQUNwQyx5REFBNkU7QUFFN0UsMkNBQXVDO0FBQ3ZDLHlFQUFtRTtBQUNuRSwrRUFBb0U7QUFDcEUsbURBQWdEO0FBQ2hELG1EQUFnRDtBQUNoRCwrQ0FBNEM7QUFzQjVDOzs7Ozs7O0dBT0c7QUFDSCxNQUFhLFdBQVksU0FBUSxzQkFBUztJQU94QyxZQUNFLEtBQWdCLEVBQ2hCLEVBQVUsRUFDVixLQUF1QjtRQUV2QixLQUFLLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxhQUFhLENBQUMsQ0FBQztRQUVqQyxNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsVUFBVSxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBRTNELGlFQUFpRTtRQUNqRSwyRkFBMkY7UUFDM0YsSUFBSSxDQUFDLE1BQU0sR0FBRyw2QkFBYSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQzdELElBQUEsNkJBQWEsRUFBQyxLQUFLLENBQUMsQ0FBQyxZQUFZLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUVuRCxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksZ0RBQXVCLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxhQUFhLEVBQUU7WUFDeEUsVUFBVTtZQUNWLFVBQVUsRUFBRSxLQUFLLENBQUMsSUFBSTtZQUN0QixNQUFNLEVBQUUsV0FBVztZQUNuQix1QkFBdUIsRUFBRSxLQUFLLENBQUMsV0FBVyxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVM7U0FDekYsQ0FBQyxDQUFDO1FBRUgsOEdBQThHO1FBQzlHLDJGQUEyRjtRQUMzRixNQUFNLEVBQUUsZUFBZSxFQUFFLEdBQUcsaUJBQWlCLEVBQUUsR0FBRyxLQUFLLENBQUMsaUJBQWlCLElBQUssRUFBaUMsQ0FBQztRQUNoSCxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksNkJBQVksQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLGNBQWMsRUFBRTtZQUMvRCxXQUFXLEVBQUUsQ0FBQyxVQUFVLENBQUM7WUFDekIsT0FBTyxFQUFFLFVBQVU7WUFDbkIsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxTQUFTO1lBQ2hFLGVBQWUsRUFBRTtnQkFDZixNQUFNLEVBQUUsdUNBQWMsQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO2dCQUMzRCxvQkFBb0IsRUFBRSxxQ0FBb0IsQ0FBQyxpQkFBaUI7Z0JBQzVELEdBQUcsZUFBZTthQUNuQjtZQUNELFdBQVcsRUFBRSxJQUFJLENBQUMsV0FBVztZQUM3QixjQUFjLEVBQUUsS0FBSyxDQUFDLGNBQWM7WUFDcEMsR0FBRyxpQkFBaUI7U0FDckIsQ0FBQyxDQUFDO1FBQ0gsSUFBQSw2QkFBYSxFQUFDLEtBQUssQ0FBQyxDQUFDLGtCQUFrQixDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFFL0Qsa0NBQWtDO1FBQ2xDLElBQUkscUJBQU8sQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRTtZQUNqQyxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUk7WUFDaEIsVUFBVSxFQUFFLFVBQVU7WUFDdEIsTUFBTSxFQUFFLDBCQUFZLENBQUMsU0FBUyxDQUFDLElBQUksc0NBQWdCLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1NBQ3hFLENBQUMsQ0FBQztRQUVILElBQUksS0FBSyxDQUFDLFdBQVcsS0FBSyxLQUFLLEVBQUUsQ0FBQztZQUNoQyw0QkFBNEI7WUFDNUIsSUFBSSx5QkFBVyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBQzlGLENBQUM7SUFDSCxDQUFDO0NBQ0Y7QUExREQsa0NBMERDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRG5zVmFsaWRhdGVkQ2VydGlmaWNhdGUgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtY2VydGlmaWNhdGVtYW5hZ2VyJztcbmltcG9ydCB7XG4gIERpc3RyaWJ1dGlvbiwgRGlzdHJpYnV0aW9uUHJvcHMsIEVycm9yUmVzcG9uc2UsIFZpZXdlclByb3RvY29sUG9saWN5LFxufSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtY2xvdWRmcm9udCc7XG5pbXBvcnQgeyBBUmVjb3JkLCBJSG9zdGVkWm9uZSwgUmVjb3JkVGFyZ2V0IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXJvdXRlNTMnO1xuaW1wb3J0IHsgQnVja2V0IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgQ2xvdWRGcm9udFRhcmdldCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1yb3V0ZTUzLXRhcmdldHMnO1xuaW1wb3J0IHsgUzNCdWNrZXRPcmlnaW4gfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtY2xvdWRmcm9udC1vcmlnaW5zJztcbmltcG9ydCB7IGdpdGh1YkFjdGlvbnMgfSBmcm9tICcuL0dpdGh1YkFjdGlvbnMnO1xuaW1wb3J0IHsgUHJpdmF0ZUJ1Y2tldCB9IGZyb20gJy4vUHJpdmF0ZUJ1Y2tldCc7XG5pbXBvcnQgeyBSZWRpcmVjdFd3dyB9IGZyb20gJy4vUmVkaXJlY3RXd3cnO1xuXG4vKipcbiAqIEBwYXJhbSB6b25lIFRoZSBETlMgem9uZSBmb3IgdGhpcyB3ZWIgYXBwLiBCeSBkZWZhdWx0IHRoZSBkb21haW4gbmFtZSBpcyBzZXQgdG8gdGhlIHpvbmUgbmFtZVxuICogVGhlIHR5cGUgSUhvc3RlZFpvbmUgZW5hYmxlcyBsb29rdXAgb2YgdGhlIHpvbmUgKElIb3N0ZWRab25lKSBhcyB3ZWxsIGFzIGEgem9uZSBjcmVhdGQgaW4gdGhlIHN0YWNrIChIb3N0ZWRab25lKVxuICogQHBhcmFtIGRvbWFpbk5hbWUgT3B0aW9uYWw6IGJ5IGRlZmF1bHQgdGhlIHpvbmUgbmFtZSB3aWxsIGJlIG1hcHBlZCB0byB0aGUgQ2xvdWRmcm9udCBkaXN0cmlidXRpb24gKGUuZy4gJ2V4YW1wbGUuY29tJykgYnV0IHlvdSBjYW4gc3BlY2lmeSBhIGRpZmZlcmVudCBkb21haW4gaGVyZSAoZS5nLiAnc3ViZG9tYWluLmV4YW1wbGUuY29tJykuXG4gKiBAcGFyYW0gZGVmYXVsdEluZGV4IERlZmF1bHQ6IHRydWUuIE1hcHMgYSB2aWV3ZXIgcmVxdWVzdCBmb3IgJy8nIHRvIGEgcmVxdWVzdCBmb3IgL2luZGV4Lmh0bWwuXG4gKiBAcGFyYW0gcmVkaXJlY3RXd3cgRGVmYXVsdDogdHJ1ZS4gUmVkaXJlY3RzIHd3dyByZXF1ZXN0cyB0byB0aGUgYmFyZSBkb21haW4gbmFtZSwgZS5nLiB3d3cuZXhhbXBsZS5jb20tPmV4YW1wbGUuY29tLCB3d3cuc3ViLmV4YW1wbGUuY29tLT5zdWIuZXhhbXBsZS5jb20uXG4gKiBAcGFyYW0gY25hbWVBbGlhc2VzIE9wdGlvbmFsOiBhZGRpdGlvbmFsIENOQU1FcyB0byBhZGQgdG8gdGhlIENsb3VkZnJvbnQgZGlzdHJpYnV0aW9uLiBUaGlzIGFsbG93cyB5b3UgdG8gdXNlIGEgZG9tYWluIG5hbWUgY29uZmlndXJlZCBvdXRzaWRlIG9mIEFXUy5cbiAqIEBwYXJhbSBkaXN0cmlidXRpb25Qcm9wcyBPcHRpb25hbDogSWYgeW91IHdhbnQgdG8gYWRkIGFkZGl0aW9uYWwgcHJvcGVydGllcyB0byB0aGUgQ2xvdWRmcm9udCBkaXN0cmlidXRpb24sIHlvdSBjYW4gcGFzcyB0aGVtIGhlcmUuXG4gKiBAcGFyYW0gZXJyb3JSZXNwb25zZXMgT3B0aW9uYWw6IElmIHlvdSB3YW50IHRvIGFkZCBjdXN0b20gZXJyb3IgcmVzcG9uc2VzIHRvIHRoZSBDbG91ZGZyb250IGRpc3RyaWJ1dGlvbiwgeW91IGNhbiBwYXNzIHRoZW0gaGVyZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBXZWJGcm9udGVuZFByb3BzIHtcbiAgem9uZTogSUhvc3RlZFpvbmUsXG4gIGRvbWFpbk5hbWU/OiBzdHJpbmcsXG4gIGRlZmF1bHRJbmRleD86IGJvb2xlYW4sXG4gIHJlZGlyZWN0V3d3PzogYm9vbGVhbixcbiAgY25hbWVBbGlhc2VzPzogc3RyaW5nW10sXG4gIGRpc3RyaWJ1dGlvblByb3BzPzogUGFydGlhbDxEaXN0cmlidXRpb25Qcm9wcz4sXG4gIGVycm9yUmVzcG9uc2VzPzogRXJyb3JSZXNwb25zZVtdLFxufVxuXG4vKipcbiAqIEEgQ2xvdWRmcm9udCBkaXN0cmlidXRpb24gYmFja2VkIGJ5IGFuIHMzIGJ1Y2tldC5cbiAqXG4gKiBUaGUgYnVja2V0IGFuZCBjb250ZW50cyBhcmUgdHJlYXRlZCBhcyBleHBlbmRhYmxlIG9uIHRoZSBiYXNpcyB0aGV5IGFyZSBhc3N1bWVkIHRvIGJlIGdlbmVyYXRlZCBieSBhIENJL0NEIHByb2Nlc3MgdGhhdCBjYW4gcmVidWlsZCB0aGUgY29udGVudC5cbiAqXG4gKiBOQiB1cy1lYXN0LTEgaXMgcmVxdWlyZWQgZm9yIENsb3VkZnJvbnQgY2VydGlmaWNhdGVzOlxuICogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Nkay9hcGkvdjEvZG9jcy9hd3MtY2xvdWRmcm9udC1yZWFkbWUuaHRtbFxuICovXG5leHBvcnQgY2xhc3MgV2ViRnJvbnRlbmQgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBidWNrZXQ6IEJ1Y2tldDtcblxuICBkaXN0cmlidXRpb246IERpc3RyaWJ1dGlvbjtcblxuICBjZXJ0aWZpY2F0ZTogRG5zVmFsaWRhdGVkQ2VydGlmaWNhdGU7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgc2NvcGU6IENvbnN0cnVjdCxcbiAgICBpZDogc3RyaW5nLFxuICAgIHByb3BzOiBXZWJGcm9udGVuZFByb3BzLFxuICApIHtcbiAgICBzdXBlcihzY29wZSwgYCR7aWR9V2ViRnJvbnRlbmRgKTtcblxuICAgIGNvbnN0IGRvbWFpbk5hbWUgPSBwcm9wcy5kb21haW5OYW1lIHx8IHByb3BzLnpvbmUuem9uZU5hbWU7XG5cbiAgICAvLyBXZSBjb25zaWRlciB0aGUgb2JqZWN0cyBpbiB0aGUgYnVja2V0IHRvIGJlIGV4cGVuZGFibGUgYmVjYXVzZVxuICAgIC8vIHRoZXkncmUgbW9zdCBsaWtlbHkgc3RhdGljIGNvbnRlbnQgd2UgZ2VuZXJhdGUgZnJvbSBzb3VyY2UgY29kZSAocmF0aGVyIHRoYW4gdXNlciBkYXRhKS5cbiAgICB0aGlzLmJ1Y2tldCA9IFByaXZhdGVCdWNrZXQuZXhwZW5kYWJsZShzY29wZSwgYCR7aWR9U3RhdGljYCk7XG4gICAgZ2l0aHViQWN0aW9ucyhzY29wZSkuYWRkR2hhQnVja2V0KGlkLCB0aGlzLmJ1Y2tldCk7XG5cbiAgICB0aGlzLmNlcnRpZmljYXRlID0gbmV3IERuc1ZhbGlkYXRlZENlcnRpZmljYXRlKHNjb3BlLCBgJHtpZH1DZXJ0aWZpY2F0ZWAsIHtcbiAgICAgIGRvbWFpbk5hbWUsXG4gICAgICBob3N0ZWRab25lOiBwcm9wcy56b25lLFxuICAgICAgcmVnaW9uOiAndXMtZWFzdC0xJyxcbiAgICAgIHN1YmplY3RBbHRlcm5hdGl2ZU5hbWVzOiBwcm9wcy5yZWRpcmVjdFd3dyAhPT0gZmFsc2UgPyBbYHd3dy4ke2RvbWFpbk5hbWV9YF0gOiB1bmRlZmluZWQsXG4gICAgfSk7XG5cbiAgICAvLyBUaGlzIGVuYWJsZXMgdXMgdG8gc2VwYXJhdGUgb3V0IHRoZSBkZWZhdWx0QmVoYXZpb3IgcHJvcHMgKGlmIGFueSkgZnJvbSB0aGUgZGlzdHJpYnV0aW9uUHJvcHMgKGlmIHByb3ZpZGVkKVxuICAgIC8vIFNlZSBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzQ3MTAxMDIvNzIzNTA2IGZvciBhbiBleHBsYW5hdGlvbiBvZiB0aGlzIGRlc3RydWN0dXJpbmdcbiAgICBjb25zdCB7IGRlZmF1bHRCZWhhdmlvciwgLi4uZGlzdHJpYnV0aW9uUHJvcHMgfSA9IHByb3BzLmRpc3RyaWJ1dGlvblByb3BzIHx8ICh7fSBhcyBQYXJ0aWFsPERpc3RyaWJ1dGlvblByb3BzPik7XG4gICAgdGhpcy5kaXN0cmlidXRpb24gPSBuZXcgRGlzdHJpYnV0aW9uKHNjb3BlLCBgJHtpZH1EaXN0cmlidXRpb25gLCB7XG4gICAgICBkb21haW5OYW1lczogW2RvbWFpbk5hbWVdLFxuICAgICAgY29tbWVudDogZG9tYWluTmFtZSxcbiAgICAgIGRlZmF1bHRSb290T2JqZWN0OiBwcm9wcy5kZWZhdWx0SW5kZXggPyAnaW5kZXguaHRtbCcgOiB1bmRlZmluZWQsXG4gICAgICBkZWZhdWx0QmVoYXZpb3I6IHtcbiAgICAgICAgb3JpZ2luOiBTM0J1Y2tldE9yaWdpbi53aXRoT3JpZ2luQWNjZXNzQ29udHJvbCh0aGlzLmJ1Y2tldCksXG4gICAgICAgIHZpZXdlclByb3RvY29sUG9saWN5OiBWaWV3ZXJQcm90b2NvbFBvbGljeS5SRURJUkVDVF9UT19IVFRQUyxcbiAgICAgICAgLi4uZGVmYXVsdEJlaGF2aW9yLFxuICAgICAgfSxcbiAgICAgIGNlcnRpZmljYXRlOiB0aGlzLmNlcnRpZmljYXRlLFxuICAgICAgZXJyb3JSZXNwb25zZXM6IHByb3BzLmVycm9yUmVzcG9uc2VzLFxuICAgICAgLi4uZGlzdHJpYnV0aW9uUHJvcHMsXG4gICAgfSk7XG4gICAgZ2l0aHViQWN0aW9ucyhzY29wZSkuYWRkR2hhRGlzdHJpYnV0aW9uKGlkLCB0aGlzLmRpc3RyaWJ1dGlvbik7XG5cbiAgICAvLyBETlMgcmVjb3JkIGZvciB0aGUgZGlzdHJpYnV0aW9uXG4gICAgbmV3IEFSZWNvcmQoc2NvcGUsIGAke2lkfUFSZWNvcmRgLCB7XG4gICAgICB6b25lOiBwcm9wcy56b25lLFxuICAgICAgcmVjb3JkTmFtZTogZG9tYWluTmFtZSxcbiAgICAgIHRhcmdldDogUmVjb3JkVGFyZ2V0LmZyb21BbGlhcyhuZXcgQ2xvdWRGcm9udFRhcmdldCh0aGlzLmRpc3RyaWJ1dGlvbikpLFxuICAgIH0pO1xuXG4gICAgaWYgKHByb3BzLnJlZGlyZWN0V3d3ICE9PSBmYWxzZSkge1xuICAgICAgLy8gUmVkaXJlY3Qgd3d3IC0+IHpvbmUgcm9vdFxuICAgICAgbmV3IFJlZGlyZWN0V3d3KHNjb3BlLCBpZCwgeyB6b25lOiBwcm9wcy56b25lLCBjZXJ0aWZpY2F0ZTogdGhpcy5jZXJ0aWZpY2F0ZSwgZG9tYWluTmFtZSB9KTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==