Skip to content

User guide

Using a deployment your administrator set up: trust, sign-in, and each kind of resource through its native client. To build a deployment, see the Quickstart.

Examples use placeholder hosts: authority-1, proxy-1, connector-1, alice@example.test. lab-read is an allowed database; lab-denied is visible and denied.

Prerequisites

The administrator supplies:

  • the client: on Linux an x86_64 static musl binary; on Windows the x86_64 .msi, which installs gdsgate.exe into %ProgramFiles%\gdsgate and adds it to PATH;
  • the Proxy address and the transport CA fingerprint;
  • the client configuration path and identity-provider instructions.

Examples use a POSIX shell. In PowerShell, set the same values as $env:PROXY_ADDR, $env:PROXY_FINGERPRINT, $env:CLIENT_CONFIG, and run each relay (db proxy, kube proxy, tcp proxy, mcp proxy) in its own window; stop it with Ctrl+C.

: "${PROXY_ADDR:?set the administrator-supplied Proxy address}"
: "${PROXY_FINGERPRINT:?set the published transport CA fingerprint}"
: "${CLIENT_CONFIG:?set a client configuration path}"
SSH_FRAGMENT="${SSH_FRAGMENT:-./gdsgate-ssh-fragment.conf}"
SSH_CONFIG="${SSH_CONFIG:-$SSH_FRAGMENT}"

SSH_CONFIG defaults to the generated fragment, used with ssh -F. If your SSH configuration includes the fragment, set SSH_CONFIG to that file.

Do not pass a token as a command argument or commit a generated file.

0. Connect to the cluster

gdsgate connect writes the client settings and the transport trust anchor. It does not sign you in. Verify the fingerprint out of band first.

gdsgate connect "$PROXY_ADDR" \
  --fingerprint "$PROXY_FINGERPRINT" \
  --output "$CLIENT_CONFIG"

An existing output file is kept unless --force is given. Check the result:

test -s "$CLIENT_CONFIG"
gdsgate --config "$CLIENT_CONFIG" doctor
Symptom Cause What to do
First contact refused in a non-interactive shell --fingerprint missing Pass the published fingerprint.
Fingerprint mismatch The Proxy offers a different CA Stop. Remove the output file and ask the administrator for the correct value.
Proxy unreachable Route or address Fix it and run connect again with the same fingerprint.

--insecure turns off encryption and peer verification. Use it only for a development process on the same host.

Keep the trust anchor until the administrator rotates the CA and supplies a new fingerprint.

1. Sign in

gdsgate --config "$CLIENT_CONFIG" login

The default device flow prints a URL and a one-time code; approve it with the identity provider. login --browser uses the Authorization Code flow with PKCE on a loopback address. Check:

gdsgate --config "$CLIENT_CONFIG" ls

Login can succeed with an empty ls and denied connections: the token has no group the policy permits. Ask the policy owner to check view and connect.

A job or service uses workload identity, not a person's token.

2. List what you can reach

gdsgate --config "$CLIENT_CONFIG" ls

One row per resource you have view on: kind, environment, labels, address. A resource with connect and no view is connectable and not listed. Filter by kind:

gdsgate --config "$CLIENT_CONFIG" db ls
gdsgate --config "$CLIENT_CONFIG" kube ls
gdsgate --config "$CLIENT_CONFIG" tcp ls
gdsgate --config "$CLIENT_CONFIG" mcp ls

In these examples, both lab-read and lab-denied are listed. A resource name that is not in the catalog is refused as unknown, before policy.

Need Use
One task or a script The explicit command for the resource kind, below
Native clients used repeatedly by one user Resident client, basic or direct
An application that cannot use a loopback address Resident transparent, with the host owner's approval and an address pool that does not overlap local networks
A shared host, server, container or service An explicit command or a workload identity; no personal Resident client

3. SSH

Generate an SSH configuration fragment:

gdsgate --config "$CLIENT_CONFIG" ssh-config '*.gds' > "$SSH_FRAGMENT"

The fragment sets a ProxyCommand, the client configuration and the gdsgate host keys. To use it from an existing SSH configuration, include it before the matching host entries and set SSH_CONFIG to that file. Include it once.

ssh -F "$SSH_CONFIG" user@RESOURCE_NAME

The audit records a connect decision, and a session close when it ends.

Symptom Cause What to do
Denied on SshHost::"RESOURCE_NAME" Policy Run the step-up or gdsgate request-access RESOURCE_NAME --reason 'ticket-1234' the message names, then retry; otherwise ask the policy owner. No downstream connection is made.
Host key changed The host key differs from the generated fragment Check with the resource owner. Do not relax host-key checking.

Interactive shell

A normal ssh login gives a PTY; resize and interrupt work. exit closes the session and writes the close event. On a Windows connector the default shell is cmd.exe (%ComSpec%).

Running a command

ssh -F "$SSH_CONFIG" user@RESOURCE_NAME -- command arg

The command's exit status is returned and the session is recorded.

-L: local port forward

Requires sshForwardLocal in policy and the destination in the backend's allow_local_forward list.

ssh -F "$SSH_CONFIG" -L 127.0.0.1:LOCAL_PORT:DEST_HOST:DEST_PORT user@RESOURCE_NAME

A denied forward is refused before any bytes reach the Connector, and audited. Ending ssh closes the listener.

-R: remote port forward

Requires sshForwardRemote in policy and the bind address in the backend's allow_remote_forward list. Bind to loopback to keep the listener off the host's network:

ssh -F "$SSH_CONFIG" -R 127.0.0.1:REMOTE_PORT:DEST_HOST:DEST_PORT user@RESOURCE_NAME

A denied bind is refused and audited.

-A: agent forwarding

Requires allow_agent_forward = true on the backend and sshForwardAgent in policy. Both are off by default; connect and sshForwardLocal do not imply them.

ssh -F "$SSH_CONFIG" -A user@RESOURCE_NAME

When allowed, programs in the session see SSH_AUTH_SOCK and can sign with your keys while the session is open: the shell, what it starts, and root on the Connector host. When refused, SSH_AUTH_SOCK is not set.

SFTP

sftp -F "$SSH_CONFIG" user@RESOURCE_NAME

A connect denial comes from gdsgate; a permission error on a file comes from the host. On a Windows connector, paths look like /C:/..., / is the root of the home drive, and mode changes are refused.

4. Databases (PostgreSQL / MySQL)

Kinds: postgres, mysql, and a cockroach backend listed as postgres. Start a loopback relay and point the client at it:

gdsgate --config "$CLIENT_CONFIG" db proxy lab-read --listen 127.0.0.1:5433 &
DB_PID=$!
trap 'kill "$DB_PID" 2>/dev/null || true' EXIT
psql -h 127.0.0.1 -p 5433 -c 'select count(*) from lab_table;'

In the lab the result is 3. connect is decided when the relay opens; a backend in restricted mode also decides each statement (dbQuery). Both are audited.

A denied resource:

gdsgate --config "$CLIENT_CONFIG" --no-remediate \
  db proxy lab-denied --listen 127.0.0.1:5434

This fails with a denial naming Database::"lab-denied"; no backend connection is made. Ask for connect or dbQuery, or run the step-up the message names. See database policy.

5. Kubernetes

Write a kubeconfig and start the local proxy:

KUBECONFIG="${KUBECONFIG:-./gdsgate-kubeconfig.yaml}"
gdsgate --config "$CLIENT_CONFIG" kube login KUBE_RESOURCE > "$KUBECONFIG"
gdsgate --config "$CLIENT_CONFIG" kube proxy KUBE_RESOURCE --listen 127.0.0.1:6443 &
KUBE_PID=$!
trap 'kill "$KUBE_PID" 2>/dev/null || true' EXIT
kubectl --kubeconfig "$KUBECONFIG" get --raw=/version

The exec plugin gets a short-lived credential. Every API request is decided as kubeRequest by verb, resource kind, namespace, name and subresource. A denied request returns 403 before it reaches the cluster.

port-forward is refused unless the backend sets allow_port_forward; when allowed, its bytes are audited as one channel. Delete the kubeconfig when you are done.

6. TCP, Redis, web

A tcp resource is relayed as bytes; gdsgate does not read the protocol.

gdsgate --config "$CLIENT_CONFIG" tcp proxy RESOURCE_NAME --listen 127.0.0.1:6390 &
TCP_PID=$!
trap 'kill "$TCP_PID" 2>/dev/null || true' EXIT
redis-cli -p 6390 ping

The audit records the connect and byte counts. A connect denial happens before the backend is dialled.

Web resources are covered under Web applications.

7. MCP servers

gdsgate --config "$CLIENT_CONFIG" mcp proxy MCP_RESOURCE --listen 127.0.0.1:8765 &
MCP_PID=$!
trap 'kill "$MCP_PID" 2>/dev/null || true' EXIT
gdsgate mcp bridge 127.0.0.1:8765

tools/list shows only the tools you may see. Each tools/call, resources/read and prompts/get is decided and audited as mcpCallTool, mcpReadResource or mcpGetPrompt; a denial is a JSON-RPC error and the server is not called. The backend's allowed_tools list always applies; Cedar per-tool decisions apply when the backend sets enforce_tool_policy.

8. Model services

For an llm resource, the Connector reads the model name from each request and decides llmCall per call. The audit row carries the model and token counts. A model the policy does not allow, or a revoked delegation, is refused at the Connector. When the backend substitutes the provider credential, the client never receives it. See AI agents and model policy.

9. Web applications

gdsgate --config "$CLIENT_CONFIG" web proxy WEB_RESOURCE --listen 127.0.0.1:0

The proxy prints a loopback address. Each request is decided as httpRequest and audited. A 403 from the gateway is a route denial; any other 403 comes from the application.

Reaching the outside through a web-egress resource

A web-egress resource is a forward proxy for outside destinations. Only public internet addresses are dialled: private, loopback, link-local, metadata and other special-purpose ranges are refused. Ranges your network routes are listed by the administrator in routed_ranges. Each request is audited.

Reaching an application from a browser with nothing installed

Available when the deployment exposes a browser entry. The administrator gives you its address. Decisions and audit are the same as with web proxy. When the browser session expires, sign in with the identity provider again.

Reaching an application by its own name

The Resident client intercepts a resource's native_name when the name is also listed in [client].intercept_names. Other names resolve normally. Stop the Resident client to stop interception. See Resident client.

10. Windows desktops

gdsgate --config "$CLIENT_CONFIG" rdp ls
gdsgate --config "$CLIENT_CONFIG" rdp proxy DESKTOP_RESOURCE --listen 127.0.0.1:3390

The listener prints a username and password for your RDP client. They are not a Windows account, are valid until the command exits, and admit one session at a time. --exec starts an RDP client with them: mstsc on Windows, xfreerdp on Linux.

The backend sets the Windows account. If it offers several, choose one with --windows-user; the policy decides. When the connector logs in to Windows itself, you never receive the Windows password.

The session appears in gdsgate session list; its open and close are audited. An account the policy does not allow is refused before Windows is contacted. Closing the RDP client ends the command.

11. Just-in-time access

Used when a denial offers approval. Approving is the Cedar action approveRequest; creating a request is not a Cedar action.

gdsgate --config "$CLIENT_CONFIG" request-access RESOURCE_NAME \
  --action connect --reason 'ticket or task identifier' --ttl 900
gdsgate --config "$CLIENT_CONFIG" requests

The request is queued with an ID. An approver runs gdsgate approve REQUEST_ID; then retry. A request that was denied or has expired cannot be reused: file a new one. See policy JIT patterns.

12. Multi-factor (MFA) and step-up

MFA at login is the identity provider's. gdsgate step-up gives a one-time grant for one action on one resource:

gdsgate --config "$CLIENT_CONFIG" step-up RESOURCE_NAME --action connect

The default factor is a passkey in the browser. --code is for a TOTP factor enrolled on the deployment. The next matching request is allowed once; a second one needs a new step-up. Both are audited.

13. Managing your sessions

gdsgate --config "$CLIENT_CONFIG" session list
gdsgate --config "$CLIENT_CONFIG" session kill SESSION_ID

session list shows the sessions policy lets you see. session kill ends one if killSession allows it; the kill is audited.

14. Delegating access to an agent

Gives a program part of your access while it runs. See AI agents.

gdsgate --config "$CLIENT_CONFIG" delegate \
  --can mcp:search@tools-dev \
  --can llm:call@models-dev \
  --ttl 900 --sandbox strict --model gateway \
  --agent-profile PROFILE_NAME \
  --exec ./agent-wrapper -- --single-search-and-single-model-call

gdsgate delegate --list-agent-profiles lists the shipped profiles with their source and review date. The program gets the listed capabilities while it runs; the grant is revoked when it exits. The audit shows delegation.create, sandbox.claim, and each tool and model call. A tool or model not in --can is refused. A --bind-key grant stays until you revoke it; then delete its directory.

On Windows, --sandbox basic and strict need the gdsgate-client-net service (installed by the .msi); without it, a grant that names a resource is refused.

What the audit log captures

The audit chain records authentication, policy decisions, sessions, delegation and administrative events. A row names the principal, resource kind, action, outcome, and the session or request ID where there is one. A denial row does not mean the backend was contacted.

Operators verify the chain from a workstation whose configuration opens the audit store and names the anchor key:

gdsgate --config "$AUDIT_VERIFY_CONFIG" authority verify-audit

It prints a chain and anchor verification summary. See Operations for events and export.

Troubleshooting

Check in this order: version, trust, identity, catalog, policy, local relay, backend. Send the administrator the error message and its request ID.

Symptom Collect What to do
First contact refused Published and offered fingerprints Ask the administrator to reconcile them.
Login succeeds, ls is empty Subject, groups, Proxy address Ask for view on the resource.
connect denied Resource kind, action, request ID Run the step-up or request-access the message names, or ask for a policy review.
Relay opens, native client fails Relay output, client error Check the local port, the generated config, and host-key or TLS trust.
Kubernetes 403 Verb, kind, namespace, name, subresource Ask for that kubeRequest.
MCP tool missing tools/list output, tool name Check allowed_tools, enforce_tool_policy, viewTools.
Agent loses access after exit Delegation ID Expected with --exec. Revoke a remaining --bind-key grant.
Windows: start the gdsgate-client-net service from an elevated prompt The service is stopped Run sc start gdsgate-client-net in an elevated prompt.