Skip to content

feat(dgw): decouple agent tunnel SAN from network endpoint#1794

Closed
irvingouj@Devolutions (irvingoujAtDevolution) wants to merge 2 commits into
masterfrom
feat/agent-tunnel-identity-pr1
Closed

feat(dgw): decouple agent tunnel SAN from network endpoint#1794
irvingouj@Devolutions (irvingoujAtDevolution) wants to merge 2 commits into
masterfrom
feat/agent-tunnel-identity-pr1

Conversation

@irvingoujAtDevolution
Copy link
Copy Markdown
Contributor

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.hostname is overloaded as both the cryptographic
identity 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):

  • New AgentTunnel.AdvertisedNames config: Vec<AdvertisedName> with serde
    untagged string-or-object form (label is informational).
  • Default to [conf.hostname] when absent so existing single-name
    deployments keep working with no admin changes.
  • Multi-SAN server cert generation: regenerate agent-tunnel-server-cert.pem
    at boot when SAN set differs from config, reusing the existing keypair so
    SPKI pins remain stable for enrolled agents.
  • Compute EnrollResponse.quic_endpoint from the validated jet_gw_url.host
    rather than conf.hostname. Add quic_port field for new agents (the
    legacy quic_endpoint is retained one release for compatibility).
  • Reject enrollment with HTTP 400 + structured {error, message, help} when
    jet_gw_url.host is not in AdvertisedNames.
  • Extend /jet/diagnostics/configuration with an agent_tunnel field so
    DVLS 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-gateway passes
  • SAN regen idempotence + host normalization unit tests
  • Manual: configure two AdvertisedNames, enroll via name1, verify cert
    SAN contains both names, reject enrollment via name3

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
@github-actions
Copy link
Copy Markdown

Let maintainers know that an action is required on their side

  • Add the label release-required Please cut a new release (Devolutions Gateway, Devolutions Agent, Jetsocat, PowerShell module) when you request a maintainer to cut a new release (Devolutions Gateway, Devolutions Agent, Jetsocat, PowerShell module)

  • Add the label release-blocker Follow-up is required before cutting a new release if a follow-up is required before cutting a new release

  • Add the label publish-required Please publish libraries (`Devolutions.Gateway.Utils`, OpenAPI clients, etc) when you request a maintainer to publish libraries (Devolutions.Gateway.Utils, OpenAPI clients, etc.)

  • Add the label publish-blocker Follow-up is required before publishing libraries if a follow-up is required before publishing libraries

@irvingoujAtDevolution
Copy link
Copy Markdown
Contributor Author

Closing — not authorized; will be reopened after explicit owner approval.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant