Manages a single
fabric_workspace_outbound_cloud_connection_rulesresource β the per-cloud-connection-type outbound allow/deny posture for one Fabric workspace β against themicrosoft/fabricprovider~> 1.12.0.
- π Sets a global fallback
default_action(Allow|Deny) for every outbound cloud connection type not otherwise covered by a specific rule. - π― Optionally defines per-connection-type rules (
SQL,LakeHouse,MySQL,Web, etc.), each with its owndefault_action, an optional set of allowed hostname patterns, and an optional set of allowed target workspace GUIDs. - π Not a wrapper around
terraform-fabric-connectionβ despite the module name, the confirmed schema has no field referencing afabric_connectionresource instance;connection_typeis a category label, not a connection ID. See Β§ Architecture Notes.
π‘ Why it matters: this is a data-governance control restricting which external cloud connections a workspace's items can reach outbound. Combined with
terraform-fabric-workspace-network-communication-policy(which must setoutbound.default_action = "Deny"for this module's allow-list to matter at all), it lets a workspace block all outbound connectivity by default and then narrowly permit only named, reviewed connection categories and destinations.
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, this workspace"]:::keystone
WS2["terraform-fabric-workspace, target workspace"]:::sibling
THIS["terraform-fabric-workspace-outbound-cloud-connection-rules"]:::this
WS -->|"workspace_id"| THIS
WS2 -->|"id, into rules.allowed_workspaces"| 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. terraform-fabric-connection is deliberately absent
from this diagram β the confirmed schema has no reference to it (see Β§ Architecture Notes for why this
deviates from the module's original naming-derived hypothesis).
flowchart TB
subgraph Inputs
A["workspace_id"]
B["default_action"]
C["rules, map keyed by caller-chosen name"]
D["timeouts"]
end
R["fabric_workspace_outbound_cloud_connection_rules.this"]:::this
A --> R
B --> R
C --> R
D --> R
R --> O1["workspace_id"]
R --> O2["default_action"]
R --> O3["rules"]
classDef this fill:#0F6CBD,color:#ffffff,stroke:#0F6CBD,stroke-width:2px;
Resource inventory: 1 resource β fabric_workspace_outbound_cloud_connection_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, not guessed, per this suite's secure-by-default convention.rules[].connection_typehas no documented closed enum. The provider's Example Usage shows only illustrative values (SQL,LakeHouse); this module cannot validate the string against a fixed list atterraform validatetime β a typo'd connection_type is a real risk only caught atapply/runtime.allowed_workspacesis honored only for Lakehouse, Warehouse, FabricSql, and PowerPlatformDataflows connection types per Microsoft's own docs; setting it elsewhere is accepted byvalidatebut ignored by the API.rulesis an unordered Attributes Set, not a list or map at the API layer β this module renders a caller-keyedmap(object({...}))into that Set shape via aforexpression; the map key is a house-style convenience only, discarded before reaching the provider.- This resource had no prior internal house pattern β newly discovered and 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 for outbound access protection.
- 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-cloud-connection-rules/
βββ providers.tf # required_providers floor β no provider {} block
βββ variables.tf # workspace_id, default_action, rules, timeouts
βββ main.tf # fabric_workspace_outbound_cloud_connection_rules.this β thin renderer
βββ outputs.tf # workspace_id (primary), default_action, rules
βββ README.md # this file
βββ SCOPE.md # lightweight standalone scope
βββ examples/
βββ basic/ # global deny, no per-connection-type rules
βββ complete/ # global deny plus SQL endpoint + Lakehouse cross-workspace carve-outs
module "outbound_cloud_connection_rules" {
source = "git::https://github.com/microsoftexpert/terraform-fabric-workspace-outbound-cloud-connection-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 |
rules[*].allowed_workspaces |
set(string) |
terraform-fabric-workspace's id output (target workspace) |
Emits
| Output | Description | Consumed by |
|---|---|---|
workspace_id |
Primary output β the workspace GUID these rules govern | Informational / cross-referencing |
default_action |
Effective global fallback default_action | Informational |
rules |
Effective set of per-connection-type rule objects | Informational |
1 Β· Basic β global deny, no exceptions
module "outbound_cloud_connection_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-bronze-prod
default_action = "Deny"
}2 Β· Global allow (permissive posture)
module "outbound_cloud_connection_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-sandbox-dev
default_action = "Allow"
}
β οΈ Reserve for dev/sandbox workspaces βdefault_action = "Allow"is not the recommended posture for a regulated production workspace.
3 Β· Single SQL endpoint carve-out
module "outbound_cloud_connection_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-curated-prod
default_action = "Deny"
rules = {
"sql-partner-endpoints" = {
connection_type = "SQL"
default_action = "Deny"
allowed_endpoints = ["*.partner-bank.example.com"]
}
}
}βΉοΈ
connection_typeis a plain string with no closed-enum validation β double-check spelling against current Microsoft Fabric documentation before applying.
4 Β· Cross-workspace Lakehouse access
module "outbound_cloud_connection_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-silver-prod
default_action = "Deny"
rules = {
"lakehouse-cross-workspace" = {
connection_type = "LakeHouse"
default_action = "Deny"
allowed_workspaces = [module.gold_workspace.id]
}
}
}π‘
allowed_workspacesis honored only for Lakehouse, Warehouse, FabricSql, and PowerPlatformDataflows connection types per Microsoft's documentation.
5 Β· Multiple connection types in one resource
module "outbound_cloud_connection_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-curated-prod
default_action = "Deny"
rules = {
"sql-partner-endpoints" = {
connection_type = "SQL"
default_action = "Deny"
allowed_endpoints = ["*.partner-bank.example.com"]
}
"web-vendor-api" = {
connection_type = "Web"
default_action = "Deny"
allowed_endpoints = ["api.vendor.example.com"]
}
}
}6 Β· Wildcard hostname patterns
module "outbound_cloud_connection_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-bronze-prod
default_action = "Deny"
rules = {
"mysql-vendor-cluster" = {
connection_type = "MySQL"
default_action = "Deny"
allowed_endpoints = ["*.vendor-mysql.example.com", "db-replica-*.vendor-mysql.example.com"]
}
}
}7 Β· Multiple allowed target workspaces
module "outbound_cloud_connection_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-silver-prod
default_action = "Deny"
rules = {
"warehouse-cross-workspace" = {
connection_type = "Warehouse"
default_action = "Deny"
allowed_workspaces = [
module.gold_workspace.id,
module.reporting_workspace.id,
]
}
}
}8 Β· Environment-scoped naming convention
module "outbound_cloud_connection_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-bronze-dev
default_action = "Deny"
rules = {
"sql-dev-sandbox-endpoints" = {
connection_type = "SQL"
default_action = "Deny"
allowed_endpoints = ["*.dev-sandbox.example.com"]
}
}
}π‘ The rule's caller-chosen map key (
sql-dev-sandbox-endpoints) is a house-style readability aid β it is discarded before reaching the Fabric API, but encoding environment in it here helps a reviewer scan the diff.
9 Β· Custom timeouts
module "outbound_cloud_connection_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-bronze-prod
default_action = "Deny"
timeouts = {
create = "30m"
}
}10 Β· 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_cloud_connection_rules" {
source = "../../"
workspace_id = module.workspace.id
default_action = "Deny"
rules = {
"sql-partner-endpoints" = {
connection_type = "SQL"
default_action = "Deny"
allowed_endpoints = ["*.partner-bank.example.com"]
}
}
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 β there is no Terraform attribute reference between the two, so the ordering is documented viadepends_on.
11 Β· At scale β for_each over multiple workspaces
variable "curated_workspace_ids" {
type = map(string)
}
module "outbound_cloud_connection_rules" {
for_each = var.curated_workspace_ids
source = "../../"
workspace_id = each.value
default_action = "Deny"
}π‘
for_eachover a caller-supplied map β adding a fifth workspace never threatens the first four.
12 Β· 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_cloud_connection_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 specifically β thispostconditiononly guards against a paused capacity, not the wrong SKU.
13 Β· Deliberately empty rules β deny everything, no exceptions
module "outbound_cloud_connection_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-locked-down-prod
default_action = "Deny"
rules = {}
}π Explicit
rules = {}documents intent β identical in effect to omittingrulesentirely, since{}is this module's own default.
14 Β· Real-Time Events cross-workspace consumption pattern
module "outbound_cloud_connection_rules" {
source = "../../"
workspace_id = module.workspace.id # ws-core-events-consumer-prod
default_action = "Deny"
rules = {
"realtime-events-cross-workspace" = {
connection_type = "RealTimeEvents"
default_action = "Deny"
allowed_workspaces = [module.events_source_workspace.id]
}
}
}βΉοΈ
"RealTimeEvents"is inferred from Microsoft Learn's Fabric-events outbound-protection material, not from the provider's own Example Usage β confirm exact spelling against current documentation before applying, sinceconnection_typehas no closed-enum validation in this module.
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-curated-prod"
capacity_id = data.fabric_capacity.core_fsku_prod.id
}
module "gold_workspace" {
source = "git::https://github.com/microsoftexpert/terraform-fabric-workspace.git?ref=v1.0.0"
display_name = "ws-core-gold-prod"
capacity_id = data.fabric_capacity.core_fsku_prod.id
}
data "fabric_capacity" "core_fsku_prod" {
display_name = "cap-casey-fsku-core-prod"
}
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_cloud_connection_rules" {
source = "git::https://github.com/microsoftexpert/terraform-fabric-workspace-outbound-cloud-connection-rules.git?ref=v1.0.0"
workspace_id = module.workspace.id
default_action = "Deny"
rules = {
"lakehouse-cross-workspace" = {
connection_type = "LakeHouse"
default_action = "Deny"
allowed_workspaces = [module.gold_workspace.id]
}
}
depends_on = [module.network_communication_policy]
}
output "outbound_cloud_connection_rules" {
value = module.outbound_cloud_connection_rules.rules
}ποΈ Wires
terraform-fabric-workspace'sidoutput (both the primary and target workspace) into this module'sworkspace_id/rules.allowed_workspaces, layered on top ofterraform-fabric-workspace-network-communication-policyfor the top-level outbound switch.
| Variable | Type | Default | Required |
|---|---|---|---|
workspace_id |
string |
β | β |
default_action |
string (Allow|Deny) |
β | β |
rules |
map(object({ connection_type, default_action = string; allowed_endpoints, allowed_workspaces = optional(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 "rules" {
type = map(object({
connection_type = string
default_action = string
allowed_endpoints = optional(set(string), [])
allowed_workspaces = optional(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 global fallback default_action | No |
rules |
Effective set of per-connection-type rule objects (unordered) | No |
rulesis rendered from a caller-keyedmap(object({...}))into the provider's unordered Attributes Set via[for _, rule in var.rules: {...}]inmain.tfβ the map key exists purely for readability in the caller's own.tfand is discarded at that boundary.allowed_endpoints/allowed_workspacesare modeled as flatset(string)variables (notmap(object({single_field}))) since each genuinely wraps a single scalar field in the provider schema βmain.tfexpands each string into the provider's{ hostname_pattern =... }/{ workspace_id =... }shape via aforexpression.- This module does not reference
terraform-fabric-connectionat all, despite the "cloud connection" name β the confirmed schema'sconnection_typeis a category string (SQL,LakeHouse, etc.), not afabric_connectionresource ID. Do not assume this module consumes that sibling'sidoutput; it does not. - No
idattribute exists on this resource βworkspace_idis the primary output.
| Concern | Safe default | Opt-out |
|---|---|---|
Global fallback (default_action) |
No safe implicit default exists in the provider β required, not optional, per this suite's secure-by-default convention | Caller must explicitly choose Allow or Deny |
Per-connection-type rules (rules) |
Empty ({}) β no carve-outs unless explicitly added |
Caller supplies named rule entries |
cd C:\GitHubCode\newfabricmodules\terraform-fabric-workspace-outbound-cloud-connection-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 invalid top-level or per-ruledefault_actionvalue, malformedrulesobject shape.- Only a live
plan/applyexercises: whetherconnection_typestrings are actually valid against the current Fabric API (no closed-enum validation exists in this module), whether the tenant/capacity prerequisites are met, and whetherallowed_workspacesis honored for the chosenconnection_type.
workspace_id = "00000000-0000-0000-0000-000000000000"
default_action = "Deny"
rules = [
{
connection_type = "SQL"
default_action = "Deny"
allowed_endpoints = [{ hostname_pattern = "*.partner-bank.example.com" }]
allowed_workspaces = []
},
]
| Symptom | Cause | Fix |
|---|---|---|
A rule's allowed_endpoints/allowed_workspaces appears to have no effect |
Field is not honored for the chosen connection_type (e.g. allowed_workspaces set on a SQL rule) |
Recheck Microsoft's connection-type-specific documentation; move the restriction to the field that type actually supports |
apply succeeds but outbound 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 β this module's rules only matter once the top-level switch is closed |
A connection_type typo passes validate but fails silently at runtime |
connection_type has no closed-enum validation in this module |
Double-check spelling against current Microsoft Fabric documentation before applying |
| Terraform reports drift on every plan | Workspace capacity is paused | Resume the capacity before planning/applying (see this suite's region/instance/scope model convention) |
- Provider resource:
fabric_workspace_outbound_cloud_connection_rules - Microsoft Learn: Workspace outbound access protection β allow-list connector
- Sibling modules:
terraform-fabric-workspace,terraform-fabric-workspace-network-communication-policy,terraform-fabric-workspace-outbound-gateway-rules - This module's SCOPE.md