【AWS CDK】VPC コンストラクタでまとめて作成したサブネットの CIDR ブロックでセキュリティグループの設定をする方法

2020.10.09

はじめに

AWS CDK で作成したサブネットの情報をどうやって取得するかハマったときのメモになります。

使用する言語は TypeScript です。

※ この記事は AWS CDK v1.63.0 のものです。 v1.64.0 以降は後述の方法で解決できます。

AWS CDK + TypeScript はいいぞ!

やること

  • VPC を作成し、パブリックサブネットを2つ、プライベートサブネットを1つ作成する
  • セキュリティグループを作成し、2つ目のパブリックサブネットから5432ポートへの通信を許可する

できたもの

import * as cdk from "@aws-cdk/core";
import * as ec2 from "@aws-cdk/aws-ec2";
import { CfnSubnet, Peer, Port, SecurityGroup } from "@aws-cdk/aws-ec2";

export class ExampleVpcSubnetStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const vpc = new ec2.Vpc(this, "VPC", {
      cidr: "192.168.0.0/16",
      subnetConfiguration: [
        {
          cidrMask: 24,
          name: "public-1",
          subnetType: ec2.SubnetType.PUBLIC,
        },
        {
          cidrMask: 24,
          name: "public-2",
          subnetType: ec2.SubnetType.PUBLIC,
        },
        {
          cidrMask: 24,
          name: "private",
          subnetType: ec2.SubnetType.PRIVATE,
        },
      ],
    });

    const securityGroup = new SecurityGroup(this, "SecurityGroup", {
      vpc: vpc,
    });

    vpc.selectSubnets({ subnetGroupName: "public-2" }).subnets.forEach((x) => {
      const cfnSubnet = x.node.defaultChild as CfnSubnet;
      securityGroup.addIngressRule(
        Peer.ipv4(cfnSubnet.cidrBlock),
        Port.tcp(5432)
      );
    });
  }
}

解説

VPC とサブネットをまとめて作成

Vpc コンストラクタsubnetConfiguration を使用することでサブネットまでまとめて作成できます。

https://docs.aws.amazon.com/cdk/api/latest/typescript/api/aws-ec2/vpcprops.html#aws_ec2_VpcProps_subnetConfiguration

    const vpc = new ec2.Vpc(this, "VPC", {
      cidr: "192.168.0.0/16",
      subnetConfiguration: [
        {
          cidrMask: 24,
          name: "public-1",
          subnetType: ec2.SubnetType.PUBLIC,
        },
        {
          cidrMask: 24,
          name: "public-2",
          subnetType: ec2.SubnetType.PUBLIC,
        },
        {
          cidrMask: 24,
          name: "private",
          subnetType: ec2.SubnetType.PRIVATE,
        },
      ],
    });

セキュリティグループの作成

ここは普通にセキュリティグループを作成しているだけです。

    const securityGroup = new SecurityGroup(this, "SecurityGroup", {
      vpc: vpc,
    });

特定サブネットの CIDER ブロックを取得しセキュリティグループ設定

VPCコンストラクタで作成したサブネットの CIDR ブロックをどうやって取得したらいいのかハマったところで今回のメインになります。

selectSubnets() で サブネット名を元に特定のサブネットを取得すること自体は IntelliSense のおかげですんなり実装できました。しかし戻り値が ISubnet インタフェースで、それを継承している PublicSubnet クラスにも CIDR ブロックを取得するためのプロパティやメソッドはありませんでした(過去形)

以下のように CfnSubnet でキャストすることで CIDR ブロックを取り出すことができました。

    vpc.selectSubnets({ subnetGroupName: "public-2" }).subnets.forEach((x) => {
      const cfnSubnet = x.node.defaultChild as CfnSubnet;
      securityGroup.addIngressRule(
        Peer.ipv4(cfnSubnet.cidrBlock),
        Port.tcp(5432)
      );
    });

(v1.64.0以降)と、思っていたら

この記事を下書きに寝かせている間にCDKのバージョンが v1.64.0 に上がり、ISubnet インタフェースに ipv4CidrBlock プロパティが生えました。

よってわざわざキャストする必要もなくなったので以下のように簡潔に記述することができるようになりました。

    vpc.selectSubnets({ subnetGroupName: "public-2" }).subnets.forEach((x) => {
      securityGroup.addIngressRule(Peer.ipv4(x.ipv4CidrBlock), Port.tcp(5432));
    });

まとめ

  • AWS CDK + TypeScript はいいぞ!
  • AWS CDK は進化が早い
  • 鉄は熱いうちに打て