From 37d80a8ba45491ce41eee360eaf9ba2e0440a560 Mon Sep 17 00:00:00 2001 From: Rafly Date: Fri, 5 Jun 2026 14:49:00 +0700 Subject: [PATCH 1/5] feat: keep Windows RDP workspaces active during RDP sessions Issue #200 asks for Windows RDP sessions to prevent a workspace from stopping while a user is still connected through RDP. The existing windows-rdp module enabled Remote Desktop and Devolutions Gateway, but it did not report activity or extend the workspace deadline after the startup script completed. That meant an active RDP session could still be shut down by the normal workspace schedule. This change keeps the fix scoped to the registry module. It adds an opt-in-by-default PowerShell keepalive monitor that is installed by the existing startup script, checks for established local RDP connections on port 3389, and uses the workspace agent token to call Coder's documented workspace deadline extension endpoint. The monitor is written to ProgramData, logs to a module-specific log file, and the installer stops any previous monitor process before starting a new one so repeated starts do not stack duplicate loops. The Terraform surface is intentionally small: keepalive_enabled controls the feature, keepalive_interval_seconds controls how often the RDP connection check runs, and keepalive_extension_minutes controls how far ahead the deadline is extended. The extension window is validated at 30 minutes or more because Coder's server-side deadline validation rejects deadlines that are too close to the current time. Disabling keepalive removes the generated monitor script and leaves the rest of the Windows RDP module behavior unchanged. Tests now assert the rendered coder_script installs the monitor by default, includes the RDP connection detection logic, sends the Coder-Session-Token header, calls /api/v2/workspaces/{workspace}/extend with the deadline body, supports custom interval/extension values, and can disable the monitor cleanly. The README documents the new behavior, configuration variables, disable switch, and log path. Validation performed locally: bun test registry/coder/modules/windows-rdp/main.test.ts; terraform -chdir=registry/coder/modules/windows-rdp validate; bun x prettier --check registry/coder/modules/windows-rdp/README.md registry/coder/modules/windows-rdp/main.test.ts registry/coder/modules/windows-rdp/main.tf; terraform fmt -check -recursive registry/coder/modules/windows-rdp; PowerShell parser checks for rdp-keepalive.ps1.tftpl and powershell-installation-script.tftpl. AI-assisted with Codex. --- registry/coder/modules/windows-rdp/README.md | 34 ++++++++ .../coder/modules/windows-rdp/main.test.ts | 65 +++++++++++++++ registry/coder/modules/windows-rdp/main.tf | 36 ++++++++ .../powershell-installation-script.tftpl | 41 ++++++++++ .../windows-rdp/rdp-keepalive.ps1.tftpl | 82 +++++++++++++++++++ 5 files changed, 258 insertions(+) create mode 100644 registry/coder/modules/windows-rdp/rdp-keepalive.ps1.tftpl diff --git a/registry/coder/modules/windows-rdp/README.md b/registry/coder/modules/windows-rdp/README.md index 111e8d7fd..36d1e8503 100644 --- a/registry/coder/modules/windows-rdp/README.md +++ b/registry/coder/modules/windows-rdp/README.md @@ -59,3 +59,37 @@ module "windows_rdp" { devolutions_gateway_version = "2025.2.2" # Specify a specific version } ``` + +### RDP Keepalive + +The module starts a small PowerShell monitor that keeps the workspace active +while an RDP session is connected. The monitor checks for established local RDP +connections and extends the workspace deadline with the workspace agent token. +Coder requires extension deadlines to be at least 30 minutes in the future, so +the extension window must be 30 minutes or more. + +```tf +module "windows_rdp" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/windows-rdp/coder" + version = "1.3.0" + agent_id = coder_agent.main.id + keepalive_interval_seconds = 60 + keepalive_extension_minutes = 30 +} +``` + +To disable the monitor: + +```tf +module "windows_rdp" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/windows-rdp/coder" + version = "1.3.0" + agent_id = coder_agent.main.id + keepalive_enabled = false +} +``` + +The monitor log is written to +`C:\ProgramData\Coder\windows-rdp\rdp-keepalive.log`. diff --git a/registry/coder/modules/windows-rdp/main.test.ts b/registry/coder/modules/windows-rdp/main.test.ts index 80c09fd0d..1291617ba 100644 --- a/registry/coder/modules/windows-rdp/main.test.ts +++ b/registry/coder/modules/windows-rdp/main.test.ts @@ -11,6 +11,9 @@ type TestVariables = Readonly<{ share?: string; admin_username?: string; admin_password?: string; + keepalive_enabled?: boolean; + keepalive_interval_seconds?: number; + keepalive_extension_minutes?: number; }>; function findWindowsRdpScript(state: TerraformState): string | null { @@ -128,4 +131,66 @@ describe("Web RDP", async () => { expect(customResultsGroup.username).toBe(customAdminUsername); expect(customResultsGroup.password).toBe(customAdminPassword); }); + + it("Installs the RDP keepalive monitor by default", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "foo", + }); + + const rdpScript = findWindowsRdpScript(state); + expect(rdpScript).toBeString(); + expect(rdpScript).toContain("Install-RDPKeepaliveMonitor"); + expect(rdpScript).toContain( + '$keepaliveEnabled = [System.Convert]::ToBoolean("true")', + ); + expect(rdpScript).toContain( + 'Join-Path $env:ProgramData "Coder\\windows-rdp"', + ); + expect(rdpScript).toContain("Stop-RDPKeepaliveMonitor"); + expect(rdpScript).toContain( + 'Start-Process -FilePath "powershell.exe" -WindowStyle Hidden', + ); + expect(rdpScript).toContain("$intervalSeconds = 60"); + expect(rdpScript).toContain("$extensionMinutes = 30"); + expect(rdpScript).toContain( + "Get-NetTCPConnection -LocalPort 3389 -State Established", + ); + expect(rdpScript).toContain( + '"Coder-Session-Token" = $env:CODER_AGENT_TOKEN', + ); + expect(rdpScript).toContain( + '$uri = "$baseUrl/api/v2/workspaces/$workspaceId/extend"', + ); + expect(rdpScript).toContain( + 'Invoke-RestMethod -Method Put -Uri $uri -Headers $headers -ContentType "application/json" -Body $body', + ); + }); + + it("Customizes the RDP keepalive interval and extension window", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "foo", + keepalive_interval_seconds: 15, + keepalive_extension_minutes: 45, + }); + + const rdpScript = findWindowsRdpScript(state); + expect(rdpScript).toBeString(); + expect(rdpScript).toContain("$intervalSeconds = 15"); + expect(rdpScript).toContain("$extensionMinutes = 45"); + }); + + it("Can disable the RDP keepalive monitor", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "foo", + keepalive_enabled: false, + }); + + const rdpScript = findWindowsRdpScript(state); + expect(rdpScript).toBeString(); + expect(rdpScript).toContain( + '$keepaliveEnabled = [System.Convert]::ToBoolean("false")', + ); + expect(rdpScript).toContain("RDP keepalive disabled"); + expect(rdpScript).toContain("Remove-Item -Path $scriptPath -Force"); + }); }); diff --git a/registry/coder/modules/windows-rdp/main.tf b/registry/coder/modules/windows-rdp/main.tf index 3c83d195b..a5c113336 100644 --- a/registry/coder/modules/windows-rdp/main.tf +++ b/registry/coder/modules/windows-rdp/main.tf @@ -70,6 +70,36 @@ variable "devolutions_gateway_version" { description = "Version of Devolutions Gateway to install. Use 'latest' for the most recent version, or specify a version like '2025.3.2'." } +variable "keepalive_enabled" { + type = bool + default = true + description = "Whether to keep the workspace active while an RDP session is connected." +} + +variable "keepalive_interval_seconds" { + type = number + default = 60 + description = "How often the RDP keepalive monitor checks for active RDP sessions." + + validation { + condition = var.keepalive_interval_seconds >= 10 + error_message = "keepalive_interval_seconds must be at least 10 seconds." + } +} + +variable "keepalive_extension_minutes" { + type = number + default = 30 + description = "How far ahead to extend the workspace deadline when an RDP session is active." + + validation { + condition = var.keepalive_extension_minutes >= 30 + error_message = "keepalive_extension_minutes must be at least 30 minutes." + } +} + +data "coder_workspace" "me" {} + resource "coder_script" "windows-rdp" { agent_id = var.agent_id display_name = "windows-rdp" @@ -79,6 +109,12 @@ resource "coder_script" "windows-rdp" { admin_username = var.admin_username admin_password = var.admin_password devolutions_gateway_version = var.devolutions_gateway_version + keepalive_enabled = var.keepalive_enabled + keepalive_script_contents = templatefile("${path.module}/rdp-keepalive.ps1.tftpl", { + workspace_id = data.coder_workspace.me.id + interval_seconds = var.keepalive_interval_seconds + extension_minutes = var.keepalive_extension_minutes + }) # Wanted to have this be in the powershell template file, but Terraform # doesn't allow recursive calls to the templatefile function. Have to feed diff --git a/registry/coder/modules/windows-rdp/powershell-installation-script.tftpl b/registry/coder/modules/windows-rdp/powershell-installation-script.tftpl index 1657b878d..5d0c58d77 100644 --- a/registry/coder/modules/windows-rdp/powershell-installation-script.tftpl +++ b/registry/coder/modules/windows-rdp/powershell-installation-script.tftpl @@ -125,7 +125,48 @@ if ($isPatched -eq $null) { } } +function Stop-RDPKeepaliveMonitor { + param ( + [string]$scriptPath + ) + + Get-CimInstance Win32_Process -Filter "name = 'powershell.exe'" | + Where-Object { $_.CommandLine -and $_.CommandLine -like "*$scriptPath*" } | + ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue } +} + +function Install-RDPKeepaliveMonitor { +$keepaliveEnabled = [System.Convert]::ToBoolean("${keepalive_enabled}") +$keepaliveRoot = Join-Path $env:ProgramData "Coder\windows-rdp" +$scriptPath = Join-Path $keepaliveRoot "rdp-keepalive.ps1" +$logPath = Join-Path $keepaliveRoot "rdp-keepalive.log" + +New-Item -ItemType Directory -Path $keepaliveRoot -Force | Out-Null +Stop-RDPKeepaliveMonitor -scriptPath $scriptPath + +if (-not $keepaliveEnabled) { + if (Test-Path $scriptPath) { + Remove-Item -Path $scriptPath -Force + } + "RDP keepalive disabled" | Set-Content -Path $logPath + return +} + +@' +${keepalive_script_contents} +'@ | Set-Content -Path $scriptPath -Encoding UTF8 + +Start-Process -FilePath "powershell.exe" -WindowStyle Hidden -ArgumentList @( + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-File", + $scriptPath +) +} + Set-AdminPassword -adminPassword "${admin_password}" Configure-RDP Install-DevolutionsGateway Patch-Devolutions-HTML +Install-RDPKeepaliveMonitor diff --git a/registry/coder/modules/windows-rdp/rdp-keepalive.ps1.tftpl b/registry/coder/modules/windows-rdp/rdp-keepalive.ps1.tftpl new file mode 100644 index 000000000..ffb149d3f --- /dev/null +++ b/registry/coder/modules/windows-rdp/rdp-keepalive.ps1.tftpl @@ -0,0 +1,82 @@ +$ErrorActionPreference = "Continue" + +$workspaceId = "${workspace_id}" +$intervalSeconds = ${interval_seconds} +$extensionMinutes = ${extension_minutes} +$logPath = Join-Path $env:ProgramData "Coder\windows-rdp\rdp-keepalive.log" + +function Write-KeepaliveLog { + param ( + [string]$Message + ) + + $timestamp = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") + "$timestamp $Message" | Add-Content -Path $logPath +} + +function Test-RDPConnectionActive { + try { + $connections = @( + Get-NetTCPConnection -LocalPort 3389 -State Established -ErrorAction Stop + ) + + return $connections.Count -gt 0 + } + catch { + Write-KeepaliveLog "Unable to inspect RDP connections: $($_.Exception.Message)" + return $false + } +} + +function Get-CoderAgentBaseUrl { + if ([string]::IsNullOrWhiteSpace($env:CODER_AGENT_URL)) { + Write-KeepaliveLog "CODER_AGENT_URL is not available" + return $null + } + + return $env:CODER_AGENT_URL.TrimEnd([char]"/") +} + +function Invoke-CoderWorkspaceExtend { + if ([string]::IsNullOrWhiteSpace($env:CODER_AGENT_TOKEN)) { + Write-KeepaliveLog "CODER_AGENT_TOKEN is not available" + return + } + + if ([string]::IsNullOrWhiteSpace($workspaceId)) { + Write-KeepaliveLog "workspace id is not available" + return + } + + $baseUrl = Get-CoderAgentBaseUrl + if ([string]::IsNullOrWhiteSpace($baseUrl)) { + return + } + + $deadline = (Get-Date).ToUniversalTime().AddMinutes($extensionMinutes).ToString("yyyy-MM-ddTHH:mm:ssZ") + $uri = "$baseUrl/api/v2/workspaces/$workspaceId/extend" + $headers = @{ + "Coder-Session-Token" = $env:CODER_AGENT_TOKEN + } + $body = @{ + deadline = $deadline + } | ConvertTo-Json -Compress + + try { + Invoke-RestMethod -Method Put -Uri $uri -Headers $headers -ContentType "application/json" -Body $body | Out-Null + Write-KeepaliveLog "Extended workspace deadline to $deadline" + } + catch { + Write-KeepaliveLog "Unable to extend workspace deadline: $($_.Exception.Message)" + } +} + +Write-KeepaliveLog "Starting Coder RDP keepalive monitor for workspace $workspaceId" + +while ($true) { + if (Test-RDPConnectionActive) { + Invoke-CoderWorkspaceExtend + } + + Start-Sleep -Seconds $intervalSeconds +} From 6b35bc2521dc835d574d67209a475c5c42bf4934 Mon Sep 17 00:00:00 2001 From: Rafly Date: Fri, 5 Jun 2026 17:04:46 +0700 Subject: [PATCH 2/5] fix: treat missing RDP connections as idle The keepalive monitor should only extend the workspace while an established local RDP connection exists. During demo verification, the no-connection path correctly skipped the extend request, but PowerShell logged the absence of matching TCP connections as an inspection error because Get-NetTCPConnection used ErrorAction Stop. Use ErrorAction SilentlyContinue for the normal idle case so a disconnected workspace remains quiet while still returning false from Test-RDPConnectionActive. The test now asserts the rendered script uses the idle-safe connection query. Validation performed locally: bun test registry/coder/modules/windows-rdp/main.test.ts; terraform -chdir=registry/coder/modules/windows-rdp validate; prettier check for changed formatted files; terraform fmt check for the module; PowerShell parser check for rdp-keepalive.ps1.tftpl. --- registry/coder/modules/windows-rdp/main.test.ts | 2 +- registry/coder/modules/windows-rdp/rdp-keepalive.ps1.tftpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/registry/coder/modules/windows-rdp/main.test.ts b/registry/coder/modules/windows-rdp/main.test.ts index 1291617ba..269e698d4 100644 --- a/registry/coder/modules/windows-rdp/main.test.ts +++ b/registry/coder/modules/windows-rdp/main.test.ts @@ -153,7 +153,7 @@ describe("Web RDP", async () => { expect(rdpScript).toContain("$intervalSeconds = 60"); expect(rdpScript).toContain("$extensionMinutes = 30"); expect(rdpScript).toContain( - "Get-NetTCPConnection -LocalPort 3389 -State Established", + "Get-NetTCPConnection -LocalPort 3389 -State Established -ErrorAction SilentlyContinue", ); expect(rdpScript).toContain( '"Coder-Session-Token" = $env:CODER_AGENT_TOKEN', diff --git a/registry/coder/modules/windows-rdp/rdp-keepalive.ps1.tftpl b/registry/coder/modules/windows-rdp/rdp-keepalive.ps1.tftpl index ffb149d3f..051c76587 100644 --- a/registry/coder/modules/windows-rdp/rdp-keepalive.ps1.tftpl +++ b/registry/coder/modules/windows-rdp/rdp-keepalive.ps1.tftpl @@ -17,7 +17,7 @@ function Write-KeepaliveLog { function Test-RDPConnectionActive { try { $connections = @( - Get-NetTCPConnection -LocalPort 3389 -State Established -ErrorAction Stop + Get-NetTCPConnection -LocalPort 3389 -State Established -ErrorAction SilentlyContinue ) return $connections.Count -gt 0 From a84b8a56a41b924fd39aac854df55677e875aa14 Mon Sep 17 00:00:00 2001 From: Rafly Date: Fri, 5 Jun 2026 22:14:58 +0700 Subject: [PATCH 3/5] feat(windows-rdp): allow configuring scoped keepalive_coder_session_token --- registry/coder/modules/windows-rdp/README.md | 14 +++++++++++ .../coder/modules/windows-rdp/main.test.ts | 23 +++++++++++++++++- registry/coder/modules/windows-rdp/main.tf | 14 ++++++++--- .../windows-rdp/rdp-keepalive.ps1.tftpl | 24 +++++++++++++++---- 4 files changed, 66 insertions(+), 9 deletions(-) diff --git a/registry/coder/modules/windows-rdp/README.md b/registry/coder/modules/windows-rdp/README.md index 36d1e8503..655391444 100644 --- a/registry/coder/modules/windows-rdp/README.md +++ b/registry/coder/modules/windows-rdp/README.md @@ -79,6 +79,20 @@ module "windows_rdp" { } ``` +If your Coder deployment does not allow the workspace agent token to update the +workspace deadline, provide a scoped Coder token with permission to update the +workspace: + +```tf +module "windows_rdp" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/windows-rdp/coder" + version = "1.3.0" + agent_id = coder_agent.main.id + keepalive_coder_session_token = var.rdp_keepalive_coder_session_token +} +``` + To disable the monitor: ```tf diff --git a/registry/coder/modules/windows-rdp/main.test.ts b/registry/coder/modules/windows-rdp/main.test.ts index 269e698d4..bbd25ce93 100644 --- a/registry/coder/modules/windows-rdp/main.test.ts +++ b/registry/coder/modules/windows-rdp/main.test.ts @@ -14,6 +14,7 @@ type TestVariables = Readonly<{ keepalive_enabled?: boolean; keepalive_interval_seconds?: number; keepalive_extension_minutes?: number; + keepalive_coder_session_token?: string; }>; function findWindowsRdpScript(state: TerraformState): string | null { @@ -156,7 +157,10 @@ describe("Web RDP", async () => { "Get-NetTCPConnection -LocalPort 3389 -State Established -ErrorAction SilentlyContinue", ); expect(rdpScript).toContain( - '"Coder-Session-Token" = $env:CODER_AGENT_TOKEN', + 'if (-not [string]::IsNullOrWhiteSpace($env:CODER_AGENT_TOKEN))', + ); + expect(rdpScript).toContain( + '"Coder-Session-Token" = $sessionToken', ); expect(rdpScript).toContain( '$uri = "$baseUrl/api/v2/workspaces/$workspaceId/extend"', @@ -166,6 +170,23 @@ describe("Web RDP", async () => { ); }); + it("Can use an explicit Coder session token for RDP keepalive", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "foo", + keepalive_coder_session_token: "test-session-token", + }); + + const rdpScript = findWindowsRdpScript(state); + expect(rdpScript).toBeString(); + expect(rdpScript).toContain( + '$configuredSessionToken = "test-session-token"', + ); + expect(rdpScript).toContain( + 'if (-not [string]::IsNullOrWhiteSpace($configuredSessionToken))', + ); + expect(rdpScript).toContain("return $configuredSessionToken"); + }); + it("Customizes the RDP keepalive interval and extension window", async () => { const state = await runTerraformApply(import.meta.dir, { agent_id: "foo", diff --git a/registry/coder/modules/windows-rdp/main.tf b/registry/coder/modules/windows-rdp/main.tf index a5c113336..5946e6807 100644 --- a/registry/coder/modules/windows-rdp/main.tf +++ b/registry/coder/modules/windows-rdp/main.tf @@ -98,6 +98,13 @@ variable "keepalive_extension_minutes" { } } +variable "keepalive_coder_session_token" { + type = string + default = null + sensitive = true + description = "Optional Coder session or API token used to extend the workspace deadline. If unset, the monitor uses CODER_AGENT_TOKEN." +} + data "coder_workspace" "me" {} resource "coder_script" "windows-rdp" { @@ -111,9 +118,10 @@ resource "coder_script" "windows-rdp" { devolutions_gateway_version = var.devolutions_gateway_version keepalive_enabled = var.keepalive_enabled keepalive_script_contents = templatefile("${path.module}/rdp-keepalive.ps1.tftpl", { - workspace_id = data.coder_workspace.me.id - interval_seconds = var.keepalive_interval_seconds - extension_minutes = var.keepalive_extension_minutes + workspace_id = data.coder_workspace.me.id + interval_seconds = var.keepalive_interval_seconds + extension_minutes = var.keepalive_extension_minutes + coder_session_token = var.keepalive_coder_session_token != null ? var.keepalive_coder_session_token : "" }) # Wanted to have this be in the powershell template file, but Terraform diff --git a/registry/coder/modules/windows-rdp/rdp-keepalive.ps1.tftpl b/registry/coder/modules/windows-rdp/rdp-keepalive.ps1.tftpl index 051c76587..9e76194fd 100644 --- a/registry/coder/modules/windows-rdp/rdp-keepalive.ps1.tftpl +++ b/registry/coder/modules/windows-rdp/rdp-keepalive.ps1.tftpl @@ -3,6 +3,7 @@ $ErrorActionPreference = "Continue" $workspaceId = "${workspace_id}" $intervalSeconds = ${interval_seconds} $extensionMinutes = ${extension_minutes} +$configuredSessionToken = "${coder_session_token}" $logPath = Join-Path $env:ProgramData "Coder\windows-rdp\rdp-keepalive.log" function Write-KeepaliveLog { @@ -37,12 +38,20 @@ function Get-CoderAgentBaseUrl { return $env:CODER_AGENT_URL.TrimEnd([char]"/") } -function Invoke-CoderWorkspaceExtend { - if ([string]::IsNullOrWhiteSpace($env:CODER_AGENT_TOKEN)) { - Write-KeepaliveLog "CODER_AGENT_TOKEN is not available" - return +function Get-CoderSessionToken { + if (-not [string]::IsNullOrWhiteSpace($configuredSessionToken)) { + return $configuredSessionToken } + if (-not [string]::IsNullOrWhiteSpace($env:CODER_AGENT_TOKEN)) { + return $env:CODER_AGENT_TOKEN + } + + Write-KeepaliveLog "No Coder session token is available" + return $null +} + +function Invoke-CoderWorkspaceExtend { if ([string]::IsNullOrWhiteSpace($workspaceId)) { Write-KeepaliveLog "workspace id is not available" return @@ -53,10 +62,15 @@ function Invoke-CoderWorkspaceExtend { return } + $sessionToken = Get-CoderSessionToken + if ([string]::IsNullOrWhiteSpace($sessionToken)) { + return + } + $deadline = (Get-Date).ToUniversalTime().AddMinutes($extensionMinutes).ToString("yyyy-MM-ddTHH:mm:ssZ") $uri = "$baseUrl/api/v2/workspaces/$workspaceId/extend" $headers = @{ - "Coder-Session-Token" = $env:CODER_AGENT_TOKEN + "Coder-Session-Token" = $sessionToken } $body = @{ deadline = $deadline From 95da927008e43eb03dd17220a1023741f4082c93 Mon Sep 17 00:00:00 2001 From: Rafly Date: Fri, 5 Jun 2026 22:53:50 +0700 Subject: [PATCH 4/5] refactor(windows-rdp): use env:CODER_SESSION_TOKEN from coder-login instead of tf variable --- registry/coder/modules/windows-rdp/README.md | 19 +++++++++++------- .../coder/modules/windows-rdp/main.test.ts | 20 +++---------------- registry/coder/modules/windows-rdp/main.tf | 7 ------- .../windows-rdp/rdp-keepalive.ps1.tftpl | 5 ++--- 4 files changed, 17 insertions(+), 34 deletions(-) diff --git a/registry/coder/modules/windows-rdp/README.md b/registry/coder/modules/windows-rdp/README.md index 655391444..2e528f214 100644 --- a/registry/coder/modules/windows-rdp/README.md +++ b/registry/coder/modules/windows-rdp/README.md @@ -80,16 +80,21 @@ module "windows_rdp" { ``` If your Coder deployment does not allow the workspace agent token to update the -workspace deadline, provide a scoped Coder token with permission to update the -workspace: +workspace deadline, use the `coder-login` module alongside `windows-rdp`. The `coder-login` module injects a scoped token into the `CODER_SESSION_TOKEN` environment variable, which the keepalive monitor will automatically use if present: ```tf +module "coder-login" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/coder-login/coder" + version = "1.1.1" + agent_id = coder_agent.main.id +} + module "windows_rdp" { - count = data.coder_workspace.me.start_count - source = "registry.coder.com/coder/windows-rdp/coder" - version = "1.3.0" - agent_id = coder_agent.main.id - keepalive_coder_session_token = var.rdp_keepalive_coder_session_token + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/windows-rdp/coder" + version = "1.3.0" + agent_id = coder_agent.main.id } ``` diff --git a/registry/coder/modules/windows-rdp/main.test.ts b/registry/coder/modules/windows-rdp/main.test.ts index bbd25ce93..30a0cd417 100644 --- a/registry/coder/modules/windows-rdp/main.test.ts +++ b/registry/coder/modules/windows-rdp/main.test.ts @@ -14,7 +14,6 @@ type TestVariables = Readonly<{ keepalive_enabled?: boolean; keepalive_interval_seconds?: number; keepalive_extension_minutes?: number; - keepalive_coder_session_token?: string; }>; function findWindowsRdpScript(state: TerraformState): string | null { @@ -156,6 +155,9 @@ describe("Web RDP", async () => { expect(rdpScript).toContain( "Get-NetTCPConnection -LocalPort 3389 -State Established -ErrorAction SilentlyContinue", ); + expect(rdpScript).toContain( + 'if (-not [string]::IsNullOrWhiteSpace($env:CODER_SESSION_TOKEN))', + ); expect(rdpScript).toContain( 'if (-not [string]::IsNullOrWhiteSpace($env:CODER_AGENT_TOKEN))', ); @@ -170,22 +172,6 @@ describe("Web RDP", async () => { ); }); - it("Can use an explicit Coder session token for RDP keepalive", async () => { - const state = await runTerraformApply(import.meta.dir, { - agent_id: "foo", - keepalive_coder_session_token: "test-session-token", - }); - - const rdpScript = findWindowsRdpScript(state); - expect(rdpScript).toBeString(); - expect(rdpScript).toContain( - '$configuredSessionToken = "test-session-token"', - ); - expect(rdpScript).toContain( - 'if (-not [string]::IsNullOrWhiteSpace($configuredSessionToken))', - ); - expect(rdpScript).toContain("return $configuredSessionToken"); - }); it("Customizes the RDP keepalive interval and extension window", async () => { const state = await runTerraformApply(import.meta.dir, { diff --git a/registry/coder/modules/windows-rdp/main.tf b/registry/coder/modules/windows-rdp/main.tf index 5946e6807..5f7752d1d 100644 --- a/registry/coder/modules/windows-rdp/main.tf +++ b/registry/coder/modules/windows-rdp/main.tf @@ -98,12 +98,6 @@ variable "keepalive_extension_minutes" { } } -variable "keepalive_coder_session_token" { - type = string - default = null - sensitive = true - description = "Optional Coder session or API token used to extend the workspace deadline. If unset, the monitor uses CODER_AGENT_TOKEN." -} data "coder_workspace" "me" {} @@ -121,7 +115,6 @@ resource "coder_script" "windows-rdp" { workspace_id = data.coder_workspace.me.id interval_seconds = var.keepalive_interval_seconds extension_minutes = var.keepalive_extension_minutes - coder_session_token = var.keepalive_coder_session_token != null ? var.keepalive_coder_session_token : "" }) # Wanted to have this be in the powershell template file, but Terraform diff --git a/registry/coder/modules/windows-rdp/rdp-keepalive.ps1.tftpl b/registry/coder/modules/windows-rdp/rdp-keepalive.ps1.tftpl index 9e76194fd..72c773f4c 100644 --- a/registry/coder/modules/windows-rdp/rdp-keepalive.ps1.tftpl +++ b/registry/coder/modules/windows-rdp/rdp-keepalive.ps1.tftpl @@ -3,7 +3,6 @@ $ErrorActionPreference = "Continue" $workspaceId = "${workspace_id}" $intervalSeconds = ${interval_seconds} $extensionMinutes = ${extension_minutes} -$configuredSessionToken = "${coder_session_token}" $logPath = Join-Path $env:ProgramData "Coder\windows-rdp\rdp-keepalive.log" function Write-KeepaliveLog { @@ -39,8 +38,8 @@ function Get-CoderAgentBaseUrl { } function Get-CoderSessionToken { - if (-not [string]::IsNullOrWhiteSpace($configuredSessionToken)) { - return $configuredSessionToken + if (-not [string]::IsNullOrWhiteSpace($env:CODER_SESSION_TOKEN)) { + return $env:CODER_SESSION_TOKEN } if (-not [string]::IsNullOrWhiteSpace($env:CODER_AGENT_TOKEN)) { From 79a310e1ba10e0eda3e9b5cf7594a5359c142dd5 Mon Sep 17 00:00:00 2001 From: Rafly Date: Fri, 5 Jun 2026 22:56:38 +0700 Subject: [PATCH 5/5] style: remove extra blank lines --- registry/coder/modules/windows-rdp/main.test.ts | 1 - registry/coder/modules/windows-rdp/main.tf | 1 - 2 files changed, 2 deletions(-) diff --git a/registry/coder/modules/windows-rdp/main.test.ts b/registry/coder/modules/windows-rdp/main.test.ts index 30a0cd417..eeef81d7c 100644 --- a/registry/coder/modules/windows-rdp/main.test.ts +++ b/registry/coder/modules/windows-rdp/main.test.ts @@ -172,7 +172,6 @@ describe("Web RDP", async () => { ); }); - it("Customizes the RDP keepalive interval and extension window", async () => { const state = await runTerraformApply(import.meta.dir, { agent_id: "foo", diff --git a/registry/coder/modules/windows-rdp/main.tf b/registry/coder/modules/windows-rdp/main.tf index 5f7752d1d..3c1a3e54f 100644 --- a/registry/coder/modules/windows-rdp/main.tf +++ b/registry/coder/modules/windows-rdp/main.tf @@ -98,7 +98,6 @@ variable "keepalive_extension_minutes" { } } - data "coder_workspace" "me" {} resource "coder_script" "windows-rdp" {