|
| 1 | +# Egress policies and network controls for Azure Container Apps sandboxes (early access) |
| 2 | + |
| 3 | +Azure Container Apps sandboxes execute arbitrary workloads, including AI-generated code, agent toolchains, and untrusted user input. Controlling what those workloads can reach on the network is a foundational security control. This article describes the egress policy model, and how policies are evaluated. |
| 4 | + |
| 5 | +## The egress policy model |
| 6 | + |
| 7 | +An egress policy answers two questions for every outbound request a sandbox makes: |
| 8 | + |
| 9 | +1. Should this request be allowed? |
| 10 | + |
| 11 | +1. Should this request be transformed (for example, by injecting an authentication header or rewriting the destination)? |
| 12 | + |
| 13 | +A policy has the following shape: |
| 14 | + |
| 15 | +| Field | Description | |
| 16 | +|---|---| |
| 17 | +| **Default action** | `Allow` or `Deny`. Applied to any request that doesn't match a more specific rule. | |
| 18 | +| **Host rules** | Pattern-matched rules keyed on hostname (for example, `*.github.com`). Each rule has its own `Allow` or `Deny` action. | |
| 19 | +| **Rules** | Richer rules that match on host, path, and HTTP method, and support `Allow`, `Deny`, `Transform`, and `Rewrite` actions. | |
| 20 | +| **Traffic inspection** | Controls how the egress proxy inspects traffic (`Legacy`, `Partial`, `Full`, or `None`). | |
| 21 | + |
| 22 | +The recommended starting posture for any sandbox that runs untrusted code is `default_action = Deny` plus an explicit allow list of the destinations the workload genuinely needs. |
| 23 | + |
| 24 | +## Where policies live |
| 25 | + |
| 26 | +You can apply egress policies at two scopes: |
| 27 | + |
| 28 | +- **At create time**: Set on the request that creates the sandbox, so the workload starts under the policy. |
| 29 | + |
| 30 | +- **At runtime**: Update on a running sandbox via the SDK. The new policy takes effect for subsequent requests. |
| 31 | + |
| 32 | +## Rule evaluation order |
| 33 | + |
| 34 | +Egress decisions follow a predictable order: |
| 35 | + |
| 36 | +1. **Rich rules** are evaluated first, in the order they appear in the `rules` list. The first rule whose `match` (host, path, method) matches the request wins. The action attached to that rule is applied. |
| 37 | + |
| 38 | +1. **Host rules** are evaluated next when no rich rule matches. Host patterns support a leading wildcard (for example, `*.example.com`). |
| 39 | + |
| 40 | +1. **Default action** is applied when no rule matches. |
| 41 | + |
| 42 | +Order rich rules from most specific to most general. A `Deny` rule on `api.example.com/admin` placed before an `Allow` rule on `api.example.com` blocks the admin path while permitting the rest of the API. |
| 43 | + |
| 44 | +## Rule actions |
| 45 | + |
| 46 | +Rules support four action types: |
| 47 | + |
| 48 | +| Action | Use case | |
| 49 | +|---|---| |
| 50 | +| **Allow** | Permit the request unchanged. | |
| 51 | +| **Deny** | Block the request before it leaves the sandbox. | |
| 52 | +| **Transform** | Permit the request and modify its headers (for example, inject an authentication token). | |
| 53 | +| **Rewrite** | Permit the request and rewrite the destination scheme, host, or path. | |
| 54 | + |
| 55 | +`Transform` and `Rewrite` together let you front a sandbox's outbound calls with policy that authenticates and routes them without the sandbox ever needing to hold the credentials directly. |
| 56 | + |
| 57 | +## Header transforms and credential injection |
| 58 | + |
| 59 | +For workloads that call authenticated upstream APIs, `Transform` actions can attach headers from one of three sources: |
| 60 | + |
| 61 | +- **Static value**: A literal string baked into the rule. |
| 62 | + |
| 63 | +- **Secret reference**: Pulled from the sandbox group's Secrets store. Use a format string like `Bearer {value}` to combine the secret with a constant prefix. |
| 64 | + |
| 65 | +- **Managed identity reference**: A token acquired on demand from a managed identity for a specified resource URI. |
| 66 | + |
| 67 | +This pattern is especially useful for AI agent scenarios where the agent needs to call an LLM API, but you don't want the agent code to handle the API key directly. |
| 68 | + |
| 69 | +## Traffic inspection |
| 70 | + |
| 71 | +The egress proxy supports several inspection modes: |
| 72 | + |
| 73 | +| Mode | Behavior | |
| 74 | +|---|---| |
| 75 | +| **Legacy** | Default for backward compatibility. Legacy host-based filtering only. | |
| 76 | +| **Partial** | Inspects request lines and headers; rich rules and transforms apply. | |
| 77 | +| **Full** | Full inspection including body for the rules and transforms that need it. | |
| 78 | +| **None** | Outbound traffic bypasses the egress proxy entirely. | |
| 79 | + |
| 80 | +Choose `Partial` or `Full` to use rich rules. Set inspection to `None` (or use the per-sandbox `skip_egress_proxy` flag at creation time) only when latency matters more than control and you trust the destination. |
| 81 | + |
| 82 | +## Considerations |
| 83 | + |
| 84 | +| Area | Detail | |
| 85 | +|---|---| |
| 86 | +| **Default-deny posture** | Workloads that execute untrusted code should default to `Deny` and add narrow allow rules for the destinations they need. | |
| 87 | +| **Layered rules** | Use `rules` for path- or method-specific decisions and `host_rules` for whole-domain decisions. Keep host rules short; promote anything that needs path matching into a rich rule. | |
| 88 | +| **Policy lifecycle** | Policies are mutable on running sandboxes. Updates apply to subsequent requests; in-flight requests aren't reevaluated. | |
| 89 | +| **Per-environment policies** | Maintain separate policies for development, staging, and production. Devs can iterate against a permissive policy while production stays locked down. | |
| 90 | +| **Audit cadence** | Pull egress decisions periodically from long-running sandboxes and review denied counts. A spike usually indicates a workload misconfiguration or an exfiltration attempt. | |
| 91 | +| **Skip the proxy carefully** | `skip_egress_proxy` (or traffic inspection `None`) trades safety for latency. Only enable it for sandboxes that don't run untrusted code and only for trusted destinations. | |
| 92 | + |
| 93 | +## Related content |
| 94 | + |
| 95 | +- [Snapshots and state management for sandboxes](sandboxes-snapshots-state-management.md) |
0 commit comments