Skip to content
CSA Loom — the Microsoft Fabric experience for Azure tenants where Fabric isn't yet available: lakehouses, warehouses, notebooks, semantic models, Activator rules, Data Agents, across Commercial, GCC, GCC-High, and DoD IL5

Console access patterns

The Container Apps env is internal-only (no public IP, env LB private in the hub VNet). Five reachability patterns are now wired into Bicep — pick what matches the deploy.

# Pattern Public? Flag Cost / mo Provision time Best for
1 Bastion → jumpbox → browser always-on ~$140 (Standard SKU + 1 D2as VM) already deployed Federal admin, ATO scope, "no public surface" requirement
2 P2S VPN Gateway (AAD auth, OpenVPN) vpnGatewayEnabled ~$30 (VpnGw1) + per-conn 30-45 min Power users on laptops who don't want Bastion every time
3 App Gateway v2 + WAF appGatewayEnabled ~$250 15-20 min Single-region public Console, WAF required, App Gateway already standard in environment
4 Front Door Premium + Private Link to ACA frontDoorEnabled ~$330 5-10 min + manual PE approval Multi-region, global edge, managed cert, best UX
5 Custom domain on the env either (custom-domain Bicep, separate) $0 extra minutes Vanity URL on any of the above

Bastion (#1) is always provisioned by network.bicep. The other three are gated by flags on the top-level main.bicep:

az deployment sub create \
  --name csa-loom-access-patterns \
  --location eastus2 \
  --template-file platform/fiab/bicep/main.bicep \
  --parameters platform/fiab/bicep/params/commercial.bicepparam \
  --parameters deployAppsEnabled=true \
  --parameters vpnGatewayEnabled=true \
  --parameters appGatewayEnabled=true \
  --parameters frontDoorEnabled=true

After the deploy, the relevant outputs surface the public/private entry points:

az deployment sub show --name csa-loom-access-patterns \
  --query "properties.outputs.{
    vpnPublicIp:    vpnGatewayPublicIp.value,
    agwPublicFqdn:  appGatewayPublicFqdn.value,
    frontDoorUrl:   frontDoorPublicUrl.value
  }"

#1 Bastion → jumpbox

The hub VNet ships with AzureBastionSubnet (10.0.1.0/26) + a Standard Bastion host (bastion-csa-loom-<region>). The UAT jumpbox (loom-uat-jumpbox, AAD-SSH only, no local password) gets you into the VNet from any browser. From there, https://loom-console.<env-domain> just works.

This is the federal default — no public surface to ATO.

#2 P2S VPN Gateway

vpn-gateway.bicep deploys a VpnGw1 (Standard SKU) into the new GatewaySubnet (10.0.7.0/27), authenticated against Entra (Azure AD). Admins install the Azure VPN Client on their laptop, sign in with their Entra account, and the laptop joins the hub VNet at 172.16.201.0/24 (configurable). Console URL loads directly in their laptop browser.

Provisioning is slow (30-45 min) — Azure VNet Gateways are not fast resources. Cost is ~$30/mo idle + $0.04/connection-hour.

#3 App Gateway v2 + WAF

app-gateway.bicep deploys WAF_v2 with OWASP 3.2 + Bot Manager rules. Backend pool points at the ACA env's static IP (10.0.2.85) with a Host header override so the env routes to the Console app. Public IP gets a DNS label loom-<hash>.eastus2.cloudapp.azure.com — operator points a custom CNAME at it if they want a real hostname.

App Gateway sits in the new snet-appgw subnet (10.0.8.0/24). Cost ~$250/mo. Provisions in ~15-20 min.

front-door.bicep deploys the Premium SKU and creates a Private Link shared resource pointing at the Container Apps env. The first deploy leaves the PE request in a pending state on the env — operator must go to Container Apps env → Network → Private endpoint connections and click Approve. After that, traffic flows from any FD edge POP through the private link into the env's internal LB — no public ACA exposure.

Public URL surfaces as https://loom-console-<hash>.z01.azurefd.net (or whatever custom domain you bind). Managed cert is free.

#5 Custom domains

Not in this PR — covered by a separate custom-domains.bicep already in the backlog. Works in front of any of #1-4. For #3 (App Gateway) or #4 (Front Door), bind the custom hostname on the listener / route and upload a cert (or use the managed cert on FD).

  • Commercial pilot: Bastion + Front Door Premium (#1 + #4). Front Door for end users, Bastion for ops.
  • GCC / GCC-High: Bastion + VPN Gateway (#1 + #2). Front Door isn't in Gov boundaries yet; App Gateway works but has no Private Link to ACA in Gov regions (uses public IP path with NSG restriction).
  • IL5: Bastion only (#1). Public ingress is generally out of scope; sideline App Gateway in a separate ATO scope if a public surface is required.
  • Dev / sandbox: Bastion + VPN (#1 + #2). Cheap, fast.

Notes on routing

Front Door's Private Link path requires the Container Apps env to allow PE connections (vnetConfiguration.internal: true envs do support this in Commercial as of 2024-11; verify support in your boundary's API version before turning the flag on).

App Gateway's backend pool uses the env's internal IP; the env's Envoy proxy will receive the request, look at the Host header, and route to the Console app. Because the Console is external ingress (by Bicep default since PR #328), the env accepts the request even though it's coming from an in-VNet origin.

VPN clients get a 172.16.201.0/24 IP (configurable via the vpnClientAddressPool parameter on vpn-gateway.bicep). DNS over the tunnel works via the hub VNet's DNS resolver — no extra config needed if you've already linked the env's private DNS zone to the hub VNet.