VPC CIDRブロックをRFC 1918の範囲に限定する方法 (Terraform&CloudFormation)

正規表現を利用してVPC CIDRブロックを検証します。
2022.03.15

大家好、コンサルティング部の西野です。

AWSはVPCのCIDRブロックをRFC 1918で定められたプライベートアドレスの範囲内で設定するよう推奨しています。1

「推奨」とされていることからわかるように、プライベートアドレスレンジから外れたCIDRブロックも設定できます。 ただしこの場合、IPアドレスのバッティングにより一部の通信に支障をきたす可能性があります。 したがって、特段の事情がない限り、このプライベートアドレスレンジからVPC CIDRを設定すると良いでしょう。

本稿ではTerraformもしくはCloudFormationによって作成されるVPC CIDRブロックをこの範囲に限定する方法を記します。

最初に結論

  • TerraformおよびCloudFormationでは変数ないしパラメータの検証に正規表現を利用できます。
  • Terraformではconditionブロック内においてcan関数およびregex関数を使用します。
  • CloudFormationではParametersセクションのパラメータにAllowedPatternプロパティを使用します。

Terraform

コード

variable "vpc_cidr_block" {
  type = string

  validation {
    condition     = can(regex("(^10\\..+)|(^172\\.(1[6-9]|2[0-9]|3[0-1])\\..+)|(^192\\.168\\..+)", var.vpc_cidr_block))
    error_message = "You must set the input variable \"vpc_cidr_block\" to the Private Address Space range of RFC 1918."
  }
}

resource "aws_vpc" "main" {
  cidr_block = var.vpc_cidr_block
}

※providerの指定などは省略しています。

解説

上記コード4-7行目のvalidationブロックで検証をしています。このvalidationブロックはconditionfalseとして評価された場合にerror_messageで指定したエラーメッセージを表示してくれます。

can関数およびregex関数の組み合わせにより、vpc_cidr_blockとして与えられた変数がパターンマッチする場合にはtrueが、そうでない場合にはfalseが渡されます。

動かしてみる

まずはプライベートアドレスレンジに含まれているCIDRブロックを渡してみます。
問題なくterraform planに成功します。

$ terraform plan -var 'vpc_cidr_block=172.16.0.0/16'

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_vpc.main will be created
  + resource "aws_vpc" "main" {
      + arn                                  = (known after apply)
      + cidr_block                           = "172.16.0.0/16"
      (省略)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

続いてプライベートアドレスレンジから外れたCIDRブロックをわたします。

$ aws-vault exec nishino-admin -- terraform plan -var 'vpc_cidr_block=172.32.0.0/16'
╷
│ Error: Invalid value for variable
│
│   on main.tf line 1:
│    1: variable "vpc_cidr_block" {
│
│ You must set the input variable "vpc_cidr_block" to the Private Address Space range of RFC 1918.
│
│ This was checked by the validation rule at main.tf:4,3-13.

しっかりエラーを出してくれました。
検証の精度は正規表現のパターンに依存するものの、本稿の目的は達しています。2

CloudFormation

コード

AWSTemplateFormatVersion: "2010-09-09"

Parameters:
  VpcCidr:
    Type: String
    AllowedPattern: (^10\..+)|(^172\.(1[6-9]|2[0-9]|3[0-1])\..+)|(^192\.168\..+)
    ConstraintDescription: You must set the parameter "VpcCidr" to the Private Address Space range of RFC 1918.

Resources: 
  VPC:
    Type: AWS::EC2::VPC
    Properties: 
      CidrBlock: !Ref VpcCidr

解説

こちらはParameterのAllowedPatternプロパティで正規表現を使用してあげるだけです。Terraformの場合と若干エスケープ処理が異なるのでご注意ください。
AllowedPatternにマッチしないパラメータを渡した場合、スタックの作成が失敗し、エラーメッセージとしてConstraintDescriptionに指定した内容が表示されます。

動かしてみる

こちらもまずはプライベートアドレスレンジに含まれているCIDRブロックを渡してみます

$ aws cloudformation create-stack \
--stack-name stack1 \
--template-body file://./vpc.yaml \
--parameters \
ParameterKey=VpcCidr,ParameterValue="10.0.0.0/16"

コマンドの実行に成功するため、少しまってから下記コマンドでリソースの状況を確認してみます。

$ aws cloudformation list-stack-resources --stack-name stack1
{
    "StackResourceSummaries": [
        {
            "LogicalResourceId": "VPC",
            "PhysicalResourceId": "vpc-039b9c5287435705a",
            "ResourceType": "AWS::EC2::VPC",
            "LastUpdatedTimestamp": "2022-03-15T11:20:11.842000+00:00",
            "ResourceStatus": "CREATE_COMPLETE",
            "DriftInformation": {
                "StackResourceDriftStatus": "NOT_CHECKED"
            }
        }
    ]
}

無事VPCが作成されています。
続いて、プライベートアドレスレンジから外れたCIDRブロックをわたします。

$ aws cloudformation create-stack \
--stack-name stack2 \
--template-body file://./vpc.yaml \
--parameters \
ParameterKey=VpcCidr,ParameterValue="192.169.0.0/16"

An error occurred (ValidationError) when calling the CreateStack operation: Parameter VpcCidr failed to satisfy constraint: You must set the parameter "VpcCidr" to the Private Address Space range of RFC 1918.

こちらも想定通りエラーを出してくれました。

終わりに

構築手段としてIaCを利用する場合でも何らかの手段によってパラメータそのものの妥当性を担保する必要があります。 本稿で説明した内容がきっとその一助になるはずです。

このブログがほんの少しでも世界を良くできれば嬉しいです。
コンサルティング部の西野 (@xiyegen) がお送りしました。

参考

Terraform

CloudFormation


  1. Overview of VPCs and subnets - Amazon Virtual Private Cloud 
  2. 文字列の先頭一致のみで検証しています。もっとイケてる書き方をご存知の方はこっそり教えてくれると嬉しいです。