RBAC & Ownership
Who can do what on which environment. The library enforces a three-level model (creator / co-owner / admin) with a hard quota on how many envs a non-admin can own.
Model at a glance
Every meta.json carries:
-
created_by— the Jenkins login that ranCreate-Environment. Immutable. -
owners— list of additional Jenkins logins with the same rights as the creator. Mutable via themanage-ownersaction.
Admins are defined globally, not per-env, via the Jenkins env var QA_ADMIN_USERS (comma-separated; default admin). The toggle QA_RBAC_ENABLED (default true) turns the whole machinery off if set to false — useful for single-tenant labs.
Role × action matrix
| Role | create | update | deploy | restore | start / stop / restart | delete | manage-owners | cleanup |
|---|---|---|---|---|---|---|---|---|
Creator ( |
n/a |
✓ |
✓ |
✓ |
✓ |
✓ |
✓ |
own env only |
Co-owner ( |
n/a |
✓ |
✓ |
✓ |
✓ |
✓ |
✓ |
own env only |
Admin (listed in |
✓ (bypasses |
✓ |
✓ |
✓ |
✓ |
✓ |
✓ |
all envs |
Anyone else |
✓ (subject to |
✗ |
✗ |
✗ |
✗ |
✗ |
✗ |
never sees other users' envs |
RBAC is enabled by default (QA_RBAC_ENABLED=true). Set QA_RBAC_ENABLED=false in Manage Jenkins → System → Global properties to fall back to the legacy "everyone can touch anything" mode.
|
Where it is enforced
-
utils.checkOwnership(meta, currentUser)— fail-fast guard called at the top of every mutating step:updateEnvStep,manageEnvStep,deleteEnvStep(delegated),restoreEnvStep,rollbackEnvStep,switchDatabaseStep,cleanupEnvsStep. -
createEnvStep— quota check (QAConfig.Limits.MAX_ENVS_PER_USER) happens before any filesystem work. Admins bypass it (commit25288f5). -
cleanupEnvsStep— filters the env list by ownership before the TTL check, so a non-admin can never delete someone else’s env. Cron-triggered runs have nocurrentUserand bypass the check so unattended cleanup still works (commit59dfbb4). -
listEnvsStep— RBAC-aware: non-admins only see their own or co-owned envs; admins see everything.
Disabling RBAC (QA_RBAC_ENABLED=false) short-circuits checkOwnership to true and canModify to true.
manage-owners — the ownership editor
Triggered via QA-Environments/Manage-Environment with ACTION=manage-owners.
ACTION=manage-owners)-
OWNERS_LIST—CascadeChoiceParameter+PT_CHECKBOXof Jenkins logins (commite48fa6d). Currently saved co-owners appear pre-checked. The creator is not in the list. -
OWNERS_PREVIEW— live HTML diff of pending change (added vs removed). Display-only.
meta.json{
"created_by": "alice", // unchanged
"owners": ["bob", "carol"] // rewritten from OWNERS_LIST submission
// all other fields untouched — no lifecycle transition
}
Why manage-owners is special:
-
It is the only
ACTIONthat does not go through the duplicate-audit code path the lifecycle actions share (commit867752a). The audit is skipped because the action does not touch containers or volumes and the ownership diff has its own audit line. -
manage-ownersis offered for envs in any state (commit2ae7a2c). You can reassign ownership on a stopped or failed env without first starting it.
Validation rules
utils.validateOwners(newOwners, meta, currentUser, adminUsers, knownJenkinsLogins):
-
Rejects an empty list (there must be at least one co-owner or the creator; the creator is always implicit).
-
Requires the submitting user to appear in the result unless they are an admin — non-admins cannot remove themselves without granting access to someone else first.
-
Enforces
MAX_OWNERS_PER_ENV(default5, override viaQA_MAX_OWNERS_PER_ENV). -
Drops unknown logins — a login is "known" if it already appears in the Jenkins user database. Users without a Full Name still count (commit
cd7881c).
Result is a List that manageEnvStep writes verbatim back into meta.owners[] via utils.atomicWriteMeta.
Limits
| Limit | Default | Override |
|---|---|---|
|
|
|
|
|
|
Transfer of ownership
There is no user-facing "transfer" action. created_by is immutable. To move an env to a new owner:
-
Admin (or current creator) adds the target user to
owners[]viamanage-owners. -
Target user now has every mutating right the creator has.
-
The audit trail (
meta.created_by+ themanage-ownersaudit line) records who did what.
If the business really requires a new created_by, an admin has to edit meta.json directly on the master under /var/jenkins_home/qa-data/envs/<env>/meta.json.
Audit trail
-
MASTER_AUDIT_LOG(${MASTER_ENVS_DIR}/.audit-log.ndjson) — one line per privileged action. -
MASTER_OPERATION_LOG(${MASTER_ENVS_DIR}/.operation-log.ndjson) — one line per step invocation.
Both are append-only NDJSON files written by utils.logOperation. Rotate them externally — the library does not rotate them.