terraform {
required_version = ">= 0.12.21" # version tested on
backend "local" {
}
}
provider "azurerm" {
version = "=2.0.0" # same issue occurs on 1.44.0
# subscription_id = "" # redacted, we always set these though
# tenant_id = "" # redacted, we always set these though
features {
}
}
data "azurerm_client_config" "current" {
}
locals {
frontdoor_name = "terraformtoyexample"
kvpartialname = "36dg23fgs2"
}
resource "azurerm_resource_group" "rg" {
name = "frontdoor"
location = "northcentralus"
}
resource "azurerm_key_vault" "kvfd" {
name = "kvfd-${local.kvpartialname}"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
tenant_id = data.azurerm_client_config.current.tenant_id
enabled_for_deployment = false
enabled_for_disk_encryption = false
enabled_for_template_deployment = false
purge_protection_enabled = false
soft_delete_enabled = false
sku_name = "standard"
network_acls {
default_action = "Allow"
bypass = "AzureServices" # Really we just need Azure Front Door, but not sure terraform provides a method to do that
}
}
resource "azurerm_key_vault_access_policy" "frontdoor" {
key_vault_id = azurerm_key_vault.kvfd.id
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = "daa778f6-798e-4f28-ac66-6d6d2be6f6cc" # az ad sp show --id ad0e1c7e-6d38-4ba4-9efd-0bc77ba9f037 | jq .objectId << Azure Front Door Application
certificate_permissions = [
"Get"
]
secret_permissions = [
"Get"
]
key_permissions = [ ]
}
resource "azurerm_key_vault_certificate" "example" {
name = "example"
key_vault_id = azurerm_key_vault.kvfd.id
certificate {
contents = filebase64("/tmp/test.txt") # file needs to exist but doesnt need to be valid certificate for this issue
password = ""
}
certificate_policy {
issuer_parameters {
name = "Unknown"
}
key_properties {
exportable = true
key_size = 4096
key_type = "RSA"
reuse_key = false
}
secret_properties {
content_type = "application/x-pkcs12"
}
}
}
# can switch between secret and certificate both will fail
resource "azurerm_key_vault_secret" "examplesecret" {
name = "examplesecret"
key_vault_id = azurerm_key_vault.kvfd.id
value = filebase64("/tmp/test.txt") # file needs to exist but doesnt need to be valid certificate for this issue
}
resource "azurerm_frontdoor" "frontdoor" {
name = local.frontdoor_name
friendly_name = "frontdoor" // not clear how this is used
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
enforce_backend_pools_certificate_name_check = true
frontend_endpoint {
name = "defaultFrontDoorFE"
host_name = "${local.frontdoor_name}.azurefd.net" // for the default front end this has to match exactly
session_affinity_enabled = false
custom_https_provisioning_enabled = false
}
# NOTE to get this to work you have to register the front door service principal
# az ad sp create --id ad0e1c7e-6d38-4ba4-9efd-0bc77ba9f037
frontend_endpoint {
name = "example1FE"
host_name = "doesntmatterforthis.example.com"
session_affinity_enabled = false
custom_https_provisioning_enabled = true
custom_https_configuration {
certificate_source = "AzureKeyVault"
azure_key_vault_certificate_vault_id = azurerm_key_vault.kvfd.id
azure_key_vault_certificate_secret_name = azurerm_key_vault_certificate.example.name
azure_key_vault_certificate_secret_version = azurerm_key_vault_certificate.example.version
# can use either both return the same error, I thought based on #5468 that you had to use secret resources, and certificates weren't support both fail
# azure_key_vault_certificate_secret_name = azurerm_key_vault_secret.examplesecret.name
# azure_key_vault_certificate_secret_version = azurerm_key_vault_secret.examplesecret.version
}
}
routing_rule {
name = "example1FEdefaultAppServiceBERR"
accepted_protocols = ["Https"]
patterns_to_match = ["/*"]
frontend_endpoints = ["defaultFrontDoorFE", "example1FE"]
forwarding_configuration {
forwarding_protocol = "HttpsOnly"
backend_pool_name = "defaultAppServiceBE"
cache_use_dynamic_compression = false
}
enabled = true
}
backend_pool {
name = "defaultAppServiceBE"
backend {
enabled = true
host_header = "alsodoesntmatterforthis.example.com"
address = "alsodoesntmatterforthis.example.com"
http_port = 80
https_port = 443
priority = 1
weight = 50
}
load_balancing_name = "defaultAppServiceLB"
health_probe_name = "defaultAppServiceHP"
}
backend_pool_load_balancing {
name = "defaultAppServiceLB"
sample_size = 4
successful_samples_required = 2
additional_latency_milliseconds = 0
}
backend_pool_health_probe {
name = "defaultAppServiceHP"
path = "/"
protocol = "Http"
interval_in_seconds = 255
}
load_balancer_enabled = true
depends_on = [
azurerm_key_vault.kvfd,
azurerm_key_vault_certificate.example,
azurerm_key_vault_secret.examplesecret # shouldnt need anything in this block
]
}
I don't want to post the entire debug output since I don't want to redact specifics.
2020-02-27T17:20:49.570-0600 [DEBUG] plugin.terraform-provider-azurerm_v2.0.0_x5: [DEBUG] Determining which Resource Providers require Registration
2020-02-27T17:20:49.570-0600 [DEBUG] plugin.terraform-provider-azurerm_v2.0.0_x5: [DEBUG] All required Resource Providers are registered
2020/02/27 17:20:49 [DEBUG] Resource instance state not found for node "azurerm_resource_group.rg", instance azurerm_resource_group.rg
2020/02/27 17:20:49 [DEBUG] ReferenceTransformer: "azurerm_resource_group.rg" references: []
2020/02/27 17:20:49 [DEBUG] ReferenceTransformer: "data.azurerm_client_config.current" references: []
2020/02/27 17:20:49 [DEBUG] Resource instance state not found for node "azurerm_key_vault.kvfd", instance azurerm_key_vault.kvfd
2020/02/27 17:20:49 [DEBUG] ReferenceTransformer: "azurerm_key_vault.kvfd" references: []
2020/02/27 17:20:49 [DEBUG] Resource instance state not found for node "azurerm_key_vault_certificate.example", instance azurerm_key_vault_certificate.example
2020/02/27 17:20:49 [DEBUG] ReferenceTransformer: "azurerm_key_vault_certificate.example" references: []
2020/02/27 17:20:49 [DEBUG] Resource instance state not found for node "azurerm_key_vault_secret.examplesecret", instance azurerm_key_vault_secret.examplesecret
2020/02/27 17:20:49 [DEBUG] ReferenceTransformer: "azurerm_key_vault_secret.examplesecret" references: []
2020/02/27 17:20:49 [DEBUG] Resource instance state not found for node "azurerm_key_vault_access_policy.frontdoor", instance azurerm_key_vault_access_policy.frontdoor
2020/02/27 17:20:49 [DEBUG] ReferenceTransformer: "azurerm_key_vault_access_policy.frontdoor" references: []
2020/02/27 17:20:49 [WARN] Provider "registry.terraform.io/-/azurerm" produced an invalid plan for azurerm_key_vault_certificate.example, but we are tolerating it because it is using the legacy plugin SDK.
The following problems may be the cause of any confusing errors from downstream operations:
- .certificate_policy[0].x509_certificate_properties: attribute representing nested block must not be unknown itself; set nested attribute values to unknown instead
2020/02/27 17:20:49 [DEBUG] Resource instance state not found for node "azurerm_frontdoor.frontdoor", instance azurerm_frontdoor.frontdoor
2020/02/27 17:20:49 [DEBUG] ReferenceTransformer: "azurerm_frontdoor.frontdoor" references: []
2020/02/27 17:20:49 [ERROR] <root>: eval: *terraform.EvalDiff, err: Error creating Front Door "terraformtoyexample" (Resource Group "frontdoor"): "frontend_endpoint":"example1FE" "custom_https_configuration" is invalid, all of the following keys must have values in the "custom_https_configuration" block: "azure_key_vault_certificate_secret_name", "azure_key_vault_certificate_secret_version", and "azure_key_vault_certificate_vault_id"
2020/02/27 17:20:49 [ERROR] <root>: eval: *terraform.EvalSequence, err: Error creating Front Door "terraformtoyexample" (Resource Group "frontdoor"): "frontend_endpoint":"example1FE" "custom_https_configuration" is invalid, all of the following keys must have values in the "custom_https_configuration" block: "azure_key_vault_certificate_secret_name", "azure_key_vault_certificate_secret_version", and "azure_key_vault_certificate_vault_id"
2020/02/27 17:20:49 [INFO] backend/local: plan operation completed
Error: Error creating Front Door "terraformtoyexample" (Resource Group "frontdoor"): "frontend_endpoint":"example1FE" "custom_https_configuration" is invalid, all of the following keys must have values in the "custom_https_configuration" block: "azure_key_vault_certificate_secret_name", "azure_key_vault_certificate_secret_version", and "azure_key_vault_certificate_vault_id"
on frontdoor.tf line 89, in resource "azurerm_frontdoor" "frontdoor":
89: resource "azurerm_frontdoor" "frontdoor" {
2020-02-27T17:20:49.613-0600 [DEBUG] plugin: plugin process exited: path=/Users/REDACTED/CloudServices/cloudlab/toy-frontdoor/.terraform/plugins/darwin_amd64/terraform-provider-azurerm_v2.0.0_x5 pid=55102
2020-02-27T17:20:49.613-0600 [DEBUG] plugin: plugin exited
The plan would have succeeded.
Plan threw an error for a resource that has not yet been created.
terraform initterraform plan (terraform apply will also produce the error)/tmp/test.txt@slynickel thanks for opening this issue, the front door resource assumes that the Key Vault has already been configured correctly prior to running the apply. If you wish to create both in the same configuration file you will need to add a depends on to your front door block to force it to wait until the key vault and the certificates have been created before creating the front door resource.
depends_on = [azurerm_key_vault_certificate.example,]
Azure Key Vault certificates: If you already have a certificate, you can upload it directly to your Azure Key Vault account or you can create a new certificate directly through Azure Key Vault from one of the partner CAs that Azure Key Vault integrates with. Upload your certificate as a certificate object, rather than a secret.
Important: You must upload the certificate in PFX format without password protection.
@WodansSon you'll note in my fully functional example (if you put an empty file at /tmp/test.txt) I explicitly provide the following block inside of the front door resource. This should ensure that the front door resource waits for the key vault and key vault certificate to be created. It does not. It errors prior to running the plan.
depends_on = [
azurerm_key_vault.kvfd,
azurerm_key_vault_certificate.example,
azurerm_key_vault_secret.examplesecret # shouldnt need anything in this block
]
It would appear there is an issue where the front door resource doesn't allow these to be filled in after. Adding the depends block does not fix the issue.
depends_on = [azurerm_key_vault_certificate.example,]
I added this to my configuration, assuming this would address the issue, but I still get the same error as @slynickel
My workaround, for now, was to create the Key Vault certificate entry in a separate terraform plan. Then run the FrontDoor plan.
But because the certificate and front door are so dependent on one another, I'd like to have them in the same plan.
I'm having trouble writing a test for this scenario. The issue is that Front Door must use a valid certificate from Key Vault, self-signed won't work.
Therefore, when trying to codify an acceptance test in the azurerm/internal/services/frontdoor/tests/resource_arm_front_door_test.go file we need to be able to supply a valid cert.
We could create one with Let's Encrypt, but this means referencing another provider - I don't think this will work using the acceptance test framework.
We could supply in based on the contents of a file, but this breaks the automation.
Anybody got any ideas?
Short of procuring a certificate from a valid CA I'm not sure of a good way to test. That's how I was testing this.
FWIW, it would appear other folks +1'ed this but I've switched to using the managed cert to avoid this. Also Key vault doesn't have great HA options for this so the managed seemed like a better option.
@slynickel, unfortunately this is currently by design given the current architecture of the API. You must first create the key vault and then add front door to the key vaults access policy. There are a number of steps that need to happen before you can use your custom domain. Given that this is currently by design I am going to close this issue, feel free to re-open the issue if you believe this is in error.
I don't believe this is by design. If the resources were created in the correct order, as defined by the implicit and explicit dependencies in the plan, then it should be possible to create the key, the key vault and the Front Door in one apply step.
The problem is that the validate stage fails as it is looking for the resource details of the to-be-created key vault secret. No calls have been made to the networking resource provider at the time of the validate so it is not an Azure API limitation.
The validate stage should recognise that the current plan will create the required resources and allow the application of the plan, substituting in the resource details once created.
Multiple apply steps should not be required to do this.
@slynickel Managed certs did not support apex domains. E.g. xyz.com. They only support www.xyz.com.
I'm hitting the same issue as the op.
I have tried adding this suggestion without success:
depends_on = [azurerm_key_vault.example, azurerm_key_vault_certificate.example, azurerm_key_vault_access_policy]
This is my section for frontend_endpoint within the FrontDoor config
custom_https_provisioning_enabled = true
custom_https_configuration {
certificate_source = "AzureKeyVault"
azure_key_vault_certificate_vault_id = azurerm_key_vault.example.id
azure_key_vault_certificate_secret_name = azurerm_key_vault_certificate.example.name
azure_key_vault_certificate_secret_version = azurerm_key_vault_certificate.example.version
}
It seems like values (below) from the creation of my keyvault resources are not being returned for use within the creations of my frontdoor resource.
azurerm_key_vault.example.id
azurerm_key_vault_certificate.example.name
azurerm_key_vault_certificate.example.version
If I hard code the values from a manually added certificate, it will work. This confirms The granted access between FrontDoor and KeyValut works.
Is there anything I should be aware of?
I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.
If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. If you feel I made an error 🤖 🙉 , please reach out to my human friends 👉 [email protected]. Thanks!
Most helpful comment
@WodansSon you'll note in my fully functional example (if you put an empty file at
/tmp/test.txt) I explicitly provide the following block inside of the front door resource. This should ensure that the front door resource waits for the key vault and key vault certificate to be created. It does not. It errors prior to running the plan.It would appear there is an issue where the front door resource doesn't allow these to be filled in after. Adding the depends block does not fix the issue.