Config reference¶
Every configuration field, extracted from the Go structs (field · JSON key · type · doc comment). See Operations for worked examples and the *.example.json files.
Broker / MCP config (config.json)¶
Config in internal/broker/engine.go
| JSON key | Type | Description |
|---|---|---|
listen |
string |
HTTP only: e.g. ":8443" |
server_cert |
string |
TLS / mTLS for the HTTP frontend (not used by the MCP, which runs over stdio). |
server_key |
string |
|
client_ca |
string |
|
ca_key |
string |
CAKey — LOCAL mode ONLY (in-process signing). When the Signer block is present, this field is ignored and the broker holds no CA key. ca_keys: per-group CA key overrides. "_default" overrides ca_key when present. See ca.CAKeyConfig for supported backends ("pem" for local files, "akv" for Azure Key Vault). Local mode only; ignored when Signer is set. |
ca_keys |
map[string]ca.CAKeyConfig |
|
signer |
*SignerClientConfig |
Signer, when present, externalises signing to a remote service (HTTP+mTLS). The broker no longer holds the CA key or the policy. |
audit_log |
string |
Audit. |
audit_key |
string |
Ed25519 seed (>=32 bytes) |
source_address |
string |
SourceAddress: broker egress IP/CIDR, used in local mode. |
max_ttl_seconds |
int |
MaxTTLSeconds caps the maximum requestable TTL. |
hosts_refresh_seconds |
int |
HostsRefreshSeconds: host-list reload interval from the signer. Remote mode only. Default: 300 (5 minutes). |
session_idle_seconds |
int |
Persistent session idle-close and maximum lifetime. |
session_max_seconds |
int |
default 1800 |
session_recording_dir |
string |
SessionRecordingDir: directory for session recordings in ASCIIcast v2 format (.cast files). One file per session: |
redact |
*redact.Config |
Redact enables secret redaction on this broker's persistent/outbound sinks: the audit log's free-text fields and session recordings. Present (even empty, "redact": {}) = built-in default patterns; absent = disabled (backward compatible). Redaction never touches the decision path — the signer and the certificate force-command always see the original command. |
hosts |
map[string]HostConfig |
Hosts: used only in local mode (single-binary). In remote mode the host list is fetched from the signer via /v1/hosts and refreshed periodically. |
command_policies |
map[string]signer.CommandPolicy |
CommandPolicies (local mode) is a named library of command policies, attachable to groups. GroupCommandPolicies maps a group name to the policy names that apply to its hosts; the reserved group "_default" applies to every host. A host's effective firewall is the composition of its inline command_policy and the policies of all its groups (additive union; deny wins). |
group_command_policies |
map[string][]string |
|
monitor_listen |
string |
MonitorListen: optional plain-HTTP monitoring listener serving /healthz (liveness) and /metrics (Prometheus text format), started by every frontend (broker, mcp-broker, mcp-broker-http). No authentication — bind to localhost or a private scrape interface. Empty = disabled. |
file_transfer_max_bytes |
int |
FileTransferMaxBytes caps ssh_put_file content and ssh_get_file reads. Default 524288 (512 KiB). The HTTP MCP frontend additionally bounds the whole request body at 1 MiB, which base64-encoded content must fit. |
oauth |
*OAuthConfig |
OAuth and ResourceURL are used only by the HTTP+OAuth frontend (cmd/mcp-broker-http); other frontends ignore them. |
resource_url |
string |
ResourceURL is the canonical URL of this MCP server, used in the Protected Resource Metadata document (RFC 9728) and the WWW-Authenticate header. |
Broker signer client (signer, remote mode)¶
SignerClientConfig in internal/broker/engine.go
| JSON key | Type | Description |
|---|---|---|
url |
string |
|
client_cert |
string |
|
client_key |
string |
|
ca |
string |
|
approval_wait_seconds |
int |
ApprovalWaitSeconds: maximum time the broker waits for a human approval to be resolved (202 response from the control plane). 0 = do not wait. |
Broker OAuth (oauth, cmd/mcp-broker-http only)¶
OAuthConfig in internal/broker/engine.go
| JSON key | Type | Description |
|---|---|---|
issuer |
string |
Issuer is the OIDC provider URL (e.g. https://keycloak.example/realms/x). |
audience |
string |
Audience is the expected value of the aud claim (this resource server). |
required_scopes |
[]string |
RequiredScopes are the scopes the token must carry to be accepted. |
user_claim |
string |
UserClaim is the claim used as user identity (default "sub"). |
groups_claim |
string |
GroupsClaim is the claim that carries groups/roles to propagate to the signer. Empty = groups are not propagated (no per-user RBAC). |
max_token_age_seconds |
int |
MaxTokenAgeSeconds limits the age of the token since issuance (iat claim). 0 = no limit (accepts any token within its exp). Recommended: 3600 (1h). M3: reduces the replay risk of leaked tokens within their exp window. |
clock_skew_seconds |
int |
ClockSkewSeconds is the tolerance applied to the nbf and iat claims to absorb small clock differences between the IdP and this host. 0 selects a 1-minute default; a negative value disables the tolerance. |
Broker host (hosts.<name>, local mode)¶
HostConfig in internal/broker/engine.go
| JSON key | Type | Description |
|---|---|---|
addr |
string |
|
user |
string |
|
principal |
string |
|
host_key |
string |
|
jump |
string |
|
source_address |
string |
SourceAddress: per-host override of the global value for THIS host's cert. LOCAL mode only. |
allow_sudo |
bool |
Elevation (NOPASSWD) — local mode. |
allowed_sudo_users |
[]string |
|
allow_pty |
bool |
AllowPTY — local mode. |
allow_file_transfer |
bool |
AllowFileTransfer authorises ssh_put_file / ssh_get_file on this host — local mode. Default false (secure by default). In remote mode this is defined by the signer in signer.json. |
groups |
[]string |
Groups lists the RBAC groups this host belongs to. When ca_keys are configured (multi-CA), the first matching group determines which CA signs certificates for this host. Also used for per-user RBAC in local mode. |
allow_as_bastion |
bool |
AllowAsBastion authorises this host to be used as a ProxyJump hop (permit-port-forwarding in its cert). Local mode only; default false to match the remote-signer default-deny gate (ARCHITECTURE.md § routing). A host referenced as another host's Jump target is enabled automatically (see policyFromHosts), so existing jump chains keep working without per-host config. |
command_policy |
signer.CommandPolicy |
CommandPolicy — local mode (AI-action firewall). In remote mode this is defined by the signer in signer.json. |
CA key (ca_keys.<name>)¶
CAKeyConfig in internal/ca/loader.go
| JSON key | Type | Description |
|---|---|---|
type |
string |
"pem" | "akv" |
path |
string |
PEM backend. |
vault_url |
string |
Azure Key Vault backend. |
key_name |
string |
|
key_version |
string |
empty = latest version |
tenant_id |
string |
AKV authentication overrides. When TenantID and ClientID are both empty, DefaultAzureCredential is used (recommended for production: picks up managed identity, workload identity, AZURE_* env vars, and Azure CLI). |
client_id |
string |
|
client_secret_env |
string |
ClientSecretEnv is the name of the environment variable holding the client secret. The secret is never stored in the config file. |
Signer config (signer.json)¶
Config in cmd/signer/main.go
| JSON key | Type | Description |
|---|---|---|
listen |
string |
e.g. ":9443" |
server_cert |
string |
mTLS: presents server_cert and requires clients signed by client_ca. |
server_key |
string |
|
client_ca |
string |
CA that signs authorised brokers |
ca_key |
string |
CA key custody. ca_key: legacy path to a PEM CA key (backward compatible). ca_keys: per-group CA key overrides. The reserved key "_default" overrides ca_key when present. See CAKeyConfig for supported backends ("pem" for local files, "akv" for Azure Key Vault). |
ca_keys |
map[string]ca.CAKeyConfig |
|
audit_log |
string |
Issuance audit log (independent of the broker). |
audit_key |
string |
|
max_ttl_seconds |
int |
MaxTTLSeconds: global cap when the host policy does not set one. |
auto_reload_seconds |
int |
AutoReloadSeconds: if > 0, the signer polls signer.json's mtime every N seconds and hot-reloads on change — same validated, atomic path as SIGHUP / POST /v1/reload, so a transiently-invalid in-progress save is rejected and the previous good state is kept. 0 or absent = disabled (default). |
sign_rate_limit_per_min |
int |
SignRateLimitPerMin caps POST /v1/sign requests per authenticated client CN per minute (token bucket: burst up to the cap, continuous refill). Keyed on the mTLS peer CN — not on_behalf_of — and enforced before body parsing; excess requests get 429 with a Retry-After hint. Hot-reloadable. 0 or absent = disabled (backward compatible). |
monitor_listen |
string |
MonitorListen: optional plain-HTTP monitoring listener serving /healthz (liveness) and /metrics (Prometheus text format). No authentication — bind to localhost or a private scrape interface. Empty = disabled. |
redact |
*redact.Config |
Redact enables secret redaction on the signer's audit log free-text fields. Present (even empty, "redact": {}) = built-in default patterns; absent = disabled (backward compatible). The signer's audit carries request metadata rather than the raw command, but errors can embed user text — every persistent sink applies the same invariant. |
state_db |
string |
StateDB: optional path to the SQLite state database that persists runtime grants and approve-and-learn waivers across restarts (pure-Go driver, no system dependency; WAL mode leaves state.db-wal/-shm sidecar files next to it). Empty or absent = in-memory only (previous behaviour: grants are lost on restart, kept across reloads). If set and the database cannot be opened or migrated, the signer refuses to start (fail-closed). Production: /var/lib/infrabroker/signer/state.db. |
max_grant_ttl_seconds |
int |
MaxGrantTTLSeconds: optional upper bound on a runtime grant's TTL (POST /v1/policy/hosts/{host}/grants). 0 or absent = no cap. |
reload_callers |
[]string |
ReloadCallers: client cert CNs authorised to invoke POST /v1/reload. Empty = HTTP endpoint disabled (403); SIGHUP still works locally. |
trusted_forwarders |
[]string |
TrustedForwarders: client cert CNs authorised to act on behalf of another broker (on_behalf_of field / X-On-Behalf-Of header). This is the control plane CN. Only these CNs may impersonate a broker for RBAC; any other CN sending on_behalf_of is rejected. |
hosts |
signer.PolicyTable |
Hosts: issuance policy + connectivity per host. Single source of truth: the broker fetches addr/user/host_key/jump via GET /v1/hosts. |
callers |
signer.CallerTable |
Callers: group-based RBAC. Maps broker mTLS cert CN → allowed groups. A CN absent from the table has no group restriction (backward compatible) unless a reserved "_default" entry exists, in which case absent CNs inherit its allowed_groups — "_default": {"allowed_groups": []} makes the table default-deny. A CN present can only see and sign hosts whose groups field intersects with its allowed_groups. |
command_policies |
map[string]signer.CommandPolicy |
CommandPolicies is a named library of command policies, attachable to groups. GroupCommandPolicies maps a group name to the policy names that apply to its hosts; the reserved group "_default" applies to every host. A host's effective firewall is the composition of its inline command_policy and the policies of all its groups (additive union; deny wins). |
group_command_policies |
map[string][]string |
|
kubernetes |
*K8sConfig |
Kubernetes is the optional Kubernetes target: a parallel map of clusters, each with its own default-deny ActionPolicy, ServiceAccount bindings, and a minter credential (token_file) whose RBAC is only create on serviceaccounts/token. Absent = SSH-only signer (backward compatible). |
Control-plane config (control-plane.json)¶
Config in cmd/control-plane/main.go
| JSON key | Type | Description |
|---|---|---|
listen |
string |
e.g. ":7443" |
server_cert |
string |
mTLS toward the broker: presents server_cert and requires clients signed by client_ca. |
server_key |
string |
|
client_ca |
string |
|
sign_callers |
[]string |
SignCallers: client cert CNs authorised to use the signing path (/v1/sign, /v1/hosts, /v1/sign/result) — i.e. the brokers. This separates the broker role from the approver role (approval.callers) when both are signed by the same client_ca. If non-empty, only these CNs may request signing. If empty/absent, any authenticated broker may — EXCEPT a CN that is in approval.callers, which is an approver, not a broker, and is denied the sign path (role separation, secure by default). |
signer |
(object) |
Signer: mTLS client toward the signing service. |
signer.url |
string |
|
signer.client_cert |
string |
|
signer.client_key |
string |
|
signer.ca |
string |
|
approval |
(object) |
Approval: human-approval orchestration. |
approval.notifier |
string |
""/"log" (default) | "webhook" | "teams" |
approval.webhook_url |
string |
required when notifier=webhook or teams |
approval.timeout_seconds |
int |
TTL for pending requests |
approval.callers |
[]string |
CNs authorised to approve/deny |
approval.teams_format |
string |
Teams-specific fields (notifier=teams). |
approval.approval_url_template |
string |
URL with "{id}" to link the request |
behavior |
control.BehaviorConfig |
Behavior: behaviour guardrails (anomaly detection + rate limiting). |
trusted_forwarders |
[]string |
TrustedForwarders: broker client cert CNs whose end_user claim is trusted (brokers that authenticate end users, e.g. via OIDC). Mirrors the signer's trusted_forwarders semantics. Behaviour guardrails key on " |
audit_log |
string |
Audit log for the control plane (independent of broker and signer). |
audit_key |
string |
|
monitor_listen |
string |
MonitorListen: optional plain-HTTP monitoring listener serving /healthz (liveness) and /metrics (Prometheus text format). No authentication — bind to localhost or a private scrape interface. Empty = disabled. |
redact |
*redact.Config |
Redact enables secret redaction on the control plane's persistent and outbound sinks: the audit log's free-text fields and the approval notification payload (log/webhook/Teams). Present (even empty, "redact": {}) = built-in default patterns; absent = disabled (backward compatible). The approval registry itself keeps the original command: the mTLS approval UI and API show the approver exactly what will run, and the approved request forwarded to the signer is untouched. |
state_db |
string |
StateDB: optional path to the SQLite state database that persists the approval registry (pending and approved-but-uncollected requests, with their original wire request) across restarts (pure-Go driver; WAL mode leaves state.db-wal/-shm sidecar files next to it). Empty or absent = in-memory only (previous behaviour: a restart clears pending approvals). If set and the database cannot be opened or migrated, the service refuses to start (fail-closed). Production: /var/lib/infrabroker/control-plane/state.db. |
Control-plane behaviour guardrails (behavior)¶
BehaviorConfig in internal/control/behavior.go
| JSON key | Type | Description |
|---|---|---|
mode |
string |
Mode: "off"|"observe"|"enforce". |
rate_limit_per_min |
int |
RateLimitPerMin: maximum requests per subject per minute (0 = no limit). |
max_subjects |
int |
MaxSubjects caps how many subjects are tracked before the least-recently -seen one is evicted (0 = defaultMaxSubjects). |
subject_ttl_minutes |
int |
SubjectTTLMinutes evicts subjects idle for longer than this (0 = defaultSubjectTTL). |
max_distinct_per_subject |
int |
MaxDistinctPerSubject caps the distinct hosts and command fingerprints retained per subject (0 = defaults). Once full, novelty detection for that dimension degrades to "seen" rather than growing without bound. |
Host policy (hosts.<name>)¶
HostPolicy in internal/signer/signer.go
| JSON key | Type | Description |
|---|---|---|
addr |
string |
Connectivity — exposed to the broker via /v1/hosts. |
user |
string |
remote SSH account |
host_key |
string |
authorized_keys line for the host key |
jump |
string |
logical name of the preceding bastion |
principal |
string |
Issuance policy — internal, never exposed to the broker. |
source_address |
string |
|
max_ttl_seconds |
int |
|
allow_as_bastion |
bool |
|
allowed_callers |
[]string |
AllowedCallers restricts which CNs may request this host. Empty = any authenticated caller. |
allow_sudo |
bool |
Elevation (sudo NOPASSWD). AllowSudo enables privilege elevation for this host. |
allowed_sudo_users |
[]string |
AllowedSudoUsers lists the permitted target users (e.g. ["root","deploy"]). Empty = root only. "root" is always implied when AllowSudo=true. |
allow_pty |
bool |
AllowPTY authorises the permit-pty extension in certificates for this host. If false, PTY requests are rejected. |
allow_file_transfer |
bool |
AllowFileTransfer authorises the file-transfer tools (ssh_put_file / ssh_get_file) for this host. If false (the default — secure by default), signing requests flagged file_transfer are rejected. The generated transfer command is still subject to the host's command policy. |
groups |
[]string |
Groups lists the RBAC groups this host belongs to. A caller restricted by groups can only access hosts that share at least one of its allowed_groups. Empty = host belongs to no group. |
command_policy |
CommandPolicy |
CommandPolicy restricts which commands may run on this host (AI-action firewall). Empty/off = no command restriction. Session commands are preflighted against the current signer policy before each exec, so reloads affect already-open sessions: target and bastion access, end-user groups, sudo, sudo_user and PTY are revalidated; the broker also rejects already-open sessions if the host's physical SSH route changed. mode=exec is allowed, while shell/pty sessions are rejected when rules are present because stateful commands are not independently verifiable. |
Command policy (command_policy)¶
CommandPolicy in internal/signer/cmdpolicy.go
| JSON key | Type | Description |
|---|---|---|
mode |
string |
Mode: "off" (or empty) | "allowlist" | "denylist". Controls allow/deny. |
enforcement |
string |
Enforcement: "enforce" (or empty) blocks/gates matching commands; "audit" lets them run and returns/audits a warning instead. In composed policies, enforce wins over audit. |
allow |
[]string |
Allow: in allowlist mode, the command must match at least one. |
deny |
[]string |
Deny: in denylist mode, the command must not match any. |
require_approval |
[]string |
RequireApproval: commands that match require out-of-band human approval. Evaluated independently of the mode (orchestrated by the control plane). |
shell_parse |
bool |
ShellParse: if true, the command is parsed as POSIX sh before evaluating the policy. Each simple command is evaluated separately; dangerous nodes (subshells, process substitution, file redirects) are rejected unconditionally. Backward compatible: false by default. |
Secret redaction (redact, all three services)¶
Config in internal/redact/redact.go
| JSON key | Type | Description |
|---|---|---|
patterns |
[]Pattern |
Patterns are extra operator-defined rules, applied after the built-in defaults. See Pattern for the regex contract. |
disable_defaults |
bool |
DisableDefaults turns off the built-in default rules, leaving only the operator's Patterns. Escape hatch when a default rule produces false positives that hurt forensics. |
Redaction pattern (redact.patterns[])¶
Pattern in internal/redact/redact.go
| JSON key | Type | Description |
|---|---|---|
name |
string |
Name identifies the rule inside the [REDACTED: |
regex |
string |
Regex is an RE2 expression (linear-time, no catastrophic backtracking — same engine and rationale as the command-policy rules). If it defines a capturing group named "secret", only that group is masked; otherwise the whole match is masked. |
Kubernetes cluster policy (kubernetes.clusters.<name>)¶
ClusterPolicy in internal/signer/k8spolicy.go
| JSON key | Type | Description |
|---|---|---|
api_server |
string |
Connectivity — exposed to the broker via /v1/clusters. |
ca_cert |
string |
path to the cluster CA bundle (PEM) |
token_file |
string |
TokenFile is the signer's minter credential for this cluster: a ServiceAccount token whose entire RBAC is create on serviceaccounts/token for the bound SAs below. Never exposed. |
token_ttl_seconds |
int |
TokenTTLSeconds bounds the minted bound-token lifetime. 0 selects 600; the valid range is [600, 900] (TokenRequest refuses less than 600). |
groups |
[]string |
Groups / AllowedCallers: same RBAC semantics as HostPolicy. |
allowed_callers |
[]string |
|
sa_bindings |
[]SABinding |
SABindings select the ServiceAccount (layer B: its native cluster RBAC) per end-user group. At least one binding is required. |
rules |
[]K8sRule |
Rules is the cluster's ActionPolicy. Unlike SSH hosts (default-allow without a command_policy, for backward compatibility), a cluster is DEFAULT-DENY: at least one allow/require_approval rule is required, and anything unmatched is refused. There is no legacy to preserve here. |
extra_resources |
[]k8s.ResourceDef |
ExtraResources extends the curated core resource table for this cluster (explicit CRDs — no API discovery). |
Kubernetes SA binding (kubernetes.clusters.<name>.sa_bindings[])¶
SABinding in internal/signer/k8spolicy.go
| JSON key | Type | Description |
|---|---|---|
groups |
[]string |
|
namespace |
string |
|
service_account |
string |
Kubernetes action rule (kubernetes.clusters.<name>.rules[])¶
K8sRule in internal/signer/k8spolicy.go
| JSON key | Type | Description |
|---|---|---|
verbs |
[]string |
|
resources |
[]string |
|
namespaces |
[]string |
|
names |
[]string |
|
effect |
string |
allow | deny | require_approval |
Kubernetes resource (kubernetes.clusters.<name>.extra_resources[])¶
ResourceDef in internal/k8s/resources.go
| JSON key | Type | Description |
|---|---|---|
resource |
string |
Resource is the lowercase plural name used in tool calls, policy rules, and REST paths (e.g. "deployments"). |
group |
string |
Group is the API group; empty = core ("" → /api/v1, else /apis/ |
version |
string |
Version is the served API version (e.g. "v1"). |
kind |
string |
Kind is the manifest kind (e.g. "Deployment") — descriptive metadata for the resource entry; required so an extra_resources declaration is self-documenting. |
namespaced |
bool |
Namespaced marks namespace-scoped resources. |
Vocabulary (enumerated constants)¶
Role distinguishes the role of a hop in the chain.: target, bastion
Purpose distinguishes the intended use of the connection.: oneshot, session
SessionMode distinguishes broker-managed session styles.: exec, shell, pty
CommandPolicy modes.: off, allowlist, denylist
CommandPolicy enforcement modes.: enforce, audit