Administer
Asset onboarding
Targets are the things users actually connect to — Linux servers, Windows hosts, databases, Kubernetes clusters. Onboarding a target is the act of telling Wardengate where it lives, how to reach it, and which accounts may be used there. This page walks through the supported kinds, the two connection modes, and the patterns that hold up as you scale from dozens to thousands.
Supported target types
- Linux and BSD hosts over SSH.
- Windows hosts over RDP with TLS or CredSSP.
- PostgreSQL, MySQL / MariaDB, MongoDB, Redis, Microsoft SQL Server.
- Kubernetes API servers — kubectl is proxied with its own policy hooks.
- HTTP applications behind Wardengate's reverse-proxy target kind.
Each target has a protocol, a network address, zero or more accounts, and a set of tags. Tags are the connective tissue: policies, scoped roles, and notification rules all select on them.
Proxy mode vs agent mode
Wardengate brokers sessions in one of two ways:
- Proxy mode — the gateway opens an outbound TCP connection to the target and relays the protocol. Nothing runs on the target. Use this when the target is in a network the gateway can reach directly.
- Agent mode — a lightweight agent on the target reaches out to the gateway and the brokered session runs over that reverse tunnel. Use this for assets behind NAT, in customer VPCs, or on laptops that must be reachable from anywhere.
Proxy mode is the default. Agent mode is selected per target by flipping spec.mode: agent and installing the agent package. Both modes honour the same policy layer.
Credential modes
Each target declares how credentials are presented to the far end:
- Stored — a password, SSH key, or certificate held in the Wardengate vault. Encrypted at rest with envelope encryption; the unwrapping key sits in a KMS or HSM.
- External secret — a reference to HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager, or Azure Key Vault. Fetched per session.
- Just-in-time — Wardengate creates a short-lived account on the target at connection time and tears it down at disconnect. Nothing to rotate, nothing to leak.
- SSH certificate — Wardengate signs an ephemeral user certificate with an internal CA that the target trusts. Zero stored secrets on the target side.
Linux SSH
apiVersion: wardengate/v1
kind: Target
metadata:
name: web-01.prod
organization: acme
spec:
protocol: ssh
address: 10.10.4.20:22
mode: proxy
hostKey:
algorithm: ssh-ed25519
fingerprint: SHA256:h8Cj...yqI=
accounts:
- name: deploy
credential: { kind: stored, ref: vault/ssh/deploy-prod }
- name: ops
credential: { kind: sshCertificate, ca: internal-ssh-ca }
tags:
env: prod
role: web
team: platformPin host keys on first onboard. Wardengate will refuse to connect if the presented key does not match the pinned fingerprint; that is the bit that protects you from a silent man-in-the-middle inside your own network.
Windows RDP
apiVersion: wardengate/v1
kind: Target
metadata:
name: win-dc01.prod
organization: acme
spec:
protocol: rdp
address: 10.10.2.5:3389
security: tls
nla: true
accounts:
- name: "CORP\\svc_admin"
credential: { kind: stored, ref: vault/win/dc-admin }
tags:
env: prod
role: dcRequire NLA where the fleet supports it — the alternative is handing Wardengate a password to type into the RDP logon screen, which is worse on every axis. If the target's CA is not in the public trust store, reference a caBundleRef on the target.
PostgreSQL
apiVersion: wardengate/v1
kind: Target
metadata:
name: billing.prod.pg
organization: acme
spec:
protocol: postgres
address: billing.prod.rds.example:5432
tls:
mode: require
serverName: billing.prod.rds.example
accounts:
- name: app_ro
credential: { kind: stored, ref: vault/pg/billing-ro }
- name: analyst
credential: { kind: jit, template: analyst-role }
tags:
env: prod
data: piiJIT Postgres accounts are created by running a connection-time template in the target database — typically a CREATE ROLE with a generated password, a role grant, and a VALID UNTIL matching the session cap. Wardengate drops the role at disconnect.
MySQL, MongoDB, Redis
apiVersion: wardengate/v1
kind: Target
metadata:
name: orders.prod.mysql
organization: acme
spec:
protocol: mysql
address: orders.prod.mysql.example:3306
tls: { mode: require }
accounts:
- name: reader
credential: { kind: stored, ref: vault/mysql/orders-ro }
---
apiVersion: wardengate/v1
kind: Target
metadata:
name: sessions.prod.mongo
organization: acme
spec:
protocol: mongodb
address: mongo.prod.example:27017
tls: { mode: require }
authMechanism: SCRAM-SHA-256
accounts:
- name: reader
credential: { kind: stored, ref: vault/mongo/sessions-ro }
---
apiVersion: wardengate/v1
kind: Target
metadata:
name: cache.prod.redis
organization: acme
spec:
protocol: redis
address: cache.prod.example:6379
tls: { mode: require }
accounts:
- name: default
credential: { kind: stored, ref: vault/redis/cache-default }Kubernetes
apiVersion: wardengate/v1
kind: Target
metadata:
name: prod-eu.k8s
organization: acme
spec:
protocol: kubernetes
apiServer: https://k8s-prod-eu.internal:6443
caBundleRef: k8s-prod-eu-ca
accounts:
- name: platform-viewer
credential:
kind: jit
template: k8s-viewer-token
groupBindings: ["platform:viewers"]
- name: platform-admin
credential:
kind: jit
template: k8s-admin-token
groupBindings: ["platform:admins"]
tags:
env: prod
region: eu-west-1The Kubernetes target type mints short-lived tokens that bind the session to a Kubernetes group; the user's RBAC in the cluster is driven by cluster-side ClusterRoleBindings against those group names. Session recording captures kubectl request bodies — including the bits of YAML you apply.
Asset groups and label selectors
Once you have more than thirty targets, naming them individually in policy becomes a liability. Asset groups are label selectors that evaluate continuously — membership is always current, nothing to reconcile.
apiVersion: wardengate/v1
kind: AssetGroup
metadata:
name: prod-web
organization: acme
spec:
selector: "env=prod,role=web"
description: "Everything tagged as a production web host."Discovery
Wardengate can pull inventory from AWS EC2/RDS, GCP Compute/Cloud SQL, Azure VMs, and Kubernetes clusters. Discovered assets land in a holding pool where an operator can review, tag, and promote them to real targets. Auto-promotion is available but off by default — the trade-off is between fewer clicks and the risk of exposing an asset before you have tagged it correctly.
wgctl discovery add aws \
--org acme \
--name aws-prod-eu \
--role-arn arn:aws:iam::111122223333:role/wardengate-discovery \
--regions eu-west-1,eu-central-1 \
--tag-filter "Environment=prod"Bulk import
For one-time migrations from spreadsheets or existing asset inventories, the CLI accepts CSV or multi-document YAML.
# CSV columns: name,protocol,address,account,tag:env,tag:role
wgctl target import --format csv --file fleet.csv --org acme
# YAML with a doc-per-target
wgctl apply -f targets/*.yamlHealth checks
Every target runs a light probe every 60 seconds from the nearest gateway — TCP open, TLS handshake, protocol greeting. Probes never authenticate, to keep them cheap and audit-clean. Failed probes flip the target to degraded and surface an alert through whatever notification channel is subscribed.
Related
- Account lifecycle — storing, rotating, and discovering credentials.
- Session policies — what users can do once they connect.
- Session management — watching and terminating live sessions.