UNPKG

@studion/infra-code-blocks

Version:
139 lines (138 loc) 5.77 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StaticSite = void 0; const aws = require("@pulumi/aws"); const pulumi = require("@pulumi/pulumi"); const acm_certificate_1 = require("./acm-certificate"); const constants_1 = require("../constants"); class StaticSite extends pulumi.ComponentResource { constructor(name, args, opts = {}) { super('studion:StaticSite', name, {}, opts); this.name = name; const { domain, hostedZoneId, viewerRequestFunctionArn, tags } = args; const hasCustomDomain = domain && hostedZoneId; if (domain && !hostedZoneId) { throw new Error('StaticSite:hostedZoneId must be provided when the domain is specified'); } if (hasCustomDomain) { this.certificate = this.createTlsCertificate({ domain, hostedZoneId }); } this.bucket = this.createPublicBucket({ tags }); this.cloudfront = this.createCloudfrontDistribution({ domain, viewerRequestFunctionArn, tags, }); if (hasCustomDomain) { this.createDnsRecord({ domain, hostedZoneId }); } this.registerOutputs(); } createTlsCertificate({ domain, hostedZoneId, }) { const certificate = new acm_certificate_1.AcmCertificate(`${domain}-acm-certificate`, { domain, hostedZoneId, }, { parent: this }); return certificate; } createPublicBucket({ tags }) { const bucket = new aws.s3.Bucket(`${this.name}-bucket`, { bucketPrefix: `${this.name}-`, website: { indexDocument: 'index.html', errorDocument: 'index.html', }, tags: Object.assign(Object.assign({}, constants_1.commonTags), tags), }, { parent: this }); const bucketPublicAccessBlock = new aws.s3.BucketPublicAccessBlock(`${this.name}-bucket-access-block`, { bucket: bucket.id, blockPublicAcls: false, blockPublicPolicy: false, ignorePublicAcls: false, restrictPublicBuckets: false, }, { parent: this }); const siteBucketPolicy = new aws.s3.BucketPolicy(`${this.name}-bucket-policy`, { bucket: bucket.bucket, policy: bucket.bucket.apply(publicReadPolicy), }, { parent: this, dependsOn: [bucketPublicAccessBlock] }); function publicReadPolicy(bucketName) { return { Version: '2012-10-17', Statement: [ { Effect: 'Allow', Principal: '*', Action: ['s3:GetObject'], Resource: [`arn:aws:s3:::${bucketName}/*`], }, ], }; } return bucket; } createCloudfrontDistribution({ domain, viewerRequestFunctionArn, tags, }) { const functionAssociations = viewerRequestFunctionArn ? [ { eventType: 'viewer-request', functionArn: viewerRequestFunctionArn, }, ] : []; const cloudfront = new aws.cloudfront.Distribution(`${this.name}-cloudfront`, Object.assign(Object.assign({ enabled: true, defaultRootObject: 'index.html' }, (domain && { aliases: [domain] })), { isIpv6Enabled: true, waitForDeployment: true, httpVersion: 'http2and3', viewerCertificate: Object.assign({}, (this.certificate ? { acmCertificateArn: this.certificate.certificate.arn, sslSupportMethod: 'sni-only', minimumProtocolVersion: 'TLSv1.2_2021', } : { cloudfrontDefaultCertificate: true, })), origins: [ { originId: this.bucket.arn, domainName: this.bucket.websiteEndpoint, connectionAttempts: 3, connectionTimeout: 10, customOriginConfig: { originProtocolPolicy: 'http-only', httpPort: 80, httpsPort: 443, originSslProtocols: ['TLSv1.2'], }, }, ], defaultCacheBehavior: { targetOriginId: this.bucket.arn, viewerProtocolPolicy: 'redirect-to-https', allowedMethods: ['GET', 'HEAD', 'OPTIONS'], cachedMethods: ['GET', 'HEAD', 'OPTIONS'], compress: true, defaultTtl: 86400, minTtl: 1, maxTtl: 31536000, forwardedValues: { cookies: { forward: 'none' }, queryString: false, }, functionAssociations, }, priceClass: 'PriceClass_100', restrictions: { geoRestriction: { restrictionType: 'none' }, }, tags: Object.assign(Object.assign({}, constants_1.commonTags), tags) }), { parent: this }); return cloudfront; } createDnsRecord({ domain, hostedZoneId, }) { const cdnAliasRecord = new aws.route53.Record(`${this.name}-cdn-route53-record`, { type: 'A', name: domain, zoneId: hostedZoneId, aliases: [ { name: this.cloudfront.domainName, zoneId: this.cloudfront.hostedZoneId, evaluateTargetHealth: true, }, ], }, { parent: this }); return cdnAliasRecord; } } exports.StaticSite = StaticSite;