Skip to content

CLI

One binary, selected by subcommand. The same gdsgate runs every service role and every client operation. A global --config <PATH> applies to all commands and overrides the loopback dev defaults.

gdsgate [--config <PATH>] <command> [args…]

Output convention:

  • stdout carries data the caller may pipe or capture (ls tables, generated config fragments, byte streams, certificate PEMs).
  • stderr carries structured logs (tracing events). The proxy-ssh transport puts only the SSH byte stream on stdout — its diagnostics go to stderr — so it composes cleanly with native ssh.

Filter the logs with RUST_LOG (default info):

RUST_LOG=info gdsgate --config auth.toml auth
RUST_LOG=gdsgate_proxy=debug,info gdsgate --config proxy.toml proxy

Global flags

Flag Purpose
--config <PATH> Path to the TOML cluster-configuration file. Optional; without it the binary uses the loopback dev profile and the GDSGATE_* environment overrides. Applies to every subcommand.
--help, -h Print help for the current command.
--version, -V Print the binary's version and exit.

Service modes

Subcommands that run a long-lived service.

gdsgate auth

Run the Auth service: control-plane gRPC listener (mutual TLS once the cluster is registered), bootstrap registration listener (plaintext, the join token is the proof), policy engine, certificate authorities, audit chain.

Reads: store_url, [endpoints], [policy], [oidc], [ca_rotation], [ha], [discovery], [approvals].

gdsgate --config auth.toml auth

Auth has the following sub-actions (one-shot commands that share the same store_url).

gdsgate auth create-token --role {proxy|agent} [--ttl <secs>]

Generates a one-time node-registration token authorising one standalone gdsgate proxy or gdsgate agent to register. Prints the token to stdout; logs to stderr.

gdsgate --config auth.toml auth create-token --role agent --ttl 3600
Flag Default Purpose
--role proxy or agent. Required.
--ttl <secs> 3600 Validity window before the token expires.

Requires the same persistent store_url the running Auth uses (not sqlite::memory:).

gdsgate auth rotate-ca

Requests a User SSH CA rotation by recording the request in the shared store. The running Auth picks it up and runs the paced double-signing rotation. Works regardless of [ca_rotation].enabled.

gdsgate --config auth.toml auth rotate-ca

gdsgate auth rotate-onward-ca

Requests an Onward SSH CA rotation (the CA Auth uses to sign the OpenSSH user certificates an agent presents to a downstream sshd in the model-B jump-host path). Same paced rotation as rotate-ca. After rotation finishes, every downstream sshd needs the new public key added to its TrustedUserCAKeys.

gdsgate --config auth.toml auth rotate-onward-ca

gdsgate auth onward-ca-pub

Prints the active Onward SSH CA public key in OpenSSH wire format (one line — the form TrustedUserCAKeys expects).

gdsgate --config auth.toml auth onward-ca-pub > /etc/ssh/gdsgate-onward-ca.pub

gdsgate auth onward-ca-pubs

Prints every persisted Onward SSH CA public key — active, retiring, and any candidate — one OpenSSH line each, newest generation first. Use this for the downstream sshd's TrustedUserCAKeys so that certificates signed by a still-trusted retiring generation keep verifying during the rotation window.

gdsgate --config auth.toml auth onward-ca-pubs \
    > /etc/ssh/gdsgate-onward-ca-bundle.pub

gdsgate auth policy validate [<FILE>]

Strict-validates a Cedar policy against gdsgate's schema and exits. Non-zero on any error — use as a CI gate. Does not start Auth or touch the store.

gdsgate --config auth.toml auth policy validate
gdsgate --config auth.toml auth policy validate ./new-policy.cedar

Without <FILE>, validates [policy].path from the config.

gdsgate proxy

Run the Proxy: public listener, internal reverse-tunnel listener, WebSocket fallback listener, single Auth client. Stateless.

Reads: [endpoints], [enroll], [proxy].

GDSGATE_ENROLL_TOKEN="$token" \
    gdsgate --config proxy.toml proxy

The Proxy registers on first start (consuming the token), persists its identity to [enroll].state_dir, and on subsequent starts reuses the persisted identity. With no [enroll].endpoint, the Proxy runs plaintext (dev / loopback only).

gdsgate agent

Run the Agent: dials the Proxy's reverse-tunnel listener, registers the resources declared in [[agent.backends]], and serves them.

Reads: [endpoints], [enroll], [agent].

GDSGATE_ENROLL_TOKEN="$token" \
    gdsgate --config agent.toml agent

For SSH backends in model A (kind = "ssh" with no addr), the agent loads its persistent host key from <state_dir>/ssh_host_ed25519_key, generating one on first start.

gdsgate all

Run Auth + Proxy + an embedded Agent in one process. With a persistent store_url, this is a self-contained single-node deployment that still accepts externally registered agents on the registration listener.

Reads: every section.

gdsgate --config all.toml all

Client commands

Commands a user runs from their own machine. They read the client configuration ([endpoints], [client], [oidc]) plus the identity-token environment variables.

gdsgate login [--browser]

Authenticate to the cluster.

  • With an [oidc] provider configured, login runs the device flow by default: prints a URL and a short code, waits for approval, then caches the obtained identity token under ~/.gdsgate/<cluster>/id_token (mode 0600). Follow-up commands reuse it.
  • --browser runs Authorization Code + PKCE over a loopback redirect — the browser opens on the same machine.
  • Without [oidc], login confirms reachability and a local-dev principal is used (GDSGATE_USER, default dev).

Headless / CI: skip login, supply the token via GDSGATE_ID_TOKEN instead.

gdsgate ls

Lists resources the policy lets you view (RBAC-filtered). Output is a table on stdout:

RESOURCE                 KIND         ENV        LABELS
prod-db                  postgres     prod       team=backend
web-01                   ssh          dev        team=frontend

gdsgate request-access <resource> --reason <text> [--ttl <secs>]

Files a JIT access request for <resource> (logged to the audit chain). Prints the request id.

Flag Default Purpose
--reason <text> Justification shown to approvers. Required.
--ttl <secs> 3600 Requested elevation window.

gdsgate approve <id>

Confirm a pending access request as one approver. The required number of distinct approvers comes from the approvals cascade.

gdsgate requests

Lists pending and recent access requests with their approval state.

gdsgate ssh <target>

Requests an SSH access certificate for the resource named in <target> (parsed as user@resource or resource). The cert is issued by Auth on Allow and cached. Useful when you want to authorise up front before the native ssh invocation.

gdsgate ssh-config [<host_pattern>]

Prints an OpenSSH client-config fragment to stdout that routes native ssh through gdsgate. The --config path of this gdsgate invocation is threaded into the generated ProxyCommand so the native ssh reaches the same cluster you signed into.

gdsgate --config ~/.gdsgate/client.toml ssh-config '*.gds' >> ~/.ssh/config
Argument Default Purpose
<host_pattern> *.gds OpenSSH Host pattern the fragment matches. Aliases under the pattern become the gdsgate resource id.

gdsgate proxy-ssh <resource>

The SSH ProxyCommand transport: relays this process's stdio to the resource's session over the cluster. Invoked by native ssh through ProxyCommand, not directly. stdout is the SSH byte stream; logs go to stderr.

gdsgate db ls

Lists database resources you can view.

gdsgate db login <resource>

Authorise a database resource: mints and caches a short-lived access certificate for it.

gdsgate db proxy <resource> [--listen <addr>]

Runs a localhost relay for psql / mysql. Each connection to the listener is authorised independently (dbConnect) and forwarded over the cluster to the database.

gdsgate db proxy prod-db --listen 127.0.0.1:5433 &
psql -h 127.0.0.1 -p 5433 
Flag Default Purpose
--listen <addr> 127.0.0.1:0 Local host:port to bind. :0 picks an ephemeral port (logged).

gdsgate kube ls

Lists Kubernetes cluster resources you can view.

gdsgate kube login <cluster> [--server <url>]

Prints a kubeconfig fragment that wires kubectl to gdsgate through an exec credential plugin. Merge it into ~/.kube/config.

gdsgate kube login prod-cluster --server https://127.0.0.1:6443 \
    > ~/.kube/gdsgate-prod
Flag Default Purpose
--server <url> https://127.0.0.1:6443 The API server URL kubectl should target — the gdsgate Kubernetes listener (run kube proxy on this same address).

The fragment carries this invocation's --config so the exec plugin (kube credentials) runs against the same cluster.

gdsgate kube credentials <cluster>

The exec credential plugin for kubectl. Prints an ExecCredential JSON on stdout. kubectl invokes it through the kubeconfig fragment above; do not run it by hand.

gdsgate kube proxy <cluster> [--listen <addr>]

Runs a localhost relay for kubectl. Each connection is authorised (k8sAccess) and forwarded to the agent, which reverse-proxies the real API with identity impersonation.

gdsgate kube proxy prod-cluster --listen 127.0.0.1:6443 &
kubectl --context prod-cluster get pods
Flag Default Purpose
--listen <addr> 127.0.0.1:0 Local host:port to bind.

gdsgate tcp ls

Lists raw-TCP resources you can view (Redis, internal HTTP, …).

gdsgate tcp proxy <resource> [--listen <addr>]

Localhost relay for any TCP client.

gdsgate tcp proxy redis-cache --listen 127.0.0.1:6390 &
redis-cli -p 6390 ping
Flag Default Purpose
--listen <addr> 127.0.0.1:0 Local host:port to bind.

gdsgate mcp ls

Lists MCP-server resources you can view.

gdsgate mcp proxy <resource> [--listen <addr>]

Localhost relay for an MCP client. The agent gates tools/call against its allowed_tools allow-list before the call reaches the backend; every tool call is audited.

gdsgate mcp proxy tools-mcp --listen 127.0.0.1:8765 &
Flag Default Purpose
--listen <addr> 127.0.0.1:0 Local host:port to bind.

gdsgate ca rotate [--all]

Requests a certificate-authority rotation through the cluster (Auth runs the paced double-signing).

Flag Default Purpose
--all off Rotate every rotatable CA with sensible defaults.

gdsgate ca learn-host-key <target>

Trust-on-first-use helper for the model-B jump-host path: connects to <target> (host or host:port, default port 22), captures the sshd's host-key, and prints its SHA256:<base64> fingerprint on stdout — ready to paste into [[agent.backends]].host_key_fingerprints (or write into the file pointed at by host_key_fingerprints_file).

gdsgate ca learn-host-key sshd-target:22 \
    > /etc/gdsgate/sshd-target.fp

Stderr carries a one-line preamble naming the target; exit code is non-zero on a connect / handshake failure.

Environment variables

Cluster-configuration overlay

Every GDSGATE_* listed in Configuration → Environment overrides overlays the matching field in the TOML file. An unset variable changes nothing.

Client-side

Variable Purpose
GDSGATE_ID_TOKEN Identity token to present to the cluster (sub becomes the principal). Skips gdsgate login.
GDSGATE_USER Local-dev principal name when no [oidc] is configured. Default dev.
RUST_LOG Tracing filter. Default info.

Node bootstrap

Variable Purpose
GDSGATE_ENROLL_TOKEN One-time node-registration token. Consumed by Auth on first start of a Proxy or Agent. Preferred over enroll.token in the file.

Exit codes

  • 0 — command succeeded.
  • 1 — generic failure (the error is logged to stderr).
  • 101 — Rust panic (unrecoverable internal error; please report).

A non-zero exit from auth policy validate indicates a policy error suitable for CI gating.