Search code examples
terraformssl-certificateazure-keyvaultterraform-provider-azureazure-application-gateway

Error Key Vault object_id is an invalid UUID - Terraform/Azure


I'm deploying an Azure Application Gateway in Terraform and I want to store my SSL private certificate for the https between Internet and my App-gtw in an Azure Key Vault. The code, omitting useless information in the application gateway module, is:


module "agw_user_assigned_identity" {
  source = "../modules/resources-blocks/user_assigned_identity"

  user_assigned_identity_name  = "agw-user-signed-id"
  resource_group_name     = module.resource_group.name
  resource_group_location = module.resource_group.location
}

module "key_vault" {
  source = "../modules/resources/key_vault"

  key_vault_name = local.key_vault_name
  resource_group_location = module.resource_group.location
  resource_group_name     = module.resource_group.name

  tenant_id = data.azurerm_client_config.current.tenant_id
  object_id = module.agw_user_assigned_identity.id

  soft_delete_retention_days  = 90

  log_analytics_workspace_id = module.log_analytics_workspace.id
  enable_diagnostic_setting  = true
}

module "key_vault_private_certificate" {
  source = "../modules/resources-blocks/key_vault_certificate"

  key_vault_id         = module.key_vault.id
  certificate_name     = local.agw_certificate_name
  certificate_path     = "./certificates/xxxxx.pfx"
  certificate_password = var.SSL_CERTIFICATE_PASSWORD
}

resource "null_resource" "previous" {}

module "agw_time_sleep" {
  source = "../modules/resources-blocks/time_sleep"

  select_module = module.key_vault
  seconds = "200s"
}

module "application_gateway" {
  source = "../modules/resources-hub/application_gateway"

  resource_group_name        = module.resource_group.name
  resource_group_location    = module.resource_group.location
  application_gateway_name   = local.agw_name

  key_vault_private_certificate_id = module.key_vault_private_certificate.certificate_id
  key_vault_private_certificate_id = azurerm_key_vault_certificate.kv_certificate.secret_id
  ssl_certificate_name             = local.agw_certificate_name
  agw_time_sleep                   = module.agw_time_sleep.id

  frontend_ports = [
    {
      name = "myFrontendPort"
      port = 443
    }
  ]


  http_listeners = [
    {
      name                      = "devListener" 
      frontend_ip_configuration = local.frontend_ip_configuration_name
      frontend_port_name        = "myFrontendPort" 
      protocol                  = "Https"
      hostname                  = "xxxxxxxxxxxxx.be"
      ssl_certificate_name      = local.agw_certificate_name
    }
  ]
}

The key_vault resource is:

resource "azurerm_key_vault" "kv" {
  name                        = var.key_vault_name
  location                    = var.resource_group_location
  resource_group_name         = var.resource_group_name
  enabled_for_disk_encryption = true
  tenant_id                   = var.tenant_id
  soft_delete_retention_days  = var.soft_delete_retention_days
  purge_protection_enabled    = false

  sku_name = "standard"

  access_policy {
    tenant_id = var.tenant_id
    object_id = var.object_id

    key_permissions = ["Get", "List", "Update", "Create", "Import", "Delete", "Recover", ]

    secret_permissions = ["Get", "List", "Set", "Delete", "Recover", "Backup", "Restore", "Purge"]

    storage_permissions = ["Get", "Set", "Delete", "Recover", "Backup", "Restore"]

    certificate_permissions = ["Get", "List", "Update", "Create", "Import", "Delete", "Recover", "Backup", "Restore", "Purge"]
  }

  lifecycle {
    ignore_changes = [access_policy]
  }
}

The key_vault_certificate resource is:

resource "azurerm_key_vault_certificate" "kv_certificate" {
  name         = var.certificate_name
  key_vault_id = var.key_vault_id

  certificate {
    contents = filebase64(var.certificate_path)
    password = var.certificate_password
  }
  certificate_policy {
    issuer_parameters {
      name = "Self"
    }

    key_properties {
      exportable = true
      key_size   = 2048
      key_type   = "RSA"
      reuse_key  = false
    }

    secret_properties {
      content_type = "application/x-pkcs12"
    }
  }
}

The application gateway resource is (omitting useless information):

resource "azurerm_application_gateway" "app_gw" {
  name                = var.application_gateway_name
  resource_group_name = var.resource_group_name
  location            = var.resource_group_location

  identity {
    type = "UserAssigned"
    identity_ids = [var.user_assigned_identity_id]
  }

  ssl_certificate {
    name     = var.ssl_certificate_name
    key_vault_secret_id = var.key_vault_private_certificate_id
  }

  dynamic "http_listener" {
    for_each = var.http_listeners
    content {
      name                           = http_listener.value.name
      frontend_ip_configuration_name = http_listener.value.frontend_ip_configuration
      frontend_port_name             = http_listener.value.frontend_port_name
      protocol                       = http_listener.value.protocol
      host_name                      = http_listener.value.hostname
      firewall_policy_id             = var.firewall_policy_id
      ssl_certificate_name           = http_listener.value.ssl_certificate_name
    } 
  }

  depends_on = [var.agw_time_sleep]

}

The error that I get when I use the command terraform plan -var-file="variables.tfvars" is:

Error: expected "access_policy.0.object_id" to be a valid UUID, got /subscriptions/xxxxxxxx/resourceGroups/xxxxxxxxx/providers/Microsoft.ManagedIdentity/userAssignedIdentities/agw-user-signed-id
│
│   with azurerm_key_vault.kv,
│   on main.tf line 344, in resource "azurerm_key_vault" "kv":
│  344:     object_id    = module.agw_user_assigned_identity.id

Apparently seems that the problem is related to the object_id that I specify in the key_vault, but I don't know how to solve it.


Solution

  • Error Explanation

    Error: expected "access_policy.0.object_id" to be a valid UUID .......
    with azurerm_key_vault.kv,
    │   on main.tf line 344, in resource "azurerm_key_vault" "kv":
    │  344:     object_id    = module.agw_user_assigned_identity.id
    

    This means that in your resource azurerm_key_vault in the access_policy block the object_id attribute is getting the incorrect value more simply the incorrect value that azure API accepts for it.

    It expects the principal_id output from the azurerm_user_assigned_identity resource in spite of id.

    in azure id would be the URI of the resource itself in azure namespaces /subscriptions/<sub-id>/resourceGroups/<resource-group-name>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<resource-name>

    So you need principal_id output in your module module.agw_user_assigned_identity and then use it in your key_vault module as follows

    Terraform code

    ## inside module.agw_user_assigned_identity add an output , ignore if already exists 
    
    output "principal_id" {
      value       = azurerm_user_assigned_identity.base.principal_id
      description = "Set accordingly or from terraform documentation"
    }
    
    ## then use the above the output in key_vault module
    module "key_vault" {
      source = "../modules/resources/key_vault"
    
      key_vault_name = local.key_vault_name
      resource_group_location = module.resource_group.location
      resource_group_name     = module.resource_group.name
    
      tenant_id = data.azurerm_client_config.current.tenant_id
      object_id = module.agw_user_assigned_identity.principal_id
    
      soft_delete_retention_days  = 90
    
      log_analytics_workspace_id = module.log_analytics_workspace.id
      enable_diagnostic_setting  = true
    }
    

    That will solve the above error message.