From 2e0882b22c409e4477debb30ec372d3a16124b30 Mon Sep 17 00:00:00 2001 From: maximthomas Date: Tue, 12 May 2026 09:27:43 +0300 Subject: [PATCH 01/13] Add SAMLv2 E2E test --- .github/workflows/build.yml | 39 +++++++ e2e/.gitignore | 5 + e2e/playwright.config.mjs | 31 +++++ e2e/saml/bootstrap.sh | 221 ++++++++++++++++++++++++++++++++++++ e2e/saml/saml-test.spec.mjs | 111 ++++++++++++++++++ e2e/saml/shutdown.sh | 6 + 6 files changed, 413 insertions(+) create mode 100644 e2e/.gitignore create mode 100644 e2e/playwright.config.mjs create mode 100755 e2e/saml/bootstrap.sh create mode 100644 e2e/saml/saml-test.spec.mjs create mode 100755 e2e/saml/shutdown.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6b826a30d0..5dbc7369bb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -359,3 +359,42 @@ jobs: http://openam3.example.org:8080/openam/json/authenticate | grep tokenId' docker inspect --format="{{json .State.Health.Status}}" test-openam3 | grep -q \"healthy\" + ui-smoke-tests: + runs-on: ubuntu-latest + needs: build-docker + services: + registry: + image: registry:2 + ports: + - 5000:5000 + strategy: + fail-fast: false + steps: + - name: Set Integration Test Environment + run: | + echo "127.0.0.1 idp.acme.org sp.mycompany.org" | sudo tee -a /etc/hosts + - name: Cache Playwright browsers + uses: actions/cache@v5 + with: + path: ~/.cache/ms-playwright + key: ${{ runner.os }}-playwright-browsers + restore-keys: ${{ runner.os }}-playwright- + - name: UI Smoke Tests (Playwright) + run: | + cd e2e + npm init -y + npm install @playwright/test + npx playwright install chromium --with-deps + npx playwright test --reporter=list + env: + OPENAM_IMAGE: localhost:5000/${GITHUB_REPOSITORY,,}:${{ env.release_version }} + - name: Upload failure artifacts + uses: actions/upload-artifact@v7 + if: ${{ failure() }} + with: + name: failure-ui-java${{ matrix.java }}-${{ matrix.context_label }}-${{ matrix.samples_label }} + retention-days: 1 + path: | + openidm/logs/** + e2e/playwright-report/** + e2e/test-results/** \ No newline at end of file diff --git a/e2e/.gitignore b/e2e/.gitignore new file mode 100644 index 0000000000..306cc7a587 --- /dev/null +++ b/e2e/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +package-lock.json +package.json +playwright-report/ +test-results/ \ No newline at end of file diff --git a/e2e/playwright.config.mjs b/e2e/playwright.config.mjs new file mode 100644 index 0000000000..27434a395a --- /dev/null +++ b/e2e/playwright.config.mjs @@ -0,0 +1,31 @@ +/* + * The contents of this file are subject to the terms of the Common Development and + * Distribution License (the License). You may not use this file except in compliance with the + * License. + * + * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the + * specific language governing permission and limitations under the License. + * + * When distributing Covered Software, include this CDDL Header Notice in each file and include + * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL + * Header, with the fields enclosed by brackets [] replaced by your own identifying + * information: "Portions copyright [year] [name of copyright owner]". + * + * Copyright 2026 3A Systems, LLC. + */ + +import { defineConfig } from "@playwright/test"; + +export default defineConfig({ + testDir: ".", + testMatch: "**/*.spec.mjs", + timeout: 180000, + retries: 0, + use: { + headless: true, + ignoreHTTPSErrors: true, + screenshot: "only-on-failure", + trace: "retain-on-failure", + }, + reporter: [["list"], ["html", { open: "never", outputFolder: "playwright-report" }]], +}); \ No newline at end of file diff --git a/e2e/saml/bootstrap.sh b/e2e/saml/bootstrap.sh new file mode 100755 index 0000000000..edf886e1da --- /dev/null +++ b/e2e/saml/bootstrap.sh @@ -0,0 +1,221 @@ +#!/bin/bash +set -e + +OPENAM_IMAGE=${OPENAM_IMAGE:-"openidentityplatform/openam"} + +echo "Using docker image: ${OPENAM_IMAGE}" + +docker network create openam-saml 2>/dev/null || true + +echo "running OpenAM IDP container..." + +docker run --rm -it -d -h idp.acme.org -p 8080:8080 -p 8000:8000 --network openam-saml --name openam-idp \ + -e JPDA_ADDRESS=*:8000 \ + -e JPDA_TRANSPORT=dt_socket \ + ${OPENAM_IMAGE} catalina.sh jpda run + +echo "waiting for OpenAM IDP to be alive..." + +timeout 3m bash -c 'until docker inspect --format="{{json .State.Health.Status}}" openam-idp | grep -q \"healthy\"; do sleep 10; done' + + +echo "Running OpenAM IDP setup" + +docker exec -w '/usr/openam/ssoconfiguratortools' openam-idp bash -c \ +'echo "ACCEPT_LICENSES=true +SERVER_URL=http://idp.acme.org:8080 +DEPLOYMENT_URI=/$OPENAM_PATH +BASE_DIR=$OPENAM_DATA_DIR +locale=en_US +PLATFORM_LOCALE=en_US +AM_ENC_KEY= +ADMIN_PWD=passw0rd +AMLDAPUSERPASSWD=p@passw0rd +COOKIE_DOMAIN=idp.acme.org +ACCEPT_LICENSES=true +DATA_STORE=embedded +DIRECTORY_SSL=SIMPLE +DIRECTORY_SERVER=idp.acme.org +DIRECTORY_PORT=50389 +DIRECTORY_ADMIN_PORT=4444 +DIRECTORY_JMX_PORT=1689 +ROOT_SUFFIX=dc=openam,dc=example,dc=org +DS_DIRMGRDN=cn=Directory Manager +DS_DIRMGRPASSWD=passw0rd" > conf.file && java -jar openam-configurator-tool*.jar --file conf.file' + +echo "Setup ssoadm tools for OpenAM IDP" + +docker exec -w '/usr/openam/ssoadmintools' openam-idp bash -c './setup -p /usr/openam/config --acceptLicense' + +docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-idp bash -c 'echo passw0rd > pwd.txt && chmod 400 pwd.txt' + +echo "Setup COT for OpenAM IDP" +docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-idp bash -c \ +'./ssoadm create-cot \ + --adminid amadmin \ + --password-file pwd.txt \ + --realm / \ + --cot MYSAML' + +echo "Create Metadata Template for OpenAM IDP" + +docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-idp bash -c \ +'./ssoadm create-metadata-templ \ + --adminid amadmin \ + --password-file pwd.txt \ + --entityid http://idp.acme.org:8080/openam \ + --identityprovider /idp \ + --idpscertalias test \ + --meta-data-file idp-metadata.xml \ + --extended-data-file idp-extended.xml' + +echo "modify idp-extended.xml" + +docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-idp bash -c ' +sed -i " + //{ + N + s|\s*|\n uid=uid\n| + } +" idp-extended.xml' + +echo "Create hosted identity provider for OpenAM IDP" + +docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-idp bash -c \ +'./ssoadm import-entity \ + --adminid amadmin \ + --password-file pwd.txt \ + --realm / \ + --cot MYSAML \ + --meta-data-file idp-metadata.xml \ + --extended-data-file idp-extended.xml' + +echo "Running OpenAM SP setup" + +docker run --rm -it -d -h sp.mycompany.org -p 8081:8080 -p 8001:8000 --network openam-saml --name openam-sp \ + -e JPDA_ADDRESS=*:8000 \ + -e JPDA_TRANSPORT=dt_socket \ + ${OPENAM_IMAGE} catalina.sh jpda run + +echo "waiting for OpenAM SP to be alive..." + +timeout 3m bash -c 'until docker inspect --format="{{json .State.Health.Status}}" openam-sp | grep -q \"healthy\"; do sleep 10; done' + +echo "Running OpenAM SP setup" + +docker exec -w '/usr/openam/ssoconfiguratortools' openam-sp bash -c \ +'echo "ACCEPT_LICENSES=true +SERVER_URL=http://sp.mycompany.org:8080 +DEPLOYMENT_URI=/$OPENAM_PATH +BASE_DIR=$OPENAM_DATA_DIR +locale=en_US +PLATFORM_LOCALE=en_US +AM_ENC_KEY= +ADMIN_PWD=passw0rd +AMLDAPUSERPASSWD=p@passw0rd +COOKIE_DOMAIN=sp.mycompany.org +ACCEPT_LICENSES=true +DATA_STORE=embedded +DIRECTORY_SSL=SIMPLE +DIRECTORY_SERVER=sp.mycompany.org +DIRECTORY_PORT=50389 +DIRECTORY_ADMIN_PORT=4444 +DIRECTORY_JMX_PORT=1689 +ROOT_SUFFIX=dc=openam,dc=example,dc=org +DS_DIRMGRDN=cn=Directory Manager +DS_DIRMGRPASSWD=passw0rd" > conf.file && java -jar openam-configurator-tool*.jar --file conf.file' + + +echo "Setup ssoadm tools for OpenAM SP" + +docker exec -w '/usr/openam/ssoadmintools' openam-sp bash -c './setup -p /usr/openam/config --acceptLicense' + +docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-sp bash -c 'echo passw0rd > pwd.txt && chmod 400 pwd.txt' + +echo "Setup COT for OpenAM SP" + +docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-sp bash -c \ +'./ssoadm create-cot \ + --adminid amadmin \ + --password-file pwd.txt \ + --realm / \ + --cot MYSAML' + +echo "Create Metadata Template for OpenAM SP" + +docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-sp bash -c \ +'./ssoadm create-metadata-templ \ + --adminid amadmin \ + --password-file pwd.txt \ + --entityid http://sp.mycompany.org:8081/openam \ + --serviceprovider /sp \ + --spscertalias test \ + --meta-data-file sp-metadata.xml \ + --extended-data-file sp-extended.xml' + +echo "modify sp-metadata.xml" + +docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-sp bash -c \ + "sed -i 's/http:\/\/sp.mycompany.org:8080/http:\/\/sp.mycompany.org:8081/g' sp-metadata.xml" + +echo "modify sp-extended.xml" + +docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-sp bash -c ' +sed -i " + //{ + N + s|\s*|\n \*=\*\n| + } +" sp-extended.xml' + +docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-sp \ + sed -i '/name="autofedEnabled"/{n;s/false/true/}' sp-extended.xml + +docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-sp \ + sed -i '/name="autofedAttribute"/{n;s||uid|}' sp-extended.xml + + +echo "Create hosted identity provider for OpenAM IDP" + +docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-sp bash -c \ +'./ssoadm import-entity \ + --adminid amadmin \ + --password-file pwd.txt \ + --realm / \ + --cot MYSAML \ + --meta-data-file sp-metadata.xml \ + --extended-data-file sp-extended.xml' + +echo "Exchange providers metadata between contaners" + +docker exec openam-sp cat /usr/openam/ssoadmintools/openam/bin/sp-metadata.xml | docker exec -i openam-idp bash -c 'cat > /usr/openam/ssoadmintools/openam/bin/remote-sp-metadata.xml' + +docker exec openam-idp cat /usr/openam/ssoadmintools/openam/bin/idp-metadata.xml | docker exec -i openam-sp bash -c 'cat > /usr/openam/ssoadmintools/openam/bin/remote-idp-metadata.xml' + +echo "Create remote SP in OpenAM IDP" + +docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-idp bash -c \ +'./ssoadm import-entity \ + --adminid amadmin \ + --password-file pwd.txt \ + --realm / \ + --cot MYSAML \ + --meta-data-file remote-sp-metadata.xml' + +echo "Create remote IDP in OpenAM SP" + +docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-sp bash -c \ +'./ssoadm import-entity \ + --adminid amadmin \ + --password-file pwd.txt \ + --realm / \ + --cot MYSAML \ + --meta-data-file remote-idp-metadata.xml' + +docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-sp bash -c \ +'./ssoadm set-realm-svc-attrs \ + --adminid amadmin \ + --password-file pwd.txt \ + --realm / \ + --servicename iPlanetAMAuthService \ + --attributevalues iplanet-am-auth-dynamic-profile-creation=ignore' \ No newline at end of file diff --git a/e2e/saml/saml-test.spec.mjs b/e2e/saml/saml-test.spec.mjs new file mode 100644 index 0000000000..03ad6472dd --- /dev/null +++ b/e2e/saml/saml-test.spec.mjs @@ -0,0 +1,111 @@ +// openam.spec.mjs – ESM edition +import { test, expect } from "@playwright/test"; +import { execSync } from "child_process"; +import { resolve } from "path"; +import { fileURLToPath } from "url"; + +/** + * OpenAM XUI Login Test Suite + * + * Configuration (override via environment variables): + * OPENAM_USERNAME – login username (default: demo) + * OPENAM_PASSWORD – login password (default: changeit) + * BOOTSTRAP_SCRIPT – path to the startup script (default: ./bootstrap.sh) + * SHUTDOWN_SCRIPT – path to the shutdown script (default: ./shutdown.sh) + */ + +// ─── __dirname equivalent in ESM ────────────────────────────────────────────── +const __filename = fileURLToPath(import.meta.url); +const __dirname = fileURLToPath(new URL(".", import.meta.url)); + +// ─── Configuration ──────────────────────────────────────────────────────────── +const USERNAME = process.env.OPENAM_USERNAME ?? "demo"; +const PASSWORD = process.env.OPENAM_PASSWORD ?? "changeit"; +const BOOTSTRAP_SCRIPT = process.env.BOOTSTRAP_SCRIPT ?? "./bootstrap.sh"; +const SHUTDOWN_SCRIPT = process.env.SHUTDOWN_SCRIPT ?? "./shutdown.sh"; + +// Derived URLs +const LOGIN_URL = "http://sp.mycompany.org:8081/openam/spssoinit?metaAlias=/sp&idpEntityID=http%3A//idp.acme.org%3A8080/openam&RelayState=http%3A//sp.mycompany.org%3A8081/openam"; +const EXPECTED_IDP_URL_PATTERN = /idp\.acme\.org/; +const EXPECTED_SP_URL_PATTERN = /sp\.mycompany\.org/; + +// ─── Selectors (XUI / LESS-based OpenAM UI) ─────────────────────────────────── +const SEL = { + usernameInput: "#idToken1", // + passwordInput: "#idToken2", // + loginButton: 'input[type="submit"]', // + userIdElement: "#input-username", +}; + +const execScript = (scriptPath) => { + return; + try { + execSync(`bash "${scriptPath}"`, { + encoding: "utf-8", + timeout: 300_000, // 5 minutes max + stdio: "inherit", + }); + } catch (err) { + throw new Error( + `${scriptPath} exited with code ${err.status}: ${err.message}` + ); + } +} + +// ─── Bootstrap – run once before all tests ──────────────────────────────────── +test.beforeAll(() => { + const scriptPath = resolve(__dirname, BOOTSTRAP_SCRIPT); + console.log(`\n▶ Running bootstrap script: ${scriptPath}`); + execScript(scriptPath); + +}); + +// ─── Shutdown – run once after all tests ──────────────────────────────────── +test.afterAll(() => { + const scriptPath = resolve(__dirname, SHUTDOWN_SCRIPT); + console.log(`\n▶ Running shutdown script: ${scriptPath}`); + execScript(scriptPath); +}); + +// ─── Tests ──────────────────────────────────────────────────────────────────── +test.describe("OpenAM XUI - Login flow", () => { + test("should log in as demo and reach the authenticated page", async ({ page }) => { + // ── 1. Open the login page ────────────────────────────────────────────── + console.log(`Navigating to: ${LOGIN_URL}`); + await page.goto(LOGIN_URL); + + await page.waitForURL(EXPECTED_IDP_URL_PATTERN, { + timeout: 20_000, + waitUntil: "networkidle", + }); + + await expect( + page.locator(SEL.usernameInput), + "Username input should be visible" + ).toBeVisible({ timeout: 15_000 }); + + // ── 2. Enter credentials ──────────────────────────────────────────────── + await page.fill(SEL.usernameInput, USERNAME); + await page.fill(SEL.passwordInput, PASSWORD); + + // ── 3. Click Login ────────────────────────────────────────────────────── + await page.click(SEL.loginButton); + + // ── 4. Wait for the post-login redirect ───────────────────────────────── + await page.waitForURL(EXPECTED_SP_URL_PATTERN, { + timeout: 20_000, + waitUntil: "networkidle", + }); + + // ── 5. Assert target URL ───────────────────────────────────────────────── + const currentUrl = page.url(); + console.log(`Redirected to: ${currentUrl}`); + expect(currentUrl, "URL should match the post-login pattern").toMatch(EXPECTED_SP_URL_PATTERN); + + // ── 6. Assert user-id element is present ──────────────────────────────── + await expect( + page.locator(SEL.userIdElement).first(), + "Authenticated user-id element should be visible after login" + ).toBeVisible({ timeout: 10_000 }); + }); +}); diff --git a/e2e/saml/shutdown.sh b/e2e/saml/shutdown.sh new file mode 100755 index 0000000000..39d8ea81ef --- /dev/null +++ b/e2e/saml/shutdown.sh @@ -0,0 +1,6 @@ +echo "Stopping docker containers..." +docker stop openam-idp openam-sp + +echo "Removing network..." +docker network rm openam-saml +echo "Finished" \ No newline at end of file From 3917f1087200346104284ca1bb0bad5eda08a792 Mon Sep 17 00:00:00 2001 From: maximthomas Date: Tue, 12 May 2026 10:35:59 +0300 Subject: [PATCH 02/13] fix failing test --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5dbc7369bb..6da019795b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -370,6 +370,7 @@ jobs: strategy: fail-fast: false steps: + - uses: actions/checkout@v6 - name: Set Integration Test Environment run: | echo "127.0.0.1 idp.acme.org sp.mycompany.org" | sudo tee -a /etc/hosts From 99cd3c9f02142e12d4e942fa52c3be87250ddba0 Mon Sep 17 00:00:00 2001 From: maximthomas Date: Tue, 12 May 2026 11:41:36 +0300 Subject: [PATCH 03/13] uncomment scripts execution & add copyright --- e2e/.gitignore | 15 +++++++++++++++ e2e/saml/bootstrap.sh | 16 ++++++++++++++++ e2e/saml/saml-test.spec.mjs | 18 +++++++++++++++++- e2e/saml/shutdown.sh | 17 +++++++++++++++++ 4 files changed, 65 insertions(+), 1 deletion(-) diff --git a/e2e/.gitignore b/e2e/.gitignore index 306cc7a587..970bdbd03b 100644 --- a/e2e/.gitignore +++ b/e2e/.gitignore @@ -1,3 +1,18 @@ +# The contents of this file are subject to the terms of the Common Development and +# Distribution License (the License). You may not use this file except in compliance with the +# License. +# +# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the +# specific language governing permission and limitations under the License. +# +# When distributing Covered Software, include this CDDL Header Notice in each file and include +# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL +# Header, with the fields enclosed by brackets [] replaced by your own identifying +# information: "Portions copyright [year] [name of copyright owner]". +# +# Copyright 2026 3A Systems, LLC. + + node_modules/ package-lock.json package.json diff --git a/e2e/saml/bootstrap.sh b/e2e/saml/bootstrap.sh index edf886e1da..e1620093cb 100755 --- a/e2e/saml/bootstrap.sh +++ b/e2e/saml/bootstrap.sh @@ -1,4 +1,20 @@ #!/bin/bash + +# The contents of this file are subject to the terms of the Common Development and +# Distribution License (the License). You may not use this file except in compliance with the +# License. +# +# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the +# specific language governing permission and limitations under the License. +# +# When distributing Covered Software, include this CDDL Header Notice in each file and include +# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL +# Header, with the fields enclosed by brackets [] replaced by your own identifying +# information: "Portions copyright [year] [name of copyright owner]". +# +# Copyright 2026 3A Systems, LLC. + + set -e OPENAM_IMAGE=${OPENAM_IMAGE:-"openidentityplatform/openam"} diff --git a/e2e/saml/saml-test.spec.mjs b/e2e/saml/saml-test.spec.mjs index 03ad6472dd..82af561588 100644 --- a/e2e/saml/saml-test.spec.mjs +++ b/e2e/saml/saml-test.spec.mjs @@ -1,3 +1,20 @@ +/* + * The contents of this file are subject to the terms of the Common Development and + * Distribution License (the License). You may not use this file except in compliance with the + * License. + * + * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the + * specific language governing permission and limitations under the License. + * + * When distributing Covered Software, include this CDDL Header Notice in each file and include + * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL + * Header, with the fields enclosed by brackets [] replaced by your own identifying + * information: "Portions copyright [year] [name of copyright owner]". + * + * Copyright 2026 3A Systems, LLC. + */ + + // openam.spec.mjs – ESM edition import { test, expect } from "@playwright/test"; import { execSync } from "child_process"; @@ -38,7 +55,6 @@ const SEL = { }; const execScript = (scriptPath) => { - return; try { execSync(`bash "${scriptPath}"`, { encoding: "utf-8", diff --git a/e2e/saml/shutdown.sh b/e2e/saml/shutdown.sh index 39d8ea81ef..685f76cb37 100755 --- a/e2e/saml/shutdown.sh +++ b/e2e/saml/shutdown.sh @@ -1,3 +1,20 @@ +#!/bin/bash + +# The contents of this file are subject to the terms of the Common Development and +# Distribution License (the License). You may not use this file except in compliance with the +# License. +# +# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the +# specific language governing permission and limitations under the License. +# +# When distributing Covered Software, include this CDDL Header Notice in each file and include +# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL +# Header, with the fields enclosed by brackets [] replaced by your own identifying +# information: "Portions copyright [year] [name of copyright owner]". +# +# Copyright 2026 3A Systems, LLC. + + echo "Stopping docker containers..." docker stop openam-idp openam-sp From 95d174a6a60aa6e86d76aa1288f670b9a0e94f4c Mon Sep 17 00:00:00 2001 From: maximthomas Date: Tue, 12 May 2026 14:22:02 +0300 Subject: [PATCH 04/13] fix test errors --- .github/workflows/build.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6da019795b..b0f08c7743 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -380,6 +380,9 @@ jobs: path: ~/.cache/ms-playwright key: ${{ runner.os }}-playwright-browsers restore-keys: ${{ runner.os }}-playwright- + - name: Set env + run: | + echo "REPO_LC=${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV - name: UI Smoke Tests (Playwright) run: | cd e2e @@ -388,7 +391,7 @@ jobs: npx playwright install chromium --with-deps npx playwright test --reporter=list env: - OPENAM_IMAGE: localhost:5000/${GITHUB_REPOSITORY,,}:${{ env.release_version }} + OPENAM_IMAGE: localhost:5000/${{ env.REPO_LC }}:${{ env.release_version }} - name: Upload failure artifacts uses: actions/upload-artifact@v7 if: ${{ failure() }} @@ -396,6 +399,5 @@ jobs: name: failure-ui-java${{ matrix.java }}-${{ matrix.context_label }}-${{ matrix.samples_label }} retention-days: 1 path: | - openidm/logs/** e2e/playwright-report/** e2e/test-results/** \ No newline at end of file From 03e58447c08405cf5759052f198ba0cb236da2a6 Mon Sep 17 00:00:00 2001 From: maximthomas Date: Tue, 12 May 2026 16:32:18 +0300 Subject: [PATCH 05/13] fix test errors --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b0f08c7743..2f596b91af 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -382,6 +382,8 @@ jobs: restore-keys: ${{ runner.os }}-playwright- - name: Set env run: | + export git_version_last="$(curl -i -o - --silent https://api.github.com/repos/OpenIdentityPlatform/OpenAM/releases/latest | grep -m1 "\"name\"" | cut -d\" -f4)" ; echo "last release: $git_version_last" + echo "release_version=$git_version_last" >> $GITHUB_ENV echo "REPO_LC=${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV - name: UI Smoke Tests (Playwright) run: | From 1d6a5b7deb7833665b8eb20b90b14037dc0e5497 Mon Sep 17 00:00:00 2001 From: maximthomas Date: Tue, 12 May 2026 18:32:38 +0300 Subject: [PATCH 06/13] share doker image between jobs --- .github/workflows/build.yml | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2f596b91af..ca47d63391 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -101,6 +101,14 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} + outputs: type=docker,dest=${{ runner.temp }}/openam-image.tar + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: myimage + path: ${{ runner.temp }}/openam-image.tar + - name: Docker test with an external OpenDJ identity store and an embedded OpenDJ configuration store shell: bash @@ -371,20 +379,35 @@ jobs: fail-fast: false steps: - uses: actions/checkout@v6 + + - name: Set env + run: | + export git_version_last="$(curl -i -o - --silent https://api.github.com/repos/OpenIdentityPlatform/OpenAM/releases/latest | grep -m1 "\"name\"" | cut -d\" -f4)" ; echo "last release: $git_version_last" + echo "release_version=$git_version_last" >> $GITHUB_ENV + echo "REPO_LC=${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV + + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: myimage + path: ${{ runner.temp }} + + - name: Load Docker image + run: | + docker load --input ${{ runner.temp }}/openam-image.tar + docker image ls -a + - name: Set Integration Test Environment run: | echo "127.0.0.1 idp.acme.org sp.mycompany.org" | sudo tee -a /etc/hosts + - name: Cache Playwright browsers uses: actions/cache@v5 with: path: ~/.cache/ms-playwright key: ${{ runner.os }}-playwright-browsers restore-keys: ${{ runner.os }}-playwright- - - name: Set env - run: | - export git_version_last="$(curl -i -o - --silent https://api.github.com/repos/OpenIdentityPlatform/OpenAM/releases/latest | grep -m1 "\"name\"" | cut -d\" -f4)" ; echo "last release: $git_version_last" - echo "release_version=$git_version_last" >> $GITHUB_ENV - echo "REPO_LC=${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV + - name: UI Smoke Tests (Playwright) run: | cd e2e From 725a6891e748df3e84ad701aa2207e0596f8a2d7 Mon Sep 17 00:00:00 2001 From: maximthomas Date: Tue, 12 May 2026 19:54:24 +0300 Subject: [PATCH 07/13] store docker to tar, temporary speedup build --- .github/workflows/build.yml | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ca47d63391..754c3a9f15 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,8 +9,10 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - java: [ '11', '17', '21', '25', '26' ] - os: [ 'ubuntu-latest', 'macos-latest', 'windows-latest' ] + # java: [ '11', '17', '21', '25', '26' ] + java: [ '11' ] + # os: [ 'ubuntu-latest', 'macos-latest', 'windows-latest' ] + os: [ 'ubuntu-latest' ] fail-fast: false steps: - uses: actions/checkout@v6 @@ -38,7 +40,8 @@ jobs: - name: Build with Maven env: MAVEN_OPTS: -Dhttps.protocols=TLSv1.2 -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.requestSentEnabled=true -Dmaven.wagon.http.retryHandler.count=10 - run: mvn --batch-mode --errors --update-snapshots package ${{ steps.maven-profile-flag.outputs.MAVEN_VERIFY_STAGE }} --file pom.xml ${{ steps.maven-profile-flag.outputs.MAVEN_PROFILE_FLAG }} + # run: mvn --batch-mode --errors --update-snapshots package ${{ steps.maven-profile-flag.outputs.MAVEN_VERIFY_STAGE }} --file pom.xml ${{ steps.maven-profile-flag.outputs.MAVEN_PROFILE_FLAG }} + run: mvn --batch-mode --errors --update-snapshots package ${{ steps.maven-profile-flag.outputs.MAVEN_VERIFY_STAGE }} --file pom.xml -DskipTests=true -Dcargo.maven.skip=true -P \!man-pages - name: Upload artifacts uses: actions/upload-artifact@v6 with: @@ -101,9 +104,12 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - outputs: type=docker,dest=${{ runner.temp }}/openam-image.tar - - name: Upload artifact + - name: Save docker image to tar + shell: bash + run: | + docker save -o ${{ runner.temp }}/openam-image.tar localhost:5000/${GITHUB_REPOSITORY,,}:${{ env.release_version }} + - name: Upload docker image uses: actions/upload-artifact@v4 with: name: myimage From 66093c4bd0064621f145ec56469b456d0ef2383e Mon Sep 17 00:00:00 2001 From: maximthomas Date: Tue, 12 May 2026 21:23:31 +0300 Subject: [PATCH 08/13] pull image before save --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 754c3a9f15..be42ce0564 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -108,6 +108,7 @@ jobs: - name: Save docker image to tar shell: bash run: | + docker pull localhost:5000/${GITHUB_REPOSITORY,,}:${{ env.release_version }} docker save -o ${{ runner.temp }}/openam-image.tar localhost:5000/${GITHUB_REPOSITORY,,}:${{ env.release_version }} - name: Upload docker image uses: actions/upload-artifact@v4 From a36d2d2df7104fd22d3432b9c031b46263014dfa Mon Sep 17 00:00:00 2001 From: maximthomas Date: Tue, 12 May 2026 21:25:16 +0300 Subject: [PATCH 09/13] shorten build time --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index be42ce0564..d2f60026db 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,7 @@ jobs: env: MAVEN_OPTS: -Dhttps.protocols=TLSv1.2 -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.requestSentEnabled=true -Dmaven.wagon.http.retryHandler.count=10 # run: mvn --batch-mode --errors --update-snapshots package ${{ steps.maven-profile-flag.outputs.MAVEN_VERIFY_STAGE }} --file pom.xml ${{ steps.maven-profile-flag.outputs.MAVEN_PROFILE_FLAG }} - run: mvn --batch-mode --errors --update-snapshots package ${{ steps.maven-profile-flag.outputs.MAVEN_VERIFY_STAGE }} --file pom.xml -DskipTests=true -Dcargo.maven.skip=true -P \!man-pages + run: mvn --batch-mode --errors --update-snapshots package ${{ steps.maven-profile-flag.outputs.MAVEN_VERIFY_STAGE }} --file pom.xml -DskipTests=true -Dcargo.maven.skip=true -P \!man-pages -rf :openam-server - name: Upload artifacts uses: actions/upload-artifact@v6 with: From ebc45eb4d9f9bcb09189bcaa9c23c277088bef5b Mon Sep 17 00:00:00 2001 From: maximthomas Date: Tue, 12 May 2026 21:30:29 +0300 Subject: [PATCH 10/13] - --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d2f60026db..be42ce0564 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,7 @@ jobs: env: MAVEN_OPTS: -Dhttps.protocols=TLSv1.2 -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.requestSentEnabled=true -Dmaven.wagon.http.retryHandler.count=10 # run: mvn --batch-mode --errors --update-snapshots package ${{ steps.maven-profile-flag.outputs.MAVEN_VERIFY_STAGE }} --file pom.xml ${{ steps.maven-profile-flag.outputs.MAVEN_PROFILE_FLAG }} - run: mvn --batch-mode --errors --update-snapshots package ${{ steps.maven-profile-flag.outputs.MAVEN_VERIFY_STAGE }} --file pom.xml -DskipTests=true -Dcargo.maven.skip=true -P \!man-pages -rf :openam-server + run: mvn --batch-mode --errors --update-snapshots package ${{ steps.maven-profile-flag.outputs.MAVEN_VERIFY_STAGE }} --file pom.xml -DskipTests=true -Dcargo.maven.skip=true -P \!man-pages - name: Upload artifacts uses: actions/upload-artifact@v6 with: From 87209278e3bef30bb1e89e3184169aaa5c6c576e Mon Sep 17 00:00:00 2001 From: maximthomas Date: Wed, 13 May 2026 17:28:57 +0300 Subject: [PATCH 11/13] fix test errors --- .../java/com/sun/identity/idm/plugins/internal/SpecialRepo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openam-core/src/main/java/com/sun/identity/idm/plugins/internal/SpecialRepo.java b/openam-core/src/main/java/com/sun/identity/idm/plugins/internal/SpecialRepo.java index dbc46e140b..2acd23555a 100644 --- a/openam-core/src/main/java/com/sun/identity/idm/plugins/internal/SpecialRepo.java +++ b/openam-core/src/main/java/com/sun/identity/idm/plugins/internal/SpecialRepo.java @@ -566,7 +566,7 @@ public RepoSearchResults search(SSOToken token, IdType type, CrestQuery crestQue if (uidVals != null && !uidVals.isEmpty()) { pattern = (String) uidVals.iterator().next(); if (crestQuery.isEscapeQueryId()) { - pattern = crestQuery.getEscapedQueryId(); + pattern = Filter.escapeAssertionValue(pattern); } } else { // pattern is "*" and avPairs is not empty, so return From fcb483c1f4803ac0e2d48b4b4de5a7faa727b85e Mon Sep 17 00:00:00 2001 From: maximthomas Date: Thu, 14 May 2026 05:30:42 +0300 Subject: [PATCH 12/13] restore full build matrix --- .github/workflows/build.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index be42ce0564..bbb3baf405 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,10 +9,8 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - # java: [ '11', '17', '21', '25', '26' ] - java: [ '11' ] - # os: [ 'ubuntu-latest', 'macos-latest', 'windows-latest' ] - os: [ 'ubuntu-latest' ] + java: [ '11', '17', '21', '25', '26' ] + os: [ 'ubuntu-latest', 'macos-latest', 'windows-latest' ] fail-fast: false steps: - uses: actions/checkout@v6 @@ -40,8 +38,7 @@ jobs: - name: Build with Maven env: MAVEN_OPTS: -Dhttps.protocols=TLSv1.2 -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.requestSentEnabled=true -Dmaven.wagon.http.retryHandler.count=10 - # run: mvn --batch-mode --errors --update-snapshots package ${{ steps.maven-profile-flag.outputs.MAVEN_VERIFY_STAGE }} --file pom.xml ${{ steps.maven-profile-flag.outputs.MAVEN_PROFILE_FLAG }} - run: mvn --batch-mode --errors --update-snapshots package ${{ steps.maven-profile-flag.outputs.MAVEN_VERIFY_STAGE }} --file pom.xml -DskipTests=true -Dcargo.maven.skip=true -P \!man-pages + run: mvn --batch-mode --errors --update-snapshots package ${{ steps.maven-profile-flag.outputs.MAVEN_VERIFY_STAGE }} --file pom.xml ${{ steps.maven-profile-flag.outputs.MAVEN_PROFILE_FLAG }} - name: Upload artifacts uses: actions/upload-artifact@v6 with: @@ -104,7 +101,7 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - + - name: Save docker image to tar shell: bash run: | @@ -116,7 +113,6 @@ jobs: name: myimage path: ${{ runner.temp }}/openam-image.tar - - name: Docker test with an external OpenDJ identity store and an embedded OpenDJ configuration store shell: bash run: | From 34f811e44a1ed8f25fc3a20fd713a8a33befbc5f Mon Sep 17 00:00:00 2001 From: Maxim Thomas Date: Fri, 15 May 2026 19:09:40 +0300 Subject: [PATCH 13/13] SAML end to end test integrated into docker build step (#8) --- .github/workflows/build.yml | 252 +++++++++++++++++++----------------- e2e/saml/bootstrap.sh | 91 +------------ e2e/saml/saml-test.spec.mjs | 13 +- e2e/saml/shutdown.sh | 23 ---- 4 files changed, 138 insertions(+), 241 deletions(-) delete mode 100755 e2e/saml/shutdown.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bbb3baf405..c81ca74587 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -102,30 +102,30 @@ jobs: tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - - name: Save docker image to tar + - name: Prepare environment shell: bash run: | - docker pull localhost:5000/${GITHUB_REPOSITORY,,}:${{ env.release_version }} - docker save -o ${{ runner.temp }}/openam-image.tar localhost:5000/${GITHUB_REPOSITORY,,}:${{ env.release_version }} - - name: Upload docker image - uses: actions/upload-artifact@v4 - with: - name: myimage - path: ${{ runner.temp }}/openam-image.tar + echo "OPENAM_IMAGE=localhost:5000/${GITHUB_REPOSITORY,,}:${{ env.release_version }}" >> $GITHUB_ENV + docker network create test-openam + echo "127.0.0.1 openam.example.org sp.mycompany.org" | sudo tee -a /etc/hosts - - name: Docker test with an external OpenDJ identity store and an embedded OpenDJ configuration store + - name: Docker test with an external OpenDJ identity store and an embedded OpenDJ configuration store (IDP) shell: bash run: | - docker network create test-openam - docker run --rm -it -d --hostname opendj -p 1389:1389 -p 4444:4444 --name test-opendj --network test-openam openidentityplatform/opendj:latest - docker run --rm -it -d --memory="2g" -h openam.example.org --name=test-openam --network test-openam localhost:5000/${GITHUB_REPOSITORY,,}:${{ env.release_version }} - + echo "Setup IDP" + + docker run --rm -it -d --hostname opendj-idp --name opendj-idp --network test-openam openidentityplatform/opendj:latest + docker run --rm -it -d -p 8080:8080 -p 8000:8000 --memory="2g" -h openam.example.org --name=openam-idp --network test-openam \ + -e JPDA_ADDRESS=*:8000 \ + -e JPDA_TRANSPORT=dt_socket \ + ${OPENAM_IMAGE} catalina.sh jpda run + echo "waiting for OpenDJ to be alive..." - timeout 3m bash -c 'until docker inspect --format="{{json .State.Health.Status}}" test-opendj | grep -q \"healthy\"; do sleep 10; done' + timeout 3m bash -c 'until docker inspect --format="{{json .State.Health.Status}}" opendj-idp | grep -q \"healthy\"; do sleep 10; done' echo "waiting for OpenAM to be alive..." - timeout 3m bash -c 'until docker inspect --format="{{json .State.Health.Status}}" test-openam | grep -q \"healthy\"; do sleep 10; done' - - docker exec -w '/usr/openam/ssoconfiguratortools' test-openam bash -c \ + timeout 3m bash -c 'until docker inspect --format="{{json .State.Health.Status}}" openam-idp | grep -q \"healthy\"; do sleep 10; done' + + docker exec -w '/usr/openam/ssoconfiguratortools' openam-idp bash -c \ 'echo "ACCEPT_LICENSES=true SERVER_URL=http://openam.example.org:8080 DEPLOYMENT_URI=/$OPENAM_PATH @@ -147,43 +147,79 @@ jobs: DS_DIRMGRPASSWD=password USERSTORE_TYPE=LDAPv3ForOpenDS USERSTORE_SSL=SIMPLE - USERSTORE_HOST=opendj + USERSTORE_HOST=opendj-idp USERSTORE_PORT=1389 USERSTORE_SUFFIX=dc=example,dc=com USERSTORE_MGRDN=cn=Directory Manager USERSTORE_PASSWD=password " > conf.file && java -jar openam-configurator-tool*.jar --file conf.file' - - docker exec test-openam bash -c \ - 'curl \ - --request POST \ - --header "Content-Type: application/json" \ - --header "X-OpenAM-Username: amadmin" \ - --header "X-OpenAM-Password: ampassword" \ - --data "{}" \ - http://openam.example.org:8080/openam/json/authenticate | grep tokenId' - - docker inspect --format="{{json .State.Health.Status}}" test-openam | grep -q \"healthy\" - - echo "Stopping containers and removing the network" - docker stop test-opendj test-openam - docker network rm test-openam - - name: Docker test with a dedicated OpenDJ container + echo "Setup ssoadm tools for OpenAM IDP" + + docker exec -w '/usr/openam/ssoadmintools' openam-idp bash -c './setup -p /usr/openam/config --acceptLicense' + + docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-idp bash -c 'echo ampassword > pwd.txt && chmod 400 pwd.txt' + + echo "Test IDP authentication" + + ADMIN_TOKEN=$(docker exec openam-idp bash -c \ + 'curl -sf \ + --request POST \ + --header "Content-Type: application/json" \ + --header "X-OpenAM-Username: amadmin" \ + --header "X-OpenAM-Password: ampassword" \ + --data "{}" \ + http://openam.example.org:8080/openam/json/authenticate' | jq -r .tokenId) + + docker inspect --format="{{json .State.Health.Status}}" openam-idp | grep -q \"healthy\" + + echo "Setup IDP test user" + + curl -sS -X POST \ + -H "iPlanetDirectoryPro: ${ADMIN_TOKEN}" \ + -H "Content-Type: application/json" \ + -H "Accept-API-Version: resource=3.0, protocol=2.1" \ + -d "{ + \"username\": \"demo\", + \"userpassword\": \"changeit\", + \"mail\": \"demo@example.com\", + \"sn\": \"Demo\", + \"givenName\": \"Demo\", + \"cn\": \"Demo Demo\" + }" \ + "http://openam.example.org:8080/openam/json/realms/root/users?_action=create" + + echo "Test demo user Auth" + + docker exec openam-idp bash -c \ + 'curl -sf \ + --request POST \ + --header "Content-Type: application/json" \ + --header "X-OpenAM-Username: demo" \ + --header "X-OpenAM-Password: changeit" \ + --data "{}" \ + http://openam.example.org:8080/openam/json/authenticate' + + - name: Docker start with a dedicated OpenDJ container (SP) shell: bash run: | - docker network create test-openam - docker run --rm -it -d --hostname opendj -p 1389:1389 -p 4444:4444 --name test-opendj --network test-openam openidentityplatform/opendj:latest - docker run --rm -it -d --memory="2g" -h openam.example.org --name=test-openam --network test-openam localhost:5000/${GITHUB_REPOSITORY,,}:${{ env.release_version }} - + echo "Setup SP" + + docker run --rm -it -d --hostname opendj-sp --name opendj-sp --network test-openam openidentityplatform/opendj:latest + + docker run --rm -it -d -p 8081:8080 -p 8001:8000 --memory="2g" -h sp.mycompany.org --name=openam-sp --network test-openam \ + -e JPDA_ADDRESS=*:8000 \ + -e JPDA_TRANSPORT=dt_socket \ + ${OPENAM_IMAGE} catalina.sh jpda run + echo "waiting for OpenDJ to be alive..." - timeout 3m bash -c 'until docker inspect --format="{{json .State.Health.Status}}" test-opendj | grep -q \"healthy\"; do sleep 10; done' + timeout 3m bash -c 'until docker inspect --format="{{json .State.Health.Status}}" opendj-sp | grep -q \"healthy\"; do sleep 10; done' echo "waiting for OpenAM to be alive..." - timeout 3m bash -c 'until docker inspect --format="{{json .State.Health.Status}}" test-openam | grep -q \"healthy\"; do sleep 10; done' - - docker exec -w '/usr/openam/ssoconfiguratortools' test-openam bash -c \ + timeout 3m bash -c 'until docker inspect --format="{{json .State.Health.Status}}" openam-sp | grep -q \"healthy\"; do sleep 10; done' + + docker exec -w '/usr/openam/ssoconfiguratortools' openam-sp bash -c \ 'echo "ACCEPT_LICENSES=true - SERVER_URL=http://openam.example.org:8080 + SERVER_URL=http://sp.mycompany.org:8080 DEPLOYMENT_URI=/$OPENAM_PATH BASE_DIR=$OPENAM_DATA_DIR locale=en_US @@ -191,10 +227,10 @@ jobs: AM_ENC_KEY= ADMIN_PWD=ampassword AMLDAPUSERPASSWD=password - COOKIE_DOMAIN=example.org + COOKIE_DOMAIN=mycompany.org DATA_STORE=dirServer DIRECTORY_SSL=SIMPLE - DIRECTORY_SERVER=opendj + DIRECTORY_SERVER=opendj-sp DIRECTORY_PORT=1389 DIRECTORY_ADMIN_PORT=4444 DIRECTORY_JMX_PORT=1689 @@ -203,26 +239,65 @@ jobs: DS_DIRMGRPASSWD=password USERSTORE_TYPE=LDAPv3ForOpenDS USERSTORE_SSL=SIMPLE - USERSTORE_HOST=opendj + USERSTORE_HOST=opendj-sp USERSTORE_PORT=1389 USERSTORE_SUFFIX=dc=example,dc=com USERSTORE_MGRDN=cn=Directory Manager USERSTORE_PASSWD=password " > conf.file && java -jar openam-configurator-tool*.jar --file conf.file' + + echo "Setup ssoadm tools for OpenAM SP" + + docker exec -w '/usr/openam/ssoadmintools' openam-sp bash -c './setup -p /usr/openam/config --acceptLicense' + + docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-sp bash -c 'echo ampassword > pwd.txt && chmod 400 pwd.txt' - docker exec test-openam bash -c \ - 'curl \ - --request POST \ - --header "Content-Type: application/json" \ - --header "X-OpenAM-Username: amadmin" \ - --header "X-OpenAM-Password: ampassword" \ - --data "{}" \ - http://openam.example.org:8080/openam/json/authenticate | grep tokenId' - - docker inspect --format="{{json .State.Health.Status}}" test-openam | grep -q \"healthy\" - - echo "Stopping containers and removing the network" - docker stop test-opendj test-openam + echo "Test SP authentication" + + docker exec openam-sp bash -c \ + 'curl \ + --request POST \ + --header "Content-Type: application/json" \ + --header "X-OpenAM-Username: amadmin" \ + --header "X-OpenAM-Password: ampassword" \ + --data "{}" \ + http://sp.mycompany.org:8080/openam/json/authenticate | grep tokenId' + + docker inspect --format="{{json .State.Health.Status}}" openam-sp | grep -q \"healthy\" + + - name: Cache Playwright browsers + uses: actions/cache@v5 + with: + path: ~/.cache/ms-playwright + key: ${{ runner.os }}-playwright-browsers + restore-keys: ${{ runner.os }}-playwright- + + - uses: actions/checkout@v6 + with: + sparse-checkout: e2e + + - name: UI Smoke Tests (Playwright) + run: | + cd e2e + npm init -y + npm install @playwright/test + npx playwright install chromium --with-deps + npx playwright test --reporter=list + + - name: Upload failure artifacts + uses: actions/upload-artifact@v7 + if: ${{ failure() }} + with: + name: failure-ui + retention-days: 1 + path: | + e2e/playwright-report/** + e2e/test-results/** + + - name: Stopping containers and removing the network + shell: bash + run: | + docker stop openam-idp opendj-idp opendj-sp openam-sp docker network rm test-openam - name: Docker multi-server test @@ -370,62 +445,3 @@ jobs: http://openam3.example.org:8080/openam/json/authenticate | grep tokenId' docker inspect --format="{{json .State.Health.Status}}" test-openam3 | grep -q \"healthy\" - ui-smoke-tests: - runs-on: ubuntu-latest - needs: build-docker - services: - registry: - image: registry:2 - ports: - - 5000:5000 - strategy: - fail-fast: false - steps: - - uses: actions/checkout@v6 - - - name: Set env - run: | - export git_version_last="$(curl -i -o - --silent https://api.github.com/repos/OpenIdentityPlatform/OpenAM/releases/latest | grep -m1 "\"name\"" | cut -d\" -f4)" ; echo "last release: $git_version_last" - echo "release_version=$git_version_last" >> $GITHUB_ENV - echo "REPO_LC=${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV - - - name: Download artifact - uses: actions/download-artifact@v4 - with: - name: myimage - path: ${{ runner.temp }} - - - name: Load Docker image - run: | - docker load --input ${{ runner.temp }}/openam-image.tar - docker image ls -a - - - name: Set Integration Test Environment - run: | - echo "127.0.0.1 idp.acme.org sp.mycompany.org" | sudo tee -a /etc/hosts - - - name: Cache Playwright browsers - uses: actions/cache@v5 - with: - path: ~/.cache/ms-playwright - key: ${{ runner.os }}-playwright-browsers - restore-keys: ${{ runner.os }}-playwright- - - - name: UI Smoke Tests (Playwright) - run: | - cd e2e - npm init -y - npm install @playwright/test - npx playwright install chromium --with-deps - npx playwright test --reporter=list - env: - OPENAM_IMAGE: localhost:5000/${{ env.REPO_LC }}:${{ env.release_version }} - - name: Upload failure artifacts - uses: actions/upload-artifact@v7 - if: ${{ failure() }} - with: - name: failure-ui-java${{ matrix.java }}-${{ matrix.context_label }}-${{ matrix.samples_label }} - retention-days: 1 - path: | - e2e/playwright-report/** - e2e/test-results/** \ No newline at end of file diff --git a/e2e/saml/bootstrap.sh b/e2e/saml/bootstrap.sh index e1620093cb..64f15943ad 100755 --- a/e2e/saml/bootstrap.sh +++ b/e2e/saml/bootstrap.sh @@ -17,53 +17,6 @@ set -e -OPENAM_IMAGE=${OPENAM_IMAGE:-"openidentityplatform/openam"} - -echo "Using docker image: ${OPENAM_IMAGE}" - -docker network create openam-saml 2>/dev/null || true - -echo "running OpenAM IDP container..." - -docker run --rm -it -d -h idp.acme.org -p 8080:8080 -p 8000:8000 --network openam-saml --name openam-idp \ - -e JPDA_ADDRESS=*:8000 \ - -e JPDA_TRANSPORT=dt_socket \ - ${OPENAM_IMAGE} catalina.sh jpda run - -echo "waiting for OpenAM IDP to be alive..." - -timeout 3m bash -c 'until docker inspect --format="{{json .State.Health.Status}}" openam-idp | grep -q \"healthy\"; do sleep 10; done' - - -echo "Running OpenAM IDP setup" - -docker exec -w '/usr/openam/ssoconfiguratortools' openam-idp bash -c \ -'echo "ACCEPT_LICENSES=true -SERVER_URL=http://idp.acme.org:8080 -DEPLOYMENT_URI=/$OPENAM_PATH -BASE_DIR=$OPENAM_DATA_DIR -locale=en_US -PLATFORM_LOCALE=en_US -AM_ENC_KEY= -ADMIN_PWD=passw0rd -AMLDAPUSERPASSWD=p@passw0rd -COOKIE_DOMAIN=idp.acme.org -ACCEPT_LICENSES=true -DATA_STORE=embedded -DIRECTORY_SSL=SIMPLE -DIRECTORY_SERVER=idp.acme.org -DIRECTORY_PORT=50389 -DIRECTORY_ADMIN_PORT=4444 -DIRECTORY_JMX_PORT=1689 -ROOT_SUFFIX=dc=openam,dc=example,dc=org -DS_DIRMGRDN=cn=Directory Manager -DS_DIRMGRPASSWD=passw0rd" > conf.file && java -jar openam-configurator-tool*.jar --file conf.file' - -echo "Setup ssoadm tools for OpenAM IDP" - -docker exec -w '/usr/openam/ssoadmintools' openam-idp bash -c './setup -p /usr/openam/config --acceptLicense' - -docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-idp bash -c 'echo passw0rd > pwd.txt && chmod 400 pwd.txt' echo "Setup COT for OpenAM IDP" docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-idp bash -c \ @@ -79,7 +32,7 @@ docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-idp bash -c \ './ssoadm create-metadata-templ \ --adminid amadmin \ --password-file pwd.txt \ - --entityid http://idp.acme.org:8080/openam \ + --entityid http://openam.example.org:8080/openam \ --identityprovider /idp \ --idpscertalias test \ --meta-data-file idp-metadata.xml \ @@ -95,7 +48,7 @@ sed -i " } " idp-extended.xml' -echo "Create hosted identity provider for OpenAM IDP" +echo "Create a hosted identity provider for OpenAM IDP" docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-idp bash -c \ './ssoadm import-entity \ @@ -108,46 +61,6 @@ docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-idp bash -c \ echo "Running OpenAM SP setup" -docker run --rm -it -d -h sp.mycompany.org -p 8081:8080 -p 8001:8000 --network openam-saml --name openam-sp \ - -e JPDA_ADDRESS=*:8000 \ - -e JPDA_TRANSPORT=dt_socket \ - ${OPENAM_IMAGE} catalina.sh jpda run - -echo "waiting for OpenAM SP to be alive..." - -timeout 3m bash -c 'until docker inspect --format="{{json .State.Health.Status}}" openam-sp | grep -q \"healthy\"; do sleep 10; done' - -echo "Running OpenAM SP setup" - -docker exec -w '/usr/openam/ssoconfiguratortools' openam-sp bash -c \ -'echo "ACCEPT_LICENSES=true -SERVER_URL=http://sp.mycompany.org:8080 -DEPLOYMENT_URI=/$OPENAM_PATH -BASE_DIR=$OPENAM_DATA_DIR -locale=en_US -PLATFORM_LOCALE=en_US -AM_ENC_KEY= -ADMIN_PWD=passw0rd -AMLDAPUSERPASSWD=p@passw0rd -COOKIE_DOMAIN=sp.mycompany.org -ACCEPT_LICENSES=true -DATA_STORE=embedded -DIRECTORY_SSL=SIMPLE -DIRECTORY_SERVER=sp.mycompany.org -DIRECTORY_PORT=50389 -DIRECTORY_ADMIN_PORT=4444 -DIRECTORY_JMX_PORT=1689 -ROOT_SUFFIX=dc=openam,dc=example,dc=org -DS_DIRMGRDN=cn=Directory Manager -DS_DIRMGRPASSWD=passw0rd" > conf.file && java -jar openam-configurator-tool*.jar --file conf.file' - - -echo "Setup ssoadm tools for OpenAM SP" - -docker exec -w '/usr/openam/ssoadmintools' openam-sp bash -c './setup -p /usr/openam/config --acceptLicense' - -docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-sp bash -c 'echo passw0rd > pwd.txt && chmod 400 pwd.txt' - echo "Setup COT for OpenAM SP" docker exec -w '/usr/openam/ssoadmintools/openam/bin' openam-sp bash -c \ diff --git a/e2e/saml/saml-test.spec.mjs b/e2e/saml/saml-test.spec.mjs index 82af561588..2137d18816 100644 --- a/e2e/saml/saml-test.spec.mjs +++ b/e2e/saml/saml-test.spec.mjs @@ -28,7 +28,6 @@ import { fileURLToPath } from "url"; * OPENAM_USERNAME – login username (default: demo) * OPENAM_PASSWORD – login password (default: changeit) * BOOTSTRAP_SCRIPT – path to the startup script (default: ./bootstrap.sh) - * SHUTDOWN_SCRIPT – path to the shutdown script (default: ./shutdown.sh) */ // ─── __dirname equivalent in ESM ────────────────────────────────────────────── @@ -39,11 +38,10 @@ const __dirname = fileURLToPath(new URL(".", import.meta.url)); const USERNAME = process.env.OPENAM_USERNAME ?? "demo"; const PASSWORD = process.env.OPENAM_PASSWORD ?? "changeit"; const BOOTSTRAP_SCRIPT = process.env.BOOTSTRAP_SCRIPT ?? "./bootstrap.sh"; -const SHUTDOWN_SCRIPT = process.env.SHUTDOWN_SCRIPT ?? "./shutdown.sh"; // Derived URLs -const LOGIN_URL = "http://sp.mycompany.org:8081/openam/spssoinit?metaAlias=/sp&idpEntityID=http%3A//idp.acme.org%3A8080/openam&RelayState=http%3A//sp.mycompany.org%3A8081/openam"; -const EXPECTED_IDP_URL_PATTERN = /idp\.acme\.org/; +const LOGIN_URL = "http://sp.mycompany.org:8081/openam/spssoinit?metaAlias=/sp&idpEntityID=http%3A//openam.example.org%3A8080/openam&RelayState=http%3A//sp.mycompany.org%3A8081/openam"; +const EXPECTED_IDP_URL_PATTERN = /openam\.example\.org/; const EXPECTED_SP_URL_PATTERN = /sp\.mycompany\.org/; // ─── Selectors (XUI / LESS-based OpenAM UI) ─────────────────────────────────── @@ -76,13 +74,6 @@ test.beforeAll(() => { }); -// ─── Shutdown – run once after all tests ──────────────────────────────────── -test.afterAll(() => { - const scriptPath = resolve(__dirname, SHUTDOWN_SCRIPT); - console.log(`\n▶ Running shutdown script: ${scriptPath}`); - execScript(scriptPath); -}); - // ─── Tests ──────────────────────────────────────────────────────────────────── test.describe("OpenAM XUI - Login flow", () => { test("should log in as demo and reach the authenticated page", async ({ page }) => { diff --git a/e2e/saml/shutdown.sh b/e2e/saml/shutdown.sh deleted file mode 100755 index 685f76cb37..0000000000 --- a/e2e/saml/shutdown.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -# The contents of this file are subject to the terms of the Common Development and -# Distribution License (the License). You may not use this file except in compliance with the -# License. -# -# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the -# specific language governing permission and limitations under the License. -# -# When distributing Covered Software, include this CDDL Header Notice in each file and include -# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL -# Header, with the fields enclosed by brackets [] replaced by your own identifying -# information: "Portions copyright [year] [name of copyright owner]". -# -# Copyright 2026 3A Systems, LLC. - - -echo "Stopping docker containers..." -docker stop openam-idp openam-sp - -echo "Removing network..." -docker network rm openam-saml -echo "Finished" \ No newline at end of file