tl;dr
俺の AWS CDK コードを恥ずかしげもなく晒すシリーズ第一弾の続き. そして, この記事は YAMAP エンジニア Advent Calendar 2019 の五日目の記事になる予定です.
実現したいこと
昨日, 恥ずかしげもなく公開したコードを少し進化させてみました. 進化の内容は以下の通り.
- 出来るだけ, 肝となるコード内にドメイン名とか ID とか汎用性の低い情報を書かないようにする
- WAF の WebACL を紐付ける
俺の AWS CDK
リポジトリ
引き続き, 以下にアップしています.
肝となる lib/tutorial01-stack.ts は以下の通り.
import cdk = require('@aws-cdk/core'); import s3 = require('@aws-cdk/aws-s3'); import cf = require('@aws-cdk/aws-cloudfront'); import iam = require('@aws-cdk/aws-iam'); import route53 = require('@aws-cdk/aws-route53'); import route53_targets = require('@aws-cdk/aws-route53-targets/lib'); interface Tutorial01InfraStackProps extends cdk.StackProps { domain: string; project: string; issue: string; owner: string; certificate_arn: {[key: string]: string}; logbucket_name: string; webacl_id: string; } export class Tutorial01InfraStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props: Tutorial01InfraStackProps) { super(scope, id, props); // const envName = this.node.tryGetContext('env'); const envName = process.env.DEPLOY_ENV ? process.env.DEPLOY_ENV : 'dev'; const domainName = this.node.tryGetContext('fqdn'); // Create Bucket for contents const websiteBucket = new s3.Bucket(this, `Tutorial01Infra-s3bucket-${this.stackName}`, { bucketName: domainName, }); // Define Bucket for logging const loggingBucket = s3.Bucket.fromBucketName( this, `Tutorial01Infra-loggingbucket-${this.stackName}`, props.logbucket_name ); // Create CloudFront Origin Access Identity const OAI = new cf.CfnCloudFrontOriginAccessIdentity(this, `Tutorial01Infra-identity-${this.stackName}`,{ cloudFrontOriginAccessIdentityConfig:{ comment: `Tutorial01Infra-identity-${this.stackName}` } }); // Create Access Policy for S3 Bucket const webSiteBucketPolicyStatement = new iam.PolicyStatement({effect: iam.Effect.ALLOW}); webSiteBucketPolicyStatement.addCanonicalUserPrincipal(OAI.attrS3CanonicalUserId); webSiteBucketPolicyStatement.addActions("s3:GetObject"); webSiteBucketPolicyStatement.addResources(`${websiteBucket.bucketArn}/*`); websiteBucket.addToResourcePolicy(webSiteBucketPolicyStatement); // Create CloudFront Distribution const distribution = new cf.CloudFrontWebDistribution(this, `Tutorial01Infra-cloudfront-${this.stackName}`, { originConfigs:[ { s3OriginSource: { s3BucketSource: websiteBucket, originAccessIdentityId: OAI.ref }, behaviors: [{ isDefaultBehavior: true}] } ], aliasConfiguration: { acmCertRef: props.certificate_arn[envName], names: [domainName], sslMethod: cf.SSLMethod.SNI, securityPolicy: cf.SecurityPolicyProtocol.TLS_V1_1_2016, }, viewerProtocolPolicy: cf.ViewerProtocolPolicy.REDIRECT_TO_HTTPS, priceClass: cf.PriceClass.PRICE_CLASS_ALL, loggingConfig: { bucket: loggingBucket, prefix: domainName + '/' }, webACLId: props.webacl_id }); const zone = route53.HostedZone.fromLookup(this, 'Zone', { domainName: props.domain }); new route53.ARecord(this, `Distribution-route53-record-${this.stackName}`, { recordName: domainName, target: route53.AddressRecordTarget.fromAlias(new route53_targets.CloudFrontTarget(distribution)), zone }); for (let cons of [websiteBucket, distribution]) { cdk.Tag.add(cons, 'Project', props.project); cdk.Tag.add(cons, 'Environment', envName); cdk.Tag.add(cons, 'Owner', props.owner); cdk.Tag.add(cons, 'Issue', props.issue); cdk.Tag.add(cons, 'Name', domainName); } // Output CloudFront URL new cdk.CfnOutput(this, 'CloudFrontURL', {value: `https://${distribution.domainName}/`}) // Output Distribution ID new cdk.CfnOutput(this, 'DistributionId', { value: distribution.distributionId }); } }
更に, bin/tutorial01-stack.ts は以下のように書きました. こちらに出来るだけユニークな情報 (汎用性の低い情報) を寄せるようにした感じです.
#!/usr/bin/env node import 'source-map-support/register'; import cdk = require('@aws-cdk/core'); import { Tutorial01Stack } from '../lib/tutorial01-stack'; const deployEnv = process.env.DEPLOY_ENV ? process.env.DEPLOY_ENV : 'dev'; const app = new cdk.App(); new Tutorial01Stack(app, `Tutorial01Stack-${deployEnv}`, { env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION }, domain: 'example.com', project: 'my-project', issue: 'my-issue', owner: 'My Team', certificate_arn: { dev: 'arn:aws:acm:us-east-1:123456789012:certificate/xxxxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx', production: 'arn:aws:acm:us-east-1:123456789012:certificate/xxxxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx' }, logbucket_name: 'my-log-bucket-name', webacl_id: 'xxxxxxxxx-xxxx-xxxx-xxxxx-xxxxxxxx' });
従来は --context
オプションを使って渡していた dev
とか production
を表現する文字列については, 環境変数から渡すようにして, 環境毎に CloudFormation スタックを作るようにしました.
以上
引き続き, 頑張って AWS CDK を習得していきたいと思います.
完