iron-control is the control plane for iron-proxy, a forwarding proxy that adds credentials to outbound HTTP requests. Applications route their traffic through iron-proxy and never hold the secrets themselves. iron-control stores the credentials, decides which proxy may use which credential on which requests, and hands each proxy its configuration.
It is a Rails application backed by Postgres. It provides a JSON API, an operator console, and encryption at rest for the secrets it stores.
- Stores credentials. Each secret is a typed record. The value is either kept inline and encrypted, or pulled from an external store such as AWS Secrets Manager, AWS SSM, 1Password, or an environment variable. The supported kinds are static secrets, GCP service-account auth, AWS SigV4 auth, OAuth tokens, Postgres connection strings, and HMAC signing keys.
- Controls who can use them. A principal is an identity that a proxy runs as. A role groups credentials so they can be assigned together. A grant gives one credential to a principal or a role. A principal can use its own grants plus the grants of every role it has.
- Limits where they apply. Each grant has request rules for host, methods, and paths, so a credential is only added to the requests it is meant for.
- Configures proxies. A proxy registers with
iron-control, gets assigned a principal, and callsPOST /api/v1/proxy/syncto fetch its configuration. The response includes a config hash that works like an ETag, so a proxy that already has the current config gets an empty response. - Issues short-lived tokens. For
token_brokercredentials,iron-controlmints and rotates the access token itself and sends only the token to the proxy. The underlying credential never leaves the control plane.
operator ──▶ console / JSON API ──▶ iron-control ──▶ Postgres (encrypted secrets)
▲
│ POST /api/v1/proxy/sync (iprx_ token)
│
application ──▶ iron-proxy ──────────────┘
│
└──▶ upstream APIs (credentials added per request rules)
Operators manage credentials, principals, roles, and grants through the API or the console. Each iron-proxy instance signs in with its own token, fetches the configuration for its assigned principal, and adds the granted credentials to matching outbound requests.
iron-control requires an authenticated user and API key before any API endpoint will respond. To bootstrap a fresh deployment without a console, set the following environment variables on startup:
| Variable | Required | Description |
|---|---|---|
IRON_CONTROL_INITIAL_USER_EMAIL |
yes | Email for the initial user. |
IRON_CONTROL_INITIAL_USER_PASSWORD |
yes | Password for the initial user (minimum 12 characters). |
IRON_CONTROL_INITIAL_API_KEY |
no | Plaintext API key for the initial user. Must match iak_ followed by 64 lowercase hex characters (a 32-byte hex string). If omitted, a token is generated and logged once at startup. |
Behavior:
- Bootstrap runs after Rails initialization on every boot, but is a no-op if any user already exists. It is safe to leave the env vars set across rolling restarts.
- If
IRON_CONTROL_INITIAL_USER_EMAILis set withoutIRON_CONTROL_INITIAL_USER_PASSWORD, the process exits with a clear error. - Concurrent pods racing the first boot are serialized with a Postgres advisory lock; exactly one user is created.
When deploying to Kubernetes, source these values from a Secret, not from a ConfigMap.
iron-control uses ActiveRecord encryption to protect secrets stored in the control plane (for example, the control_plane secret source type). The following environment variables configure the encryption keys:
| Variable | Required | Description |
|---|---|---|
IRON_CONTROL_AR_ENCRYPTION_PRIMARY_KEY |
yes (in production) | Primary key used for non-deterministic encryption. |
IRON_CONTROL_AR_ENCRYPTION_DETERMINISTIC_KEY |
yes (in production) | Key used for deterministic encryption. |
IRON_CONTROL_AR_ENCRYPTION_KEY_DERIVATION_SALT |
yes (in production) | Salt used to derive per-attribute keys. |
Generate suitable values with bin/rails db:encryption:init and store them in your secret manager. In production, the process refuses to boot if any of the three are missing. In development and test, fixed fallback values are used so the suite runs without configuration.
Rotating any of these keys makes previously encrypted data unreadable. Treat them as long-lived secrets and back them up alongside other production credentials.
iron-control exposes a JSON API under /api/v1. All resource endpoints authenticate with an API key sent as a bearer token (Authorization: Bearer iak_...); the one exception is POST /api/v1/proxy/sync, which iron-proxy instances call with a proxy bearer token.
See docs/API.md for the full reference: authentication, request/response conventions, pagination, error formats, the shared secret-source and request-rule shapes, and detailed payloads for every endpoint (static secrets, GCP auth secrets, OAuth token secrets, principals, roles, grants, API keys, proxies, and proxy sync).