Closed jabba2324 closed 3 years ago
Issue described here too https://github.com/terraform-providers/terraform-provider-azurerm/issues/3058
Hi @cdesewell, please see my comment in #3058. The issue is that if we use managed identity in api_management this will create a service principal which has no access to keyvault. In case we define hostname_configuration with key_vault_id this will fail due to missing permissions (401 Forbidden).
This are the steps to get the required permissions:
The above 3 steps are not a good solution. Because if we delete and recreate api_management, permissions for service principal are gone.
As a temporary workaround we could do something like this:
data "azurerm_key_vault" "my_key_vault" {
name = var.name
resource_group_name = var.resource_group
}
data "azurerm_key_vault_secret" "my_key_vault_secret" {
name = "my-cert"
key_vault_id = data.azurerm_key_vault.my_key_vault.id
}
.....
hostname_configuration {
management {
host_name = var.host
certificate = data.azurerm_key_vault_secret.my_key_vault_secret.value
}
}
But please keep in mind that this workaround will pull out the certificate in terraform.
Thanks for your response @NickMetz I can't have the cert being displayed in terraform, additionally I can't have the cert password being used in terraform either.
The above 3 steps are not a good solution. Because if we delete and recreate api_management, permissions for service principal are gone.
You say this, what kind of changes would make terraform destroy and re-create the api manager as opposed to just making changes?
Just giving the key vault access policy a try to find that It's not possible to get the principal id. I'm met with
"object_id" is an invalid UUUID: uuid: UUID string too short
Similar issue reported here: https://github.com/terraform-providers/terraform-provider-azurerm/issues/2103
HI @cdesewell,
You say this, what kind of changes would make terraform destroy and re-create the api manager as opposed to just making changes?
I would expect if we delete an api managment which use managed identity, relying service principal will also be deleted.
Just giving the key vault access policy a try to find that It#s not possible to get the principal id. I'm met with.
You should find the principal id searching for the same name as your api managment name.
Thanks @NickMetz the Principal id attribute being empty is a bug
Hi @cdesewell,
can you please provide a code sample of what you tried?
The only thing i can imagine you tried something like this:
data "azurerm_api_management" "test" {
name = "example-apim"
resource_group_name = "example-resource-group"
}
data "azurerm_key_vault" "my_key_vault" {
name = "example-key-vault"
resource_group_name = "example-resource-group"
}
data "azurerm_key_vault_secret" "my_key_vault_secret" {
name = "my-cert"
key_vault_id = data.azurerm_key_vault.my_key_vault.id
}
resource "azurerm_api_management" "test" {
name = "example-apim"
location = "westeurope"
resource_group_name = "example-resource-group"
publisher_name = "My Company"
publisher_email = "company@terraform.io"
hostname_configuration {
management {
host_name = "foo.example.com"
key_vault_id = data.azurerm_key_vault_secret.my_key_vault_secret.id
}
}
identity {
type = "SystemAssigned"
}
sku {
name = "Developer"
capacity = 1
}
}
resource "azurerm_key_vault_access_policy" "test" {
vault_name = "example-vault"
resource_group_name = "example-resource-group"
tenant_id = data.azurerm_api_management.test.tenant_id
object_id = data.azurerm_api_management.test.principal_id
key_permissions = [
"get",
]
secret_permissions = [
"get",
]
}
But this won't work because api_management creation will fail due to missing permissions to key_vault (required to fetch certificate in hostname_configuration). If creation of api_management fail managed service principal will not be created. That for it would also not be possible to get object_id from service principal any you can't attach right permissions.
Like it wrote in #3058 chicken vs. egg causality dilemma. It would be better if we had the possibility to add a predefined service principal to api_managment with access to keyvault. But this is something that needs to be fixed from Azure side.
example (is not possible at the moment)
service_principal {
client_id = "00000000-0000-0000-0000-000000000000"
client_secret = "00000000000000000000000000000000"
}
@NickMetz your example is spot on, it's a chicken and egg dilemma. Could one solution be to have host configuration as a separate terraform resource definition. Similiar to how an App Service Custom Hostname: https://www.terraform.io/docs/providers/azurerm/r/app_service_custom_hostname_binding.html
Bumped into this "chicken and egg" problem today. It seems that the proper solution should be a separate resource for host_configuration
, as @cdesewell suggested.
Yup, having the same issue. And as Mikhail said, @cdesewell's suggestion seems to make sense most.
Can we get an update on this? Is this something that will get addressed?
I managed to fix this, with the assistance of Microsoft. Things are a bit different than I thought (read the tip section in https://docs.microsoft.com/en-us/azure/api-management/configure-custom-domain). My steps are:
This solves the chicken-egg problem.
I just wanted to chime in with how I solved it using the suggestion from @jeanpaulsmit. Hope this helps anyone until there is a proper REST endpoint for doing this.
I added this resource in the same terraform script that creates the API service:
data "azurerm_key_vault" "storemanager-common" {
name = "key-vault-name"
resource_group_name = data.azurerm_resource_group.resource_group.name
}
resource "azurerm_key_vault_access_policy" "key_vault_access_policy" {
key_vault_id = data.azurerm_key_vault.storemanager-common.id
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = azurerm_api_management.api_management.identity[0].principal_id
secret_permissions = [
"get"
]
provisioner "local-exec" {
command = format("%s/add-domain.ps1 %s %s %s %s",
path.module,
"hostname.com",
"certificateId",
azurerm_api_management.api_management.resource_group_name,
azurerm_api_management.api_management.name
)
}
}
And add-domain.ps1
. This requires PowerShell to be installed as a snap. If you have installed it some other way, change the hashbang to point to your PowerShell bin.
#!/snap/bin/pwsh
$hostname = $args[0]
$certificateId = $args[1]
$resourceGroupName = $args[2]
$apiServiceName = $args[3]
if (!(Get-Module -ListAvailable -Name Az)) {
Write-Host "Installing Azure module"
Install-Module -Name Az -AllowClobber
}
Write-Host "Assigning custom hostname $hostname"
$apim = Get-AzApiManagement -ResourceGroupName $resourceGroupName -Name $apiServiceName
$apim.ProxyCustomHostnameConfiguration = @(New-AzApiManagementCustomHostnameConfiguration -Hostname $hostname -HostnameType Proxy -KeyVaultId $certificateId)
Set-AzApiManagement -InputObject $apim
Write-Host "Assigned hostname $hostname"
I've got this very issue too. I can see two workaround above, but I'd love someone from hashicorp to chip in on if they can see why this circular dependancy just doesnt work. @tombuildsstuff maybe? it defintely feels like a bug to me.
I get that I can use a workaround and we actually already have one, in that we deploy an APIM instance without the hostname config, then in the very same template we repeat the APIM resource with another name and add the hostname config in. its a double deployment of APIM, its a bit hacky, but it ususally works. until today when its erroring for some unknown reason. this is some pretty nasty code that at some point im going to have to hand over to the client an explain that the tool i told them would revolutionise their deployments has some pretty hacky workarounds in it.
resolved this issue using azurerm_api_management_custom_domain
I believe this issue is resolved using the newly added azurerm_api_management_custom_domain resource, so I'm going to close this issue accordingly. Thanks!
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 👉 hashibot-feedback@hashicorp.com. Thanks!
Hello, question & possible bug.
How do you correctly add a certificate to an api manager hostname block from key vault. I've noticed there isn't certificate data source so I've tried using the secret data source instead as advised here: https://github.com/terraform-providers/terraform-provider-azurerm/issues/2898#issuecomment-465098754
This doesn't seem to work as I'm met with a forbidden error (which is not the case, I can see the certificate in Azure). Terraform attempts to the the following url:
https://product-dev.vault.azure.net/secrets/my-cert/1234?api-version=7.0'
Manually adding this URL for the cert
https://product-dev.vault.azure.net/certificates/my-cert/1234
Given me this error:My terraform looks something like this.