frostmoln_appgw_waf_policy_attachment (Resource)
Attaches a Web Application Firewall policy to an Application Gateway, to one of its listeners, or to one of its routes.
Three levels, two scopes
With neither listener_id nor route_id this attaches to the gateway, which takes a gateway-scoped policy — the one carrying the managed ruleset. With listener_id, or with listener_id and route_id, it attaches an overlay-scoped policy to that listener or route.
The scope has to match the level and the provider checks it before sending: attaching an overlay to the gateway would leave the gateway with no managed protection at all, and that is not a mistake worth discovering from a 400.
~> A tcp listener cannot carry a policy, and neither can anything beneath it. The firewall inspects HTTP requests; a tcp listener forwards bytes and parses none, so attaching a policy to one is refused. Its traffic is filtered by the listener's own source-CIDR, geo, rate-limit and connection controls instead.
Attaching is not authoring
The policy is a separate resource with its own rules and version history. Destroying this attachment detaches the policy; it does not delete it, and the policy can be attached again.
~> A destroy detaches only the policy it recorded. It names the policy_id in state — the one the plan shows — and the platform detaches only if that policy is still the one attached. If the attachment was changed outside Terraform since state was last refreshed — another policy attached there, or none — nothing is detached: the destroy succeeds, removes the resource from state, leaves whatever is attached in place, and says what it found in a warning.
~> Detaching the gateway policy changes every inheriting overlay. An overlay whose mode is inherit resolves against the gateway policy; with no gateway policy there is nothing blocking to inherit, so those overlays fall back to detect and stop refusing anything.
~> Attaching is not applying. The attachment reaches the appliance on the gateway's next configuration apply — see frostmoln_appgw_config_apply.
Authoritative scope — who owns what on this resource, declared in internal/scopedecl and machine-checked against the schema.
Enacted and reconciled — every configurable attribute not listed below: the platform applies it, and a refresh reads the truth back.
Create-immutable — gateway_id, listener_id, route_id: the attachment is identified by where it attaches — gateway, listener or route; moving it is a different attachment (policy_id itself swaps in place).
Example Usage
# WHERE a policy applies is a separate act from WHAT it says. A policy exists,
# is authored and is published without being attached to anything, and
# destroying an attachment detaches the policy rather than deleting it.
# The gateway level takes a gateway-scoped policy — the one carrying the managed
# ruleset for everything this gateway serves.
resource "frostmoln_appgw_waf_policy_attachment" "gateway" {
gateway_id = frostmoln_application_gateway.edge.id
policy_id = frostmoln_appgw_waf_policy.main.id
}
# A listener takes an overlay-scoped policy.
resource "frostmoln_appgw_waf_policy_attachment" "api_listener" {
gateway_id = frostmoln_application_gateway.edge.id
listener_id = frostmoln_appgw_listener.https.id
policy_id = frostmoln_appgw_waf_policy.api.id
}
# So does a single route. A route id is unique only within its listener, so
# listener_id is required alongside it.
resource "frostmoln_appgw_waf_policy_attachment" "admin_route" {
gateway_id = frostmoln_application_gateway.edge.id
listener_id = frostmoln_appgw_listener.https.id
route_id = frostmoln_appgw_route.admin.id
policy_id = frostmoln_appgw_waf_policy.admin.id
}
# Destroying the GATEWAY attachment changes every inheriting overlay: with no
# gateway policy to resolve against, an overlay whose mode is "inherit" falls
# back to detect and stops refusing anything.
#
# A destroy detaches only the policy_id recorded in state. If the attachment was
# changed outside Terraform in the meantime (another policy attached, or none),
# it detaches nothing, leaves what is there in place and warns.
# What the ATTACHED POLICY resolves to, with "inherit" resolved.
#
# Not "what is in force" for traffic through this listener. The platform builds
# ONE ruleset per gateway: the managed ruleset applies across the whole gateway,
# and each scope's customer rules are added inside it. An overlay adds rules to
# its listener or route and never exempts it from that baseline — so this value
# describes the overlay, not the protection the listener has.
#
# It is null when it cannot be determined, so read it through try().
output "api_listener_overlay_effective_mode" {
value = try(frostmoln_appgw_waf_policy_attachment.api_listener.effective_mode, "unknown")
}Schema
Required
gateway_id(String) The Application Gateway.policy_id(String) The WAF policy to attach. Changing it replaces the attachment in place — the API's PUT is a replace, so there is no window with nothing attached.
Optional
listener_id(String) Attach to this listener instead of the gateway. Requires anoverlay-scoped policy.route_id(String) Attach to this route instead of the listener. Requireslistener_id(a route id is unique only within its listener) and anoverlay-scoped policy.
Read-Only
effective_mode(String) What the attached policy itself resolves to — itsmodewithinheritresolved.Read this, never the policy's
mode: an overlay set toinheritunder a blocking gateway policy readsinheritthere and blocks. It isnullwhen that cannot be determined, and never the literal stringinherit.~> This is this policy's mode, not "what is in force for traffic". The platform composes one artifact per gateway with the managed ruleset applied across the whole gateway; an overlay adds rules to its listener or route and never exempts it from that baseline. So a detecting overlay does not mean traffic to that route is unprotected.
id(String) The identifier of this attachment: the point it attaches to.scope(String) The attached policy's scope, read back from it:gatewayoroverlay.