Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 72046a8b29 | |||
| 73e1cc807a |
@@ -8,6 +8,18 @@ orchestration code; see each submodule's own `CHANGELOG.md`
|
||||
[sso-manager-node](https://github.com/theta42/sso-manager-node/blob/master/CHANGELOG.md))
|
||||
for what changed inside the apps it composes.
|
||||
|
||||
## [v1.37.0] - 2026-08-04
|
||||
|
||||
### Changed
|
||||
- **Group naming corrected to match docs/GROUPS.md** — per-resource groups are `{site}_{kind}_{name}_{level}` (kind always present; a host `host_theta-env` → `site_local_host_theta-env_access`, a service → `site_local_app_sso-manager_access`). The spec's §3 text was updated to state this explicitly.
|
||||
- **Roll up sso v1.27.0** — group names match the docs, a site carries only god + site-wide groups, duplicate group links removed, `/api/agent/*` no longer 404s, shared-secrets POST/GET fixed, Vault Apps tab lists minted tokens, discovery promote + plugin run logs fixed. See the [sso changelog](https://github.com/theta42/sso-manager-node/blob/master/CHANGELOG.md).
|
||||
|
||||
## [v1.36.1] - 2026-08-04
|
||||
|
||||
### Fixed
|
||||
- **`setup.sh` no longer aborts with `CFG_BASE_DN: unbound variable`** — the ldap-client `ldap.vars` generation read the CFG_* first-run vars, which `ensure_config` only derives once (it returns early on a re-run once `sso-secrets.js` exists). It now reads the real values from the operator-owned `./config/sso-secrets.js` when the CFG_* vars are unset, so LDAP enrollment works on re-runs too. The generated `ldap_access_groups` now references `god_admin` (the legacy `app_super_admin` is gone).
|
||||
- **Roll up sso v1.26.1** — drops the legacy `app_super_admin`: `SUPER_ADMIN_GROUP` is now `god_admin` (nested into every resource's `_admin` group), and `docker-entrypoint.sh` no longer seeds/nests `app_super_admin`. See the [sso changelog](https://github.com/theta42/sso-manager-node/blob/master/CHANGELOG.md).
|
||||
|
||||
## [v1.36.0] - 2026-08-04
|
||||
|
||||
### Added
|
||||
|
||||
Vendored
+4
-3
@@ -90,10 +90,11 @@ const CLIENT_NAME = 'theta-proxy';
|
||||
const ADMIN_DN = `cn=${ADMIN_UID},ou=people,${BASE_DN}`;
|
||||
const SVC_DN = `cn=ldapclient,ou=people,${BASE_DN}`;
|
||||
// god_admin is the global super group (docs/GROUPS.md §2); the bootstrapped
|
||||
// admin is its first member. app_sso_admin / app_sso_oauth_admin are the legacy
|
||||
// admin is its first member. app_sso_admin / app_sso_oauth_admin are the
|
||||
// per-console admin groups still used by the SSO UI. god_admin is nested into
|
||||
// app_super_admin by docker-entrypoint.sh, so LDAP-level consumers (SSSD, sudo)
|
||||
// resolve it transitively.
|
||||
// the app_sso_* groups (and every resource's _admin group) by
|
||||
// docker-entrypoint.sh + api_directory_admin, so LDAP-level consumers (SSSD,
|
||||
// sudo) resolve it transitively.
|
||||
const ADMIN_GROUPS = ['god_admin', 'app_sso_admin', 'app_sso_oauth_admin'];
|
||||
|
||||
const log = (...a) => process.stderr.write('[bootstrap] ' + a.join(' ') + '\n');
|
||||
|
||||
+12
-12
@@ -76,17 +76,15 @@ enumerated as LDAP members, and cannot be used as Unix groups.
|
||||
|
||||
- The **structural delimiter is `_`**. It appears only between the fixed segments
|
||||
of a group name.
|
||||
- **The `S` site segment is the site resource's slug verbatim.** In the SSO
|
||||
Directory, site/host resource slugs carry a kind prefix (`site_local`,
|
||||
`host_theta-env`); the group builders keep them verbatim rather than
|
||||
re-slugifying (which would corrupt the delimiter: `site_local` → `site-local`)
|
||||
or inserting a separate kind segment. So a host resource `host_theta-env` under
|
||||
site `site_local` yields `site_local_host_theta-env_access` (the `host_` is part
|
||||
of the resource slug), and the site's own admin group is `site_local_super_admin`.
|
||||
Services are stored without a prefix, giving `site_local_sso-manager_access`.
|
||||
The kind (`host`/`app`) is used only to pick the **aggregate** the resource's
|
||||
group nests into (`{site}_hosts_*` / `{site}_apps_*`), not the resource's own
|
||||
group name.
|
||||
- **The `S` site segment is the site resource's slug verbatim** (`site_local`),
|
||||
NOT re-slugified (which would corrupt the delimiter: `site_local` → `site-local`).
|
||||
- **Per-resource groups are `{S}_{kind}_{name}_{level}`.** `kind` is `host` or
|
||||
`app`; `name` is the resource's **name slug with the kind prefix stripped** — a
|
||||
host resource `host_theta-env` has name `theta-env`, so its groups are
|
||||
`site_local_host_theta-env_access` / `_admin`. A service (the group model's
|
||||
`app`, docs §11) `sso-manager` gives `site_local_app_sso-manager_access`. The
|
||||
kind segment is always present, which is what makes a resource's name
|
||||
unambiguous even if a host and a service share a name.
|
||||
- **Within a segment, normalize to lowercase** — spaces and stray `_` → `-`; strip
|
||||
other non-`[a-z0-9-]`. A host named `Web 01` and a site `Main Office` (resource
|
||||
slugs `host_web-01` and `site_main-office`) yield groups `site_main-office_host_web-01_*`.
|
||||
@@ -150,7 +148,9 @@ def effective(resource, level_or_cap, site):
|
||||
if level_or_cap in ("admin","access"):
|
||||
agg = f"{site}_{resource.kind}s_{level_or_cap}"
|
||||
if user in agg: return True
|
||||
specific = f"{site}_{resource.slug}_{level_or_cap}" # slug carries its kind
|
||||
# resource.name is the resource's name slug (kind prefix stripped); the kind
|
||||
# is its own segment. A host `host_theta-env` has name `theta-env`, kind `host`.
|
||||
specific = f"{site}_{resource.kind}_{resource.name}_{level_or_cap}"
|
||||
if user in specific: return True
|
||||
if level_or_cap == "access": return effective(resource, "admin", site)
|
||||
if level_or_cap == "admin": return False # access does not imply admin
|
||||
|
||||
@@ -292,6 +292,21 @@ dn_from_domain() {
|
||||
echo "dc=$1" | sed 's/\./,dc=/g'
|
||||
}
|
||||
|
||||
# Read a value from the (operator-owned) ./config/sso-secrets.js -- the source of
|
||||
# truth on re-runs, where the CFG_* first-run shell vars are not (re)derived
|
||||
# (ensure_config returns early once sso-secrets.js exists). Reads `stack.<key>`.
|
||||
# Prints empty on any failure. Usage: sso_secrets_get ldapBaseDn
|
||||
sso_secrets_get() {
|
||||
node -e 'const c=require(process.argv[1]);const k=process.argv[2];console.log(c&&c.stack&&c.stack[k]!=null?c.stack[k]:"")' \
|
||||
"$PWD/$CONFIG_DIR/sso-secrets.js" "$1" 2>/dev/null || true
|
||||
}
|
||||
|
||||
# Read a top-level (non-stack) secret from sso-secrets.js, e.g. serviceAccountPass.
|
||||
sso_secrets_get_top() {
|
||||
node -e 'const c=require(process.argv[1]);const k=process.argv[2];console.log(c&&c[k]!=null?c[k]:"")' \
|
||||
"$PWD/$CONFIG_DIR/sso-secrets.js" "$1" 2>/dev/null || true
|
||||
}
|
||||
|
||||
# Write ./config/sso-secrets.js from the CFG_* shell vars.
|
||||
write_sso_secrets() {
|
||||
local dn="$CFG_BASE_DN" domain="$CFG_DOMAIN"
|
||||
@@ -1265,15 +1280,25 @@ if [[ "$CFG_THETA_AGENT_ENABLE" == "1" ]] && [[ -x /usr/local/bin/theta-agent ]]
|
||||
# ldap.vars (cp ldap.vars.template ldap.vars + edit) is always kept.
|
||||
if [[ ! -f ldap-client/ldap.vars ]]; then
|
||||
info " Generating ldap-client/ldap.vars from the stack config..."
|
||||
# CFG_* first-run vars may be unset on a re-run (ensure_config returns
|
||||
# early once sso-secrets.js exists), so fall back to reading the real
|
||||
# values from the operator-owned sso-secrets.js. All `:-` guarded so a
|
||||
# missing value degrades to an empty ldap.vars field, not a set -u abort.
|
||||
ldap_base_dn="${CFG_BASE_DN:-$(sso_secrets_get ldapBaseDn)}"
|
||||
ldap_site="${CFG_SITE_NAME:-$(sso_secrets_get siteName)}"
|
||||
ldap_bind_pass="${CFG_SVC_PASS:-$(sso_secrets_get_top serviceAccountPass)}"
|
||||
sso_host="${CFG_SSO_HOST:-$(sso_secrets_get ssoHost)}"
|
||||
ldaps_host="${CFG_LDAPS_HOST:-}"
|
||||
[[ -n "$ldaps_host" ]] || ldaps_host="${sso_host:-}"
|
||||
cat > ldap-client/ldap.vars <<LDAPVARS
|
||||
export ldap_host="${CFG_LDAPS_HOST:-sso.${CFG_DOMAIN}}"
|
||||
export ldap_base_dn="${CFG_BASE_DN}"
|
||||
export ldap_bind_dn="cn=ldapclient,ou=people,${CFG_BASE_DN}"
|
||||
export ldap_bind_password="${CFG_SVC_PASS}"
|
||||
export sso_url="https://${CFG_SSO_HOST}"
|
||||
export ldap_host="${ldaps_host}"
|
||||
export ldap_base_dn="${ldap_base_dn}"
|
||||
export ldap_bind_dn="cn=ldapclient,ou=people,${ldap_base_dn}"
|
||||
export ldap_bind_password="${ldap_bind_pass}"
|
||||
export sso_url="https://${sso_host}"
|
||||
export sso_token=""
|
||||
export ldap_location="${CFG_SITE_NAME:-local}"
|
||||
ldap_access_groups=( "\${ldap_location}_access" "\${ldap_location}_host_\$(hostname)_access" "app_super_admin" )
|
||||
export ldap_location="${ldap_site:-local}"
|
||||
ldap_access_groups=( "\${ldap_location}_access" "\${ldap_location}_host_\$(hostname)_access" "god_admin" )
|
||||
LDAPVARS
|
||||
else
|
||||
info " ldap-client/ldap.vars exists -- keeping it"
|
||||
|
||||
+1
-1
Submodule sso-manager-node updated: 8a9de94d24...e8d04203c3
Reference in New Issue
Block a user