-
Notifications
You must be signed in to change notification settings - Fork 183
Upgrade Guacamole to version 1.6.0 (required extension changes) and OAuth Proxy to 7.13.0 #4754
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
marrobi
merged 43 commits into
microsoft:main
from
marrobi:copilot/update-guacamole-auth-azure-credentials
Nov 20, 2025
Merged
Changes from all commits
Commits
Show all changes
43 commits
Select commit
Hold shift + click to select a range
10fccd7
Initial plan
Copilot 4e0af73
Upgrade Guacamole auth-azure to use 1.6.0 API with RequestDetails
Copilot c950a3f
Fix failing tests with JVM module access and upgrade porter.yaml
Copilot c202077
Add comprehensive unit tests for TreUserContext and TokenInjectingCon…
Copilot 45e4fce
Fix security issues: credential cleanup, exception logging, and add e…
Copilot cc82b0f
Add local integration tests that run without cloud dependencies
Copilot 311e630
Add RDP credential injection integration tests
Copilot 86fa08d
Update Dockerfile to use Guacamole 1.6.0 components
Copilot 1c3174f
Update Dockerfile to use Java 17 with updated CA certificates to fix …
Copilot 2a197f0
Upgrade Tomcat to 9.0.111 and add comprehensive E2E test infrastructu…
Copilot 17966f6
Add devcontainer for Guacamole development with Java 17, Node.js, and…
Copilot 2eab5d2
Switch Maven base image from Alpine to Debian for better compatibility
Copilot bcfee6a
Fix SSL certificate chain issues in Docker build by updating CA certi…
Copilot d0c8a4d
Fix Maven Central SSL certificate validation by importing certificate…
Copilot 4c7e4d5
Revert build stage to Alpine-based image with SSL certificate fix
Copilot fb92380
Fix Alpine EOL issue by updating repositories to v3.20 for both build…
Copilot 78e8b5d
Add from-source Dockerfile for building Guacamole 1.6.0 with RDP-only…
Copilot 68d6427
Addressing PR comments
Copilot af49adf
Fix s6-overlay installation order in Debian from-source Dockerfile to…
Copilot ee0e5b6
Update E2E tests to use Playwright 1.56.1 with Debian from-source Doc…
Copilot 86cd381
Add RDP connection test with xrdp container and update E2E test scree…
Copilot 3a247b4
Fix E2E tests: remove nginx proxy, add Playwright custom headers, fix…
Copilot bb547ce
Working, needs review.
marrobi 7dd03fc
Remove dev container
marrobi 0c2efb3
update test configurations
marrobi d351bac
PR comments and remove s6
marrobi fbd5070
Merge branch 'main' of https://github.com/microsoft/AzureTRE into cop…
marrobi 172a59b
update java version in workflow and validate service
marrobi 77fa1ac
Fix tests
marrobi 05546e3
fix lining issues.
marrobi 492b800
fix review comments
marrobi 0771475
Fix some more linting.
marrobi 6262998
Update templates/workspace_services/guacamole/e2e-tests/run-tests.sh
marrobi d1152ca
Merge branch 'main' into copilot/update-guacamole-auth-azure-credentials
marrobi 390428b
Add override
marrobi 83fc6bd
Merge branch 'copilot/update-guacamole-auth-azure-credentials' of htt…
marrobi d77d4d2
Merge branch 'main' of https://github.com/microsoft/AzureTRE into cop…
marrobi 7b5dd8d
Update script permissions and changelog
marrobi 791418d
Merge branch 'main' into copilot/update-guacamole-auth-azure-credentials
marrobi fd3aff5
Merge branch 'main' into copilot/update-guacamole-auth-azure-credentials
marrobi ef117e7
only one of javascript and typescript
marrobi 6e8b056
Trigger codeql
marrobi 6070eaf
trigger
marrobi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
templates/workspace_services/guacamole/e2e-tests/.gitignore
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| # Ignore node modules | ||
| node_modules/ | ||
|
|
||
| # Ignore test results | ||
| test-results/ | ||
| playwright-report/ | ||
|
|
||
| # Ignore screenshots and videos from local runs | ||
| screenshots/*.png | ||
| videos/*.webm | ||
|
|
||
| # Ignore package-lock if using npm | ||
| package-lock.json | ||
|
|
||
| # Ignore OS files | ||
| .DS_Store | ||
| Thumbs.db | ||
|
|
||
| # Ignore IDE files | ||
| .vscode/ | ||
| .idea/ | ||
| *.sw |
32 changes: 32 additions & 0 deletions
32
templates/workspace_services/guacamole/e2e-tests/config/expectations.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| [ | ||
| { | ||
| "httpRequest": { | ||
| "method": "GET", | ||
| "path": "/api/workspaces/test-workspace/workspace-services/vm-service-001/user-resources" | ||
| }, | ||
| "httpResponse": { | ||
| "statusCode": 200, | ||
| "headers": { | ||
| "Content-Type": [ | ||
| "application/json" | ||
| ] | ||
| }, | ||
| "body": { | ||
| "userResources": [ | ||
| { | ||
| "id": "vm-resource-001", | ||
| "templateName": "tre-service-guacamole-windowsvm", | ||
| "templateVersion": "1.0.0", | ||
| "properties": { | ||
| "hostname": "vm-resource-001", | ||
| "ip": "xrdp", | ||
| "display_name": "Test Virtual Machine", | ||
| "vm_resource_id": "/subscriptions/test/resourceGroups/test/providers/Microsoft.Compute/virtualMachines/test-vm", | ||
| "is_exposed_externally": true | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| ] |
81 changes: 81 additions & 0 deletions
81
templates/workspace_services/guacamole/e2e-tests/docker-compose.yml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| services: | ||
| # Mock xrdp server for testing | ||
| xrdp: | ||
| image: danielguerra/ubuntu-xrdp:20.04 | ||
| hostname: xrdp-test | ||
| ports: | ||
| - "3390:3389" | ||
| environment: | ||
| - TZ=UTC | ||
| networks: | ||
| - guac-test-network | ||
|
|
||
| # Guacamole backend server with TRE auth extension (Debian-based from-source build) | ||
| guacamole-backend: | ||
| image: guacamole-tre:latest | ||
| environment: | ||
| # Azure TRE Configuration (mock values for testing) | ||
| - TRE_ID=test-tre | ||
| - API_URL=http://mock-api:1080 | ||
| - WORKSPACE_ID=test-workspace | ||
| - SERVICE_ID=vm-service-001 | ||
| - KEYVAULT_URL=https://mock-keyvault.vault.azure.net/ | ||
| - AAD_TENANT_ID=${GUAC_OIDC_TENANT_ID:?Set GUAC_OIDC_TENANT_ID (run ./run-tests.sh setup-auth)} | ||
| # Disable oauth2-proxy for E2E tests (routes are skipped via configuration) | ||
| - AUDIENCE=${GUAC_OIDC_AUDIENCE:?Set GUAC_OIDC_AUDIENCE (run ./run-tests.sh setup-auth)} | ||
| - ISSUER=${GUAC_OIDC_ISSUER_URL:?Set GUAC_OIDC_ISSUER_URL (run ./run-tests.sh setup-auth)} | ||
| - OAUTH2_PROXY_CLIENT_ID=${GUAC_OIDC_CLIENT_ID:?Set GUAC_OIDC_CLIENT_ID (run ./run-tests.sh setup-auth)} | ||
| - OAUTH2_PROXY_CLIENT_SECRET=${GUAC_OIDC_CLIENT_SECRET:?Set GUAC_OIDC_CLIENT_SECRET (run ./run-tests.sh setup-auth)} | ||
| - OAUTH2_PROXY_REDIRECT_URI=${GUAC_OIDC_REDIRECT_URI:?Set GUAC_OIDC_REDIRECT_URI (run ./run-tests.sh setup-auth)} | ||
| - OAUTH2_PROXY_EMAIL_DOMAIN=${GUAC_OIDC_EMAIL_DOMAIN:-*} | ||
| - OAUTH2_PROXY_OIDC_ISSUER_URL=${GUAC_OIDC_ISSUER_URL:?Set GUAC_OIDC_ISSUER_URL (run ./run-tests.sh setup-auth)} | ||
| - OAUTH2_PROXY_JWKS_ENDPOINT=${GUAC_OIDC_JWKS_URL:?Set GUAC_OIDC_JWKS_URL (run ./run-tests.sh setup-auth)} | ||
| ports: | ||
| - "8080:8085" # Expose OAuth2 proxy (HTTP) | ||
| - "8443:8086" # Optional HTTPS endpoint from oauth2-proxy | ||
| depends_on: | ||
| - xrdp | ||
| - mock-api | ||
| healthcheck: | ||
| test: ["CMD-SHELL", "wget -qO- http://localhost:8085/ping >/dev/null"] | ||
| interval: 10s | ||
| timeout: 5s | ||
| retries: 15 | ||
| start_period: 90s | ||
| networks: | ||
| - guac-test-network | ||
|
|
||
| # Mock TRE API server | ||
| mock-api: | ||
| image: mockserver/mockserver:5.15.0 | ||
| ports: | ||
| - "8000:1080" | ||
| environment: | ||
| - MOCKSERVER_LOG_LEVEL=INFO | ||
| networks: | ||
| - guac-test-network | ||
|
|
||
| # Playwright test runner | ||
| playwright: | ||
| build: | ||
| context: ./playwright | ||
| dockerfile: Dockerfile | ||
| depends_on: | ||
| guacamole-backend: | ||
| condition: service_healthy | ||
| xrdp: | ||
| condition: service_started | ||
| mock-api: | ||
| condition: service_started | ||
| environment: | ||
| - GUACAMOLE_URL=http://guacamole-backend:8085 | ||
| volumes: | ||
| - ./playwright/screenshots:/screenshots | ||
| - ./playwright/videos:/videos | ||
| networks: | ||
| - guac-test-network | ||
| command: npx playwright test --reporter=html | ||
|
|
||
| networks: | ||
| guac-test-network: | ||
| driver: bridge | ||
53 changes: 53 additions & 0 deletions
53
templates/workspace_services/guacamole/e2e-tests/mock-api-config.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| [ | ||
| { | ||
| "httpRequest": { | ||
| "method": "GET", | ||
| "path": "/api/workspaces/test-workspace/workspace-services/.*" | ||
| }, | ||
| "httpResponse": { | ||
| "statusCode": 200, | ||
| "headers": { | ||
| "Content-Type": ["application/json"] | ||
| }, | ||
| "body": { | ||
| "workspaceServices": [ | ||
| { | ||
| "id": "vm-service-001", | ||
| "templateName": "tre-service-guacamole", | ||
| "properties": { | ||
| "vm_name": "test-vm", | ||
| "vm_resource_id": "/subscriptions/test/resourceGroups/test/providers/Microsoft.Compute/virtualMachines/test-vm", | ||
| "is_exposed_externally": true | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| }, | ||
| { | ||
| "httpRequest": { | ||
| "method": "GET", | ||
| "path": "/api/workspaces/test-workspace/workspace-services/.*/user-resources" | ||
| }, | ||
| "httpResponse": { | ||
| "statusCode": 200, | ||
| "headers": { | ||
| "Content-Type": ["application/json"] | ||
| }, | ||
| "body": { | ||
| "userResources": [ | ||
| { | ||
| "id": "vm-001", | ||
| "templateName": "tre-service-windows-vm", | ||
| "properties": { | ||
| "vm_name": "testvm001", | ||
| "fqdn": "xrdp", | ||
| "connection_port": "3389", | ||
| "is_exposed_externally": true | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| ] |
15 changes: 15 additions & 0 deletions
15
templates/workspace_services/guacamole/e2e-tests/playwright/Dockerfile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| FROM mcr.microsoft.com/playwright:v1.56.1-noble | ||
|
|
||
| WORKDIR /app | ||
|
|
||
| # Copy package files | ||
| COPY package.json package-lock.json* ./ | ||
|
|
||
| RUN npm install | ||
|
|
||
| # Copy Playwright project files (tests live under ./tests) | ||
| COPY . . | ||
|
|
||
| # Run tests | ||
| CMD ["npx", "playwright", "test"] | ||
|
|
15 changes: 15 additions & 0 deletions
15
templates/workspace_services/guacamole/e2e-tests/playwright/package.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| { | ||
| "name": "guacamole-e2e-tests", | ||
| "version": "1.0.0", | ||
| "description": "End-to-end tests for Guacamole TRE integration", | ||
| "scripts": { | ||
| "test": "playwright test", | ||
| "test:headed": "playwright test --headed", | ||
| "test:debug": "playwright test --debug", | ||
| "test:report": "playwright show-report" | ||
| }, | ||
| "devDependencies": { | ||
| "@playwright/test": "1.56.1", | ||
| "@types/node": "^20.11.0" | ||
| } | ||
| } |
34 changes: 34 additions & 0 deletions
34
templates/workspace_services/guacamole/e2e-tests/playwright/playwright.config.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import { defineConfig, devices } from '@playwright/test'; | ||
|
|
||
| const GUACAMOLE_URL = process.env.GUACAMOLE_URL || 'http://localhost:8080'; | ||
| const TEST_DIR = process.env.PLAYWRIGHT_TEST_DIR || 'tests'; | ||
|
|
||
| export default defineConfig({ | ||
| testDir: TEST_DIR, | ||
| timeout: 60000, | ||
| expect: { | ||
| timeout: 10000, | ||
| }, | ||
| fullyParallel: false, | ||
| forbidOnly: !!process.env.CI, | ||
| retries: process.env.CI ? 2 : 0, | ||
| workers: 1, | ||
| reporter: [ | ||
| ['html', { outputFolder: 'test-results/html' }], | ||
| ['json', { outputFile: 'test-results/results.json' }], | ||
| ['list'] | ||
| ], | ||
| use: { | ||
| baseURL: GUACAMOLE_URL, | ||
| trace: 'on-first-retry', | ||
| screenshot: 'only-on-failure', | ||
| video: 'retain-on-failure', | ||
| }, | ||
| projects: [ | ||
| { | ||
| name: 'chromium', | ||
| use: { ...devices['Desktop Chrome'] }, | ||
| }, | ||
| ], | ||
| outputDir: 'test-results/output', | ||
| }); |
73 changes: 73 additions & 0 deletions
73
templates/workspace_services/guacamole/e2e-tests/playwright/tests/guacamole-e2e.spec.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| import { test, expect } from '@playwright/test'; | ||
|
|
||
| const OAUTH_LOGIN_URL_REGEX = /(login\.microsoftonline\.com|oauth2\/(start|auth|callback))/i; | ||
|
|
||
| test.describe('Guacamole TRE OAuth-protected E2E checks', () => { | ||
| test('redirects unauthenticated users to Azure AD', async ({ request }) => { | ||
| const response = await request.get('/guacamole/', { | ||
| failOnStatusCode: false, | ||
| maxRedirects: 0, | ||
| }); | ||
|
|
||
| expect([200, 302, 303]).toContain(response.status()); | ||
|
|
||
| const locationHeader = response.headers()['location'] ?? ''; | ||
| if (locationHeader) { | ||
| expect(locationHeader).toMatch(OAUTH_LOGIN_URL_REGEX); | ||
| } else { | ||
| expect(response.url()).toMatch(OAUTH_LOGIN_URL_REGEX); | ||
| } | ||
| }); | ||
|
|
||
| test('browser navigation tries to reach Azure AD login', async ({ page }) => { | ||
| await page.route('https://login.microsoftonline.com/**', route => { | ||
| route.fulfill({ status: 200, contentType: 'text/html', body: '<html><body>Azure AD Stub</body></html>' }); | ||
| }); | ||
|
|
||
| const response = await page.goto('/guacamole/', { waitUntil: 'commit' }); | ||
| const redirectLocation = response?.headers()['location']; | ||
|
|
||
| if (redirectLocation) { | ||
| expect(response?.status()).toBe(302); | ||
| expect(redirectLocation).toMatch(OAUTH_LOGIN_URL_REGEX); | ||
| } else { | ||
| // When Playwright follows the redirect, assert the current URL instead. | ||
| expect(page.url()).toMatch(OAUTH_LOGIN_URL_REGEX); | ||
| } | ||
|
|
||
| await page.screenshot({ path: '/screenshots/01-login-redirect.png', fullPage: true }); | ||
| }); | ||
|
|
||
| test('blocks REST API access without authentication', async ({ request }) => { | ||
| const response = await request.get('/guacamole/api/session/data', { | ||
| failOnStatusCode: false, | ||
| maxRedirects: 0, | ||
| }); | ||
|
|
||
| expect([200, 302, 303, 401, 403]).toContain(response.status()); | ||
|
|
||
| if (response.status() === 200) { | ||
| const body = await response.text(); | ||
| expect(body).toMatch(/<html/i); | ||
| expect(response.url()).toMatch(OAUTH_LOGIN_URL_REGEX); | ||
| } | ||
| }); | ||
|
|
||
| test('exposes oauth2-proxy ping endpoint', async ({ request }) => { | ||
| const response = await request.get('http://guacamole-backend:8085/ping'); | ||
| expect(response.status()).toBe(200); | ||
| expect(await response.text()).toContain('OK'); | ||
| }); | ||
|
|
||
| test('enforces security headers on protected resources', async ({ request }) => { | ||
| const response = await request.get('/guacamole/', { | ||
| failOnStatusCode: false, | ||
| maxRedirects: 0, | ||
| }); | ||
|
|
||
| const headers = response.headers(); | ||
|
|
||
| expect(headers['cache-control']).toBeDefined(); | ||
| expect(response.status()).toBeLessThan(500); | ||
| }); | ||
| }); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.