Add enterprise-auth -revoke-membership-*/-list-memberships-tenant flags
Rounds out the tenant_memberships operator flags added earlier this
phase (-create-tenant/-grant-membership-*): grant had no way to undo
itself, and there was no way to see who was actually in a tenant
without querying Postgres directly.
rbacstore.RevokeMembership deletes a tenant_memberships row, but
refuses to revoke a tenant's current Owner -- Owner is also a
dedicated tenants.owner_user_id column (SetOwner), so deleting that
membership without transferring ownership first would leave
owner_user_id pointing at a user with no membership in the tenant at
all. Ownership transfer is a deliberate, separate action per the RBAC
matrix ("Transfer tenant Owner -- Owner only"), not a side effect of
revoking access.
rbacstore.ListMembershipsForTenant is ListMembershipsForUser's
inverse -- joined with users so the result is actually useful (email,
display name), not just a bare user ID list.
enterprise-auth gains -revoke-membership-tenant/
-revoke-membership-user-email (both required together, same shape as
-grant-membership-*) and -list-memberships-tenant (prints tab-separated
id/email/display-name/role to stdout and exits -- an operator
convenience, not a machine-readable API; this binary deliberately has
no admin HTTP surface, per its own doc comment on why). Changing a
role is unchanged: re-run -grant-membership-* with a different
-grant-membership-role, SetMembership's upsert already handles it.
Covered by five new skip-gated integration tests in rbacstore_test.go
(RBACSTORE_TEST_POSTGRES_ADDR), including the Owner-revocation refusal
and cross-tenant leak check for ListMembershipsForTenant -- not run
against a live database in this environment, same disclosed gap as the
rest of this phase's Postgres-backed work. Docs updated:
phase-4-runbook.md's known-gaps bullet, enterprise/README.md's
bootstrap walkthrough and package layout table.
This commit is contained in:
+13
-4
@@ -156,7 +156,7 @@ silently left out:
|
||||
## Package layout
|
||||
|
||||
```
|
||||
cmd/enterprise-auth/ config loading, OIDC discovery at startup, health/authorize/features endpoints, -mint-service-token, -create-tenant, -grant-membership-*
|
||||
cmd/enterprise-auth/ config loading, OIDC discovery at startup, health/authorize/features endpoints, -mint-service-token, -create-tenant, -grant-membership-*, -revoke-membership-*, -list-memberships-tenant
|
||||
cmd/enterprise-api/ multi-tenant-aware alternative to api/cmd/api -- see its own doc comment
|
||||
internal/tenant/ the ID type -- see its package doc comment before touching it
|
||||
internal/oidc/ coreos/go-oidc wiring: discovery, login redirect, code exchange + ID token verification
|
||||
@@ -271,15 +271,24 @@ docker compose run --rm enterprise-auth -create-tenant=acme -display-name="Acme
|
||||
# users row by then, which -grant-membership-user-email needs.
|
||||
docker compose run --rm enterprise-auth \
|
||||
-grant-membership-tenant=acme -grant-membership-user-email=[email protected] -grant-membership-role=owner
|
||||
|
||||
# See who's actually in a tenant, and take access away again:
|
||||
docker compose run --rm enterprise-auth -list-memberships-tenant=acme
|
||||
docker compose run --rm enterprise-auth \
|
||||
-revoke-membership-tenant=acme -revoke-membership-user-email=[email protected]
|
||||
```
|
||||
|
||||
`-create-tenant` only touches `rbacstore` -- pair with `enterprise-api
|
||||
-provision-tenant` (below) for a tenant to actually be able to run
|
||||
queries, not just log in. `role=owner` also calls `SetOwner`, since a
|
||||
tenant's Owner is a dedicated `tenants.owner_user_id` column, not just
|
||||
the highest `tenant_memberships` role. Not yet built: revoking a
|
||||
membership, listing a tenant's members, or a flag for
|
||||
`dashboard_permissions` grants (those go through the HTTP endpoints
|
||||
the highest `tenant_memberships` role -- `-revoke-membership-*` refuses
|
||||
to revoke a tenant's current Owner for the same reason (transferring
|
||||
ownership first has no flag yet, only `rbacstore.SetOwner` at the
|
||||
storage layer). Changing a role is just re-running
|
||||
`-grant-membership-*` with a different `-grant-membership-role`
|
||||
(`SetMembership`'s upsert already supports it). Not yet built: a flag
|
||||
for `dashboard_permissions` grants (those go through the HTTP endpoints
|
||||
`api/dashboards`' handler now exposes -- `PUT`/`DELETE
|
||||
/dashboards/{id}/permissions/{userId}`, `GET .../permissions`).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user