Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
850fc93
test(playwright): add nightly SSO login spec starting with Okta
Apr 8, 2026
45d8c95
ci: add dedicated SSO Login Nightly workflow
Apr 8, 2026
ae7f190
refactor(playwright): simplify ssoAuth helpers
Apr 8, 2026
3f9fbcc
refactor(playwright): address SSO suite review feedback
Apr 8, 2026
8b3f993
ci: avoid CodeQL "Excessive Secrets Exposure" in SSO Login Nightly
Apr 8, 2026
13849af
refactor(playwright): capture/restore real security config in SSO suite
Apr 9, 2026
3143312
ci(sso-login): extract per-provider composite action
Apr 9, 2026
8a5706a
refactor(playwright): move Okta tenant config to a repo constant
Apr 9, 2026
325405e
ci(sso-login): move timeout-minutes from composite step to job level
Apr 9, 2026
31a3cf2
ci(sso-login): consolidate dispatcher + composite action into one file
Apr 9, 2026
e0c3f4f
ci(sso-login): drop provider-prefix bash step; use case-insensitive l…
Apr 9, 2026
a37aff0
ci(sso-login): drop redundant case-insensitivity comment
Apr 9, 2026
b054b6f
ci(sso-login): pin playwright install to 1.57.0 to match package.json
Apr 9, 2026
e0a148e
Merge branch 'main' into test/playwright/sso-login-okta
siddhant1 Apr 9, 2026
891d976
refactor(playwright): address SSO suite review comments [skip ci]
Apr 9, 2026
39fb53a
saml
Apr 10, 2026
633d185
test(playwright): add SAML providers to SSO login nightly
Apr 14, 2026
b12e7af
refactor(playwright): fetch Azure SAML IdP cert at runtime
Apr 14, 2026
484105b
refactor(playwright): drop hosted Azure SAML provider
Apr 14, 2026
01406f3
test(playwright): cover SSO session lifecycle end-to-end
Apr 14, 2026
824aa35
Merge branch 'main' into test/playwright/sso-login-okta
siddhant1 Apr 15, 2026
6824868
remove slow from individual spec
siddhant1 Apr 15, 2026
fc1655d
remove slow from beforeAll
siddhant1 Apr 15, 2026
12d913c
style(playwright): fix SSOLogin spec prettier issues
Apr 15, 2026
b7fa14a
Merge branch 'main' into test/playwright/sso-login-okta
siddhant1 Apr 15, 2026
be3d298
test(playwright): tighten SSO sign-in locator and await logout response
Apr 15, 2026
49394db
Merge branch 'main' into test/playwright/sso-login-okta
siddhant1 Apr 15, 2026
eb1dc7b
fix
Apr 15, 2026
2f382c3
Merge branch 'test/playwright/sso-login-okta' of https://github.com/o…
Apr 15, 2026
014eeae
Update openmetadata-ui/src/main/resources/ui/playwright/e2e/Auth/SSOL…
siddhant1 Apr 15, 2026
7d64bfc
fix
siddhant1 Apr 15, 2026
b6032a8
Merge branch 'main' into test/playwright/sso-login-okta
siddhant1 Apr 15, 2026
2104639
test(playwright): resolve SSO creds via env vars, drop keycloak-googl…
Apr 15, 2026
f918b65
test(playwright): post SSO login nightly results to Slack
Apr 15, 2026
5106511
Merge branch 'main' into test/playwright/sso-login-okta
siddhant1 Apr 15, 2026
c13e1dc
fix(playwright): drop logout response wait in SSO spec
Apr 15, 2026
2130e87
Merge branch 'main' into test/playwright/sso-login-okta
siddhant1 Apr 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 145 additions & 0 deletions .github/workflows/playwright-sso-login-nightly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# Copyright 2025 Collate
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: SSO Login Nightly

on:
schedule:
- cron: '0 3 * * *'
workflow_dispatch:
inputs:
sso_provider:
description: 'SSO provider (or "all")'
required: true
default: okta
type: choice
options:
- okta
- keycloak-azure-saml
- all

permissions:
contents: read

concurrency:
group: sso-login-nightly-${{ github.event.inputs.sso_provider || 'scheduled' }}
cancel-in-progress: true

jobs:
# To onboard a new provider:
# 1. Add a matrix entry below (`name` is the lowercase provider id used by
# the Playwright helper; `env_prefix` is the uppercase/underscore form
# used to look up credentials). Also add `name` to the dispatch
# `options:` list above.
# 2. Add <ENV_PREFIX>_SSO_USERNAME (variable) and <ENV_PREFIX>_SSO_PASSWORD
# (variable) to the `test` environment. Use a secret instead of a
# variable for the password if the provider uses a real (non-fixture)
# credential.
# 3. Register the helper in playwright/utils/sso-providers/index.ts.
sso-login:
runs-on: ubuntu-latest
environment: test
timeout-minutes: 45
Comment thread
siddhant1 marked this conversation as resolved.
strategy:
fail-fast: false
matrix:
provider:
${{ (github.event_name == 'schedule' || github.event.inputs.sso_provider == 'all')
&& fromJSON('[{"name":"okta","env_prefix":"OKTA"},{"name":"keycloak-azure-saml","env_prefix":"KEYCLOAK_AZURE_SAML"}]')
|| (github.event.inputs.sso_provider == 'keycloak-azure-saml'
&& fromJSON('[{"name":"keycloak-azure-saml","env_prefix":"KEYCLOAK_AZURE_SAML"}]')
|| fromJSON('[{"name":"okta","env_prefix":"OKTA"}]')) }}
steps:
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
Comment thread
siddhant1 marked this conversation as resolved.
with:
tool-cache: false
android: true
dotnet: true
haskell: true
large-packages: false
swap-storage: true
docker-images: false

- name: Checkout
uses: actions/checkout@v4

- name: Cache Maven Dependencies
uses: actions/cache@v4
with:
path: ~/.m2
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-

- name: Setup OpenMetadata Test Environment
uses: ./.github/actions/setup-openmetadata-test-environment
with:
python-version: '3.10'
args: '-d postgresql -i false'
ingestion_dependency: 'all'

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: 'openmetadata-ui/src/main/resources/ui/.nvmrc'

- name: Install dependencies
working-directory: openmetadata-ui/src/main/resources/ui/
run: yarn --ignore-scripts --frozen-lockfile

- name: Install Playwright Browsers
run: npx playwright@1.57.0 install chromium --with-deps

- name: Start Keycloak SAML IdP
if: startsWith(matrix.provider.name, 'keycloak-')
run: |
docker compose -f docker/local-sso/keycloak-saml/docker-compose.yml up -d
timeout 180 bash -c 'until curl -fsS http://localhost:8080/realms/om-azure-saml >/dev/null; do sleep 2; done'

- name: Run SSO Login Spec
working-directory: openmetadata-ui/src/main/resources/ui
env:
SSO_PROVIDER_TYPE: ${{ matrix.provider.name }}
SSO_USERNAME: ${{ vars[format('{0}_SSO_USERNAME', matrix.provider.env_prefix)] }}
SSO_PASSWORD: ${{ vars[format('{0}_SSO_PASSWORD', matrix.provider.env_prefix)] || secrets[format('{0}_SSO_PASSWORD', matrix.provider.env_prefix)] }}
Comment thread
siddhant1 marked this conversation as resolved.
KEYCLOAK_SAML_BASE_URL: http://localhost:8080
Comment thread
siddhant1 marked this conversation as resolved.
Comment thread
siddhant1 marked this conversation as resolved.
PLAYWRIGHT_IS_OSS: true
run: |
npx playwright test playwright/e2e/Auth/SSOLogin.spec.ts \
--project=sso-auth \
Comment thread
siddhant1 marked this conversation as resolved.
--workers=1

- name: Upload HTML report
if: always()
uses: actions/upload-artifact@v4
with:
name: sso-login-html-report-${{ matrix.provider.name }}
path: openmetadata-ui/src/main/resources/ui/playwright/output/playwright-report
retention-days: 5

- name: Send Slack Notification
if: always()
working-directory: openmetadata-ui/src/main/resources/ui
env:
RUN_TITLE: "SSO Login Nightly: ${{ matrix.provider.name }} (${{ github.ref_name }})"
RUN_URL: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
SLACK_BOT_USER_OAUTH_TOKEN: ${{ secrets.E2E_SLACK_BOT_OAUTH_TOKEN }}
run: |
npx playwright-slack-report -c playwright/slack-cli.config.json -j playwright/output/results.json > slack_report.json

- name: Clean Up
if: always()
run: |
docker compose -f docker/local-sso/keycloak-saml/docker-compose.yml down --remove-orphans || true
cd ./docker/development
docker compose down --remove-orphans
sudo rm -rf ${PWD}/docker-volume
22 changes: 22 additions & 0 deletions docker/local-sso/keycloak-saml/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Keycloak SAML Fixture

Local SAML IdP fixture for the Playwright SSO login spec.

```bash
docker compose -f docker/local-sso/keycloak-saml/docker-compose.yml up -d
```

It imports one realm for an OpenMetadata server running at `http://localhost:8585`:

- `om-azure-saml`
- User: `azure.saml@openmetadata.local`
- Password: `OpenMetadata@123`

Use the matching Playwright provider type:

```bash
SSO_PROVIDER_TYPE=keycloak-azure-saml \
SSO_USERNAME=azure.saml@openmetadata.local \
SSO_PASSWORD=OpenMetadata@123 \
npx playwright test playwright/e2e/Auth/SSOLogin.spec.ts --project=sso-auth --workers=1
```
23 changes: 23 additions & 0 deletions docker/local-sso/keycloak-saml/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: openmetadata-keycloak-saml

services:
keycloak:
image: ${KEYCLOAK_IMAGE:-quay.io/keycloak/keycloak:26.3.3}
container_name: openmetadata-keycloak-saml
command: ['start-dev', '--import-realm']
environment:
KC_BOOTSTRAP_ADMIN_USERNAME: ${KEYCLOAK_BOOTSTRAP_ADMIN_USERNAME:-admin}
KC_BOOTSTRAP_ADMIN_PASSWORD: ${KEYCLOAK_BOOTSTRAP_ADMIN_PASSWORD:-admin123}
KC_HEALTH_ENABLED: 'true'
KC_HTTP_ENABLED: 'true'
KC_HTTP_PORT: '8080'
ports:
- '${KEYCLOAK_SAML_PORT:-8080}:8080'
volumes:
- ./realms:/opt/keycloak/data/import:ro
healthcheck:
test: ['CMD-SHELL', 'exec 3<>/dev/tcp/localhost/8080']
Comment thread
siddhant1 marked this conversation as resolved.
interval: 10s
timeout: 5s
retries: 18
start_period: 20s
109 changes: 109 additions & 0 deletions docker/local-sso/keycloak-saml/realms/om-azure-saml-realm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
{
"realm": "om-azure-saml",
"enabled": true,
"displayName": "OpenMetadata Azure SAML",
"sslRequired": "none",
"registrationAllowed": false,
"loginWithEmailAllowed": true,
"duplicateEmailsAllowed": false,
"resetPasswordAllowed": false,
"editUsernameAllowed": false,
"clients": [
{
"clientId": "http://localhost:8585/api/v1/saml/metadata",
"name": "OpenMetadata",
"enabled": true,
"protocol": "saml",
"publicClient": true,
"frontchannelLogout": true,
"redirectUris": ["http://localhost:8585/*"],
"baseUrl": "http://localhost:8585",
"adminUrl": "http://localhost:8585",
"attributes": {
"saml.assertion.signature": "true",
"saml.authnstatement": "true",
"saml.client.signature": "false",
"saml.encrypt": "false",
"saml.force.name.id.format": "true",
"saml.force.post.binding": "true",
"saml.multivalued.roles": "false",
"saml.server.signature": "true",
"saml.signature.algorithm": "RSA_SHA256",
"saml_assertion_consumer_url_post": "http://localhost:8585/api/v1/saml/acs",
"saml_force_name_id_format": "true",
"saml_name_id_format": "email"
},
"protocolMappers": [
{
"name": "Email",
"protocol": "saml",
"protocolMapper": "saml-user-property-mapper",
"consentRequired": false,
"config": {
"attribute.name": "email",
"attribute.nameformat": "Basic",
"friendly.name": "email",
"user.attribute": "email"
}
},
{
"name": "Display Name",
"protocol": "saml",
"protocolMapper": "saml-user-attribute-mapper",
"consentRequired": false,
"config": {
"attribute.name": "http://schemas.microsoft.com/identity/claims/displayname",
"attribute.nameformat": "Basic",
"friendly.name": "displayname",
"user.attribute": "displayName"
}
},
{
"name": "Given Name",
"protocol": "saml",
"protocolMapper": "saml-user-property-mapper",
"consentRequired": false,
"config": {
"attribute.name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname",
"attribute.nameformat": "Basic",
"friendly.name": "givenname",
"user.attribute": "firstName"
}
},
{
"name": "Surname",
"protocol": "saml",
"protocolMapper": "saml-user-property-mapper",
"consentRequired": false,
"config": {
"attribute.name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname",
"attribute.nameformat": "Basic",
"friendly.name": "surname",
"user.attribute": "lastName"
}
}
]
}
],
"users": [
{
"username": "azure.saml@openmetadata.local",
"email": "azure.saml@openmetadata.local",
"firstName": "Azure",
"lastName": "SAML",
"enabled": true,
"emailVerified": true,
"requiredActions": [],
"attributes": {
"displayName": ["Azure SAML User"]
},
"credentials": [
{
"type": "password",
"value": "OpenMetadata@123",
"temporary": false
}
]
}
]
}
8 changes: 8 additions & 0 deletions openmetadata-ui/src/main/resources/ui/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,16 @@ export default defineConfig({
'**/DataAssetRulesDisabled.spec.ts',
'**/SystemCertificationTags.spec.ts',
'**/SearchRBAC.spec.ts',
'**/SSOLogin.spec.ts',
Comment thread
siddhant1 marked this conversation as resolved.
],
},
{
name: 'sso-auth',
testMatch: '**/SSOLogin.spec.ts',
use: { ...devices['Desktop Chrome'] },
fullyParallel: false,
Comment thread
siddhant1 marked this conversation as resolved.
workers: 1,
},
Comment thread
siddhant1 marked this conversation as resolved.
{
name: 'entity-data-teardown',
testMatch: '**/entity-data.teardown.ts',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2025 Collate.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

export const OM_BASE_URL =
process.env.PLAYWRIGHT_TEST_BASE_URL ?? 'http://localhost:8585';

export const SSO_ENV = {
PROVIDER_TYPE: 'SSO_PROVIDER_TYPE',
USERNAME: 'SSO_USERNAME',
PASSWORD: 'SSO_PASSWORD',
OKTA_CLIENT_ID: 'OKTA_CLIENT_ID',
OKTA_DOMAIN: 'OKTA_DOMAIN',
OKTA_PRINCIPAL_DOMAIN: 'OKTA_PRINCIPAL_DOMAIN',
KEYCLOAK_SAML_BASE_URL: 'KEYCLOAK_SAML_BASE_URL',
KEYCLOAK_SAML_AZURE_REALM: 'KEYCLOAK_SAML_AZURE_REALM',
KEYCLOAK_SAML_PRINCIPAL_DOMAIN: 'KEYCLOAK_SAML_PRINCIPAL_DOMAIN',
} as const;
Loading
Loading