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 ran Create-Environment. Immutable.

  • owners — list of additional Jenkins logins with the same rights as the creator. Mutable via the manage-owners action.

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 (meta.created_by, immutable)

n/a

own env only

Co-owner (meta.owners[])

n/a

own env only

Admin (listed in QA_ADMIN_USERS, default admin)

✓ (bypasses MAX_ENVS_PER_USER)

all envs

Anyone else

✓ (subject to MAX_ENVS_PER_USER)

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 (commit 25288f5).

  • 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 no currentUser and bypass the check so unattended cleanup still works (commit 59dfbb4).

  • 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.

Parameters (shown only when ACTION=manage-owners)
  • OWNERS_LISTCascadeChoiceParameter + PT_CHECKBOX of Jenkins logins (commit e48fa6d). 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.

Effect on 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 ACTION that does not go through the duplicate-audit code path the lifecycle actions share (commit 867752a). The audit is skipped because the action does not touch containers or volumes and the ownership diff has its own audit line.

  • manage-owners is offered for envs in any state (commit 2ae7a2c). 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 (default 5, override via QA_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

MAX_ENVS_PER_USER

5

QA_MAX_ENVS_PER_USER — admins bypass this.

MAX_OWNERS_PER_ENV

5

QA_MAX_OWNERS_PER_ENV.

Transfer of ownership

There is no user-facing "transfer" action. created_by is immutable. To move an env to a new owner:

  1. Admin (or current creator) adds the target user to owners[] via manage-owners.

  2. Target user now has every mutating right the creator has.

  3. The audit trail (meta.created_by + the manage-owners audit 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.

RBAC off

If you set QA_RBAC_ENABLED=false, the library falls back to the legacy "any logged-in Jenkins user can act on any env" behaviour. Quotas and MAX_OWNERS_PER_ENV still apply.