動機
Lightsail上にWordPressサイトを複数設置しているのですが、最近DDoS攻撃が激しくWAFを導入することにしました。
ただ、WAFはCloudFront、APIGateway、ALBにしか対応していないため、Lightsailに適用しようと思うと前段にALBまたはCloudFrontをおく必要があります。
じゃあ、CloudFrontを前段に置こう!
ん?
ってことはCloudFrontのディストリビューションをサイトごとに作成しないといけない。。。
コンソール上でぽちぽちするのは結構大変だな。
ここでAWS-CDKの出番です。
AWS CDKとは
IaC(Infrastructure as Code)を行えるフレームワークです。
TypeScript、Python、Java、.NET、Goなどの様々なプログラミング言語でAWSのサービスをデプロイする処理を記述することができます。
私の場合、TypeScriptの経験があるので今回はTypeScriptでCloudFrontをデプロイするコードを書き、パラメータを変更するだけで複数のディストリビューションを作成できるようにしました。
前提条件
- ACM(AmazonCertificateManager)およびWAF(WebApplicationFirewall)はすでに作成済みとします
- 各種パラメータはdotenvを利用して.envファイルから取得することとします(dotenvインストール済みの前提)
ACMでの証明書発行もCDK上で行なってしまおうとしたのですが、証明書認証待ちでタイムアウトしてしまい、デプロイがロールバックするのでACMでの証明書発行はコンソール上で手動で行うことにしました。
実際のコード
以下のコマンドを実行してCDKプロジェクトを作成します。
$ cdk init app --language typescript
libフォルダにあるファイルを修正します。
import * as cdk from 'aws-cdk-lib'
import { Construct } from 'constructs'
import * as acm from 'aws-cdk-lib/aws-certificatemanager'
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
import * as origins from 'aws-cdk-lib/aws-cloudfront-origins';
import 'dotenv/config'
export class WordpressCloudFrontStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props)
// 証明書取得
const certificate = acm.Certificate.fromCertificateArn(
this,
process.env.SITE_CERT?? '',
process.env.CERT_ARN?? ''
);
// オリジン設定
const origin = new origins.HttpOrigin(process.env.ORIGIN_DOMAIN_NAME?? '')
// ディストリビューション作成
const distribution = new cloudfront.Distribution(this, process.env.DISTRIBUTION_NAME?? '', {
defaultBehavior: {
origin: origin,
viewerProtocolPolicy:cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
},
domainNames:[process.env.DOMAIN_NAME?? ''],
certificate:certificate,
enableLogging: true, // Optional, this is implied if logBucket is specified
logBucket: new s3.Bucket(this, 'wordpress-cloudfront-log', {
objectOwnership: s3.ObjectOwnership.OBJECT_WRITER,
}),
logFilePrefix: process.env.DOMAIN_NAME?? ''+'/',
logIncludesCookies: false,
})
// ビヘイビアの追加
const pathsStr = process.env.PATHS?? ''
for(let path of pathsStr.split(':')){
distribution.addBehavior(
path,origin,
{
viewerProtocolPolicy:cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
cachePolicy:cloudfront.CachePolicy.CACHING_DISABLED
}
)
}
}
}
また.envファイルに以下のように記述します。
CDK_DEFAULT_ACCOUNT='[利用していないので空でいい]'
CDK_DEFAULT_REGION='[メインで使うリージョン]'
SITE_CERT='[ACMで作成した証明書の名前]'
CERT_ARN='[ACMで作成した証明書のARN]'
DOMAIN_NAME='[ACMで作成した証明書の ドメイン]'
ORIGIN_DOMAIN_NAME='[Lightsail上のWordPressに設定しているドメイン]'
DISTRIBUTION_NAME='[CloudFront上に作成するディストリビューションにつける名前]'
PATHS="/wp-admin/*:*.php"
WEB_ACL_ID="[WAFで作成したWebACLのID]"
PATHSはキャッシュしないファイルパスを指定しています。
今回はWordPressでキャッシュするとまずい/wp-admin/内のファイルおよびphpファイルに対してCACHING_DISABLEDポリシーを設定します。
まとめ
無事にCloudFrontディストリビューションをデプロイし、WAFのルールセットを反映させることができました。
今後もAWS-CDKをうまく利用しながら開発効率を上げていきたいと思います。