'Terraform AzureRM Continually Modifying API Management with Proxy Configuration for Default Endpoint

We are terraforming our Azure API Management instance.

...
resource "azurerm_api_management" "apim" {
  name                = "the-apim"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

...

  hostname_configuration {
    proxy {
      host_name = "the-apim.azure-api.net"
      negotiate_client_certificate = true
    }
  }
}
...

We need to include the hostname_configuration block so that we can switch negotiate_client_certificate to true for the default endpoint.

This does the job, however every time Terraform runs it plans to modify the APIM instance by adding the hostname_configuration block again:


      + hostname_configuration {

          + proxy {
              + host_name                    = "the-apim.azure-api.net"
              + negotiate_client_certificate = true
            }
        }

Is there a way to prevent this from happening? In the portal I can see this value is set to true.



Solution 1:[1]

I suggest you try to pair with lifecycle > ignore_changes.

The ignore_changes feature is intended to be used when a resource is created with references to data that may change in the future, but should not affect said resource after its creation. In some rare cases, settings of a remote object are modified by processes outside of Terraform, which Terraform would then attempt to "fix" on the next run. In order to make Terraform share management responsibilities of a single object with a separate process, the ignore_changes meta-argument specifies resource attributes that Terraform should ignore when planning updates to the associated remote object.

In your case, the hostname_configuration is considered a "nested block" or "attribute as block" in Terraform. So the usage of ignore_changes is not so straightforward (you can't just add the property name, as you would do if you wanted to ignore changes in your resource_group_name for example, which is directly a property). From an issue in GitHub back from 2018, it seems you could use the TypeSet hash of the nested block to add to an ignore sections.

Even though I can't test this, my suggestion for you:

  1. deploy your azurerm_api_management resource normally with the hostname_configuration block
  2. check the state file from your resource and get the typeset hash of the hostname_configuration part; should be similar to hostname_configuration.XXXXXX
  3. add an ignore_changes section passing the above
resource "azurerm_api_management" "apim" {
  # ...

  lifecycle {
    ignore_changes = [
      "hostname_configuration.XXXXXX",
    ]
  }
}

Solution 2:[2]

Sometimes such issues occur due to issues in the provider. Probably it is not storing the configuration in the state file or not retrieving the stored state for this block. Try upgrading the provider to the latest available provider and see if it sorts the issue.

If that does not solve it, you can try defining this configuration as a separate resource. As per the terraform documentation: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/api_management

It's possible to define Custom Domains both within the azurerm_api_management resource via the hostname_configurations block and by using the azurerm_api_management_custom_domain resource. However it's not possible to use both methods to manage Custom Domains within an API Management Service, since there'll be conflicts.

So Please try removing that hostname_configuration block and add it as separate resource as per this documentation: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/api_management_custom_domain

This will most likely fix the issue.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 tyron
Solution 2 Technowise