test(agent): e2e + registry + routing test suite - #1772
Open
irvingouj@Devolutions (irvingoujAtDevolution) wants to merge 12 commits into
Open
test(agent): e2e + registry + routing test suite#1772irvingouj@Devolutions (irvingoujAtDevolution) wants to merge 12 commits into
irvingouj@Devolutions (irvingoujAtDevolution) wants to merge 12 commits into
Conversation
irvingouj@Devolutions (irvingoujAtDevolution)
marked this pull request as draft
April 29, 2026 17:16
irvingouj@Devolutions (irvingoujAtDevolution)
force-pushed
the
feat/quic-tunnel-2-routing
branch
2 times, most recently
from
May 12, 2026 17:40
b4ec360 to
a2b2ff5
Compare
irvingouj@Devolutions (irvingoujAtDevolution)
added a commit
that referenced
this pull request
May 12, 2026
Address CBenoit's review on #1741: in addition to the `#[doc(hidden)]` marker and the `_for_test` naming, gate `AgentPeer::set_last_seen_for_test` and `set_received_at_for_test` behind `#[cfg(any(test, feature = "test-utils"))]` so production builds of `devolutions-gateway` and `devolutions-agent` don't compile these methods at all. Cross-crate test consumers (the workspace `testsuite` crate carrying the agent-tunnel integration tests, in #1772) opt in via `features = ["test-utils"]` on their `agent-tunnel` dev-dep.
irvingouj@Devolutions (irvingoujAtDevolution)
force-pushed
the
feat/agent-tunnel-tests
branch
3 times, most recently
from
May 19, 2026 19:05
8887df1 to
c2da5a9
Compare
irvingouj@Devolutions (irvingoujAtDevolution)
force-pushed
the
feat/agent-tunnel-tests
branch
from
May 25, 2026 18:50
c2da5a9 to
f711d50
Compare
irvingouj@Devolutions (irvingoujAtDevolution)
marked this pull request as ready for review
May 25, 2026 21:10
irvingouj@Devolutions (irvingoujAtDevolution)
requested review from
Benoît Cortier (CBenoit) and
Copilot
and removed request for
Copilot
May 25, 2026 21:19
Copilot started reviewing on behalf of
irvingouj@Devolutions (irvingoujAtDevolution)
May 25, 2026 21:19
View session
- testsuite/tests/agent_tunnel/integration.rs: full QUIC e2e (CA → enroll → mTLS → control stream → ConnectRequest → echo) and a domain-routing variant. - testsuite/tests/agent_tunnel/registry.rs: AgentRegistry unit tests covering online/offline timeouts, route epoch handling (replace vs refresh vs ignore stale), domain advertisement persistence, and the agent-info snapshot. - testsuite/tests/agent_tunnel/routing.rs: RoutePlan::resolve / try_route decision matrix — explicit jet_agent_id, subnet match, domain match, fallback to direct, offline filtering, and the no-handle paths. Also includes the read_cert_chain rewrite from #1771 (needed for the e2e tests to parse the rcgen-produced PEM); once #1771 lands this collapses to just the test files.
…iants Backfills coverage that the original test suite (#1741-era) predates: - New `common.rs` consolidates the QUIC + mTLS test scaffolding so all E2E tests share one `bind_test_listener` helper instead of duplicating ~80 lines per test. - New `cert.rs` pins three invariants of `agent-tunnel/src/cert.rs`: - `sign_agent_csr` must encode the caller-passed agent_id in the URN SAN, *ignoring* the CSR's Common Name (#1775 review feedback — prevents a compromised agent from impersonating via CSR subject). - `extract_agent_id_from_pem` round-trips a freshly signed cert. - `extract_agent_id_from_pem` rejects a cert with no urn:uuid SAN (e.g. the CA root cert). - Extra `routing.rs` cases against a live `AgentTunnelHandle`: - `route_and_connect` errors on empty candidate slice. - `try_route` with handle present and no match returns `Ok(None)`. - `try_route` with handle present and missing explicit agent_id errors rather than silently falling back to direct. - New `cert_renewal_preserves_mtls_identity_e2e` runs the full QUIC `CertRenewalRequest` → `CertRenewalResponse::Success` round-trip with a renewal CSR filed under `CN=evil-impersonator`. Asserts the renewed cert still encodes the mTLS-authenticated `agent_id` — guards the #1775 handler's "never trust the CSR subject" comment with a test. 32 tests now pass; 3 parallel runs verified stable (~0.3s each).
…dvertise `ctrl.send(&RouteAdvertise)` only guarantees the message is on the wire, not that the gateway has processed it and updated `peer.route_state()`. A fixed 200ms `tokio::time::sleep` was racy on slow/loaded CI runners. Replace the three call sites with `wait_for_route_advertised`, a 10ms poll loop that exits as soon as the agent appears in the registry with `route_state().epoch >= min_epoch`, or panics with a clear message after 5s. Default `RouteAdvertisementState` has epoch 0, so any successful RouteAdvertise bumps it to >= 1. Side effect: the e2e tests finish in ~0.16s instead of ~0.32s because they no longer eat the worst-case fixed delay.
Exercise registration, routing, KDC forwarding, certificate renewal, and real Agent processes over QUIC. Add a Docker scenario that isolates DNS and IP targets from the Gateway so direct connections cannot create false positives.
Run the ignored Docker scenario on Ubuntu and include it in the required CI success gate.
irvingouj@Devolutions (irvingoujAtDevolution)
force-pushed
the
feat/agent-tunnel-tests
branch
from
August 19, 2026 18:57
8ff13d0 to
dddce7e
Compare
irvingouj@Devolutions (irvingoujAtDevolution)
requested review from
a team
as code owners
August 19, 2026 18:57
Copilot started reviewing on behalf of
irvingouj@Devolutions (irvingoujAtDevolution)
August 19, 2026 18:58
View session
Contributor
There was a problem hiding this comment.
Pull request overview
Adds broad agent-tunnel coverage across routing, QUIC integration, certificate renewal, KDC forwarding, and Docker-isolated real-agent scenarios.
Changes:
- Adds agent-tunnel integration and routing tests.
- Adds Docker-based end-to-end testing and CI execution.
- Extends test configuration and generalizes agent stream helpers.
Reviewed changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/ci.yml |
Runs the Docker end-to-end test. |
Cargo.lock |
Records new test dependencies. |
devolutions-agent/src/tunnel.rs |
Enables stream-based unit tests and tests renewal/proxy behavior. |
testsuite/Cargo.toml |
Adds agent-tunnel test dependencies. |
testsuite/src/cli.rs |
Adds asynchronous agent process launching. |
testsuite/src/dgw_config.rs |
Supports tunnel-specific gateway configuration. |
testsuite/tests/agent_tunnel/cert.rs |
Tests certificate identity handling. |
testsuite/tests/agent_tunnel/common.rs |
Provides shared QUIC fixtures. |
testsuite/tests/agent_tunnel/integration.rs |
Tests routed and direct upstream flows. |
testsuite/tests/agent_tunnel/kdc.rs |
Tests KDC routing behavior. |
testsuite/tests/agent_tunnel/mod.rs |
Registers test modules; advertised registry suite is absent. |
testsuite/tests/agent_tunnel/routing.rs |
Tests routing decisions and fallback behavior. |
testsuite/tests/cli/agent/mod.rs |
Registers agent tunnel CLI tests. |
testsuite/tests/cli/agent/tunnel.rs |
Adds real-process and Docker end-to-end tests. |
testsuite/tests/main.rs |
Registers the agent-tunnel suite. |
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+1
to
+5
| mod cert; | ||
| mod common; | ||
| mod integration; | ||
| mod kdc; | ||
| mod routing; |
Linux Docker rejects static container addresses on networks without a user-configured subnet. Derive a private /24 from the test ID so the target and Agent containers keep stable addresses.
Keep the real Docker coverage while removing test-only seams from the Agent runtime.
Limit APT request stalls and leave enough time for the real Docker end-to-end test.
Bound each APT attempt so mirror stalls cannot consume the entire end-to-end job.
Bound and retry both APT phases so a stalled package mirror cannot skip the end-to-end test.
The Agent Tunnel test dependency tree does not require libsystemd, so avoid the unreliable APT mirror entirely.
Marc-André Moreau (mamoreau-devolutions)
approved these changes
Aug 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the agent-tunnel test suite under
testsuite/tests/agent_tunnel/:integration.rs— full QUIC end-to-end (CA → enroll → mTLS → control stream → ConnectRequest → echo) plus the domain-routing variantregistry.rs—AgentRegistryunit tests (online/offline timeouts, route epoch handling, domain advertisement persistence, agent-info snapshot)routing.rs—RoutePlan::resolve/try_routedecision matrix (explicitjet_agent_id, subnet/domain match, fallback, offline filtering, no-handle paths)Why split out
The routing/upstream feature (#1741, since merged) kept its diff focused on production code. Tests live here so the test scaffolding diff doesn't muddle the feature review.
Test plan
cargo test -p testsuite --test integration_tests agent_tunnel::— 25/25 pass locally