diff --git a/docs/prds/0017-egress-proxy-via-mitmproxy.md b/docs/prds/0017-egress-proxy-via-mitmproxy.md index 031306b..ef723cf 100644 --- a/docs/prds/0017-egress-proxy-via-mitmproxy.md +++ b/docs/prds/0017-egress-proxy-via-mitmproxy.md @@ -21,7 +21,8 @@ are split between cred-proxy and pipelock: the cred-proxy URL. 3. **Credential injection.** Continues cred-proxy's existing role: match by hostname (or hostname + path), strip inbound - Authorization, inject one based on `auth_scheme` + `token_ref`. + Authorization, inject one based on the route's optional `auth: + { scheme, token_ref }` block. Pipelock's role narrows to hostname allowlist + DLP body scanning on the egress-proxy → upstream leg. Pipelock no longer holds the @@ -90,8 +91,10 @@ delivery. (was pipelock's CA). - Manifest rename: `bottle.cred_proxy.routes[]` → `bottle.egress_proxy.routes[]`. The route shape gains optional - `path_allowlist: [, ...]` and supports `auth_scheme: - "none"`. + `path_allowlist: [, ...]` and a nested optional `auth: + { scheme, token_ref }` block (presence/absence of `auth` is the + authenticated vs unauthenticated signal — replaces the old + `auth_scheme: "none"` pattern). - Agent's `HTTP_PROXY` / `HTTPS_PROXY` env vars repointed at the egress-proxy (was pipelock). - Pipelock retains its sidecar slot and its own DLP + hostname @@ -151,30 +154,41 @@ default proxy path. ```yaml egress_proxy: routes: - # Authenticated route (today's cred-proxy shape, slightly - # renamed). path_allowlist optional. + # Authenticated route — `auth` block carries the injection + # config. path_allowlist optional. - host: "api.github.com" - auth_scheme: "Bearer" - token_ref: "GH_PAT" + auth: + scheme: "Bearer" + token_ref: "GH_PAT" path_allowlist: - "/repos/didericis/" - "/users/didericis" - # Unauthenticated path-filtered route. + # Unauthenticated path-filtered route — `auth` omitted + # entirely (presence/absence of the key is the auth signal). - host: "github.com" - auth_scheme: "none" path_allowlist: - "/didericis/" - # Bare-pass route: no auth injection, no path enforcement. - # Useful when you want a host to skip path filtering but - # still be DLP-scanned by pipelock. + # Bare-pass route: no auth, no path constraint. Useful when + # you want a host to skip path filtering but still be + # DLP-scanned by pipelock on the outbound leg. - host: "api.anthropic.com" - auth_scheme: "none" - # no path_allowlist → all paths pass ``` Route matching is on `host` (was `path` prefix). The hostname gates whether a route applies; `path_allowlist` (if present) -constrains the URL path under that host. +constrains the URL path under that host. The optional `auth` +block carries credential-injection config: + +- Omit `auth` → no Authorization header injected (replaces the + earlier draft's `auth_scheme: "none"`). +- `auth.scheme` → one of `Bearer`, `token` (the values + cred-proxy supports today; sidesteps the gitea-token quirk). +- `auth.token_ref` → host env var holding the secret. Same + semantics as cred-proxy's `TokenRef` field today. + +Validation: `auth` (if present) must contain both `scheme` and +`token_ref`. An empty `auth: {}` is an error rather than a +synonym for "no auth" — that's what omission is for. ### mitmproxy addon shape @@ -187,9 +201,10 @@ The egress-proxy ships a small Python addon that: matches → forward unchanged (pipelock will hostname-gate it). If route matches and has `path_allowlist`, check `flow.request.path` against the prefix list; 403 with a clear reason if no match. -- On approved requests: strip inbound Authorization, inject - `Authorization: ` if `auth_scheme - != "none"`. +- On approved requests: strip inbound Authorization. If the route + carries an `auth` block, inject `Authorization: + `. If the route omits + `auth`, leave Authorization unset. - SIGHUP / file-mtime watch on `routes.yaml` for hot-reload (same cadence as today's cred-proxy SIGHUP path).