Manages a single
fabric_workspace_outbound_gateway_rulesresource β the gateway-routed outbound allow/deny posture for one Fabric workspace β against themicrosoft/fabricprovider~> 1.12.0.
- πͺ Sets a
default_action(Allow|Deny) governing outbound traffic through gateways not explicitly listed. - β
Optionally defines an
allowed_gatewaysset β gateway GUIDs (fromterraform-fabric-gateway) permitted regardless of the default action. - π Unlike the sibling cloud-connection-rules module, this one's naming-derived hypothesis about
cross-module references held up:
allowed_gatewaysgenuinely referencesfabric_gatewayresource instances.
π‘ Why it matters: this is a data-governance control restricting which gateways a workspace's items can route outbound traffic through β e.g. limiting an on-premises data gateway connection to only the gateways an organization has explicitly reviewed and registered, rather than any gateway visible in the tenant.
If these Terraform modules have been helpful to you or your organization, I'd appreciate your support in any of the following ways:
- β Star this repository to help others discover this Terraform module.
- π€ Connect with me on LinkedIn: linkedin.com/in/microsoftexpert
- β Buy me a coffee: buymeacoffee.com/microsoftexpert
Whether it's a star, a professional connection, or a coffee, every gesture helps keep these modules actively maintained and continually improving. Thank you for being part of the community!
flowchart LR
WS["terraform-fabric-workspace"]:::keystone
GW["terraform-fabric-gateway"]:::sibling
THIS["terraform-fabric-workspace-outbound-gateway-rules"]:::this
WS -->|"workspace_id"| THIS
GW -->|"id, into allowed_gateways"| THIS
classDef keystone fill:#143551,color:#ffffff,stroke:#143551,stroke-width:2px;
classDef this fill:#0F6CBD,color:#ffffff,stroke:#0F6CBD,stroke-width:2px;
classDef sibling fill:#e8e8e8,color:#111111,stroke:#999999,stroke-width:1px;
Diagram validated for correct rendering before embedding.
flowchart TB
subgraph Inputs
A["workspace_id"]
B["default_action"]
C["allowed_gateways, set of gateway GUIDs"]
D["timeouts"]
end
R["fabric_workspace_outbound_gateway_rules.this"]:::this
A --> R
B --> R
C --> R
D --> R
R --> O1["workspace_id"]
R --> O2["default_action"]
R --> O3["allowed_gateways"]
classDef this fill:#0F6CBD,color:#ffffff,stroke:#0F6CBD,stroke-width:2px;
Resource inventory: 1 resource β fabric_workspace_outbound_gateway_rules.this.
| Terraform | >= 1.12.0 |
| Provider | microsoft/fabric ~> 1.12.0 |
| Provider block | None β the caller configures provider "fabric" {} at the root |
Schema notes that bite:
- No
idattribute β confirmed viaterraform providers schema -json;workspace_idis the sole key. Outputs lead withworkspace_id. default_actionis required with no documented provider-native default β modeled as a required module variable per this suite's secure-by-default convention.allowed_gatewaysis an unordered Attributes Set of{ id = string }objects β this module accepts a flatset(string)of gateway GUIDs and expands each inmain.tf.- This resource had no prior internal house pattern β confirmed fresh this session against the live provider schema and the binary provider schema.
- No delegated-auth requirement (provider doc: "This resource supports Service Principal authentication").
- Fabric: Workspace Admin role on the target workspace.
- Entra: calling Service Principal (or Managed Identity) enabled under "Service principals can use Fabric APIs".
- Fabric tenant administrator must have separately enabled the relevant tenant setting (see Prerequisites).
- Tenant setting "Configure workspace-level outbound network rules" enabled by a Fabric tenant admin (off by default).
- Workspace must reside on a Fabric (F SKU) capacity β no other capacity type is supported.
- This module's rules only matter if
terraform-fabric-workspace-network-communication-policy'soutbound.default_actionisDenyfor the same workspace. - Universal tenant-level SPN/MSI API access switch.
- Deployment pipelines are not supported alongside workspace outbound access protection.
terraform-fabric-workspace-outbound-gateway-rules/
βββ providers.tf # required_providers floor β no provider {} block
βββ variables.tf # workspace_id, default_action, allowed_gateways, timeouts
βββ main.tf # fabric_workspace_outbound_gateway_rules.this β thin renderer
βββ outputs.tf # workspace_id (primary), default_action, allowed_gateways
βββ README.md # this file
βββ SCOPE.md # lightweight standalone scope
βββ examples/
βββ basic/ # global deny, no allowed gateways
βββ complete/ # global deny plus two explicit allowed gateways
module "outbound_gateway_rules" {
source = "git::https://github.com/microsoftexpert/terraform-fabric-workspace-outbound-gateway-rules.git?ref=v1.0.0"
workspace_id = module.workspace.id
default_action = "Deny"
}Consumes
| Input | Type | Source module |
|---|---|---|
workspace_id |
string |
terraform-fabric-workspace's id output |
allowed_gateways |
set(string) |
terraform-fabric-gateway's id output |
Emits
| Output | Description | Consumed by |
|---|---|---|
workspace_id |
Primary output β the workspace GUID these rules govern | Informational / cross-referencing |
default_action |
Effective default_action for unlisted gateways | Informational |
allowed_gateways |
Effective set of allowed gateway objects | Informational |
1 Β· Basic β global deny, no allowed gateways
module "outbound_gateway_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-bronze-prod
default_action = "Deny"
}2 Β· Global allow (permissive posture)
module "outbound_gateway_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-sandbox-dev
default_action = "Allow"
}
β οΈ Reserve for dev/sandbox workspaces β not the recommended posture for a regulated production workspace.
3 Β· Single on-premises gateway allowed
module "outbound_gateway_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-onprem-integration-prod
default_action = "Deny"
allowed_gateways = [module.onprem_gateway.id]
}4 Β· Two allowed gateways β primary and secondary
module "outbound_gateway_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-onprem-integration-prod
default_action = "Deny"
allowed_gateways = [
module.onprem_gateway_primary.id,
module.vnet_gateway_secondary.id,
]
}5 Β· VNet data gateway only
module "outbound_gateway_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-azure-native-prod
default_action = "Deny"
allowed_gateways = [module.vnet_gateway.id]
}βΉοΈ Consumes
terraform-fabric-gateway'sidoutput for aVirtualNetwork-type gateway registration.
6 Β· Custom timeouts
module "outbound_gateway_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-bronze-prod
default_action = "Deny"
timeouts = {
create = "30m"
}
}7 Β· Deliberately empty allow list β deny every gateway
module "outbound_gateway_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-locked-down-prod
default_action = "Deny"
allowed_gateways = []
}π Explicit
allowed_gateways = []documents intent β identical in effect to omitting the argument, since[]is this module's own default.
8 Β· Environment-scoped naming convention
module "outbound_gateway_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-onprem-integration-dev
default_action = "Deny"
allowed_gateways = [module.onprem_gateway_dev.id]
}9 Β· Paired with the workspace-level outbound switch
module "network_communication_policy" {
source = "git::https://github.com/microsoftexpert/terraform-fabric-workspace-network-communication-policy.git?ref=v1.0.0"
workspace_id = module.workspace.id
outbound = {
public_access_rules = { default_action = "Deny" }
}
}
module "outbound_gateway_rules" {
source = "../../"
workspace_id = module.workspace.id
default_action = "Deny"
allowed_gateways = [module.onprem_gateway.id]
depends_on = [module.network_communication_policy]
}
β οΈ This module's rules have no effect unless the sibling network-communication-policy module'soutbound.default_actionisDenyfor the same workspace β an explicitdepends_ondocuments the operational ordering.
10 Β· At scale β for_each over multiple workspaces sharing one gateway
variable "onprem_integration_workspace_ids" {
type = map(string)
}
module "outbound_gateway_rules" {
for_each = var.onprem_integration_workspace_ids
source = "../../"
workspace_id = each.value
default_action = "Deny"
allowed_gateways = [module.shared_onprem_gateway.id]
}π‘
for_eachover a caller-supplied map β adding a fifth workspace never threatens the first four.
11 Β· Guarding against a paused/wrong-SKU capacity
data "fabric_capacity" "target" {
display_name = "cap-casey-fsku-prod"
lifecycle {
postcondition {
condition = self.state == "Active"
error_message = "Target capacity must be Active for outbound access protection reads/writes to behave reliably."
}
}
}
module "outbound_gateway_rules" {
source = "../../"
workspace_id = module.workspace.id
default_action = "Deny"
depends_on = [data.fabric_capacity.target]
}
β οΈ Outbound access protection additionally requires an F-SKU capacity β thispostconditiononly guards against a paused capacity, not the wrong SKU.
12 Β· Personal on-premises gateway reference
module "outbound_gateway_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-analyst-sandbox-prod
default_action = "Deny"
allowed_gateways = [module.personal_gateway.id]
}βΉοΈ
<VERIFY: whether OnPremisesPersonal-type gateways are fully supported as allow-list entries here β not distinguished in this resource's confirmed schema, which accepts any gateway GUID string uniformly>.
13 Β· Rotating a gateway β replace one allowed entry without disturbing others
module "outbound_gateway_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-onprem-integration-prod
default_action = "Deny"
allowed_gateways = [
module.onprem_gateway_v2.id, # replaces onprem_gateway_v1
]
}βΉοΈ Since
allowed_gatewaysis rendered into an unordered Set, swapping one entry in the caller'sset(string)produces a minimal update diff rather than a full replacement of the resource.
14 Β· Documenting the tenant prerequisite in a runbook comment
# NOTE: requires the Fabric tenant admin to have enabled "Configure workspace-level outbound network
# rules" and the workspace to be on an F-SKU capacity β neither is enforceable from Terraform.
module "outbound_gateway_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-bronze-prod
default_action = "Deny"
}15 Β· ποΈ End-to-end composition
module "workspace" {
source = "git::https://github.com/microsoftexpert/terraform-fabric-workspace.git?ref=v1.0.0"
display_name = "ws-core-onprem-integration-prod"
capacity_id = data.fabric_capacity.core_fsku_prod.id
}
data "fabric_capacity" "core_fsku_prod" {
display_name = "cap-casey-fsku-core-prod"
}
module "gateway" {
source = "git::https://github.com/microsoftexpert/terraform-fabric-gateway.git?ref=v1.0.0"
display_name = "gw-onprem-primary-prod"
type = "OnPremises"
}
module "network_communication_policy" {
source = "git::https://github.com/microsoftexpert/terraform-fabric-workspace-network-communication-policy.git?ref=v1.0.0"
workspace_id = module.workspace.id
outbound = {
public_access_rules = { default_action = "Deny" }
}
}
module "outbound_gateway_rules" {
source = "git::https://github.com/microsoftexpert/terraform-fabric-workspace-outbound-gateway-rules.git?ref=v1.0.0"
workspace_id = module.workspace.id
default_action = "Deny"
allowed_gateways = [module.gateway.id]
depends_on = [module.network_communication_policy]
}
output "allowed_gateways" {
value = module.outbound_gateway_rules.allowed_gateways
}ποΈ Wires
terraform-fabric-workspace's andterraform-fabric-gateway'sidoutputs into this module'sworkspace_id/allowed_gateways, layered on top of the workspace-level outbound switch.
| Variable | Type | Default | Required |
|---|---|---|---|
workspace_id |
string |
β | β |
default_action |
string (Allow|Deny) |
β | β |
allowed_gateways |
set(string) |
[] |
β |
timeouts |
object({ create, read, update, delete = optional(string) }) |
null |
β |
Full object schemas
variable "workspace_id" {
type = string
}
variable "default_action" {
type = string
}
variable "allowed_gateways" {
type = set(string)
default = []
}
variable "timeouts" {
type = object({
create = optional(string)
read = optional(string)
update = optional(string)
delete = optional(string)
})
default = null
}| Output | Description | Sensitive |
|---|---|---|
workspace_id |
Primary output β the workspace GUID (no id attribute exists) |
No |
default_action |
Effective default_action for gateways not explicitly listed | No |
allowed_gateways |
Effective set of allowed gateway objects (unordered) | No |
allowed_gatewaysis rendered from a flatset(string)of gateway GUIDs into the provider's{ id = string }Attributes Set shape via[for gateway_id in var.allowed_gateways: { id = gateway_id }]inmain.tf.- No
idattribute exists on this resource βworkspace_idis the primary output, confirmed viaterraform providers schema -json. - Since
allowed_gatewaysis a Set, swapping one entry produces a minimal diff rather than threatening to replace the whole resource β there is nocount-style index-shifting risk here even though the module's own variable is a flat collection rather than a caller-keyed map.
| Concern | Safe default | Opt-out |
|---|---|---|
default_action |
No safe implicit default exists in the provider β required | Caller must explicitly choose Allow or Deny |
allowed_gateways |
Empty ([]) β no gateways allowed unless explicitly added |
Caller supplies gateway GUIDs |
cd C:\GitHubCode\newfabricmodules\terraform-fabric-workspace-outbound-gateway-rules
terraform init -backend=false
terraform validate
terraform fmt -checkPin ?ref=v1.0.0 β never a branch. Plan-only; a human applies from a reviewed pipeline.
validate/fmtcatch: missingworkspace_id/default_action, an invaliddefault_actionvalue, malformedallowed_gatewaysshape.- Only a live
plan/applyexercises: whether the referenced gateway GUIDs actually exist and are reachable from the workspace's capacity, whether the tenant/capacity prerequisites are met.
workspace_id = "00000000-0000-0000-0000-000000000000"
default_action = "Deny"
allowed_gateways = [
{ id = "11111111-1111-1111-1111-111111111111" },
]
| Symptom | Cause | Fix |
|---|---|---|
A gateway GUID in allowed_gateways produces no effect |
GUID does not correspond to an existing fabric_gateway reachable by this workspace's capacity |
Confirm the gateway ID against terraform-fabric-gateway's id output |
apply succeeds but outbound gateway traffic is not actually restricted |
The sibling terraform-fabric-workspace-network-communication-policy's outbound.default_action is still Allow |
Set that sibling module's outbound default_action to Deny |
apply fails with a permissions error |
Calling principal lacks Workspace Admin role | Grant Admin via terraform-fabric-workspace's role_assignments |
| Terraform reports drift on every plan | Workspace capacity is paused | Resume the capacity before planning/applying |
- Provider resource:
fabric_workspace_outbound_gateway_rules - Microsoft Learn: Workspace outbound access protection overview
- Sibling modules:
terraform-fabric-workspace,terraform-fabric-gateway,terraform-fabric-workspace-network-communication-policy - This module's SCOPE.md