Skip to main content

Crate ironflow_auth_proxy

Crate ironflow_auth_proxy 

Source
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.

One listener serves:

  • GET /healthz - liveness;
  • /admin/v1/... - token issuance and revocation, behind Authorization: Bearer <IRONFLOW_AUTH_PROXY_ADMIN_KEY>;
  • anything else - the 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_ENV is 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 the IRONFLOW_SECRET_KEYS key ring.

Logs never contain a token or a credential, 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§

AuthProxyConfig
Configuration of the proxy. Its Debug output never shows the admin key.
AuthProxyState
Shared state of the proxy: the token registry, the configuration and the upstream HTTP client. Cheap to clone.

Enums§

RegistryConfigError
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.

Functions§

registry_from_config
Build the token registry: in memory when database_url is None or blank, otherwise shared in PostgreSQL, the credentials encrypted with key_ring. Opening the database runs the store migrations.
router
The proxy router: health, admin API and relay.
serve
Serve the proxy on listener until ctrl-c or SIGTERM, letting in-flight requests finish.
spawn_purge
Spawn a task dropping the expired grants of registry every interval.