Skip to content

Integrations

This page covers how gdsgate plugs into the systems around it: identity providers, native clients per protocol, CI pipelines, and the SIEM / observability stack.

OIDC identity provider (Keycloak)

gdsgate is an OIDC relying party. Auth verifies each identity token against the provider's published signing keys (RS256 via JWKS) and maps the token's claims to a principal and its groups, which the Cedar policy authorises. The example below uses Keycloak; any standards-compliant OIDC provider works.

Configure gdsgate

[oidc]
issuer    = "https://keycloak.example.com/realms/gdsgate"
client_id = "gdsgate"
# audience defaults to client_id when unset

Auth fetches <issuer>/.well-known/openid-configuration and the JWKS at startup and verifies every token's signature, issuer, audience, and expiry.

Issuer must match exactly

The configured issuer, the issuer Keycloak advertises, and the token's iss claim must all be byte-identical. Keycloak derives the issuer from the request host, so reach Keycloak by one hostname from every node and client.

Configure the Keycloak client

Register a client gdsgate in your realm:

  • Public client (no secret) with the flows the CLI uses:
    • Standard flow (Authorization Code + PKCE) — desktop login (gdsgate login --browser);
    • Direct access grants — headless / CI token retrieval;
    • OAuth 2.0 Device Authorization Grantgdsgate login (device flow, the default and works over SSH).
  • Redirect URIs for the PKCE loopback: http://127.0.0.1/*, http://localhost/*.

Emit a groups claim

gdsgate authorises on the token's groups claim. Add a Group Membership mapper to the client (or to a shared client scope):

  • Mapper type: Group Membership
  • Token claim name: groups
  • Full group path: off (emit bare names like admins, not /admins)
  • Add to ID token: on

A user in the realm group admins then receives "groups": ["admins"] in the identity token, and the Cedar policy can match principal in Group::"admins".

Map groups to access with Cedar

The token's groups become the principal's Cedar group memberships. Scope each action to a group:

permit(principal, action == Action::"dbConnect", resource)
when { principal in Group::"admins" };

permit(principal, action == Action::"sshConnect", resource)
when { principal in Group::"admins" };

With this policy a user in admins is allowed database and SSH access while a user in any other group is denied — across every protocol, from one policy. See Policy for more patterns.

Headless tokens (CI, scripts)

The device flow is the human path. For automation, obtain the token out of band and pass it through GDSGATE_ID_TOKEN. For Keycloak with direct grants:

GDSGATE_ID_TOKEN=$(curl -s \
    -d client_id=gdsgate -d grant_type=password \
    -d username=alice -d password= -d scope=openid \
    https://keycloak.example.com/realms/gdsgate/protocol/openid-connect/token \
    | jq -r .id_token)

Now every gdsgate <command> and every kubectl / psql invocation through gdsgate proxies will run as alice.

Native clients per protocol

For full client-side workflows see the User guide. Summary of the integration points:

ssh (OpenSSH)

A client-config fragment routes ssh through gdsgate via ProxyCommand. The fragment is emitted by:

gdsgate --config ~/.gdsgate/client.toml ssh-config '*.gds' >> ~/.ssh/config

The --config path is woven into the generated ProxyCommand so native ssh (with no gdsgate flags of its own) reaches the right cluster. -L, -R, PTY, exec, SFTP, agent-forwarding, and live window-resize all work. Forward channels are gated by sshForwardLocal / sshForwardRemote in Cedar plus the agent's allow-lists.

psql / mysql

A localhost relay accepts native database clients:

gdsgate db proxy prod-db --listen 127.0.0.1:5433 &
psql -h 127.0.0.1 -p 5433 

The agent taps the client→server stream and emits a structured query log into the audit chain.

kubectl

kubectl integrates through an exec credential plugin plus a localhost relay. Emit a kubeconfig fragment, point kubectl at the relay, and on every call kubectl runs gdsgate kube credentials for a short-lived credential. The gdsgate Kubernetes listener resolves the identity and impersonates the user on the real API.

redis-cli and other TCP clients

Run a localhost TCP relay:

gdsgate tcp proxy redis-cache --listen 127.0.0.1:6390 &
redis-cli -p 6390 

MCP clients

MCP servers are reached the same way as TCP, with the agent gating each tools/call against allowed_tools before it reaches the backend.

CI pipelines

CI jobs reach resources through gdsgate exactly like a user — authorise once with a service-account identity token, then use native tools:

export GDSGATE_ID_TOKEN="$CI_GDSGATE_TOKEN"     # a service-account id_token

# Database migration
gdsgate --config /etc/gdsgate/client.toml db proxy prod-db --listen 127.0.0.1:5433 &
DBPID=$!
psql -h 127.0.0.1 -p 5433 -f migrations.sql
kill "$DBPID"

# Or a one-off SSH exec
ssh -o StrictHostKeyChecking=accept-new \
    -o UserKnownHostsFile=$CI_PROJECT_DIR/known_hosts \
    deploy@web-01.gds 'sudo systemctl reload nginx'

The job's access is policy-controlled, audited, and the identity appears in the audit log under the service account's sub.

Tips:

  • Cache transport-ca.pem as a CI variable and write it to client.transport_ca at job start.
  • Pick a short TTL on the service-account identity token so a leaked token does limited damage.
  • Keep CI service accounts in dedicated Cedar groups (e.g. ci-migrations) so the policy can scope their reach explicitly.

Observability and SIEM

gdsgate writes two streams:

  • Structured logs to stderr, in tracing format (filterable with RUST_LOG).
  • Hash-chained audit records to Auth's state store, exportable as canonical JSON, Splunk HEC, or CEF / syslog.

Ship the structured logs to your normal log pipeline (journald, container log driver, Loki) and export the audit log to a SIEM that verifies the chain. See Operations.

Backend kinds — what plugs in

A single Cedar policy speaks for every protocol the agent serves.

kind What the agent does Cedar action Native client
ssh (model A) Terminates and records the SSH session sshConnect, plus sshForward* and mintOnwardSshCert for model B ssh, sftp, scp
ssh (model B) Forwards the session to a downstream sshd with an OpenSSH cert from Auth same ssh
postgres Forwards the wire to addr, taps the query log dbConnect psql, pgbench, any libpq client
mysql Forwards the wire to addr, taps the query log dbConnect mysql, mariadb, any MySQL client
kubernetes Reverse-proxies the API with identity impersonation k8sAccess kubectl, helm, kustomize
tcp Raw byte forward tcpConnect redis-cli, curl, anything plaintext
mcp JSON-RPC forward with tools/call allow-list tcpConnect (transport) + mcpCallTool (per call) any MCP client

See Configuration → [agent] for every field per kind.