Skip to content

feat(agent-installer): add Agent Tunnel configuration dialog#1789

Draft
irvingouj@Devolutions (irvingoujAtDevolution) wants to merge 2 commits into
masterfrom
feat/agent-installer-tunnel
Draft

feat(agent-installer): add Agent Tunnel configuration dialog#1789
irvingouj@Devolutions (irvingoujAtDevolution) wants to merge 2 commits into
masterfrom
feat/agent-installer-tunnel

Conversation

@irvingoujAtDevolution
Copy link
Copy Markdown
Contributor

Summary

Adds an optional Agent Tunnel wizard step to the Devolutions Agent MSI installer so admins can enrol the agent in a Gateway QUIC tunnel during install — UI or unattended.

Three text fields in the dialog: enrolment string, advertise subnets, advertise domains. The feature is opt-in (isEnabled: false, allowChange: true); the dialog is skipped when the feature isn't selected, and an empty enrolment string skips tunnel setup even if the feature is on, so the installer remains usable for non-tunnel deployments.

Smoke-tested end-to-end against a local DVLS + Gateway + Agent stack: MSI built clean, agent enrolled successfully, RDP TCP traffic routed through the agent tunnel to IT-HELP-DC:3389.

MSI public properties (unattended install)

msiexec /i DevolutionsAgent.msi /qn ADDLOCAL="...,AgentTunnel" \
  AGENT_TUNNEL_ENROLLMENT_STRING="dgw-enroll:v1:<base64>" \
  AGENT_TUNNEL_ADVERTISE_SUBNETS="10.10.0.0/24" \
  AGENT_TUNNEL_ADVERTISE_DOMAINS="corp.example.com"

Custom action

EnrollAgentTunnel is deferred + elevated + Impersonate=false, runs Before StartServices, gated by Features.AGENT_TUNNEL_FEATURE.BeingInstall(). It:

  1. Validates the dgw-enroll:v1: prefix, strips whitespace, pads base64url, decodes JSON payload (api_base_url, enrollment_token, optional name).
  2. Shells out to devolutions-agent.exe enroll <url> <token> <name> [subnets] with a 60s timeout; on timeout the child is killed.
  3. Token is redacted (***) symmetrically across the command-line log and child stdout/stderr.
  4. After enrolment, advertise domains are patched into Tunnel.AdvertiseDomains of %ProgramData%\Devolutions\Agent\agent.json. This matches the design that advertise domains live in config, not on the CLI (replaces the closed feat(agent): --advertise-domains CLI flag #1774).

Depends on

Both merged to master 2026-05-20.

Test plan

  • Cold MSI build clean, no errors (8 preexisting CNDL1138/CNDL1006 warnings from existing code, not introduced here)
  • Wizard order: Welcome → Features → AgentTunnel → InstallDir → VerifyReady
  • AgentTunnel dialog skipped when feature not selected
  • Empty enrolment string skips enrolment (no failure)
  • Invalid dgw-enroll:v1: prefix → validation error in dialog
  • Invalid base64 → validation error in dialog (caught client-side, not at CA time)
  • Smoke test against local DVLS-signed enrolment JWT — agent registered, cert issued
  • Smoke test routing: RDP TCP through agent tunnel to IT-HELP-DC:3389 succeeds

Review history

Pre-review and codex-review passes folded into the single commit. Notable points addressed:

  • Robust JSON payload parsing (JObject, Value<string>(), IsNullOrWhiteSpace validation)
  • Symmetric token redaction (cmdline + stdout + stderr)
  • WaitForExit(60_000) return-value check with child kill on timeout
  • Whitespace-stripped + padded base64url decoding on both dialog validation and CA
  • ADDLOCAL CSV value trimming for admin-supplied lists with whitespace
  • Dropped 2 stray InstallDirDlg* strings leaked into en-us
  • Added 5 missing fr-fr translations

@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

Adds an optional Agent Tunnel wizard step to the Devolutions Agent
installer so admins can enroll the agent in a Gateway QUIC tunnel as
part of MSI install (UI or unattended).

Surfaces three MSI public properties for unattended installs:
- AGENT_TUNNEL_ENROLLMENT_STRING (dgw-enroll:v1:<base64> from DVLS/Hub/Gateway)
- AGENT_TUNNEL_ADVERTISE_SUBNETS (CSV CIDR; empty = none)
- AGENT_TUNNEL_ADVERTISE_DOMAINS (CSV DNS suffixes; empty = auto-detect only)

Wires a new deferred elevated custom action (EnrollAgentTunnel) that
runs Before StartServices when AGENT_TUNNEL_FEATURE is being installed.
It base64-decodes the enrollment payload, shells out to
`devolutions-agent.exe enroll <url> <token> <name> [subnets]` with a 60s
timeout, and redacts the token in the session log. Advertise domains
are persisted by patching `Tunnel.AdvertiseDomains` in agent.json
post-enrollment, matching the agreed direction that domain config lives
in the file rather than as a CLI flag.

The Tunnel feature itself is opt-in (isEnabled:false, allowChange:true);
the dialog is skipped when the feature isn't selected. An empty
enrollment string also skips tunnel setup, allowing the installer to be
used without touching the tunnel.
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