AWS CDK で VPC Block Public Access の除外設定を作成する

AWS CDK で VPC Block Public Access の除外設定を作成する

Clock Icon2025.03.23

こんにちは、製造ビジネステクノロジー部の若槻です。

Amazon VPC Block Public Access (BPA) を設定すると、リージョン内のすべての VPC に対するインターネットアクセスをアカウントレベルで制御することができます。

前回の記事では、AWS CDK を使用して VPC Block Public Access を設定しました。
https://dev.classmethod.jp/articles/aws-cdk-vpc-block-public-access/

そしてこの VPC BPA では Exclusion (除外) を設定することにより、特定の VPC やサブネットを BPA の非対象にすることができます。
https://docs.aws.amazon.com/vpc/latest/userguide/security-vpc-bpa-basics.html#security-vpc-bpa-exclusions

今回はこの VPC Block Public Access の除外設定を AWS CDK で行う方法を確認してみました。

やってみた

AWS CDK による VPC Block Public Access の除外設定は CfnVPCBlockPublicAccessExclusion L1 コンストラクトクラスを使用します。
https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.CfnVPCBlockPublicAccessExclusion.html

VPC の除外設定

まずは VPC の除外設定のみを行ってみます。

lib/constructs/vpc-block-public-access/index.ts
import * as ec2 from "aws-cdk-lib/aws-ec2";
import { Construct } from "constructs";

export class VpcBlockPublicAccessConstruct extends Construct {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    // VPC Block Public Access の設定
    new ec2.CfnVPCBlockPublicAccessOptions(this, "Default", {
      internetGatewayBlockMode: "block-bidirectional", // 双方向のトラフィックをブロック
    });

    // VPC 1 の作成
    const vpc = new ec2.Vpc(this, "Vpc1", {
      maxAzs: 1,
    });

    // VPC 1 の除外設定
    new ec2.CfnVPCBlockPublicAccessExclusion(this, "Vpc1Exclusion", {
      internetGatewayExclusionMode: "allow-egress",
      vpcId: vpc.vpcId,
    });
  }
}

アカウント全体 → VPC の順で制限が緩くなるようにしています。

  • アカウント全体: 双方向のトラフィックをブロック
    • VPC 1: アウトバウンドのトラフィックを許可

上記をデプロイします。デプロイ開始から完了まで除外設定の作成も削除も2,3分ほど要しました。

デプロイ完了後、VPC Block Public Access のダッシュボードで VPC に対する除外設定が作成されていることが確認できました。ちなみに一度作成して削除した除外設定も一覧に残るんですね。

VPC およびサブネットの除外設定

続いて VPC と、その VPC のパブリックサブネットの除外設定を行ってみます。

lib/constructs/vpc-block-public-access/index.ts
import * as ec2 from "aws-cdk-lib/aws-ec2";
import { Construct } from "constructs";

export class VpcBlockPublicAccessConstruct extends Construct {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    // VPC Block Public Access の設定
    new ec2.CfnVPCBlockPublicAccessOptions(this, "VpcBlockPublicAccess", {
      internetGatewayBlockMode: "block-bidirectional", // 双方向のトラフィックをブロック
    });

    // VPC 1 の作成
    const vpc = new ec2.Vpc(this, "Vpc1", {
      maxAzs: 1,
    });

    // VPC 1 の除外設定
    new ec2.CfnVPCBlockPublicAccessExclusion(this, "Vpc1Exclusion", {
      internetGatewayExclusionMode: "allow-egress",
      vpcId: vpc.vpcId,
    });

    new cdk.CfnOutput(this, "Subnet1", {
      value: vpc.publicSubnets[0].subnetId,
    });

    // VPC 1 のパブリックサブネットの除外設定
    new ec2.CfnVPCBlockPublicAccessExclusion(
      this,
      "Vpc1PublicSubnetExclusion",
      {
        internetGatewayExclusionMode: "allow-bidirectional",
        subnetId: vpc.publicSubnets[0].subnetId,
      }
    );
  }
}

アカウント全体 → VPC → パブリックサブネットの順で制限が緩くなるようにしています。

  • アカウント全体: 双方向のトラフィックをブロック
    • VPC 1: アウトバウンドのトラフィックを許可
      • VPC 1 のパブリックサブネット: 双方向のトラフィックを許可

デプロイ完了後、VPC Block Public Access のダッシュボードでパブリックサブネットに対する除外設定が作成されていることが確認できました。

注意点

CfnVPCBlockPublicAccessExclusion では vpcIdsubnetId はプロパティとしては同時に指定可能ですが、実際にはどちらか一方のみを指定して除外設定を作成する必要があります。

lib/constructs/vpc-public-block-access/index.ts
import * as ec2 from "aws-cdk-lib/aws-ec2";
import { Construct } from "constructs";

export class VpcBlockPublicAccessConstruct extends Construct {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    // VPC Block Public Access の設定
    new ec2.CfnVPCBlockPublicAccessOptions(this, "Default", {
      internetGatewayBlockMode: "block-bidirectional", // 双方向のトラフィックをブロック
    });

    // VPC 1 の作成
    const vpc = new ec2.Vpc(this, "Vpc1", {
      maxAzs: 1,
    });

    // VPC 1 の除外設定
    new ec2.CfnVPCBlockPublicAccessExclusion(
      this,
      "Vpc1Exclusion",
      {
        internetGatewayExclusionMode: "allow-egress",
        vpcId: vpc.vpcId,
      }
    );

    // VPC 1 のパブリックサブネットの除外設定
    new ec2.CfnVPCBlockPublicAccessExclusion(
      this,
      "Vpc1PublicSubnetExclusion",
      {
        internetGatewayExclusionMode: "allow-bidirectional",
        vpcId: vpc.vpcId, // subnetId 指定時は vpcId は指定不要
        subnetId: vpc.publicSubnets[0].subnetId,
      }
    );
  }
}

上記の Vpc1PublicSubnetExclusion のように両方を指定してデプロイをすると、下記のように The following resource(s) failed to create というエラーとなりデプロイが失敗します。

9:42:24 PM | CREATE_FAILED        | AWS::EC2::VPCBlockPublicAccessExclusion | VpcBlockPublicAcce...licSubnetExclusion
Properties validation failed for resource VpcBlockPublicAccessVpc1PublicSubnetExclusionB5DC1522 with message:
#: #: only 1 subschema matches out of 2
#: #: 2 subschemas matched instead of one
9:42:24 PM | UPDATE_ROLLBACK_IN_P | AWS::CloudFormation::Stack              | Security
The following resource(s) failed to create: [VpcBlockPublicAccessVpc1PublicSubnetExclusionB5DC1522].
9:42:27 PM | UPDATE_ROLLBACK_COMP | AWS::CloudFormation::Stack              | Security

試しに VPC Block Public Access のダッシュボードから除外設定の作成メニューを開いてみると、やはり VPC とサブネットのいずれか一方を指定するようになっています。

AWS CDK でも同様にどちらか一方のみを指定して除外設定を作成するようにしましょう。

おわりに

今回は AWS CDK を使用して VPC Block Public Access の除外設定を行ってみました。

本記事がどなたかの参考になれば幸いです。

以上

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.