Files
computer-playbook/roles/web-app-suitecrm/templates/playwright.env.j2
kevinveenbirkenbachandClaude Opus 5 093c84c620 fix(suitecrm): block the personas SAML cannot serve, cover their ground natively
Both shared flows gate performKeycloakLogin on 'openid-connect/auth' (personas/biber.js:85, personas/admin.js:64). SuiteCRM's SSO is SAML - d15716643 moved it off the oauth2-proxy onto nbgrp/onelogin-saml-bundle - so its auth URL is /realms/<realm>/login-actions/authenticate for client <base>/saml/metadata. The gate never opens, performKeycloakLogin never runs, and the personas fail at 'did NOT reach an authenticated surface'.

The trace of job 95883075126 carries no fill() at all: goto, clearCookies x2, waitForSelector x5, click x2, waitForFunction x2, fetch. Nothing was ever typed. Keycloak's 24 LOGIN_ERROR entries are the consequence - requests to login-actions/authenticate without credentials, which is also why they carry no username attribute.

The block alone would drop coverage, so saml.spec.js takes it over where the session already exists: assertCspInjections on the authenticated surface, inAppLogout, session-status must report active:false, then assertUnauthenticatedLanding. That is what runBiberFlow asserted, minus runRoleInteraction, which SuiteCRM never passed. The SAML round trip itself stays green in the two existing tests.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 16:41:09 +02:00

42 lines
2.9 KiB
Bash

{% if not SUITECRM_LDAP_ENABLED | bool %}
ADMIN_NATIVE_PASSWORD={{ lookup('config', application_id, 'secrets.credentials.administrator_password') | dotenv_quote }}
{% endif %}
ADMIN_PASSWORD={{ lookup('users', 'administrator').password | dotenv_quote }}
ADMIN_USERNAME={{ lookup('users', 'administrator').username | dotenv_quote }}
APP_BASE_URL={{ lookup('tls', application_id, 'url.base') | dotenv_quote }}
BIBER_PASSWORD={{ lookup('users', 'biber').password | dotenv_quote }}
BIBER_USERNAME={{ lookup('users', 'biber').username | dotenv_quote }}
CANONICAL_DOMAIN={{ lookup('domain', application_id) | dotenv_quote }}
# nocheck: playwright-service-gate — the CSP helper gates css through a computed loop variable (personas/utils/csp.js:87-93), never a literal argument, so test_spec_env_gates.py's literal-only regex cannot see the gate
CSS_SERVICE_ENABLED={{ lookup('config', application_id, 'services.css.enabled') | string | lower }}
# nocheck: playwright-service-gate — the role wires no SMTP at all: templates/env.j2 renders no mail key and services.suitecrm.email.from_name is read by nothing, so the flag has no surface to gate
EMAIL_SERVICE_ENABLED={{ lookup('config', application_id, 'services.email.enabled') | string | lower }}
# nocheck: playwright-service-gate — only swaps SuiteCRM's own AUTH_TYPE to ldap, and only when SSO is off; with SSO on, templates/env.j2 selects saml and the LDAP block is never rendered
LDAP_SERVICE_ENABLED={{ lookup('config', application_id, 'services.ldap.enabled') | string | lower }}
LOGOUT_SERVICE_ENABLED={{ lookup('config', application_id, 'services.logout.enabled') | string | lower }}
# nocheck: playwright-service-gate — SuiteCRM refuses to boot past its installer without the database, so every scenario already proves it
MARIADB_SERVICE_ENABLED={{ lookup('config', application_id, 'services.mariadb.enabled') | string | lower }}
MATOMO_BASE_URL={{ lookup('tls', 'web-app-matomo', 'url.base') | dotenv_quote }}
MATOMO_SERVICE_ENABLED={{ lookup('config', application_id, 'services.matomo.enabled') | string | lower }}
# nocheck: persona-block-rationale — both shared flows gate performKeycloakLogin on `openid-connect/auth` (personas/admin.js:64), and SuiteCRM's SSO is SAML: its auth URL is /realms/<realm>/login-actions/authenticate for client <base>/saml/metadata, so the gate never opens and the persona never signs in. The role covers the same ground natively: files/playwright/saml.spec.js drives the SAML round trip for both personas and asserts the in-app logout ends SuiteCRM's own session, files/playwright/ldap.spec.js covers the sso-off variant (see README "Persona contract opt-outs").
PERSONA_ADMINISTRATOR_BLOCKED=true
# nocheck: persona-block-rationale — see PERSONA_ADMINISTRATOR_BLOCKED above; the shared biber flow is gated the same way (personas/biber.js:85).
PERSONA_BIBER_BLOCKED=true
SSO_SERVICE_ENABLED={{ lookup('config', application_id, 'services.sso.enabled') | string | lower }}