Skip to content

saif-resources / api

Creates the standard Forge API compute stack: Linux web app, APIM registration (backend + API + policies), and Front Door route. APIM policies are pluggable — pass API-level XML and per-operation policy maps.

Usage

module "api" {
  source  = "app.terraform.io/SAIFCorp/resources/saif//modules/api"
  version = "~> 1.0.0"

  context  = module.environment.context
  identity = module.identity.identity

  resource_group_name     = module.resource_group.resource_group_name
  resource_group_location = var.resource_location

  api_name      = var.project_id
  api_type      = "Experience"
  open_api_spec = file("${path.module}/openapi/openapi.yaml")

  auth_config = {
    audience          = module.identity.identity.app_client_id
    tenant_id         = module.environment.context.tenant_id
    default_auth_type = "entra_user"
  }

  # Per-operation overrides (optional)
  operation_auth_policies = {
    postActivity = { auth_type = "bot_framework" }
    mcpRequest   = { streaming = true }
  }

  # Merge app settings from all resource modules
  app_settings = merge(
    module.identity.app_settings,
    module.cosmosdb.app_settings,
    { /* caller-specific settings */ }
  )
}

Outputs

Name Description
web_app_name Web app name
web_app_id Web app resource ID
web_app_default_hostname Web app default hostname
api_path APIM API path
api_name APIM API name
backend_name APIM backend name
bot_endpoint Bot Framework messaging endpoint URL
base_url Base URL via Front Door + APIM

Providers

Name Version
azurerm >= 4.0, < 5.0
azurerm.shared-services >= 4.0, < 5.0
random >= 3.5.1, < 4.0.0

Inputs

Name Description Type Default Required
api_name Application name for APIM naming (e.g. project_id) string n/a yes
api_protocol The API protocol type. Currently only 'rest' is supported (imports OpenAPI spec into APIM). string "rest" no
api_type The API type for APIM naming: Experience, Process, or System string "Experience" no
auth_config Auth configuration for governed APIM policies. Required when operation_auth_policies is non-empty.
audience: The application (client) ID for JWT validation.
tenant_id: The Entra ID tenant ID for issuer/openid-config URLs.
default_auth_type: Default auth type for operations. "bot_framework", "entra_user" for simple
per-operation policies; "standard" for dual Okta/Entra routing;
"subscription_key" for APIM subscription key auth.
corp_auth_server_url: (standard) Entra corporate auth server URL for JWT validation.
external_auth: (standard) External (Okta) auth config — server URL and audience.
web_app_client_id: (standard/subscription_key) App registration client ID for managed identity
auth to the backend web app (api://{project_id}-{environment}).
object({
audience = string
tenant_id = string
default_auth_type = optional(string)
# Standard auth extensions
corp_auth_server_url = optional(string)
external_auth = optional(object({
auth_server_url = string
audience = string
}))
web_app_client_id = optional(string)
})
null no
backends Named APIM backends to register. Key is the logical name used in policy references.
url: Backend URL (e.g. https://myapp.azurewebsites.net)
resource_id: ARM resource ID for Private Link validation. Null for external URLs.
name: APIM backend name override. Defaults to api_name if not provided.
map(object({
url = string
resource_id = optional(string)
name = optional(string)
}))
n/a yes
context Platform context from the environment module any n/a yes
cookie_secret_reader_ids Map of principal IDs to grant Key Vault Secrets User role on the cookie secret. Keyed by a stable label (e.g. "webapp"). Use a static key to avoid for_each errors when the principal ID is computed. map(string) {} no
enable_auth_endpoints Whether to create /auth/* operations (login, me, callback, signedout, logout) for Experience APIs that use browser-based authentication. bool false no
enable_cookie_secret Whether to create a Key Vault secret for cookie encryption and grant RBAC access to UAMI and APIM. Requires azurerm.shared-services provider. bool false no
enable_frontdoor_route Whether to create a Front Door route bool true no
enable_mocking_backend Whether to create a mocking backend from the OpenAPI spec x-mocking server for x-mocking header support. bool false no
enable_service_discovery Whether to register service discovery entries in App Configuration. Requires azurerm.shared-services provider. bool false no
filevine_config Filevine Identity Server configuration for webhook JWT validation.
Required when auth_config.default_auth_type = "filevine".
openid_config_url: OIDC discovery endpoint (default: Filevine Identity Server).
audience: Expected JWT audience claim.
issuer: Expected JWT issuer claim.
scope: Required JWT scope claim.
object({
openid_config_url = optional(string, "https://identity.filevine.com/.well-known/openid-configuration")
audience = optional(string, "filevine-v2-webhooks")
issuer = optional(string, "https://identity.filevine.com")
scope = optional(string, "filevine-v2-webhooks-access")
})
null no
is_external Whether this is an external-facing API (uses external Front Door endpoint). bool false no
open_api_spec OpenAPI spec content to import into APIM. Required when api_protocol is 'rest'; must be non-empty. string "" no
operation_auth_policies Per-operation APIM auth policy overrides. Map of operation_id to auth config.
Only applies to simple auth modes (bot_framework/entra_user): all discovered operations
get auth_config.default_auth_type; use this to override specific operations to a different
simple auth type. Standard/subscription_key/filevine per-operation policies are
auto-generated from OpenAPI spec scopes/roles/mocking and do not use this variable.
auth_type: "bot_framework" or "entra_user".
Optional — defaults to auth_config.default_auth_type when omitted.
streaming: true for SSE/streaming endpoints (disables response buffering, 120s timeout).
map(object({
auth_type = optional(string)
streaming = optional(bool, false)
}))
{} no
service_discovery_config Service discovery configuration for App Configuration registration.
Required when enable_service_discovery = true.
external_auth_server_url: Okta auth server URL (for external tenant callers).
external_auth_server_audience: Okta auth server audience.
corp_auth_server_url: Entra corp auth server URL.
corp_auth_server_audience: Entra corp auth server audience (typically the app client ID).

enable_external_auth_server: Whether to register the external auth server URL key.
enable_corp_auth_server: Whether to register the corp auth server URL key.
enable_external_authserver_audience: Whether to register the external auth server audience key.
enable_corp_authserver_audience: Whether to register the corp auth server audience key.

These enable flags must be set to plan-time-known values (e.g. variables or literals).
Do not derive them from resource outputs — Terraform cannot use unknown values in count.
object({
external_auth_server_url = optional(string)
external_auth_server_audience = optional(string)
corp_auth_server_url = optional(string)
corp_auth_server_audience = optional(string)
enable_external_auth_server = optional(bool, false)
enable_corp_auth_server = optional(bool, false)
enable_external_authserver_audience = optional(bool, false)
enable_corp_authserver_audience = optional(bool, false)
})
null no
subscription_primary_key User-provided primary subscription key. When null, APIM auto-generates the key. string null no
subscription_required Whether APIM subscription key is required bool false no
subscription_secondary_key User-provided secondary subscription key. When null, APIM auto-generates the key. string null no

Outputs

Name Description
api_name The APIM API name
api_path The APIM API path
backend_name The default APIM backend name
base_url Base URL via shared internal Front Door + APIM path
bot_endpoint Bot Framework messaging endpoint URL (base_url + /api/messages)
cookie_secret_name The Key Vault secret name for the cookie encryption key. Null when cookie secret is not enabled.
cookie_secret_versionless_id The versionless ID of the cookie secret in Key Vault. Null when cookie secret is not enabled.
subscription_primary_key Primary key of the APIM subscription. Null when subscription is not enabled.
subscription_secondary_key Secondary key of the APIM subscription. Null when subscription is not enabled.

Resources

  • resource.azurerm_api_management_api.main (/terraform-docs/modules/api/apimanagement.tf#76)
  • resource.azurerm_api_management_api_operation.auth (/terraform-docs/modules/api/auth_endpoints.tf#45)
  • resource.azurerm_api_management_api_operation_policy.auth (/terraform-docs/modules/api/auth_endpoints.tf#64)
  • resource.azurerm_api_management_api_operation_policy.main (/terraform-docs/modules/api/apimanagement.tf#106)
  • resource.azurerm_api_management_api_policy.main (/terraform-docs/modules/api/apimanagement.tf#97)
  • resource.azurerm_api_management_backend.main (/terraform-docs/modules/api/apimanagement.tf#23)
  • resource.azurerm_api_management_backend.mocking (/terraform-docs/modules/api/apimanagement.tf#50)
  • resource.azurerm_api_management_named_value.backend (/terraform-docs/modules/api/apimanagement.tf#38)
  • resource.azurerm_api_management_named_value.cookie_secret (/terraform-docs/modules/api/apimanagement.tf#122)
  • resource.azurerm_api_management_named_value.mocking (/terraform-docs/modules/api/apimanagement.tf#64)
  • resource.azurerm_api_management_subscription.main (/terraform-docs/modules/api/apimanagement.tf#142)
  • resource.azurerm_app_configuration_key.service_corp_authserver (/terraform-docs/modules/api/service_discovery.tf#52)
  • resource.azurerm_app_configuration_key.service_corp_authserveraudience (/terraform-docs/modules/api/service_discovery.tf#80)
  • resource.azurerm_app_configuration_key.service_ext_authserver (/terraform-docs/modules/api/service_discovery.tf#38)
  • resource.azurerm_app_configuration_key.service_ext_authserveraudience (/terraform-docs/modules/api/service_discovery.tf#66)
  • resource.azurerm_app_configuration_key.service_path (/terraform-docs/modules/api/service_discovery.tf#24)
  • resource.azurerm_app_configuration_key.service_url (/terraform-docs/modules/api/service_discovery.tf#10)
  • resource.azurerm_cdn_frontdoor_custom_domain_association.main (/terraform-docs/modules/api/frontdoor.tf#29)
  • resource.azurerm_cdn_frontdoor_route.main (/terraform-docs/modules/api/frontdoor.tf#5)
  • resource.azurerm_key_vault_secret.cookie_secret (/terraform-docs/modules/api/cookie_secret.tf#18)
  • resource.azurerm_role_assignment.cookie_secret_readers (/terraform-docs/modules/api/cookie_secret.tf#41)
  • resource.azurerm_role_assignment.cookie_secret_user (/terraform-docs/modules/api/cookie_secret.tf#27)
  • resource.random_id.cookie_secret (/terraform-docs/modules/api/cookie_secret.tf#9)

View source on GitHub