PRD 0010: Credential proxy for agent-bound API tokens #14

Merged
didericis merged 24 commits from cred-proxy into main 2026-05-24 14:24:52 -04:00
Showing only changes of commit 6b91506706 - Show all commits
+38 -28
View File
@@ -71,43 +71,53 @@ pieces of v1.
A bottle is the agent container plus up to three per-protocol egress A bottle is the agent container plus up to three per-protocol egress
sidecars on a per-agent Docker `--internal` network. The agent has no sidecars on a per-agent Docker `--internal` network. The agent has no
default route off-box; its only way out is through the pipelock default route off-box. All HTTP and HTTPS egress — from the agent
sidecar (for HTTP/HTTPS), the git-gate sidecar (for git operations *and* from cred-proxy when it dials an upstream — funnels through
against declared upstreams), or the cred-proxy sidecar (for API pipelock, where the egress allowlist, TLS interception, and
calls that need a manifest-declared token — Anthropic OAuth, GitHub request-body DLP scanner enforce the manifest before any byte leaves
PAT, Gitea PAT, npm). Each sidecar also sits on an egress network the host. The only egress that doesn't traverse pipelock is git-gate's
that does have internet access, so the agent's traffic always passes SSH push/fetch to `bottle.git` upstreams — pipelock can't proxy SSH,
through a container that enforces the manifest before it leaves the so git-gate is its own L4-style egress path with gitleaks doing the
host. pre-receive scan.
``` ```
host ( ./cli.py ) host ( ./cli.py )
starts │ stops starts │ stops
┌─────────────────────────── bottle ──────────────────────────┐ ┌─────────────────────────── bottle ──────────────────────────────────
│ │ │ │
│ ┌──────────────────┐ │ │ ┌──────────────────┐ │
│ │ agent image │ HTTPS_PROXY ┌────────────────┐ HTTPS to │ │ agent image │ HTTPS_PROXY
│ │ (claude-code, │ ───────────────► │ pipelock image │──── allowlisted │ │ (claude-code, │ ────────────────────────
│ │ built locally) │ │ (TLS bump, DLP,│ │ hosts │ │ built locally) │ │ │
│ │ │ allowlist) │ │ │ │ plain HTTP
│ │ skills, env, │ ────────────────┘ │ │ skills, env, │ (token injection) ┌─────────────
│ │ ~/.gitconfig, │ │ │ ~/.gitconfig, │ ──────────────────►│ cred-proxy
│ │ ~/.npmrc, tea │ git ops ┌────────────────┐ SSH (push/ │ │ ~/.npmrc, tea │ │ (strips/inj │ │
│ │ │ ───────────────► │ git-gate image │──┼──► fetch) to │ │ │ │ Authoriz.) │ │
│ │ │ │ (gitleaks + │ │ bottle.git │ │ environ: URLs │ └─────┬────────┘ │
│ │ environ: URLs │ git daemon) upstreams │ │ only, no real │ HTTPS_PROXY
│ │ only, no real└────────────────┘ │ │ tokens
│ │ tokensbearer-auth ┌────────────────┐ │ HTTPS to │ │ ┌────────────────┐ │ HTTPS to
│ │ │ ───────────────► │ cred-proxy │──┼──► bottle.tokens │ │ │ │ pipelock image │──────────┼──► allowlisted
│ │ │ HTTP, plain │ (strips/injects│ │ upstreams │ │ │ │ (TLS bump, DLP │ │ hosts (incl.
│ │ │ │ Authorization)│ │ (with the │ │ │ │ body scan, │ │ cred-proxy
└──────────────────┘ └────────────────┘ │ real token) │ │ │ allowlist) │ │ upstreams)
│ │ │ └────────────────┘ │
│ │ │ │
│ │ │ git:// ┌────────────────┐ │ SSH push/fetch
│ │ │ ────────────────►│ git-gate image │──────────┼──► to bottle.git
│ │ │ │ (gitleaks + │ │ upstreams
│ └──────────────────┘ │ git daemon) │ │ (direct — not
│ └────────────────┘ │ via pipelock)
│ │ │ │
│ agent on internal network (no default route); │ agent on internal network (no default route); pipelock,
sidecars also attached to an egress network. cred-proxy, and git-gate straddle internal + egress networks. │
└─────────────────────────────────────────────────────────────┘ │ pipelock is the single HTTP/HTTPS chokepoint — cred-proxy's │
│ outbound traverses it too. git-gate's SSH egress is direct │
│ because pipelock is HTTP-only. │
└─────────────────────────────────────────────────────────────────────┘
``` ```
- **agent image** — built from the repo `Dockerfile` (`node:22-slim` - **agent image** — built from the repo `Dockerfile` (`node:22-slim`