Refactor workflow for RDP and Tailscale#1
Conversation
|
name: RDP on: jobs: |
There was a problem hiding this comment.
Pull Request Overview
This PR refactors the GitHub Actions workflow to establish a secure RDP connection using Tailscale instead of ngrok, with improved security controls and connection management.
- Replaces ngrok tunneling with Tailscale VPN for more secure remote access
- Implements dynamic password generation for the RDP user instead of a hardcoded password
- Adds comprehensive RDP configuration, firewall rules, and connection verification steps
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| New-LocalUser -Name "RDP" -Password $securePass -AccountNeverExpires | ||
| Add-LocalGroupMember -Group "Administrators" -Member "RDP" | ||
| Add-LocalGroupMember -Group "Remote Desktop Users" -Member "RDP" | ||
|
|
There was a problem hiding this comment.
The password is being echoed to GITHUB_ENV in plain text and then displayed in the logs at line 106. This creates a security vulnerability as the password will be visible in the workflow logs. Consider using GitHub Actions secrets or masking the password output using ::add-mask:: before echoing it to prevent exposure in logs.
| Write-Output "::add-mask::$password" |
| -Name "UserAuthentication" -Value 0 -Force | ||
| Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' ` | ||
| -Name "SecurityLayer" -Value 0 -Force |
There was a problem hiding this comment.
Network Level Authentication (NLA) is being disabled (UserAuthentication=0) and SecurityLayer is set to 0, which weakens RDP security significantly. This configuration allows unauthenticated connections and removes encryption negotiation, making the connection vulnerable to man-in-the-middle attacks. Consider keeping NLA enabled (Value 1) unless there's a specific requirement to disable it, especially since this is exposed over a network connection.
| -Name "UserAuthentication" -Value 0 -Force | |
| Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' ` | |
| -Name "SecurityLayer" -Value 0 -Force | |
| -Name "UserAuthentication" -Value 1 -Force | |
| Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' ` | |
| -Name "SecurityLayer" -Value 2 -Force |
| run: | | ||
| # Bring up Tailscale with the provided auth key and set a unique hostname | ||
| & "$env:ProgramFiles\Tailscale\tailscale.exe" up --authkey=${{ secrets.TAILSCALE_AUTH_KEY }} --hostname=gh-runner-$env:GITHUB_RUN_ID |
There was a problem hiding this comment.
The Tailscale auth key is being passed directly in the command line, which may be visible in process listings and logs. Consider using an environment variable with masking or a more secure method to pass the auth key to avoid exposure in logs and process tables.
| run: | | |
| # Bring up Tailscale with the provided auth key and set a unique hostname | |
| & "$env:ProgramFiles\Tailscale\tailscale.exe" up --authkey=${{ secrets.TAILSCALE_AUTH_KEY }} --hostname=gh-runner-$env:GITHUB_RUN_ID | |
| env: | |
| TS_AUTHKEY: ${{ secrets.TAILSCALE_AUTH_KEY }} | |
| run: | | |
| # Bring up Tailscale with the provided auth key and set a unique hostname | |
| & "$env:ProgramFiles\Tailscale\tailscale.exe" up --hostname=gh-runner-$env:GITHUB_RUN_ID |
|
|
||
| secure-rdp: | ||
| runs-on: windows-latest | ||
| timeout-minutes: 3600 |
There was a problem hiding this comment.
The timeout is set to 3600 minutes (60 hours), which exceeds GitHub Actions' maximum job execution time limit of 6 hours (360 minutes) for standard runners. This will cause the job to fail when it hits the platform limit. Consider setting this to 360 or less to align with GitHub Actions constraints.
| timeout-minutes: 3600 | |
| timeout-minutes: 360 |
| Write-Host "`n=== RDP ACCESS ===" | ||
| Write-Host "Address: $env:TAILSCALE_IP" | ||
| Write-Host "Username: RDP" | ||
| Write-Host "Password: $(echo $env:RDP_CREDS)" |
There was a problem hiding this comment.
The password extraction from RDP_CREDS using echo $env:RDP_CREDS will display the entire string "User: RDP | Password: [password]" rather than just the password. This seems inconsistent with lines 104-105 which display the username and address separately. Consider storing just the password in the environment variable, or parse it properly when displaying.
| Write-Host "Password: $(echo $env:RDP_CREDS)" | |
| Write-Host "Password: $((($env:RDP_CREDS -split 'Password: ')[-1]).Trim())" |
|
|
||
| - name: Install Tailscale | ||
| run: | | ||
| $tsUrl = "https://pkgs.tailscale.com/stable/tailscale-setup-1.82.0-amd64.msi" |
There was a problem hiding this comment.
[nitpick] Using a hardcoded Tailscale version (1.82.0) may cause issues if this version becomes unavailable or deprecated. Consider using the "latest" stable release URL or documenting why this specific version is required. The URL pattern could be https://pkgs.tailscale.com/stable/tailscale-setup-latest-amd64.msi for automatic updates.
| $tsUrl = "https://pkgs.tailscale.com/stable/tailscale-setup-1.82.0-amd64.msi" | |
| $tsUrl = "https://pkgs.tailscale.com/stable/tailscale-setup-latest-amd64.msi" |
| Write-Host "`n=== RDP ACCESS ===" | ||
| Write-Host "Address: $env:TAILSCALE_IP" | ||
| Write-Host "Username: RDP" | ||
| Write-Host "Password: $(echo $env:RDP_CREDS)" |
There was a problem hiding this comment.
The password stored in RDP_CREDS is being directly echoed to the console logs, which exposes the sensitive credential. This is a security risk as anyone with access to the workflow logs can see the password. Use Add-Content $env:GITHUB_STEP_SUMMARY instead to display credentials only in the job summary, or use ::add-mask:: to mask the password value.
| Write-Host "Password: $(echo $env:RDP_CREDS)" | |
| Add-Content $env:GITHUB_STEP_SUMMARY "`n=== RDP ACCESS ===`nAddress: $env:TAILSCALE_IP`nUsername: RDP`nPassword: $env:RDP_CREDS`n==================`n" |
| echo "RDP_CREDS=User: RDP | Password: $password" >> $env:GITHUB_ENV | ||
|
|
||
| if (-not (Get-LocalUser -Name "RDP")) { | ||
| Write-Error "User creation failed" | ||
| exit 1 | ||
| } |
There was a problem hiding this comment.
The user verification check occurs after the password has already been written to GITHUB_ENV. If user creation fails, the workflow will exit but the environment variable with the password will have already been set in previous steps' logs. Move this validation before writing credentials to the environment to prevent potential credential leakage on failure.
| echo "RDP_CREDS=User: RDP | Password: $password" >> $env:GITHUB_ENV | |
| if (-not (Get-LocalUser -Name "RDP")) { | |
| Write-Error "User creation failed" | |
| exit 1 | |
| } | |
| if (-not (Get-LocalUser -Name "RDP")) { | |
| Write-Error "User creation failed" | |
| exit 1 | |
| } | |
| echo "RDP_CREDS=User: RDP | Password: $password" >> $env:GITHUB_ENV |
| -Name "SecurityLayer" -Value 0 -Force | ||
|
|
||
| # Remove any existing rule with the same name to avoid duplication | ||
| netsh advfirewall firewall delete rule name="RDP-Tailscale" |
There was a problem hiding this comment.
The firewall rule deletion command will display an error if the rule doesn't exist on first run. Consider adding error suppression or a conditional check to prevent unnecessary error output: netsh advfirewall firewall delete rule name="RDP-Tailscale" 2>$null or check for rule existence first.
| netsh advfirewall firewall delete rule name="RDP-Tailscale" | |
| netsh advfirewall firewall delete rule name="RDP-Tailscale" 2>$null |
No description provided.