azure 如何在Terraform中验证IP地址?

flseospp  于 2023-04-22  发布在  其他
关注(0)|答案(4)|浏览(132)

我正在使用Terraform将代码部署到我的Azure基础架构中。
我有一个Azure防火墙,它有一些网络规则,其中有一堆自由文本IP地址作为源/目标。下面的例子;[请注意,为了这个例子,真实的的IP地址已经改变了];

网络规则收集

network_rule_collection {
    name     = "test_rules"
    priority = 400
    action   = "Allow"
    rule {
      name                  = "test-rule-1"
      protocols             = ["Any"]
      source_addresses      = ["123.0.2.10/32"]
      destination_ports     = ["1234"]
      destination_addresses = ["124.82.189.200/32","125,82.189.200/32","126..82.189.200/32"]
    }
  }
}

[note IP地址中有错误是为了证明]
然而,当我运行Terraform Validate时,它没有显示任何错误(即使上面输入了无效的IP地址)
所以我需要一种方法来验证自由文本IP地址作为Terraform验证/计划的一部分。目前,Terraform接受这一点,并将无效的IP部署到基础设施中。

lpwwtiir

lpwwtiir1#

由于您正在填充的参数被定义为接受CIDR块地址,原则上提供程序可以验证这些地址,但在这种特定情况下,它似乎没有自己的验证规则,因此它依赖于远程API的验证,因此只有在应用步骤中才会生效。
在提供者的GitHub存储库中打开一个问题来讨论在这里添加内置验证的可能性可能是值得的,但是为了这个答案,我假设这是不可能的,并讨论如何在自己的配置中定义验证规则。
由于这些值直接硬编码在资源配置中,因此不需要进行自定义验证,因为resource块的内容(除了一些特殊参数,如countfor_each)完全由相应的提供程序负责。
但是,如果您打算编写一个共享的Terraform模块,将这些IP地址作为input variables,然后从资源配置中引用它们,则可以编写自定义验证规则来描述附加的约束,这些约束必须为真,才能使该变量的特定值被视为有效。
validation块中的condition参数期望一个布尔值,如果条件成立,则为true,如果条件不满足,则为false。然而,由于Terraform也有很多内置函数,如果不满足其自己的验证规则,则会失败并返回错误。Terraform也有一个特殊的can function,它在一个特殊的上下文中评估表达式,其中失败被转换为false结果,而任何成功都被转换为true结果。因此满足condition参数的期望。
一个典型的策略是识别一个现有的Terraform函数,该函数具有您想要应用的相同验证规则,并在can中调用该值,以使用其成功或失败作为验证条件。
特别是对于CIDR块地址,Terraform有少量的函数,它们将这些作为输入并产生派生的CIDR块地址或IP地址。例如,cidrnetmask接受IPv4 CIDR块地址并以网络掩码表示法返回相同的地址。如果给定的字符串不是有效的IPv4 CIDR块,它将失败,因此,它似乎是描述您要在这里检查的规则的一个很好的候选者:

variable "source_address" {
  type = string

  validation {
    condition     = can(cidrnetmask(var.source_address))
    error_message = "Must be a valid IPv4 CIDR block address."
  }
}

这里的示例有一个额外的要求,即接受 * 多个 * 地址,因此需要稍微复杂一点的验证规则来测试条件是否对给定集合的所有成员都成立,这正是the alltrue function的目的:

variable "source_addresses" {
  type = set(string)

  validation {
    condition = alltrue([
      for a in var.source_addresses : can(cidrnetmask(a))
    ])
    error_message = "All elements must be valid IPv4 CIDR block addresses."
  }
}

这里的[ for ... ]表达式是通过对集合中的每个元素a尝试can(cidrnetmask(a))来生成一个布尔结果列表。alltrue然后解释该结果,并仅当列表中的每个元素都是true时才返回单个true
为了应用这些规则,你需要通过这些输入变量传递可能无效的IP地址,而不是像你的例子中那样直接在resource块中提供它们。只有当你打算编写一个可重用的模块,调用者将为每个示例提供不同的IP地址时,这才真正有意义。如果你打算只使用一组固定的IP地址,更简单方法是,在最初指定它们时确保它们有效,并相信它们在将来保持有效,除非进行更改。

06odsfpq

06odsfpq2#

根据文档,Validate将验证语法,而不是值。
Validate运行检查,以验证配置在语法上是否有效
一种选择是定义一个变量并使用regex.Reference添加自定义验证规则。

variable "ip_address" {
    type          = string
    description   = "Example to validate IP address."
    validation {
        condition = can(regex("^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$",var.ip_address))
        error_message = "Invalid IP address provided."
    }
}
x8goxv8g

x8goxv8g3#

您可以将IP地址定义为变量并使用验证规则:
https://www.terraform.io/language/values/variables#custom-validation-rules
除了如上所述的类型约束之外,模块作者可以使用嵌套在相应变量块内的验证块来为特定变量指定任意自定义验证规则:
然后使用正则表达式来验证给定的IP地址看看这个中型博客来获得启发https://ishusinghkanwar.medium.com/variable-validation-in-terraform-a9c887d987ff

nr9pn0ug

nr9pn0ug4#

或者测试非CIDR格式的单个地址

variable "source_address" {
  type = string

  validation {
    condition     = can(cidrnetmask("${var.source_address}/32"))
    error_message = "Must be a valid IPv4 CIDR block address."
  }
}

相关问题