Skip to content

Administration configuration

The flat configuration hub remains the compatibility route. This page is the canonical source-checked field reference for its family, including nested tables and list rows.

Paths in the tables are relative to the section heading. Each row gives the serde type and source default or unset meaning; keep credentials in protected files or the supported environment overlay. Check parsing, unknown keys, and cross-field startup rules with gdsgate doctor --config <PATH> --json, then follow the admin configuration templates.

[admin]

Used by: the operator workstation (the gdsgate CLI run by an administrator).

The mTLS identity the CLI uses for the certificate route: authority create-token, five CA rotations (rotate-ca, rotate-onward-ca, rotate-host-tls-ca, rotate-spiffe-ca, rotate-jwt-ca), registry and catalog actions (revoke-node, delete-node, revoke-workload, import-node, list-nodes, list-offered, list-workloads, list-resources, set-resource, remove-resource), and the audit list. Provision the identity once with gdsgate authority bootstrap-admin and point this section at the directory it writes.

Policy pull, push, edit, approve-edit, and pending-edits, plus the recordings viewer, use the identity-token gateway route instead of this certificate route. The emergency socket has its own narrower route.

Key Type Default Purpose
endpoint string unset Running Authority's mTLS gRPC endpoint, for example https://auth.example.com:50051. https:// only: the transport selects TLS off the scheme, so a cleartext URL drops the operator's certificate before the dial and every admin RPC arrives unauthenticated. Refused rather than ignored, and reported by gdsgate doctor as config.admin.endpoint_scheme.
identity_dir string unset Directory holding cert.pem, key.pem and ca.pem issued at bootstrap. Bootstrap creates a missing directory, but the source sets each file to 0o600, not the directory mode. The operator must create or protect the directory and its ownership.
transport enum direct What endpoint names. direct is Authority itself. fronted is a gateway or router that sorts connections by TLS server name, and the CLI then asks for auth.gdsgate.internal instead of the shared name. See below.
[admin]
endpoint     = "https://auth.example.com:50051"
identity_dir = "/etc/gdsgate/admin"

Administering through the gateway

transport = "fronted" says the endpoint is not Authority but something in front of it. The only thing that changes on the wire is the TLS server name the CLI asks for: auth.gdsgate.internal instead of the shared gdsgate.internal. That is what a gateway carrying the relayed control-plane branch sorts the connection on, putting the call in the administrative lane rather than in the fleet's, so a roll-out and an operator stop sharing a ceiling. Nothing about the identity changes: the CLI presents the same certificate and Authority authenticates it the same way.

[admin]
endpoint     = "https://gate.example.com:50061"
identity_dir = "/etc/gdsgate/admin"
transport    = "fronted"
GDSGATE_ADMIN_TRANSPORT overrides the value; an unrecognised one is ignored and leaves the configured mode in place.

Switch the name after the rollout, not during it. A role name verifies only once Authority's own certificate has been reissued carrying it, and a certificate is reissued on enrolment or renewal, never on CA rotation. An Authority still serving a leaf from before the role names existed answers fronted with a verification failure naming auth.gdsgate.internal. The wait is one transport identity's life, a day by default; gdsgate doctor on the Authority host reports when its transport identity expires, which is when the new name arrives. The shared name keeps working throughout, and so does a direct dial after the switch, since Authority's leaf carries both names.

On a relayed connection Authority's peer is the gateway, so the address in an administrative audit row and in context.src_ip is the gateway's rather than the operator's. The gateway moves opaque bytes and never sees the request, so there is nothing for it to annotate. A policy rule of the form context.src_ip.isInRange(ip("10.0.0.0/8")) on an administrative action does not mean what it means on a direct dial: on this path it sees one address, the gateway's. Keep such a rule and the direct dial together, or write the rule about the gateway knowing that is what it is about.

The requirement on the gateway side is [proxy].public_join, which is what puts the relayed branch on the client-facing listener at all. Where it is off, the listener terminates the connection and the dial fails.

[policy.editor]

Used by: Authority.

Controls policy-edit quorum and break-glass recovery. Optional. When unset, a single editPolicy permit is enough to push a new active version.

Key Type Default Purpose
min_approvers usize 1 Number of distinct approvers required before a proposed policy version becomes active. 1 keeps the single-editor flow; 2 or more enables the quorum flow, where authority policy push queues a proposal that reviewers vote on with authority policy approve-edit <version>.
break_glass_policy_file string unset Path to a Cedar policy on the Authority host, read at every start, after the stored policy is resumed. A file that differs from the active version lands as a new active version past the editPolicy gate, recorded in the store with break-glass:<hostname> as its proposer and logged as break-glass policy restore. Content identical to the active version changes nothing; a missing file lets the start proceed unchanged, and gdsgate doctor reports a configured path with no file as a failed check. The file must keep the break-glass rule or the start stops. This is the recovery path from a policy that locked policy editing out; [policy].path is not, since it only seeds a store with no policy version. See Admin guide → Lock-out and recovery.
[policy.editor]
min_approvers           = 2
break_glass_policy_file = "/etc/gdsgate/break-glass.cedar"

[approvals]

Used by: Authority.

Just-in-time access thresholds. The number of distinct approvers a gdsgate request-access needs is resolved by a cascade, narrowest wins:

  1. The resource's own catalog row (min_approvers stored on it),
  2. Per-resource config ([[discovery.resources]].min_approvers),
  3. Per-environment ([approvals].per_environment),
  4. Global ([approvals].min_approvers).

The floor is 1.

The first level is the row Authority reads when it decides, and every instance of an HA set reads the same row; the three below it are whatever TOML the instance answering happens to have been started with. A catalog declared in TOML keeps the two in step by construction, since the startup seed writes [[discovery.resources]].min_approvers into the row, so a deployment whose catalog lives in the config file resolves as it did before the column existed. A threshold written to the row through Authority's catalog API outranks the config levels below it; where the same resource is also declared in [[discovery.resources]], the next Authority start seeds the file's value back over it.

Key Type Default Purpose
min_approvers usize 1 Global default.
per_environment table of string to usize {} Per-environment override, keyed by environment name (prod, staging, dev).
[approvals]
min_approvers = 1

[approvals.per_environment]
prod    = 2
staging = 1
dev     = 1