fix(stalwart): fixed secrets

This commit is contained in:
Alejandro Roman committed 2026-09-30 16:00:58 +04:00
1 parent 90a0f06396
commit 6144c85978
8 files changed
+16 -36

No files matched your search

+1
View File
@@ -48,6 +48,7 @@ API:
OIDC_OVERRIDE:
CLIENT:
SECRET: VERYUNSAFESAMPLEPASSWORD1234
PLAYWRIGHT_MAPACHE_PASSWORD: "VeryUnsecureMapache!1"
users:
administrator:
authorized_keys:
@@ -7,22 +7,11 @@
* provisions it once; consumers prove they create the account on first
* OIDC login.
*
* `mapachePassword(secret)`
* The password mapache carries, derived from the generated
* `secrets.credentials.mapache_password` both specs receive, so the
* provisioning spec and every consumer compute the same value.
*
* Args:
* secret: the rendered credential (64 hex characters).
*
* Returns: the credential extended to satisfy the realm password policy.
*
* `provisionKeycloakUser(browser, options)`
* Signs the master-realm administrator into the admin console, creates
* `options.user` in `options.realm` when it is missing, and sets
* `options.password` as its permanent password either way: the matrix
* rotates every credential between its two passes, so an existing user
* must take the current value.
* `options.password` as its permanent password either way, so a user
* left on a reused stack always ends up on the inventory's value.
*
* Args:
* browser: Playwright `Browser`; the flow runs in its own context.
@@ -44,10 +33,6 @@ const MAPACHE = {
lastName: "Mapache",
};
function mapachePassword(secret) {
return `${secret}Aa1!`;
}
async function openUser(page, username) {
const search = page.getByPlaceholder(/search user/i).first();
await search.waitFor({ state: "visible", timeout: resolveTimeout(60_000) });
@@ -132,6 +117,5 @@ async function provisionKeycloakUser(browser, options) {
module.exports = {
MAPACHE,
mapachePassword,
provisionKeycloakUser,
};
@@ -1,7 +1,7 @@
const { test, expect } = require("@playwright/test");
const { resolveTimeout } = require("./timeouts");
const { MAPACHE, mapachePassword, assertCspMetaParity, assertCspResponseHeader, decodeDotenvQuotedValue, expectNoCspViolations, gotoOnion, installCspViolationObserver, normalizeBaseUrl, provisionKeycloakUser, runAdminFlow, runBiberFlow, runGuestFlow, safeSkipUnlessEnabled } = require("./personas");
const { MAPACHE, assertCspMetaParity, assertCspResponseHeader, decodeDotenvQuotedValue, expectNoCspViolations, gotoOnion, installCspViolationObserver, normalizeBaseUrl, provisionKeycloakUser, runAdminFlow, runBiberFlow, runGuestFlow, safeSkipUnlessEnabled } = require("./personas");
test.use({ ignoreHTTPSErrors: true });
// -----------------------------------------------------------------------------
@@ -82,7 +82,7 @@ const adminPassword = decodeDotenvQuotedValue(process.env.ADMIN_PASSWORD);
const biberUsername = decodeDotenvQuotedValue(process.env.BIBER_USERNAME);
const biberPassword = decodeDotenvQuotedValue(process.env.BIBER_PASSWORD);
const domainPrimary = decodeDotenvQuotedValue(process.env.DOMAIN_PRIMARY);
const mapacheSecret = decodeDotenvQuotedValue(process.env.MAPACHE_PASSWORD);
const mapachePassword = decodeDotenvQuotedValue(process.env.MAPACHE_PASSWORD);
const canonicalDomain = decodeDotenvQuotedValue(process.env.CANONICAL_DOMAIN);
test.beforeEach(async ({ page }) => {
@@ -203,17 +203,16 @@ test("super administrator onboards mapache in the admin console and mapache sign
const diagnostics = attachDiagnostics(page);
expect(domainPrimary, "DOMAIN_PRIMARY must be set in the Playwright env file").toBeTruthy();
expect(mapacheSecret, "MAPACHE_PASSWORD must be set in the Playwright env file").toBeTruthy();
expect(mapachePassword, "MAPACHE_PASSWORD must be set in the Playwright env file").toBeTruthy();
const mapacheUsername = MAPACHE.username;
const mapachePasswordValue = mapachePassword(mapacheSecret);
await provisionKeycloakUser(browser, {
baseUrl: appBaseUrl,
realm: realmName,
adminUsername: superAdminUsername,
adminPassword: superAdminPassword,
user: { ...MAPACHE, email: `${MAPACHE.username}@${domainPrimary}` },
password: mapachePasswordValue,
password: mapachePassword,
});
const accountUrl = `${appBaseUrl}/realms/${realmName}/account/`;
@@ -226,7 +225,7 @@ test("super administrator onboards mapache in the admin console and mapache sign
await signInButton.click({ timeout: resolveTimeout(30_000) });
}
await fillKeycloakLoginForm(page, mapacheUsername, mapachePasswordValue);
await fillKeycloakLoginForm(page, mapacheUsername, mapachePassword);
await expect
.poll(() => page.url(), {
-4
View File
@@ -8,10 +8,6 @@ credentials:
description: Password for the Keycloak administrator user (used in bootstrap and CLI access)
algorithm: sha256
validation: ^[a-f0-9]{64}$
mapache_password:
description: Password the Playwright provision test sets on the mapache persona it creates in the admin console; consumer specs log in with it.
algorithm: sha256
validation: ^[a-f0-9]{64}$
oidc_client_secret:
description: Client secret for the shared OIDC client; consumed by the SSO-proxy sidecar and the Keycloak realm client, and used as the default for
OIDC.CLIENT.SECRET when the inventory sets none.
@@ -27,7 +27,7 @@ LDAP_SERVICE_ENABLED={{ lookup('config', application_id, 'services.ldap.enabled'
# nocheck: playwright-service-gate — auth-provider role; generic persona scenarios are exempt (covered by bespoke realm-account / admin-console tests above)
LOGOUT_SERVICE_ENABLED={{ lookup('config', application_id, 'services.logout.enabled') | string | lower }}
MAPACHE_PASSWORD={{ lookup('config', application_id, 'secrets.credentials.mapache_password') | dotenv_quote }}
MAPACHE_PASSWORD={{ PLAYWRIGHT_MAPACHE_PASSWORD | dotenv_quote }}
MATOMO_BASE_URL={{ lookup('tls', 'web-app-matomo', 'url.base') | dotenv_quote }}
@@ -12,7 +12,7 @@ const stalwartAdminPassword = decodeDotenvQuotedValue(process.env.STALWART_ADMIN
const biberEmail = decodeDotenvQuotedValue(process.env.BIBER_EMAIL || "");
const biberUsername = decodeDotenvQuotedValue(process.env.BIBER_USERNAME || "");
const biberPassword = decodeDotenvQuotedValue(process.env.BIBER_PASSWORD || "");
const mapacheSecret = decodeDotenvQuotedValue(process.env.MAPACHE_PASSWORD || "");
const mapachePassword = decodeDotenvQuotedValue(process.env.MAPACHE_PASSWORD || "");
const expectedOidcAuthUrl = `${oidcIssuerUrl.replace(/\/$/, "")}/protocol/openid-connect/auth`;
@@ -30,5 +30,5 @@ module.exports = {
biberEmail,
biberUsername,
biberPassword,
mapacheSecret,
mapachePassword,
};
@@ -1,11 +1,11 @@
const { test, expect } = require("@playwright/test");
const { MAPACHE, mapachePassword, safeSkipUnlessEnabled, gotoOnion } = require("./personas");
const { MAPACHE, safeSkipUnlessEnabled, gotoOnion } = require("./personas");
const { isSplitRealmOidc, resolveTimeout } = require("./timeouts");
const { roundcubeSsoLogin, roundcubeLogout, sendMail, waitForEmailInMailbox } = require("./webmail");
const {
webmailBaseUrl,
mapacheSecret,
mapachePassword,
biberEmail,
biberUsername,
biberPassword,
@@ -14,8 +14,8 @@ const {
const mapacheUsername = MAPACHE.username;
function mapacheLoginPassword() {
expect(mapacheSecret, "MAPACHE_PASSWORD must be set").toBeTruthy();
return mapachePassword(mapacheSecret);
expect(mapachePassword, "MAPACHE_PASSWORD must be set").toBeTruthy();
return mapachePassword;
}
test("stalwart: an OIDC user the deploy never provisioned can sign in", async ({ page }) => {
@@ -16,7 +16,7 @@ CANONICAL_DOMAIN={{ lookup('domain', application_id) | dotenv_quote }}
LOGOUT_SERVICE_ENABLED={{ lookup('config', application_id, 'services.logout.enabled') | string | lower }}
MAPACHE_PASSWORD={{ lookup('config', 'web-app-keycloak', 'secrets.credentials.mapache_password') | dotenv_quote }}
MAPACHE_PASSWORD={{ PLAYWRIGHT_MAPACHE_PASSWORD | dotenv_quote }}
MATOMO_BASE_URL={{ lookup('tls', 'web-app-matomo', 'url.base') | dotenv_quote }}