Tiered LDAP groups
This commit is contained in:
@@ -99,6 +99,44 @@ the application. Level 0 is the free account baseline; paid offers are levels
|
||||
groupOfUniqueNames groups, sentinel and ACLs separately. Override group DNs if
|
||||
needed; sandbox testing requires separate test-mode prices.
|
||||
|
||||
### Service access groups, including free Level 0
|
||||
|
||||
Set `www_membership_service_groups` to a mapping of **quoted effective level**
|
||||
keys to lists of pre-created LDAP group DNs. The default `{}` grants no additional
|
||||
groups. For example:
|
||||
|
||||
```yaml
|
||||
www_membership_service_groups:
|
||||
"0": ["cn=community-chat,ou=membership-services,dc=example,dc=org"]
|
||||
"1": ["cn=community-chat,ou=membership-services,dc=example,dc=org"]
|
||||
"2":
|
||||
- "cn=community-chat,ou=membership-services,dc=example,dc=org"
|
||||
- "cn=game-servers,ou=membership-services,dc=example,dc=org"
|
||||
```
|
||||
|
||||
The highest valid paid membership selects exactly that level's list. **No implicit
|
||||
inheritance**: include groups again for levels 3–5 if they should also receive
|
||||
them. Level 0 is selected only when no paid entitlement remains; repeat a free
|
||||
service DN at every level to offer it to all members. Original tier `group_dn`
|
||||
grants are unchanged and independent of these additional service groups.
|
||||
|
||||
The role serializes the mapping into the existing membership-tiers ConfigMap as
|
||||
`service-groups.json`, sets `MEMBERSHIP_SERVICE_GROUPS_FILE`, and includes it in
|
||||
the configuration revision so updates trigger workload rollout. Do not override
|
||||
it using `MEMBERSHIP_SERVICE_GROUPS_JSON` in the public environment. Publish an
|
||||
updated membership image before deploying this role change; no new DB migration
|
||||
is needed. See [tests/example-vars.yml](tests/example-vars.yml) for all six levels.
|
||||
|
||||
Targets must be dedicated `groupOfUniqueNames` groups with the existing sentinel;
|
||||
provision groups and narrow `uniqueMember` worker ACLs separately. Configure each
|
||||
service/Dex to authorize those groups. Never map admin/staff or independently
|
||||
managed groups: the worker **removes noneligible local members**, including
|
||||
manually granted memberships. Keep retired groups/ACLs until revocation completes.
|
||||
Historical group targets persist for safe removal after mappings change. Expiry
|
||||
returns users to level 0 without waiting for Stripe/SHKeeper, but LDAP outages
|
||||
and downstream cached sessions can still delay access changes. Free grants cover
|
||||
local membership accounts, not untouched users elsewhere in LDAP.
|
||||
|
||||
### Secrets
|
||||
|
||||
Create an Opaque Secret using External Secrets, Sealed Secrets or your secret
|
||||
@@ -124,12 +162,66 @@ Do not use root/admin LDAP credentials. Restrict ACLs to the website account OU
|
||||
and dedicated group attributes. Use SHKeeper's invoice API key, never wallet
|
||||
private keys or UI/payout credentials.
|
||||
|
||||
`LDAP_BIND_DN` names the membership service account; `LDAP_BIND_PASSWORD` must
|
||||
be its original plaintext password, **not** its stored LDAP `userPassword` hash
|
||||
or an already-base64-encoded value. Supply original values in
|
||||
`www_membership_secret_data`; the role base64-encodes them once for Secret `data`.
|
||||
Current membership login uses verified Dex issuer/subject claims without an LDAP
|
||||
connection. These service credentials remain required for account registration
|
||||
and worker group synchronization. Older images logging
|
||||
`LDAP service bind rejected during Dex callback` or
|
||||
`Dex callback rejected kind=LDAPInvalidCredentialsResult` still perform the
|
||||
retired callback lookup; upgrade the membership image to remove that dependency.
|
||||
Fix service credentials separately for registration/sync, then rerun the role to
|
||||
roll out web and worker. Do not use directory administrator credentials.
|
||||
`LDAP_PASSWORD_SCHEME` gates new registrations only; it does not select the hash
|
||||
algorithm for existing-user login.
|
||||
|
||||
The Dex-only login release adds migration `0004_dex_login_identity`. Keep
|
||||
`DEX_ISSUER` unchanged during this upgrade so existing subjects are pinned to
|
||||
their original issuer, and coordinate replacing web/worker together. Existing
|
||||
subject bindings and billing data are retained. Unbound local accounts require
|
||||
proof from their recent registration session or an administrator's explicit
|
||||
`bind_dex_identity` mapping (`--account`, `--uid`, `--subject`); they are never
|
||||
claimed by email/username matching alone. Review any retired connector bindings
|
||||
before deployment. Keep Dex's existing connector/uid mapping unchanged and do not
|
||||
recycle usernames. The worker pins new users' directory UUIDs separately; LDAP
|
||||
outages can still delay paid group grants/revocations even though login works.
|
||||
|
||||
Private trust roots belong in a separate CA Secret. Set paths such as
|
||||
`LDAP_CA_CERT_FILE`, `SHKEEPER_CA_CERT_FILE`, `PGSSLROOTCERT` or
|
||||
`REQUESTS_CA_BUNDLE` to `/etc/membership/ca/<secret-key>`. The read-only mount is
|
||||
shared by web, worker and migrations. Verify certificate expiry, strong keys,
|
||||
SHA-2 signatures and trust independently; do not disable TLS verification.
|
||||
|
||||
### Self-service profiles
|
||||
|
||||
The profile release requires a membership image with Pillow and migration
|
||||
`0005_profile_email_change`, plus the updated website templates/CSS. The role's
|
||||
migration Job still runs before workloads. Deploy matching reviewed versions of
|
||||
the application and website; do not reuse cached image tags.
|
||||
|
||||
The membership page links to an authenticated editor with friendly labels for
|
||||
the requested inetOrgPerson attributes, with `displayName` labelled **Gamer tag**.
|
||||
Dex's normal claims do not contain the full profile; opening the editor reads
|
||||
the current LDAP entry, while ordinary sign-in remains LDAP-independent. The
|
||||
service identity needs read/search access to profile attributes and operational
|
||||
UUID/timestamp fields. Writes use the member's current password and **user bind**,
|
||||
not broader service privileges. Configure narrow self-write ACLs, server-side
|
||||
mail/uid uniqueness and RFC 4528 assertion support. SSH key edits additionally
|
||||
require the `ldapPublicKey` schema and pre-added auxiliary class or an ACL allowing
|
||||
only that specific self-add. This role does not create schema/ACLs automatically.
|
||||
|
||||
Email changes require mailbox verification plus the current password and replace
|
||||
all existing mail values. Password hashing is delegated to slapd's Password Modify
|
||||
policy; the application does not generate MD5-Crypt or expose stored hashes.
|
||||
Review legacy hashing separately. See the application's self-service profile
|
||||
documentation for the full attribute mapping and directory prerequisites.
|
||||
|
||||
The ingress upload limit is 2 MiB to accommodate a 1 MiB JPEG and multipart
|
||||
overhead. Apache retains 256 KiB for non-profile member routes. Keep access/body
|
||||
logging disabled for verification URLs, passwords and other profile data.
|
||||
|
||||
### Example inventory and hostname
|
||||
|
||||
[tests/example-vars.yml](tests/example-vars.yml) contains public configuration
|
||||
|
||||
Reference in New Issue
Block a user