An API Management gateway's working configuration in one call: APIs (with their policies, imported definitions, product links, and diagnostics), products (with their policies), backends, named values, loggers, and subscriptions, all keyed by readable names that cross-reference each other. The second layer of the estate's MCP gateway architecture, and the consolidation of six former single-resource wrapper modules into one surface that composes.
The instance arrives as its resource id (api_management_id; name and resource group parse from
it). Everything else is a map keyed by a readable name, and the maps point at each other by key,
never by constructed id: an API's products list joins products, its diagnostic.logger_key
names a logger, a subscription's product_key or api_key scopes it, and a backend's
credentials can reference a named value as {{its-key}} so secrets stay server-side. The keys
are plan-known, so the cross-links never trip the for_each unknown-key trap.
- APIs default to
httpsonly andsubscription_required = true: an anonymous API is a choice, never a default. - Subscriptions default to
state = active(a Terraform-managed subscription should work on apply, not sit in an approval queue) andallow_tracing = false(traces expose backend internals; enable deliberately, briefly). - Backend TLS validation stays on; a Key Vault-sourced named value is secret whether you said so or not.
- Policies attach at API and product scope via
policy_xml_content(inline,templatefilefriendly) orpolicy_xml_link. Operation-level policies and operations themselves are out of scope on purpose: import an OpenAPI definition and the operations come with it. - The
subscription_primary_keysoutput is sensitive; it is what a client presents inOcp-Apim-Subscription-Key. - Loggers take Application Insights (connection string, or
identity_client_idfor keyless) or Event Hub; an API opts into telemetry with itsdiagnosticobject.
CI runs a trivy config scan that gates on HIGH and CRITICAL findings. Waivers live in
.trivyignore.yaml, and every waiver is recorded here. There are currently none.
| ID | Where | Justification |
|---|
| Name | Version |
|---|---|
| terraform | >= 1.9.0, < 2.0.0 |
| azurerm | >= 4.0.0, < 5.0.0 |
| Name | Version |
|---|---|
| azurerm | 4.81.0 |
No modules.
| Name | Type |
|---|---|
| azurerm_api_management_api.this | resource |
| azurerm_api_management_api_diagnostic.this | resource |
| azurerm_api_management_api_policy.this | resource |
| azurerm_api_management_backend.this | resource |
| azurerm_api_management_logger.this | resource |
| azurerm_api_management_named_value.this | resource |
| azurerm_api_management_product.this | resource |
| azurerm_api_management_product_api.this | resource |
| azurerm_api_management_product_policy.this | resource |
| azurerm_api_management_subscription.this | resource |
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| api_management_id | Resource id of the API Management instance to configure; the instance name and resource group parse from it, per the estate's pass-ids principle. | string |
n/a | yes |
| apis | APIs on the instance, keyed by API name. display_name defaults to the key, protocols to https, and subscription_required to true (anonymous APIs are a choice, never a default). Definitions arrive through import (an OpenAPI/Swagger/WSDL document, inline or by link); policy_xml_content or policy_xml_link attaches the API-scope policy; products lists product keys from var.products to link; diagnostic wires the API to a logger from var.loggers by key. |
map(object({ |
{} |
no |
| backends | Backends, keyed by name: the targets policies route to with set-backend-service. Credentials can inject headers or query parameters (a named value reference like {{my-secret}} keeps the secret server-side), and tls validation stays on unless self-signed backends force it off. | map(object({ |
{} |
no |
| loggers | Loggers, keyed by name: Application Insights (connection string, or identity_client_id for keyless) or Event Hub sinks that APIs reference by key in their diagnostic. | map(object({ |
{} |
no |
| named_values | Named values, keyed by name: the {{placeholders}} policies reference. Exactly one of value or value_from_key_vault per entry; a Key Vault value is implicitly secret. | map(object({ |
{} |
no |
| products | Products, keyed by product id. display_name defaults to the key, published to true, and subscription_required to true. APIs join a product from the API side (apis[*].products). | map(object({ |
{} |
no |
| subscriptions | Subscriptions, keyed by a stable logical name. Scope by product_key or api_key (keys into var.products / var.apis), or neither for an all-APIs subscription. state defaults to active (a Terraform-managed subscription should work on apply, not sit in an approval queue) and allow_tracing to false (traces expose backend internals; turn it on deliberately, briefly). | map(object({ |
{} |
no |
| Name | Description |
|---|---|
| api_ids | Map of API key to resource id. |
| api_ids_zipmap | Map of API key to {name, id} for easy composition. |
| backend_ids | Map of backend key to resource id. |
| logger_ids | Map of logger key to resource id. |
| named_value_ids | Map of named value key to resource id. |
| product_ids | Map of product key to resource id. |
| subscription_ids | Map of subscription key to resource id. |
| subscription_primary_keys | Map of subscription key to its primary key; what a client presents in Ocp-Apim-Subscription-Key. |