AWS CDKのカスタムリソースでAWS-managed prefix listsを扱う
はじめに
2024/6月時点でaws cdkでS3やCloudFrontのAWS-managed prefix listsを扱うには、プレフィックスのIDを事前に把握する必要があります。
例えば、以下のようにすれば、SecurityGroupのインバウンドに許可を追加できます。
ここでは、pl-02cd2c6b
をマネジメントコンソールなどから把握しておきます。
export class MyStack extends Stack {
constructor(scope: Construct, id: string, props: StackProps = {}) {
super(scope, id, props);
const vpc = new Vpc(this, 'Vpc', {
natGateways: 0,
});
const sg = new SecurityGroup(this, 'SecurityGroup', {
vpc: vpc,
});
// us-east-1のDynamoDB用のAWS-magaged prefix lists
sg.connections.allowFrom(Peer.prefixList('pl-02cd2c6b'), Port.HTTPS);
}
}
問題点というほどでもないのですが、リージョンごとに異なるプレフィックスIDを事前に用意しておくことはめんどうです。
そこで、カスタムリソースを使用して入力されたプレフィックスリスト名からプレフィックスIDを動的に取得するAwsManagedPrefixList
というConstructを作ってみました。
AwsManagedPrefixList
作ったもの
このブログを書きながら作ったので誤字脱字はあるかもしれません。
使い方
main.tsをみればだいたいわかると思います。
nameにプレフィックスリスト名を入れることで、プレフィックスIDを取得できます。
CDK上でリージョンを動的に取得するようにすれば、いちいちコードを書き換えなくても問題ありません。
import { AwsManagedPrefixList } from './utils/aws-managed-prefix-list';
export class MyStack extends Stack {
constructor(scope: Construct, id: string, props: StackProps = {}) {
super(scope, id, props);
const vpc = new Vpc(this, 'Vpc', {
natGateways: 0,
});
const sg = new SecurityGroup(this, 'SecurityGroup', {
vpc: vpc,
});
// S3 AWS-managed prefix lists
const s3PrefixList = new AwsManagedPrefixList( this, 'S3PrefixList',
{ name: `com.amazonaws.${Aws.REGION}.s3` },
).prefixList;
sg.connections.allowFrom(Peer.prefixList(s3PrefixList.prefixListId), Port.HTTPS);
// CloudFront AWS-managed prefix lists
const cloudfrontPrefixList = new AwsManagedPrefixList(
this,
'CloudfrontOriginPrefixList',
{ name: 'com.amazonaws.global.cloudfront.origin-facing' },
).prefixList;
sg.connections.allowFrom(Peer.prefixList(cloudfrontPrefixList.prefixListId), Port.HTTPS);
}
}
仕組み
元ネタはこのissueです。
やっていることは簡単で、AwsCustomResource
を使ってDescribeManagedPrefixListsCommand
をたたいています。
実行するためにIAMポリシーも付与していますが、Resouce
句にはドキュメントを参考にすべてを指定しています。
physicalResourceId
がいまいちよくわかってないので、適当にかわらなそうなIDにしておきました。
AwsCustomResource
の説明は以下がわかりやすいです。
export class AwsManagedPrefixList extends Construct {
public readonly prefixList: IPrefixList;
constructor(scope: Construct, id: string, { name }: AwsManagedPrefixListProps) {
super(scope, id);
const prefixListId = new AwsCustomResource(this, 'GetPrefixListId', {
installLatestAwsSdk: true,
onUpdate: {
service: '@aws-sdk/client-ec2',
action: 'DescribeManagedPrefixListsCommand',
parameters: {
Filters: [
{
Name: 'prefix-list-name',
Values: [name],
},
],
},
physicalResourceId: PhysicalResourceId.of(`${id}-${this.node.addr.slice(0, 16)}`),
},
policy: AwsCustomResourcePolicy.fromStatements([
new PolicyStatement({
effect: Effect.ALLOW,
actions: ['ec2:DescribeManagedPrefixLists'],
resources: ['*'],
}),
]),
}).getResponseField('PrefixLists.0.PrefixListId');
this.prefixList = PrefixList.fromPrefixListId(this, 'PrefixList', prefixListId);
}
}
実行結果
GitHubに上がっているCDKを実行した結果です。
ちゃんとインバウンドに許可が追加されました!
おわりに
簡単ですが、AwsCustomResource
を使ってAWS-managed prefix listsのプレフィックスIDを取得するコンストラクタを作りました。
内部で使う場合には利用するリージョンもある程度見えていると思いますが、GitHubなどで公開するときに、プレフィックスIDを取得する方法が欲しくて作ってみました。
簡単にできるかわりにLambdaが増えるという問題点が生まれるのが気になりポイント
Construct Hubに上げるかは悩み中。公開するなら将来名前が衝突しなさそうな名前に変えたいところ
Discussion