Search code examples
validationvariablesterraform

Terraform CIDR block variable validation


Terraform variable validation for CIDR, looking alternative for regex

Below is the tested code in Terraform version 13.0 is there any alternative way to achieve same thing with not using regex?

cidr block - start 172.28.0.0.0/16

    variable "vpc_cidr" {
      description = "Kubernetes cluster CIDR notation for vpc."
      validation {
        condition     = can(regex("^([0-9]{1,3}\\.){3}[0-9]{1,3}($|/(16))$", var.pod_cidr))
        error_message = "Vpc_cidr value must be greater than 172.0.0.0/16."
      }
    }

how to validate CIDR block 172.28.x.x/16 with cidrsubnet function? https://www.terraform.io/docs/language/functions/cidrsubnet.html

validation condition - if IP range is outof 172.28.x.x/16 then validation will be failed


Solution

  • I can't think of a direct way to achieve what you want with the functions in today's Terraform, but I think we can break the check into two conditions that, taken together, lead to the same effect:

    1. The zeroth address in the subnet must be 172.28.0.0.
    2. The netmask of the range must be 255.255.0.0.

    We can test these two rules using two expressions:

    1. cidrhost(var.vpc_cidr, 0) == "172.28.0.0"
    2. cidrnetmask(var.vpc_cidr) == "255.255.0.0"

    Both of these functions can fail if given something that isn't valid CIDR block syntax at all, and cidrnetmask will additionally fail if given an IPv6 address, so we can add try guards to both of them to turn that error into a false result as condition expects:

    1. try(cidrhost(var.vpc_cidr, 0), null) == "172.28.0.0"
    2. try(cidrnetmask(var.vpc_cidr), null) == "255.255.0.0"

    The try function will return the result of the first expression that doesn't produce a dynamic error, so in the above examples an invalid input to the cidrhost or cidrnetmask function will cause an expression like null == "172.28.0.0", which will always be false and thus the condition will still not be met.

    Finally, we can combine these together using the && operator to get the complete condition expression:

      condition = (
        try(cidrhost(var.vpc_cidr, 0), null) == "172.28.0.0" &&
        try(cidrnetmask(var.vpc_cidr), null) == "255.255.0.0"
      )