Skip to content

feat(dgw): persist agent tunnel authorization - #1958

Open
irvingouj@Devolutions (irvingoujAtDevolution) wants to merge 4 commits into
masterfrom
feat/agent-tunnel-identity-lifecycle
Open

feat(dgw): persist agent tunnel authorization#1958
irvingouj@Devolutions (irvingoujAtDevolution) wants to merge 4 commits into
masterfrom
feat/agent-tunnel-identity-lifecycle

Conversation

@irvingoujAtDevolution

@irvingoujAtDevolution irvingouj@Devolutions (irvingoujAtDevolution) commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Persists accepted Agent identities and authorized public keys so deleting an Agent remains effective after Gateway restarts.

Gateway now admits tunnel connections only when the certificate Agent ID and SPKI match stored authorization. Deleting an Agent removes that authorization before closing its live tunnel connection, and management endpoints continue to list accepted Agents while offline.

Existing pre-stable Agents must be re-enrolled after upgrading.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

Record the human-owned authorization, enrollment, routing, and deletion contracts that the stable Agent Tunnel implementation must preserve.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Persist accepted Agent identities and public-key bindings so deletion
remains effective across Gateway restarts.

Gate tunnel admission on the stored identity and SPKI, close live
connections on deletion, and include offline accepted Agents in the
management endpoints.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@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 irvingouj@Devolutions (irvingoujAtDevolution) changed the title feat/agent tunnel identity lifecycle feat(dgw): persist agent tunnel authorization Aug 27, 2026
Acquire Agent authorization write transactions immediately to avoid
read-to-write upgrade failures under SQLite WAL contention.

Distinguish rejected credentials from authorization store failures and
close each connection with an explicit reason.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@irvingoujAtDevolution
irvingouj@Devolutions (irvingoujAtDevolution) marked this pull request as ready for review August 28, 2026 17:53
Copilot AI balanced review requested due to automatic review settings August 28, 2026 17:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds durable Agent tunnel authorization so enrollment, deletion, and identity-key validation survive Gateway restarts.

Changes:

  • Adds a CA-bound libSQL authorization store.
  • Enforces Agent ID/SPKI authorization and same-key certificate renewal.
  • Updates management APIs, documentation, and integration tests.

Reviewed changes

Copilot reviewed 18 out of 19 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
testsuite/tests/cli/agent/tunnel.rs Tests offline listing and durable deletion.
testsuite/tests/agent_tunnel/integration.rs Tests renewal key restrictions.
testsuite/tests/agent_tunnel/common.rs Adds authorization-aware test setup.
testsuite/Cargo.toml Adds test storage dependency.
docs/adr/0001-authorize-agent-identities-with-an-allowlist.md Records authorization design.
devolutions-gateway/tests/token_security.rs Allows enrollment-token retries.
devolutions-gateway/src/token.rs Delegates enrollment replay protection.
devolutions-gateway/src/service.rs Initializes persistent authorization storage.
devolutions-gateway/src/api/tunnel.rs Persists enrollment and exposes offline Agents.
devolutions-gateway/Cargo.toml Adds storage crate dependency.
crates/agent-tunnel/src/listener.rs Enforces authorization during tunnel admission.
crates/agent-tunnel/src/lib.rs Exports authorization interfaces.
crates/agent-tunnel/src/cert.rs Adds CA loading and SPKI helpers.
crates/agent-tunnel/src/authorization.rs Defines authorization-store contracts.
crates/agent-tunnel/agent-tunnel.intent.md Documents Agent tunnel intent.
crates/agent-tunnel-libsql/src/lib.rs Implements durable authorization storage.
crates/agent-tunnel-libsql/migrations/01_agent_authorization.sql Defines the initial schema.
crates/agent-tunnel-libsql/Cargo.toml Configures the new crate.
Cargo.lock Locks the new workspace package.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.


## Technical Background

#### Enrollment Process
Comment on lines +121 to +125
let outcome = handle
.enroll(agent_tunnel::authorization::EnrollmentAttempt {
token_id: jti,
token_expires_at: exp,
agent_id,
Comment on lines +312 to +316
let accepted = match authorization_store.authorize(agent_id, client_spki_sha256).await {
Ok(Some(accepted)) => accepted,
Ok(None) => {
warn!(%agent_id, %peer_addr, "Rejecting Agent connection: credential is not accepted");
conn.close(0u32.into(), b"agent-not-accepted");
Log the full Agent authorization error chain so operators can identify
the underlying database failure.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

2 participants