Splits the Gateway's cryptographic identity (the SAN written to the agent
tunnel server certificate) from its network reachability (the host the agent
dials). A single `conf.hostname` was previously overloaded as both, which broke
deployments where the gateway is reachable by several names depending on the
agent's network position (internal FQDN, IP literal, public DNS).
`AgentTunnel.AdvertisedNames` is the authoritative list of names/IPs the
gateway accepts enrollments through, and is the SAN set written into
`agent-tunnel-server-cert.pem`. Each entry is either a bare string or
`{ "Name": "...", "Label": "..." }` for DVLS UI grouping. When absent, the
config defaults to `[conf.hostname]` so existing deployments are unaffected.
At gateway boot the server cert is regenerated whenever the on-disk SAN set
differs from the configured advertised names. The existing server keypair is
reused so the SPKI pin held by already-enrolled agents stays stable; only the
cert document is reissued. The new cert fingerprint is logged.
`/jet/tunnel/enroll` now parses the JWT's `jet_gw_url`, normalises the host
(DNS lowercased, IP literals canonicalised), and rejects with HTTP 400 +
`{ error, message, help }` body when the host is not in
`AgentTunnel.AdvertisedNames`. The enrollment response now carries both
`quic_endpoint` (legacy, computed from the validated JWT host and the listen
port) and `quic_port` (new); a follow-up release will drop `quic_endpoint`.
`/jet/diagnostics/configuration` now exposes an `agent_tunnel` field with
`enabled`, `listen_port`, and the advertised name list (with optional labels).
DVLS reads this to build the "Generate enrollment string" dropdown.
Issue: DGW-Agent-Tunnel-Identity
Summary
First of three PRs implementing the agent-tunnel identity refactor
described in
AGENT_TUNNEL_IDENTITY_DESIGN.md. This PR is gateway-only.Today the gateway's
conf.hostnameis overloaded as both the cryptographicidentity written into the agent-tunnel server cert SAN and the network
hostname returned to agents as their QUIC dial target. In any realistic
deployment a single gateway is reachable via multiple names (internal FQDN,
LAN IP literal, public DNS), so picking one and forcing every agent to use
it breaks agents whose network can't resolve that chosen name.
Scope (per spec PR 1):
AgentTunnel.AdvertisedNamesconfig:Vec<AdvertisedName>with serdeuntagged string-or-object form (label is informational).
[conf.hostname]when absent so existing single-namedeployments keep working with no admin changes.
agent-tunnel-server-cert.pemat boot when SAN set differs from config, reusing the existing keypair so
SPKI pins remain stable for enrolled agents.
EnrollResponse.quic_endpointfrom the validatedjet_gw_url.hostrather than
conf.hostname. Addquic_portfield for new agents (thelegacy
quic_endpointis retained one release for compatibility).{error, message, help}whenjet_gw_url.hostis not inAdvertisedNames./jet/diagnostics/configurationwith anagent_tunnelfield soDVLS can introspect via the existing endpoint instead of a new route.
Dependency
This PR is the base for #pr2 (agent) and #pr3 (installer).
Spec
See
AGENT_TUNNEL_IDENTITY_DESIGN.md(PR 1 section).Test plan
cargo test -p devolutions-gatewaypassesSAN contains both names, reject enrollment via name3