📝
CDK で Amplify アプリに WAF をアタッチしてみた
- Enabling AWS WAF for an Amplify application using the AWS CDK - AWS Amplify Hosting
-
CodeCommit をソースとする Amplify アプリを CDK で作成してみた
上記資料を組み合わせてやってみました。
前提
- CDK 実行環境は Cloud9
- CDK の言語は TypeScript
- CodeCommit リポジトリは作成済み
- index.html のみプッシュ済み
事前準備
# TypeScript をインストール
$ mkdir -p ~/.npm-global
$ npm config set prefix '~/.npm-global'
$ echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc
$ source ~/.bashrc
$ npm install -g typescript
$ mkdir amplify-waf-cdk
$ cd amplify-waf-cdk
$ cdk init app --language typescript
# 既存のスタックファイルを削除
$ rm lib/amplify-waf-cdk-stack.ts
# 新しいスタックファイルを作成
$ touch lib/amplify-stack.ts
$ touch lib/waf-stack.ts
コード
以下のようにコードを定義しました。
lib/amplify-stack.ts
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as amplify from 'aws-cdk-lib/aws-amplify';
import * as customResources from 'aws-cdk-lib/custom-resources';
export class AmplifyStack extends cdk.Stack {
public readonly appArn: string;
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const amplifyRole = new iam.Role(this, 'AmplifyServiceRole', {
assumedBy: new iam.ServicePrincipal('amplify.amazonaws.com'),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('AdministratorAccess-Amplify')
]
});
const amplifyApp = new amplify.CfnApp(this, 'AmplifyApp', {
name: 'cdk-app',
repository: 'https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/test',
iamServiceRole: amplifyRole.roleArn,
enableBranchAutoDeletion: false
});
this.appArn = amplifyApp.attrArn;
const amplifyBranch = new amplify.CfnBranch(this, 'AmplifyBranch', {
appId: amplifyApp.attrAppId,
branchName: 'main',
stage: 'PRODUCTION',
enablePullRequestPreview: false,
enableAutoBuild: true,
enablePerformanceMode: false
});
amplifyBranch.addDependency(amplifyApp);
const deployTrigger = new customResources.AwsCustomResource(this, 'AmplifyDeployTrigger', {
onCreate: {
service: 'Amplify',
action: 'startJob',
parameters: {
appId: amplifyApp.attrAppId,
branchName: 'main',
jobType: 'RELEASE'
},
physicalResourceId: customResources.PhysicalResourceId.of('AmplifyDeployTrigger'),
},
policy: customResources.AwsCustomResourcePolicy.fromSdkCalls({
resources: customResources.AwsCustomResourcePolicy.ANY_RESOURCE
})
});
deployTrigger.node.addDependency(amplifyBranch);
}
}
lib/waf-stack.ts
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as wafv2 from 'aws-cdk-lib/aws-wafv2';
interface WafStackProps extends cdk.StackProps {
appArn: string;
}
export class WafStack extends cdk.Stack {
constructor(scope: Construct, id: string, props: WafStackProps) {
super(scope, id, props);
// WAF Web ACL を作成
const webAcl = new wafv2.CfnWebACL(this, 'WebACL', {
defaultAction: { allow: {} },
scope: 'CLOUDFRONT',
rules: [
],
visibilityConfig: {
cloudWatchMetricsEnabled: true,
metricName: 'amplify-waf-metric',
sampledRequestsEnabled: true,
},
});
new wafv2.CfnWebACLAssociation(this, 'WebACLAssociation', {
resourceArn: props.appArn, // AmplifyStack から渡された appArn
webAclArn: webAcl.attrArn,
});
}
}
lib/waf-stack.ts
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { AmplifyStack } from '../lib/amplify-stack';
import { WafStack } from '../lib/waf-stack';
const app = new cdk.App();
const amplifyStack = new AmplifyStack(app, 'AmplifyStack', {
env: {
region: 'ap-northeast-1',
account: process.env.CDK_DEFAULT_ACCOUNT
},
});
new WafStack(app, 'WafStack', {
env: {
region: 'us-east-1',
account: process.env.CDK_DEFAULT_ACCOUNT
},
crossRegionReferences: true,
appArn: amplifyStack.appArn,
});
デプロイ
$ cdk synth
# 東京リージョン (ap-northeast-1) をブートストラップ
cdk bootstrap aws://$(aws sts get-caller-identity --query Account --output text)/ap-northeast-1
# バージニア北部リージョン (us-east-1) をブートストラップ
cdk bootstrap aws://$(aws sts get-caller-identity --query Account --output text)/us-east-1
# デプロイ
$ cdk deploy
WAF のアタッチを確認
Amplify コンソールから対象のアプリに WAF がアタッチされていることを確認できれば OK です。

また、WAF コンソールからも対象のアプリに WAF がアタッチされていることを確認できます。

まとめ
今回は CDK で Amplify アプリに WAF をアタッチしてみました。
どなたかの参考になれば幸いです。
Discussion