【コスト削減】中小企業やスタートアップがサーバーレスを使うべき理由
November 08, 2022
1 min
サーバーレスでウェブサーバーを作ってみます。
Lorem markdownum obvius in seque opus, est bicorni forte; laeva. Iurant patria beatam semel communis et atra qua fugit, solet invicti cui inter patulas regibus remolliat volumina sorori? Quidem miscentem regna interea natura in adligat, aenum onere placere lympha. Sunt tantum intentare exhortatus avidas Scythides lacrimis imitatus prohibent terraeque donec ulterius thalamosque fero comitantibus. Tela cervicem insiluit locis, falsa et umida ulterius digitos excipiunt!
import { Fn, RemovalPolicy, Stack, StackProps } from "aws-cdk-lib"; import * as cloudfront from "aws-cdk-lib/aws-cloudfront"; import * as origins from "aws-cdk-lib/aws-cloudfront-origins"; import * as route53 from "aws-cdk-lib/aws-route53"; import * as s3 from "aws-cdk-lib/aws-s3"; import * as s3deploy from "aws-cdk-lib/aws-s3-deployment"; import { Construct } from "constructs"; import * as targets from "aws-cdk-lib/aws-route53-targets"; import * as certificatemanager from "aws-cdk-lib/aws-certificatemanager"; import * as iam from "aws-cdk-lib/aws-iam"; import { tagMyConstruct } from "./tagging"; import * as crypto from "crypto"; export class WebsiteStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); // Retrieve environment configurations. const environment = this.node.tryGetContext("environment"); const envParams = this.node.tryGetContext(environment); // Make temporary variable. const siteFqdn = `${envParams.subDomainPrefix}.${envParams.rootDomainName}`; // S3 bucket as a web server. const websiteBucket = new s3.Bucket(this, "WebsiteBucket", { // publicReadAccess: true, websiteIndexDocument: "index.html", websiteErrorDocument: "404.html", autoDeleteObjects: true, removalPolicy: RemovalPolicy.DESTROY, websiteRoutingRules: [ { condition: { httpErrorCodeReturnedEquals: "403", }, httpRedirectCode: "302", hostName: siteFqdn, protocol: s3.RedirectProtocol.HTTPS, }, ], }); tagMyConstruct(this, websiteBucket); // Make referer key. const sha1sum = crypto.createHash("sha1"); sha1sum.update(siteFqdn); const siteFqdnSha1 = sha1sum.digest("base64"); // Policy to limit access origin. const websiteBucketPolicyStatement = new iam.PolicyStatement({ sid: `Allow access originating from ${siteFqdn}.`, principals: [new iam.AnyPrincipal()], actions: ["s3:GetObject"], effect: iam.Effect.ALLOW, resources: [`${websiteBucket.bucketArn}/*`], conditions: { StringLike: { "aws:Referer": siteFqdnSha1, }, }, }); websiteBucket.addToResourcePolicy(websiteBucketPolicyStatement); // Make basic auth function if required. const cfFunctions: cloudfront.FunctionAssociation[] = (() => { if (envParams.basicAuth) { // CloudFront Functionリソースの定義 const basicAuthFunction = new cloudfront.Function( this, "BasicAuthFunction", { functionName: `basic-authentication-${environment}`, code: cloudfront.FunctionCode.fromFile({ filePath: "../lambda/basic-auth.ts", }), } ); return [ { eventType: cloudfront.FunctionEventType.VIEWER_REQUEST, function: basicAuthFunction, }, ]; } return []; })(); // Certificate const certificate = certificatemanager.Certificate.fromCertificateArn( this, "WebsiteCertificate", envParams.certificateArn ); // LogBucket const logBucketArn = Fn.importValue(envParams.logBucketReference); const logBucket = s3.Bucket.fromBucketArn(this, "LogBucket", logBucketArn); // Cloudfront const distribution = new cloudfront.Distribution(this, "Distribution", { defaultBehavior: { origin: new origins.S3Origin(websiteBucket, { customHeaders: { Referer: siteFqdnSha1, }, }), viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS, functionAssociations: cfFunctions, }, certificate, domainNames: [siteFqdn], comment: `Samurai Apps Website ${envParams.envName}`, priceClass: cloudfront.PriceClass.PRICE_CLASS_200, logBucket, logFilePrefix: envParams.logPrefix, }); tagMyConstruct(this, distribution); // S3 deployment with refreshing cloudfront's cache. new s3deploy.BucketDeployment(this, "WebsiteDeployment", { // sources: [s3deploy.Source.asset("../src/public")], sources: [s3deploy.Source.asset("../src/site/public")], destinationBucket: websiteBucket, distribution, distributionPaths: ["/*"], }); // DNS configuration. const zone = route53.HostedZone.fromLookup(this, "HostedZone", { domainName: envParams.rootDomainName, }); const aliasRecord = new route53.ARecord(this, "AliasRecord", { zone, recordName: envParams.subDomainPrefix, target: route53.RecordTarget.fromAlias( new targets.CloudFrontTarget(distribution) ), }); tagMyConstruct(this, aliasRecord); } }
これにてご免!
画像クレジット: UnsplashのTaylor Vickが撮影した写真