From e46768bb68f6ffbd66ff166102273c82f6f11ca3 Mon Sep 17 00:00:00 2001 From: William Mantly Date: Sat, 18 Jul 2026 22:11:13 -0400 Subject: [PATCH] chore(release): public-release readiness fixes for 1.1.18 - CHANGELOG.md now embeds full app-level release notes for submodule bumps. - .env.example uses explicit CHANGE-ME placeholders instead of realistic-looking defaults. - config.example comments describe the actual CONF_SECRETS mechanism. - setup.sh summary no longer prints generated passwords to stdout. - bootstrap.js fails hard instead of falling back to weak default passwords. Note: submodule pins will be updated to v1.1.16 after the app PRs merge. Co-Authored-By: Claude --- .env.example | 9 ++++-- CHANGELOG.md | 37 +++++++++++++++++++++++++ bootstrap/bootstrap.js | 15 +++++++--- config.example/proxy-secrets.js.example | 4 +-- config.example/sso-secrets.js.example | 4 +-- setup.sh | 6 ++-- 6 files changed, 61 insertions(+), 14 deletions(-) diff --git a/.env.example b/.env.example index fd46c0e..e7fda17 100644 --- a/.env.example +++ b/.env.example @@ -14,7 +14,8 @@ LDAP_BASE_DN=dc=example,dc=com # DNS domain (dc=foo,dc=bar -> foo.bar). Leave blank to derive from LDAP_BASE_DN. LDAP_DOMAIN= -LDAP_ADMIN_PASS=change-me-ldap-admin-password +# LDAP admin password. MUST be changed. Leave blank and setup.sh will generate one. +LDAP_ADMIN_PASS=CHANGE-ME ORG_NAME="My Org" # ── Public hostnames (REQUIRED) ─────────────────────────────────────────────── @@ -30,13 +31,15 @@ PROXY_HOST=proxy.example.com # app_sso_oauth_admin, and logs in as them to register the proxy OAuth client. # Re-running setup.sh resets this password to BOOTSTRAP_ADMIN_PASS. BOOTSTRAP_ADMIN_UID=admin -BOOTSTRAP_ADMIN_PASS=change-me-admin-password +# First admin password. MUST be changed. Leave blank and setup.sh will generate one. +BOOTSTRAP_ADMIN_PASS=CHANGE-ME BOOTSTRAP_ADMIN_EMAIL=admin@example.com # ── Proxy LDAP service account (created by the bootstrap) ──────────────────── # The proxy binds to LDAP as cn=ldapclient,ou=people, with this password. # Re-running setup.sh resets it to LDAP_SERVICE_PASS. -LDAP_SERVICE_PASS=change-me-ldap-service-password +# LDAP service-account password. MUST be changed. Leave blank and setup.sh will generate one. +LDAP_SERVICE_PASS=CHANGE-ME # ── OAuth JWT secret (REQUIRED — persist it) ──────────────────────────────── # Signs the SSO's access/refresh tokens. Generate with: openssl rand -hex 32 diff --git a/CHANGELOG.md b/CHANGELOG.md index 890e435..baf21de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,43 @@ for what changed inside the apps it composes. ## [Unreleased] +## [1.1.18] - 2026-07-18 + +### Bumped +- proxy -> [v1.1.16](https://github.com/theta42/proxy/releases/tag/v1.1.16) +- sso-manager-node -> [v1.1.16](https://github.com/theta42/sso-manager-node/releases/tag/v1.1.16) + +proxy: + +### Changed +- Public-release packaging: removed `"private": true` from `nodejs/package.json`, corrected the repository URL to `https://github.com/theta42/proxy.git`, and fixed the MIT `LICENSE` copyright line. +- Genericized committed config defaults in `conf/base.js` and `conf/development.js` (`example.com` / `localhost` instead of theta42 infrastructure). +- The bootstrap `proxyadmin2` account now gets a random, one-time password when `auth.localAdminPass` is unset, instead of the well-known default. + +### Fixed +- The global error handler no longer leaks `err.keys`, stack traces, or internal details in JSON responses. +- `DEPLOYMENT.md` and `docs/docker.md` now correctly describe the `CONF_SECRETS` env-var mechanism. + +sso-manager-node: + +### Security +- Hardened LDAP filter and DN construction against injection in `models/group_ldap.js` and `models/user_ldap.js`. +- Replaced `Math.random()`-based token/UUID/OTP generation with `crypto.randomUUID()` / `crypto.randomInt()` in `models/token.js`, `models/oauth_code.js`, and `models/oauth_client.js`. +- Refused startup when `oauth.jwtSecret` is missing or placeholder. + +### Changed +- Public-release packaging: removed `"private": true` from `nodejs/package.json` and bumped version to `1.1.16`. + +### Fixed +- `models/email.js`: fixed from-address template rendering bug. + +### theta-env own changes +- `CHANGELOG.md` now embeds the full app-level release notes for each submodule bump, not just links. +- `.env.example` no longer ships realistic-looking default passwords; values are clearly placeholders. +- `config.example/*.js.example` comments now describe the actual `CONF_SECRETS` env-var loading mechanism. +- `setup.sh` summary no longer prints generated passwords to stdout; it points to `./config/*.js`. +- `bootstrap/bootstrap.js` fails hard instead of falling back to weak default passwords when config is missing. + ## [1.1.17] - 2026-07-18 ### Bumped diff --git a/bootstrap/bootstrap.js b/bootstrap/bootstrap.js index a9a15b5..3e5a873 100644 --- a/bootstrap/bootstrap.js +++ b/bootstrap/bootstrap.js @@ -44,8 +44,15 @@ const fs = require('fs'); const sso = require('/config/sso-secrets.js'); const proxy = require('/config/proxy-secrets.js'); -const BASE_DN = (sso.stack && sso.stack.ldapBaseDn) || 'dc=example,dc=com'; -const ADMIN_PASS = (sso.ldap && sso.ldap.bindPassword) || 'admin'; +function requireConf(value, name) { + if (value === undefined || value === null || value === '' || value === 'CHANGE-ME') { + throw new Error(`${name} is not configured in /config/sso-secrets.js`); + } + return value; +} + +const BASE_DN = requireConf((sso.stack && sso.stack.ldapBaseDn), 'stack.ldapBaseDn'); +const ADMIN_PASS = requireConf((sso.ldap && sso.ldap.bindPassword), 'ldap.bindPassword'); const BIND_DN = `cn=admin,${BASE_DN}`; const LDAP_URL = 'ldap://localhost:389'; @@ -53,9 +60,9 @@ const ADMIN_UID = (sso.bootstrap && sso.bootstrap.adminUid) || 'admin'; // The first admin *user's* password (cn=,ou=people,). Distinct from // ADMIN_PASS above, which is the LDAP *root* (cn=admin,) bind password — // two different accounts, two different secrets. -const ADMIN_USER_PASS = (sso.bootstrap && sso.bootstrap.adminPass) || 'admin'; +const ADMIN_USER_PASS = requireConf((sso.bootstrap && sso.bootstrap.adminPass), 'bootstrap.adminPass'); const ADMIN_EMAIL = (sso.bootstrap && sso.bootstrap.adminEmail) || ''; -const SVC_PASS = sso.serviceAccountPass || 'service'; +const SVC_PASS = requireConf(sso.serviceAccountPass, 'serviceAccountPass'); const SSO_HOST = (sso.stack && sso.stack.ssoHost) || 'sso.example.com'; const PROXY_HOST = (sso.stack && sso.stack.proxyHost) || 'proxy.example.com'; diff --git a/config.example/proxy-secrets.js.example b/config.example/proxy-secrets.js.example index 7e4c92d..d53312a 100644 --- a/config.example/proxy-secrets.js.example +++ b/config.example/proxy-secrets.js.example @@ -5,8 +5,8 @@ // bootstrap writes the OAuth client clientId/clientSecret back into it; this // file documents the shape for manual editing / reference. // -// The proxy app reads this via @simpleworkjs/conf (docker-entrypoint.sh -// symlinks it to /app/conf/secrets.js). Never commit ./config/. +// The proxy app reads this via @simpleworkjs/conf (docker-entrypoint.sh sets +// CONF_SECRETS to point at it). Never commit ./config/. module.exports = { oidc: { diff --git a/config.example/sso-secrets.js.example b/config.example/sso-secrets.js.example index 060ae10..03645d0 100644 --- a/config.example/sso-secrets.js.example +++ b/config.example/sso-secrets.js.example @@ -4,8 +4,8 @@ // `./setup.sh` generates ./config/sso-secrets.js for you on first run; this file // documents the shape for manual editing / reference. // -// The SSO app reads this via @simpleworkjs/conf (docker-entrypoint.sh symlinks -// it to /app/conf/secrets.js). The app ignores the extra stack/bootstrap/ +// The SSO app reads this via @simpleworkjs/conf (docker-entrypoint.sh sets +// CONF_SECRETS to point at it). The app ignores the extra stack/bootstrap/ // serviceAccountPass keys (read by the orchestrator). Back this up off-host — // it holds all SSO secrets. Never commit ./config/. diff --git a/setup.sh b/setup.sh index cbdba57..875ec13 100755 --- a/setup.sh +++ b/setup.sh @@ -717,13 +717,13 @@ echo " first-run fallback: http://127.0.0.1:${SSO_PORT:-300 echo " Proxy mgmt UI: https://${PROXY_HOST}" echo " first-run fallback: http://127.0.0.1:${MGMT_PORT:-3000}" echo -echo " First admin login:" +echo " First admin login credentials are in ./config/sso-secrets.js:" echo " user: ${ADMIN_UID}" -echo " pass: ${ADMIN_PASS}" +echo " pass: bootstrap.adminPass" echo echo " Proxy local admin (anti-lockout fallback if the SSO is unreachable):" echo " user: proxyadmin2" -echo " pass: ${PROXY_LOCAL_ADMIN_PASS}" +echo " pass: auth.localAdminPass in ./config/proxy-secrets.js" echo " (only shown when the account is first created; edit ./config/proxy-secrets.js" echo " or use the proxy UI to change it afterward)" echo