Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f27ce70c5d |
@@ -8,6 +8,12 @@ orchestration code; see each submodule's own `CHANGELOG.md`
|
|||||||
[sso-manager-node](https://github.com/theta42/sso-manager-node/blob/master/CHANGELOG.md))
|
[sso-manager-node](https://github.com/theta42/sso-manager-node/blob/master/CHANGELOG.md))
|
||||||
for what changed inside the apps it composes.
|
for what changed inside the apps it composes.
|
||||||
|
|
||||||
|
## [v1.40.0] - 2026-08-05
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- **No more spurious "Invalid Credentials, login failed" during LDAP enrollment** (ldap-client v1.25.0, gitlink `68fcdb5`) — `index.sh` self-registered the host in the Directory when `sso_token` was *declared but empty* (it checked `[[ -v ]]`), POSTing an empty Bearer token and getting a misleading `LDAPLoginFailed`. It now only registers with a real token; the stack host (already seeded by the bootstrap) skips registration.
|
||||||
|
- **The `cn=ldapclient` service account now shows in the SSO Users UI** — it was created as a bare `organizationalRole` (invisible to the `posixAccount` user filter) and never joined `app_sso_service_account`, so it never appeared as a service account. The bootstrap now creates it as a `posixAccount` (uid 10001, above the regular-user reserved floor) and adds it to `app_sso_service_account`; for an existing account it best-effort adds the `posixAccount` shape (auxiliary, so it can't conflict with the structural `organizationalRole`) + the group membership.
|
||||||
|
|
||||||
## [v1.39.0] - 2026-08-05
|
## [v1.39.0] - 2026-08-05
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
Vendored
+70
-13
@@ -178,31 +178,88 @@ function ldapModify(ldif) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── 1. LDAP service account for the proxy ───────────────────────────────────
|
// ── 1. LDAP service account for the proxy ───────────────────────────────────
|
||||||
|
// The proxy / ldap-client bind as cn=ldapclient. For it to SHOW in the SSO Users
|
||||||
|
// UI as a service account it must (a) match the user filter (posixAccount) and
|
||||||
|
// (b) be a member of app_sso_service_account (that membership is what the Users
|
||||||
|
// page marks as a non-person/service account). Older bootstraps created it as a
|
||||||
|
// bare organizationalRole (invisible to the Users list) and never joined the
|
||||||
|
// group, so it never appeared. Both are fixed here; the existing-path shape add
|
||||||
|
// is best-effort so a pre-existing account still binds even if the upgrade add
|
||||||
|
// fails.
|
||||||
function ensureServiceAccount() {
|
function ensureServiceAccount() {
|
||||||
const pw = hashPasswordSSHA512(SVC_PASS);
|
const pw = hashPasswordSSHA512(SVC_PASS);
|
||||||
|
const uidNum = '10001'; // distinct from the bootstrap admin's 10000; above uidGidReservedFloor so regular-user id allocation ignores it
|
||||||
if (entryExists(SVC_DN)) {
|
if (entryExists(SVC_DN)) {
|
||||||
log(`Service account ${SVC_DN} exists — resetting password to ./config`);
|
log(`Service account ${SVC_DN} exists — ensuring service-account shape + password`);
|
||||||
const r = ldapModify([
|
// Add the auxiliary posixAccount objectClass + required attrs so the entry
|
||||||
|
// matches the Users list filter. inetOrgPerson is deliberately NOT added:
|
||||||
|
// it is structural and would conflict with the existing organizationalRole.
|
||||||
|
const shape = [
|
||||||
|
`dn: ${SVC_DN}`,
|
||||||
|
'changetype: modify',
|
||||||
|
'add: objectClass',
|
||||||
|
'objectClass: posixAccount',
|
||||||
|
'-',
|
||||||
|
'add: uid',
|
||||||
|
'uid: ldapclient',
|
||||||
|
'-',
|
||||||
|
'add: uidNumber',
|
||||||
|
`uidNumber: ${uidNum}`,
|
||||||
|
'-',
|
||||||
|
'add: gidNumber',
|
||||||
|
`gidNumber: ${uidNum}`,
|
||||||
|
'-',
|
||||||
|
'add: homeDirectory',
|
||||||
|
'homeDirectory: /nonexistent',
|
||||||
|
'-',
|
||||||
|
'add: description',
|
||||||
|
'description: LDAP bind service account (proxy / ldap-client)',
|
||||||
|
'',
|
||||||
|
].join('\n');
|
||||||
|
const rs = ldapModify(shape);
|
||||||
|
if (rs.code !== 0 && !/already exists|Type or value exists/i.test(rs.stderr)) {
|
||||||
|
log(' service-account shape warning (account still binds):', rs.stderr.trim());
|
||||||
|
}
|
||||||
|
const rp = ldapModify([
|
||||||
`dn: ${SVC_DN}`,
|
`dn: ${SVC_DN}`,
|
||||||
'changetype: modify',
|
'changetype: modify',
|
||||||
'replace: userPassword',
|
'replace: userPassword',
|
||||||
`userPassword: ${pw}`,
|
`userPassword: ${pw}`,
|
||||||
'',
|
'',
|
||||||
].join('\n'));
|
].join('\n'));
|
||||||
if (r.code !== 0) log(' password reset warning:', r.stderr.trim());
|
if (rp.code !== 0) log(' password reset warning:', rp.stderr.trim());
|
||||||
return;
|
} else {
|
||||||
|
log(`Creating service account ${SVC_DN}`);
|
||||||
|
const entry = [
|
||||||
|
`dn: ${SVC_DN}`,
|
||||||
|
'objectClass: inetOrgPerson',
|
||||||
|
'objectClass: posixAccount',
|
||||||
|
'objectClass: top',
|
||||||
|
'cn: ldapclient',
|
||||||
|
'sn: ldapclient',
|
||||||
|
'uid: ldapclient',
|
||||||
|
`uidNumber: ${uidNum}`,
|
||||||
|
`gidNumber: ${uidNum}`,
|
||||||
|
'homeDirectory: /nonexistent',
|
||||||
|
'description: LDAP bind service account (proxy / ldap-client)',
|
||||||
|
`userPassword: ${pw}`,
|
||||||
|
'',
|
||||||
|
].join('\n');
|
||||||
|
const r = ldapAdd(entry);
|
||||||
|
if (r.code !== 0) throw new Error(`ldapadd service account failed: ${r.stderr.trim()}`);
|
||||||
}
|
}
|
||||||
log(`Creating service account ${SVC_DN}`);
|
// Mark it as a service account (the Users UI's service-account signal).
|
||||||
const r = ldapAdd([
|
const gdn = `cn=app_sso_service_account,ou=groups,${BASE_DN}`;
|
||||||
`dn: ${SVC_DN}`,
|
const rm = ldapModify([
|
||||||
'objectClass: organizationalRole',
|
`dn: ${gdn}`,
|
||||||
'objectClass: simpleSecurityObject',
|
'changetype: modify',
|
||||||
'objectClass: top',
|
'add: member',
|
||||||
'cn: ldapclient',
|
`member: ${SVC_DN}`,
|
||||||
`userPassword: ${pw}`,
|
|
||||||
'',
|
'',
|
||||||
].join('\n'));
|
].join('\n'));
|
||||||
if (r.code !== 0) throw new Error(`ldapadd service account failed: ${r.stderr.trim()}`);
|
if (rm.code === 0) log(` marked ${SVC_DN} as a service account`);
|
||||||
|
else if (/already exists|Type or value exists/i.test(rm.stderr)) log(` ${SVC_DN} already in app_sso_service_account`);
|
||||||
|
else log(` app_sso_service_account membership warning:`, rm.stderr.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── 2. First admin user ─────────────────────────────────────────────────────
|
// ── 2. First admin user ─────────────────────────────────────────────────────
|
||||||
|
|||||||
+1
-1
Submodule ldap-client updated: ebaac181bc...68fcdb53bd
Reference in New Issue
Block a user