I have two types of variables in terrafrom.
First two are object() type
variable "var1" {
type = object({
host_name = string
key_vault_id = optional(string)
})
default = {
host_name = "api.example.com"
key_vault_id = "https://keyvault1.vault.azure.net/secrets/example-cert1"
}
}
variable "var2" {
type = object({
host_name = string
key_vault_id = optional(string)
})
default = {
host_name = "portal.example.com"
key_vault_id = "https://keyvault2.vault.azure.net/secrets/example-cert2"
}
}
and, second one is map(object())
variable "var3" {
type = map(object({
value = string
secret = bool
secret_id = optional(string)
identity_client_id = optional(string)
}))
default = {
"my-named-value-1" = {
value = ""
secret = true
secret_id = "https://keyvault3.vault.azure.net/secrets/secret1003"
}
"my-named-value-2" = {
value = ""
secret = true
secret_id = "https://keyvault4.vault.azure.net/secrets/secret1003"
}
}
}
To extract the key vault id from this variable i'm using the below code
locals {
key_vault_names = distinct(
compact(
concat(
[
var.var1!= null ? regex("https://([a-zA-Z0-9-]{3,24})", var.var1.key_vault_id) : null,
var.var2!= null ? regex("https://([a-zA-Z0-9-]{3,24})", var.var2.key_vault_id) : null
],
[
for value in values(var.var3) : regex("https://([^.]+).vault.azure.net", value.secret_id) if value.secret_id != ""
]
)
)
)
}
data "azurerm_key_vault" "key_vaults" {
for_each = toset(local.key_vault_names)
name = each.key
resource_group_name = var.resource_group_name
}
locals {
key_vault_ids = [
for kv in data.azurerm_key_vault.key_vaults : kv.id
]
}
But it is failing because of below code
Error: Invalid function argument
│
│
│ 26: compact(
│ 27: concat(
│ 28: [
│ 29: var.var1!= null ? regex("https://([a-zA-Z0-9-]{3,24})",
var.var1.key_vault_id) : null,
var.var2!= null ? regex("https://([a-zA-Z0-9-]{3,24})", var.var2.key_vault_id)
: null
│ 32: ],
│ 33: # [
│ 34: # for value in values(var.var3) :
regex("https://([^.]+).vault.azure.net", value.secret_id) if value.secret_id != ""
│ 35: # ]
│ 36: )
│ 37: )
│ ├────────────────
│ │ while calling compact(list)
│ │ var.var2 is a object
│ │ var.var2.key_vault_id is a string
│ │ var.var1 is a object
│ │ var.var1.key_vault_id is a string
│ │ var.var3 is map of object with 2 elements
│
│ Invalid value for "list" parameter: element 0: string required.
╵
Operation failed: failed running terraform plan (exit 1)
Fetching Azure keyvault id from two types of Terraform variable inputs
As per the document the regex
function returns a list but you're referring it to place where it requires string.
Retry changing your locals as mentioned below so that you fetch the key vault ids as required.
Configuration:
variable "var1" {
type = object({
host_name = string
key_vault_id = optional(string)
})
default = {
host_name = "api.example.com"
key_vault_id = "https://tesagsbvk.vault.azure.net/secrets/secret1"
}
}
variable "var2" {
type = object({
host_name = string
key_vault_id = optional(string)
})
default = {
host_name = "portal.example.com"
key_vault_id = "https://tesagsbvk2.vault.azure.net/secrets/secret2"
}
}
variable "var3" {
type = map(object({
host_name = string
key_vault_id = optional(string)
}))
default = {
"tesagsbvk5" = {
host_name = "app.example.com"
key_vault_id = "https://tesagsbvk5.vault.azure.net/secrets/secret5"
}
"tesagsbvk6" = {
host_name = "service.example.com"
key_vault_id = "https://tesagsbvk6.vault.azure.net/secrets/secret6"
}
}
}
locals {
key_vault_names = compact(concat(
[
length(regexall("https://([a-zA-Z0-9-]+).vault.azure.net/secrets/.*", var.var1.key_vault_id)) > 0 ? regex("https://([a-zA-Z0-9-]+).vault.azure.net/secrets/.*", var.var1.key_vault_id)[0] : "",
length(regexall("https://([a-zA-Z0-9-]+).vault.azure.net/secrets/.*", var.var2.key_vault_id)) > 0 ? regex("https://([a-zA-Z0-9-]+).vault.azure.net/secrets/.*", var.var2.key_vault_id)[0] : "",
],
[for value in var.var3 : (
length(regexall("https://([a-zA-Z0-9-]+).vault.azure.net/secrets/.*", value.key_vault_id)) > 0 ? regex("https://([a-zA-Z0-9-]+).vault.azure.net/secrets/.*", value.key_vault_id)[0] : ""
)]
))
}
data "azurerm_key_vault" "key_vaults" {
for_each = toset(local.key_vault_names)
name = each.key
resource_group_name = "vinay-rg"
}
output "key_vault_ids" {
value = {
for name, key_vault in data.azurerm_key_vault.key_vaults : name => key_vault.id
}
}
Deployment:
Refer:
https://developer.hashicorp.com/terraform/language/functions/regex
https://registry.terraform.io/providers/hashicorp/assert/latest/docs/functions/regex
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/waf_regex_match_set.html