Skip to content

Commit ae56597

Browse files
fix(agent-tunnel): address Copilot review on PR #1773
- EnrollmentClaims: override GetDefaultLifetime() to 3600s (was 300s). The operator copy/paste flow easily exceeds 5 minutes; the old EnrollmentTokenStore had a 1h default for the same reason. - api/tunnel.rs: return 403 instead of 404 when JWT validation fails and no static enrollment_secret is configured. The user's token is unauthenticated, not a server-config issue. 404 stays for the case where the agent tunnel feature is fully disabled. - extract.rs: sync top-level rustdoc on AgentManagementReadAccess to list AgentRead alongside the existing back-compat scopes.
1 parent a55e6e9 commit ae56597

3 files changed

Lines changed: 20 additions & 2 deletions

File tree

devolutions-gateway/src/api/tunnel.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,16 @@ async fn enroll_agent(
145145
let jwt_valid = validate_enrollment_jwt(provided_token, &conf.provisioner_public_key);
146146

147147
if !jwt_valid {
148+
// The JWT failed to validate against the provisioner key. The static
149+
// `enrollment_secret` is only a fallback for environments without DVLS;
150+
// when it is not configured, the request is simply unauthenticated, not
151+
// a server-config issue — so 403, not 404 (404 is reserved for the agent
152+
// tunnel feature itself being disabled).
148153
let enrollment_secret = conf
149154
.agent_tunnel
150155
.enrollment_secret
151156
.as_deref()
152-
.ok_or_else(|| HttpError::not_found().msg("agent enrollment is not configured"))?;
157+
.ok_or_else(|| HttpError::forbidden().msg("invalid enrollment token"))?;
153158

154159
if !timing_safe_eq(provided_token.as_bytes(), enrollment_secret.as_bytes()) {
155160
return Err(HttpError::forbidden().msg("invalid enrollment token"));

devolutions-gateway/src/extract.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,9 @@ where
408408

409409
/// Grants read access to agent management endpoints.
410410
///
411-
/// Accepts a scope token with `DiagnosticsRead`, `ConfigWrite`, or `Wildcard` scope.
411+
/// Accepts a scope token with `AgentRead`, `DiagnosticsRead`, `ConfigWrite`, or
412+
/// `Wildcard` scope. `DiagnosticsRead` / `ConfigWrite` are kept for
413+
/// back-compat with callers that predate the dedicated `AgentRead` scope.
412414
#[derive(Clone, Copy)]
413415
pub struct AgentManagementReadAccess;
414416

utils/dotnet/Devolutions.Gateway.Utils/src/EnrollmentClaims.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,15 @@ public string GetContentType()
5555
{
5656
return "ENROLLMENT";
5757
}
58+
59+
/// <summary>
60+
/// One hour. The operator typically generates the enrollment string in
61+
/// the admin UI, copies it, walks to the target machine, installs the
62+
/// agent, and pastes it — the 5-minute interface default is too short
63+
/// for that flow. Callers can still override via <c>TokenUtils.Sign</c>.
64+
/// </summary>
65+
public long? GetDefaultLifetime()
66+
{
67+
return 3600;
68+
}
5869
}

0 commit comments

Comments
 (0)