param( [string]$DockerSshAlias = "docker-test", [string]$WorkerImage = "rap-rdp-worker:dp1c-hardened", [string]$WorkerID = "rdp-worker-1", [int]$Port = 18443 ) $ErrorActionPreference = "Stop" function ConvertTo-Base64Url([byte[]]$Bytes) { return [Convert]::ToBase64String($Bytes).TrimEnd("=").Replace("+", "-").Replace("/", "_") } function New-DataPlaneJwt([hashtable]$Payload) { $encoding = [Text.Encoding]::UTF8 $headerJson = @{ alg = "RS256"; typ = "JWT" } | ConvertTo-Json -Compress $payloadJson = $Payload | ConvertTo-Json -Compress -Depth 6 $body = "$(ConvertTo-Base64Url $encoding.GetBytes($headerJson)).$(ConvertTo-Base64Url $encoding.GetBytes($payloadJson))" $signature = ConvertTo-Base64Url $script:DataPlaneRsa.SignData( $encoding.GetBytes($body), [System.Security.Cryptography.HashAlgorithmName]::SHA256, [System.Security.Cryptography.RSASignaturePadding]::Pkcs1) return "$body.$signature" } function ConvertTo-Pem([string]$Label, [byte[]]$Bytes) { $base64 = [Convert]::ToBase64String($Bytes) $lines = for ($i = 0; $i -lt $base64.Length; $i += 64) { $base64.Substring($i, [Math]::Min(64, $base64.Length - $i)) } $joined = $lines -join "`n" return "-----BEGIN $Label-----`n$joined`n-----END $Label-----`n" } $now = [int][DateTimeOffset]::UtcNow.ToUnixTimeSeconds() $script:DataPlaneRsa = [System.Security.Cryptography.RSA]::Create(2048) $publicKeyPem = ConvertTo-Pem "PUBLIC KEY" $script:DataPlaneRsa.ExportSubjectPublicKeyInfo() $publicKeyB64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($publicKeyPem)) $validPayload = [ordered]@{ session_id = "session-without-runtime" attachment_id = "attachment-1" user_id = "user-1" organization_id = "org-1" worker_id = $WorkerID resource_id = "resource-1" allowed_channels = @("control", "input", "render") jti = [guid]::NewGuid().ToString() aud = @("rap-data-plane", "worker:$WorkerID") iat = $now nbf = $now exp = $now + 300 } $validToken = New-DataPlaneJwt $validPayload $remoteScript = @" set -eu rm -rf /tmp/rap-dp1c && mkdir -p /tmp/rap-dp1c openssl req -x509 -newkey rsa:2048 -nodes -keyout /tmp/rap-dp1c/key.pem -out /tmp/rap-dp1c/cert.pem -subj '/CN=localhost' -days 1 >/tmp/rap-dp1c/openssl.log 2>&1 printf '%s' '$publicKeyB64' | base64 -d >/tmp/rap-dp1c/dp-public.pem (docker rm -f rap_worker_dp1c_probe >/dev/null 2>&1 || true) docker run -d --name rap_worker_dp1c_probe --network rdp-proxy_default -p ${Port}:${Port} -v /tmp/rap-dp1c:/certs:ro \ -e RDP_WORKER_ID=$WorkerID \ -e RDP_WORKER_REDIS_HOST=rap_redis \ -e RDP_WORKER_DATA_PLANE_ENABLED=true \ -e RDP_WORKER_DATA_PLANE_LISTEN_HOST=0.0.0.0 \ -e RDP_WORKER_DATA_PLANE_LISTEN_PORT=$Port \ -e RDP_WORKER_DATA_PLANE_PUBLIC_KEY_FILE=/certs/dp-public.pem \ -e RDP_WORKER_DATA_PLANE_TLS_CERT_FILE=/certs/cert.pem \ -e RDP_WORKER_DATA_PLANE_TLS_KEY_FILE=/certs/key.pem \ $WorkerImage >/tmp/rap-dp1c/container.id sleep 2 printf 'invalid token response:\n' printf 'GET /rap/v1/data-plane?data_plane_token=bad HTTP/1.1\r\nHost: localhost\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\nSec-WebSocket-Version: 13\r\n\r\n' | timeout 5 openssl s_client -connect 127.0.0.1:$Port -servername localhost -quiet 2>/dev/null | head -20 printf '\nvalid token without runtime response:\n' printf 'GET /rap/v1/data-plane?data_plane_token=$validToken HTTP/1.1\r\nHost: localhost\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\nSec-WebSocket-Version: 13\r\n\r\n' | timeout 5 openssl s_client -connect 127.0.0.1:$Port -servername localhost -quiet 2>/dev/null | head -20 printf '\nreplayed jti response:\n' printf 'GET /rap/v1/data-plane?data_plane_token=$validToken HTTP/1.1\r\nHost: localhost\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\nSec-WebSocket-Version: 13\r\n\r\n' | timeout 5 openssl s_client -connect 127.0.0.1:$Port -servername localhost -quiet 2>/dev/null | head -20 printf '\nworker logs:\n' docker logs rap_worker_dp1c_probe --tail 30 docker rm -f rap_worker_dp1c_probe >/dev/null 2>&1 || true rm -rf /tmp/rap-dp1c "@ ssh $DockerSshAlias $remoteScript