diff --git a/windows-rdp/README.md b/windows-rdp/README.md index 5d86082..a050854 100644 --- a/windows-rdp/README.md +++ b/windows-rdp/README.md @@ -19,17 +19,11 @@ module "windows_rdp" { agent_id = resource.coder_agent.main.id resource_id = resource.aws_instance.dev.id } -module "windows_rdp" { - count = data.coder_workspace.me.start_count - source = "github.com/coder/modules//windows-rdp" - agent_id = resource.coder_agent.main.id - resource_id = resource.google_compute_instance.dev[0].id -} ``` ## Video -<-- Insert demo video here --> +https://github.com/coder/modules/assets/28937484/fb5f4a55-7b69-4550-ab62-301e13a4be02 ## Examples diff --git a/windows-rdp/devolutions-patch.js b/windows-rdp/devolutions-patch.js index a1e9da4..020a40f 100644 --- a/windows-rdp/devolutions-patch.js +++ b/windows-rdp/devolutions-patch.js @@ -12,11 +12,10 @@ * - A lot of the HTML selectors in this file will look nonstandard. This is * because they are actually custom Angular components. * - It is strongly advised that you avoid template literals that use the - * placeholder syntax via the dollar sign. The Terraform script looks for - * these characters so that it can inject Coder-specific values, so any - * template literal that uses the character actually needs to double up each - * of them. There are already a few places in this file where it couldn't be - * avoided, but avoiding this as much as possible will save you some headache. + * placeholder syntax via the dollar sign. The Terraform file is treating this + * as a template file, and because it also uses a similar syntax, there's a + * risk that some values will trigger false positives. If a template literal + * must be used, be sure to use a double dollar sign to escape things. * - All the CSS should be written via custom style tags and the !important * directive (as much as that is a bad idea most of the time). We do not * control the Angular app, so we have to modify things from afar to ensure diff --git a/windows-rdp/main.tf b/windows-rdp/main.tf index f3ecba3..563e10f 100644 --- a/windows-rdp/main.tf +++ b/windows-rdp/main.tf @@ -34,89 +34,21 @@ resource "coder_script" "windows-rdp" { agent_id = var.agent_id display_name = "windows-rdp" icon = "https://svgur.com/i/158F.svg" # TODO: add to Coder icons - script = <', "$patch") | Set-Content $devolutionsHtml - } - } + script = templatefile("${path.module}/powershell-installation-script.tftpl", { + admin_username = var.admin_username + admin_password = var.admin_password - Set-AdminPassword -adminPassword "${var.admin_password}" - Configure-RDP - Install-DevolutionsGateway - Patch-Devolutions-HTML + # Wanted to have this be in the powershell template file, but Terraform + # doesn't allow recursive calls to the templatefile function. Have to feed + # results of the JS template replace into the powershell template + patch_file_contents = templatefile("${path.module}/devolutions-patch.js", { + CODER_USERNAME = var.admin_username + CODER_PASSWORD = var.admin_password + }) + }) - EOF - -run_on_start = true + run_on_start = true } resource "coder_app" "windows-rdp" { @@ -142,26 +74,3 @@ resource "coder_app" "rdp-docs" { url = "https://coder.com/docs/v2/latest/ides/remote-desktops#rdp-desktop" external = true } - -# For some reason this is not rendering, commented out for now -# resource "coder_metadata" "rdp_details" { -# resource_id = var.resource_id -# daily_cost = 0 -# item { -# key = "Host" -# value = "localhost" -# } -# item { -# key = "Port" -# value = "3389" -# } -# item { -# key = "Username" -# value = "Administrator" -# } -# item { -# key = "Password" -# value = var.admin_password -# sensitive = true -# } -# } diff --git a/windows-rdp/powershell-installation-script.tftpl b/windows-rdp/powershell-installation-script.tftpl new file mode 100644 index 0000000..1b7ab48 --- /dev/null +++ b/windows-rdp/powershell-installation-script.tftpl @@ -0,0 +1,85 @@ +function Set-AdminPassword { + param ( + [string]$adminPassword + ) + # Set admin password + Get-LocalUser -Name "${admin_username}" | Set-LocalUser -Password (ConvertTo-SecureString -AsPlainText $adminPassword -Force) + # Enable admin user + Get-LocalUser -Name "${admin_username}" | Enable-LocalUser +} + +function Configure-RDP { + # Enable RDP + New-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -Name "fDenyTSConnections" -Value 0 -PropertyType DWORD -Force + # Disable NLA + New-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name "UserAuthentication" -Value 0 -PropertyType DWORD -Force + New-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name "SecurityLayer" -Value 1 -PropertyType DWORD -Force + # Enable RDP through Windows Firewall + Enable-NetFirewallRule -DisplayGroup "Remote Desktop" +} + +function Install-DevolutionsGateway { +# Define the module name and version +$moduleName = "DevolutionsGateway" +$moduleVersion = "2024.1.5" + +# Install the module with the specified version for all users +# This requires administrator privileges +try { + # Install-PackageProvider is required for AWS. Need to set command to + # terminate on failure so that try/catch actually triggers + Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -ErrorAction Stop + Install-Module -Name $moduleName -RequiredVersion $moduleVersion -Force +} +catch { + # If the first command failed, assume that we're on GCP and run + # Install-Module only + Install-Module -Name $moduleName -RequiredVersion $moduleVersion -Force +} + +# Construct the module path for system-wide installation +$moduleBasePath = "C:\Windows\system32\config\systemprofile\Documents\PowerShell\Modules\$moduleName\$moduleVersion" +$modulePath = Join-Path -Path $moduleBasePath -ChildPath "$moduleName.psd1" + +# Import the module using the full path +Import-Module $modulePath +Install-DGatewayPackage + +# Configure Devolutions Gateway +$Hostname = "localhost" +$HttpListener = New-DGatewayListener 'http://*:7171' 'http://*:7171' +$WebApp = New-DGatewayWebAppConfig -Enabled $true -Authentication None +$ConfigParams = @{ + Hostname = $Hostname + Listeners = @($HttpListener) + WebApp = $WebApp +} +Set-DGatewayConfig @ConfigParams +New-DGatewayProvisionerKeyPair -Force + +# Configure and start the Windows service +Set-Service 'DevolutionsGateway' -StartupType 'Automatic' +Start-Service 'DevolutionsGateway' +} + +function Patch-Devolutions-HTML { +$root = "C:\Program Files\Devolutions\Gateway\webapp\client" +$devolutionsHtml = "$root\index.html" +$patch = '' + +# Always copy the file in case we change it. +@' +${patch_file_contents} +'@ | Set-Content "$root\coder.js" + +# Only inject the src if we have not before. +$isPatched = Select-String -Path "$devolutionsHtml" -Pattern "$patch" -SimpleMatch +if ($isPatched -eq $null) { + (Get-Content $devolutionsHtml).Replace('', "$patch") | Set-Content $devolutionsHtml +} +} + +Set-AdminPassword -adminPassword "${admin_password}" +Configure-RDP +Install-DevolutionsGateway +Patch-Devolutions-HTML