Expand description
§ironflow-auth-proxy
HTTP service that keeps the Claude credential out of ironflow agent pods.
The worker (K8sEphemeralProvider::auth_proxy) asks the admin API for an
opaque token bound to one run and one step, and hands only that token to
the pod. Claude Code sends it as Authorization: Bearer to this proxy,
which swaps it for the real credential and relays the request to
api.anthropic.com, streaming the answer back.
The same mechanism keeps other secrets (a GitHub or GitLab token, an API
key) out of the pod: a grant can hold a proxied secret with a host
allowlist instead of the Claude credential. The pod calls
/r/<host>/<path> with its opaque token (as Authorization: Bearer,
x-api-key, Private-Token or the password of Authorization: Basic),
and the proxy relays to https://<host>/<path> with the real secret
injected the way the grant says (bearer, Private-Token, x-api-key, a
named header or Basic). A host outside the allowlist (exact names or a
leading *., no port, no IP) gets a 403, so does a Claude token on /r/
and a secret token on the Anthropic API. Redirects are returned to the
pod, never followed.
One listener serves:
GET /healthz- liveness;GET /metrics- Prometheus metrics, when a recorder handle is given (AuthProxyState::with_metrics):REQUESTS_TOTALcounts the/r/requests bysecretname andresult;/admin/v1/...- token issuance and revocation, behindAuthorization: Bearer <IRONFLOW_AUTH_PROXY_ADMIN_KEY>;/r/<host>/<path>- the relay of proxied secrets: an unknown, expired or revoked token gets a 401, a host outside the allowlist or a path with..,//or percent-encoding a 403, CONNECT, TRACE or OPTIONS a 405. Each request logs onesecret relayevent with itsresult(relayed,forbidden_host,forbidden_path,forbidden_method,unknown_token,expired,revoked,upstream_error,unavailable);- anything else - the Anthropic relay: an unknown, expired or revoked
token gets a 401, a path outside
/v1/or a request for another host a 403, a method other than GET/POST a 405.
Grants live in a registry with two backends:
- in memory (default): a single replica, tokens lost on restart;
- PostgreSQL, when
DATABASE_URL_ENVis set (registry_from_config): shared by several replicas and surviving restarts. Only the token SHA-256 is stored, never the token, and the credential is AES-256-GCM encrypted at rest with theIRONFLOW_SECRET_KEYSkey ring.
Logs never contain a token, a credential, a secret, a header or a query string, only the short token id.
§Examples
use std::env::var;
use std::time::Duration;
use ironflow_auth_proxy::{
AuthProxyConfig, AuthProxyState, DATABASE_URL_ENV, registry_from_config, serve, spawn_purge,
};
use ironflow_store::crypto::KeyRing;
use tokio::net::TcpListener;
let database_url = var(DATABASE_URL_ENV).ok();
let registry = registry_from_config(database_url.as_deref(), KeyRing::from_env()?).await?;
let config = AuthProxyConfig::new("0123456789abcdef0123456789abcdef");
let state = AuthProxyState::with_registry(config, registry)?;
let purge = spawn_purge(state.registry().clone(), Duration::from_secs(60));
let listener = TcpListener::bind("0.0.0.0:8080").await?;
serve(listener, state).await?;
purge.abort();Structs§
- Auth
Proxy Config - Configuration of the proxy. Its
Debugoutput never shows the admin key. - Auth
Proxy State - Shared state of the proxy: the token registry, the configuration and the upstream HTTP client. Cheap to clone.
Enums§
- Registry
Config Error - Why the token registry could not be built. No variant carries the database URL, a key or a credential.
Constants§
- DATABASE_
URL_ ENV - Environment variable holding the PostgreSQL URL of the shared token registry. Unset (or empty), tokens live in memory.
- DEFAULT_
MAX_ BODY_ BYTES - Default largest request body relayed: 32 MiB.
- MIN_
ADMIN_ KEY_ LEN - Shortest admin key accepted.
- REQUESTS_
TOTAL - Prometheus counter of the requests to the
/r/relay, labelled bysecret(its name, empty for an unknown token) andresult.
Functions§
- registry_
from_ config - Build the token registry: in memory when
database_urlisNoneor blank, otherwise shared in PostgreSQL, the credentials encrypted withkey_ring. Opening the database runs the store migrations. - router
- The proxy router: health, metrics, admin API and relays.
- serve
- Serve the proxy on
listeneruntil ctrl-c or SIGTERM, letting in-flight requests finish. - spawn_
purge - Spawn a task dropping the expired grants of
registryeveryinterval.