Jenkins Course
Users, Roles and Permissions
Matrix-based security works for small teams. But when you have 50 engineers across 6 teams, managing individual user permissions in a matrix becomes unworkable. Role-Based Access Control is how production Jenkins teams solve this at scale.
This lesson covers
The Role-Based Authorization Strategy plugin → Every Jenkins permission explained → Creating global and item roles → Assigning users to roles → Permission quick-reference table → Managing users via the UI and CLI
In Lesson 28 you learned the difference between authentication and authorisation, and saw matrix-based security configured programmatically. This lesson goes deeper — into the Role-Based Authorization Strategy plugin, which is the standard for teams that need to give different people different levels of access to different jobs.
The Analogy
Matrix security is like writing each person's name on a building access list and specifying exactly which rooms they can enter. Role-based security is like giving people badges — admin badge, developer badge, read-only badge. When someone joins the team, you give them the right badge. When they change roles, you swap badges. When they leave, you deactivate the badge. You manage a small number of badge types, not a growing list of individual names.
The Role-Based Authorization Strategy Plugin
The plugin to install is role-strategy (full name: Role-based Authorization Strategy). After installing it, go to Manage Jenkins → Configure Global Security → Authorization and select Role-Based Strategy. Then the role management screen appears at Manage Jenkins → Manage and Assign Roles.
The plugin has three types of roles that work at different scopes:
Global Roles
Apply across all of Jenkins — every job, every agent, every config screen. Use for top-level permissions like who can manage plugins, who can configure security, and who can read the system dashboard.
Item Roles
Apply to specific jobs matching a pattern. A pattern like payments-.* matches all jobs whose names start with "payments-". Team A can only see and build Team A's jobs. This is the feature that makes RBAC powerful for multi-team Jenkins.
Agent Roles
Apply to specific build agents. Teams that own dedicated agents can be given exclusive rights to configure or connect to those agents without touching the rest of the agent fleet.
A Real-World Role Design
Here's the role model most mid-sized engineering organisations end up with. Four global roles covering the full spectrum of access needs, plus team-scoped item roles for job-level isolation:
| Role | Who gets it | Key permissions |
|---|---|---|
| admin | Platform engineers, DevOps leads | Full control — Administer, manage plugins, configure security, manage nodes |
| developer | Engineers with their own pipelines | Read Jenkins, build jobs, view logs, cancel builds — no admin access |
| viewer | Stakeholders, QA, management | Read-only — see jobs, view logs, check build status. Cannot trigger builds. |
| release-manager | Release engineers, tech leads | Read + build + deploy permissions. Can approve input gates. Cannot manage plugins or security. |
Combined with item roles, this means a developer from the payments team gets the global developer role (so they can log in and see the dashboard) plus an item role scoped to payments-.* jobs (so they can build and view only their team's pipelines).
Manage Roles Screen — What It Looks Like
Global roles
| Role | Administer | Read | Job Build | Job Read | Job Cancel |
|---|---|---|---|---|---|
| admin | |||||
| developer | |||||
| viewer |
Item roles — team-scoped job access
| Role | Pattern | Build | Read | Configure |
|---|---|---|---|---|
| payments-team | payments-.* | |||
| frontend-team | frontend-.* |
Jenkins Permissions — The Complete Reference
Every permission in Jenkins has a unique string ID in the format ClassName/PermissionName. When you tick a checkbox in the Manage Roles UI, Jenkins is setting one of these permission IDs internally. When you configure roles via Groovy, you reference them directly. Here are all the permissions you'll actually use — grouped by what they control.
Overall (Jenkins-wide)
hudson.model.Hudson.Administer
Full system administration. Can change security settings, install plugins, manage nodes, read all credentials. Admins only.
hudson.model.Hudson.Read
Can log in and see the Jenkins dashboard. Without this, a user can't do anything — not even see the home page. Every non-admin role needs this.
hudson.model.Hudson.SystemRead
Can read Jenkins system configuration (but not change it). Useful for auditors who need to verify settings without being admins.
hudson.model.Hudson.ConfigureUpdateCenter
Can configure the Jenkins update centre and manage plugin updates. Usually only admins, but sometimes granted to a senior DevOps role.
Jobs (Item Permissions)
hudson.model.Item.Read
Can see the job in the job list and view its configuration and build history. Without this, the job is invisible to the user.
hudson.model.Item.Build
Can trigger a build manually (Build Now button) or via a parameterised build form. Requires Item.Read to also be set.
hudson.model.Item.Cancel
Can abort a running build. Developers usually need this so they can stop a build they triggered by mistake.
hudson.model.Item.Configure
Can open the job configuration page and save changes. Grant to senior developers who own a pipeline. Do not grant to general developers — they could accidentally change a production pipeline.
hudson.model.Item.Create
Can create new jobs. Usually only DevOps/platform engineers and tech leads.
hudson.model.Item.Delete
Can delete a job and all its build history. Restrict this carefully — there is no recycle bin. Deleted jobs are gone.
hudson.model.Item.Workspace
Can browse the job's workspace on the agent — see the files that were checked out and produced by the build. Useful for debugging.
hudson.model.Item.Move
Can move a job between folders. Folder-based organisations use this for job reorganisation.
Builds (Run Permissions)
hudson.model.Run.Update
Can update the build description and mark a build as keep forever. Developers typically need this to annotate builds with release notes.
hudson.model.Run.Delete
Can delete individual build records. Restrict this — deleted build records remove audit history.
hudson.model.Run.Replay
Can replay a pipeline build with a modified Jenkinsfile — a powerful debugging tool. Grant to developers, but be aware it allows running arbitrary code.
org.jenkinsci.plugins.workflow.job.WorkflowRun.Replay
Pipeline-specific replay permission — same concept as Run.Replay but scoped to Pipeline jobs specifically.
Views and Agents
hudson.model.View.Read
Can see dashboard views (the tabs on the Jenkins home page). Needed for users to see custom views created by admins.
hudson.model.View.Configure
Can create and configure dashboard views. Usually only admins and senior engineers who own the Jenkins setup.
hudson.model.Computer.Build
Can use the agent to run builds. Required when using agent-level roles to restrict which agents a team can use.
hudson.model.Computer.Configure
Can change agent configuration — labels, executors, connection settings. Platform engineers only.
Quick Reference — Which Permissions Go in Which Role
| Permission | admin | developer | viewer | release-mgr |
|---|---|---|---|---|
| Hudson.Administer | ✅ | — | — | — |
| Hudson.Read | ✅ | ✅ | ✅ | ✅ |
| Item.Read | ✅ | ✅ | ✅ | ✅ |
| Item.Build | ✅ | ✅ | — | ✅ |
| Item.Cancel | ✅ | ✅ | — | ✅ |
| Item.Configure | ✅ | — | — | — |
| Item.Create / Delete | ✅ | — | — | — |
| Run.Update | ✅ | ✅ | — | ✅ |
| Run.Replay | ✅ | ✅ | — | — |
Critical: Hudson.Administer implicitly grants all other permissions. A user with Administer can bypass every other restriction in Jenkins — including reading credentials stored in the credential store. Grant this permission only to the platform engineering team.
Configuring RBAC via Groovy Script
The scenario:
You're a platform engineer at a 40-person company with four product teams. You need to configure RBAC so that the payments team can only see and build payments pipelines, the frontend team can only see frontend pipelines, and senior engineers can build anything. A new contractor is joining Monday — read-only access only. You want this done reproducibly via a script so you can reapply it if Jenkins is rebuilt.
New terms in this code:
- RoleBasedAuthorizationStrategy — the Java class for the role-strategy plugin's authorization engine. Instantiate this to switch Jenkins to role-based access control.
- Role — represents a named role with a set of permissions and optionally a pattern (for item roles). Created with
new Role(name, pattern, permissions). - RoleType.Global — specifies that the role applies across all of Jenkins. Use
RoleType.Projectfor item roles scoped to job name patterns. - strategy.addRole() — adds a role definition to the strategy. Takes the role type and the role object.
- strategy.assignRole() — assigns a user or group to a role. Takes the role type, role name, and the username or group name as a string.
- Permissions.fromId() — looks up a Jenkins permission by its string ID. Permission IDs follow the pattern
ClassName/PermissionName.
// Run this in the Jenkins Script Console at /script
// or via: java -jar jenkins-cli.jar ... groovy = < rbac-setup.groovy
// Requires the role-strategy plugin to be installed
import jenkins.model.Jenkins
import com.michelin.cio.hudson.plugins.rolestrategy.*
import org.jenkinsci.plugins.rolestrategy.permissions.PermissionHelper
def j = Jenkins.instance
// Switch to Role-Based Authorization Strategy
def strategy = new RoleBasedAuthorizationStrategy()
// -------------------------------------------------------
// STEP 1: Define Global Roles
// Global roles control access to Jenkins-wide features
// -------------------------------------------------------
// Admin role — full Jenkins control
def adminPermissions = new HashSet([
Permission.fromId('hudson.model.Hudson.Administer')
])
def adminRole = new Role('admin', adminPermissions)
strategy.addRole(RoleType.Global, adminRole)
// Developer role — read Jenkins + build jobs
def developerPermissions = new HashSet([
Permission.fromId('hudson.model.Hudson.Read'),
Permission.fromId('hudson.model.Item.Build'),
Permission.fromId('hudson.model.Item.Read'),
Permission.fromId('hudson.model.Item.Cancel'),
Permission.fromId('hudson.model.Run.Update'),
])
def developerRole = new Role('developer', developerPermissions)
strategy.addRole(RoleType.Global, developerRole)
// Viewer role — read-only access
def viewerPermissions = new HashSet([
Permission.fromId('hudson.model.Hudson.Read'),
Permission.fromId('hudson.model.Item.Read'),
])
def viewerRole = new Role('viewer', viewerPermissions)
strategy.addRole(RoleType.Global, viewerRole)
// -------------------------------------------------------
// STEP 2: Define Item Roles (team-scoped job access)
// The pattern is a regex — jobs matching it are accessible
// -------------------------------------------------------
// Payments team — can build and read payments-* jobs only
def paymentsPermissions = new HashSet([
Permission.fromId('hudson.model.Item.Build'),
Permission.fromId('hudson.model.Item.Read'),
Permission.fromId('hudson.model.Item.Cancel'),
])
// 'payments-.*' matches: payments-service-build, payments-api-deploy, etc.
def paymentsItemRole = new Role('payments-team', 'payments-.*', paymentsPermissions)
strategy.addRole(RoleType.Project, paymentsItemRole)
// Frontend team — can build and read frontend-* jobs only
def frontendItemRole = new Role('frontend-team', 'frontend-.*', paymentsPermissions)
strategy.addRole(RoleType.Project, frontendItemRole)
// -------------------------------------------------------
// STEP 3: Assign users to roles
// -------------------------------------------------------
strategy.assignRole(RoleType.Global, 'admin', 'platform-eng-alice')
strategy.assignRole(RoleType.Global, 'developer', 'dev-sarah')
strategy.assignRole(RoleType.Global, 'developer', 'dev-omar')
strategy.assignRole(RoleType.Global, 'viewer', 'contractor-raj') // Monday's new contractor
// Item role assignments — in addition to the global developer role
strategy.assignRole(RoleType.Project, 'payments-team', 'dev-sarah')
strategy.assignRole(RoleType.Project, 'frontend-team', 'dev-omar')
// -------------------------------------------------------
// STEP 4: Apply and save
// -------------------------------------------------------
j.authorizationStrategy = strategy
j.save()
println "RBAC configured successfully"
println "Roles:"
println " admin → platform-eng-alice (full control)"
println " developer → dev-sarah (all Jenkins + payments-* jobs)"
println " developer → dev-omar (all Jenkins + frontend-* jobs)"
println " viewer → contractor-raj (read-only, no build access)"
Where to practice: First install the role-strategy plugin from Manage Jenkins → Plugin Manager. Enable Role-Based Strategy in Configure Global Security → Authorization. Then paste this script into the Script Console at http://localhost:8080/script. After running, go to Manage Jenkins → Manage and Assign Roles to verify the roles appear correctly. Full plugin docs at plugins.jenkins.io/role-strategy.
RBAC configured successfully Roles: admin → platform-eng-alice (full control) developer → dev-sarah (all Jenkins + payments-* jobs) developer → dev-omar (all Jenkins + frontend-* jobs) viewer → contractor-raj (read-only, no build access)
What just happened?
- Three global roles created and assigned — admin, developer, and viewer. The
developerrole gives Read access to Jenkins plus the ability to build, cancel, and update jobs. Theviewerrole gives only Read. Nobody except the admin can install plugins or change security settings. - Two item roles created with regex patterns —
payments-.*andfrontend-.*. A job namedpayments-service-buildmatches the payments pattern. A job namedfrontend-testmatches the frontend pattern. Jobs that match no pattern are invisible to developers — they literally don't appear in the job list. - dev-sarah has both a global and an item role — the global developer role lets her log in and see the Jenkins dashboard. The payments-team item role lets her see and build only payments-* jobs. She cannot see frontend pipelines even though dev-omar can build them.
- contractor-raj is viewer only — no item roles assigned, which means he can only see jobs because the viewer role gives him
Item.Read. He cannot trigger a build. This is exactly the right access for a contractor starting Monday. j.save()persisted everything — the roles, the patterns, and all assignments are written to disk. Restart Jenkins and everything stays intact.
Managing Users — Creating and Listing
When Jenkins is using its own user database (not LDAP or SSO), you can create and list users via the CLI. This is useful for scripting the onboarding of new team members.
# List all users currently in Jenkins
java -jar jenkins-cli.jar \
-s http://jenkins-master-01:8080 \
-auth admin:your-api-token \
list-credentials-as-xml system::system::jenkins _ 2>/dev/null || \
java -jar jenkins-cli.jar \
-s http://jenkins-master-01:8080 \
-auth admin:your-api-token \
groovy = << 'EOF'
import jenkins.model.Jenkins
import hudson.model.User
// List all Jenkins users with their full names
User.getAll().each { user ->
println "${user.id.padRight(25)} ${user.fullName}"
}
println "\nTotal users: ${User.getAll().size()}"
EOF
# Create a new user via the Groovy script console
# Useful for scripting team onboarding
java -jar jenkins-cli.jar \
-s http://jenkins-master-01:8080 \
-auth admin:your-api-token \
groovy = << 'EOF'
import jenkins.model.Jenkins
import hudson.model.User
import hudson.security.HudsonPrivateSecurityRealm
def realm = Jenkins.instance.securityRealm as HudsonPrivateSecurityRealm
// Create the user with a temporary password — they should change it on first login
def user = realm.createAccount('contractor-raj', 'ChangeMe123!')
user.setFullName('Raj Patel (Contractor)')
user.save()
println "Created user: contractor-raj"
println "Full name: Raj Patel (Contractor)"
println "Temporary password set — user should change on first login"
EOF
# list-users output: admin Jenkins Admin dev-sarah Sarah Chen dev-omar Omar Hassan platform-eng-alice Alice Kamau contractor-raj Raj Patel (Contractor) Total users: 5 # create-user output: Created user: contractor-raj Full name: Raj Patel (Contractor) Temporary password set — user should change on first login
What just happened?
- User list shows IDs and full names — the
User.getAll()Groovy call returns every user registered in Jenkins, including users who have logged in via OAuth but haven't been manually created. Theidis what you use in role assignments. ThefullNameis what appears in the UI. - User created with a temporary password — the
createAccount()call on theHudsonPrivateSecurityRealmcreates the user in Jenkins' internal database. The password should be communicated securely to the new user and changed on first login. - The role assignment from the RBAC script applies immediately — because we already ran the RBAC script that assigned
viewertocontractor-raj, this user already has the right permissions. Creating the account just enables them to log in with those permissions.
Role Design Best Practices
Start with minimum permissions and add as needed
It's easier to grant more access than to revoke it after someone has depended on it. Start tight, expand deliberately.
Never assign the admin role to service accounts
Automation scripts and CI tools should use dedicated service accounts with the minimum required permissions — not the admin account. If the script's token leaks, the blast radius is limited.
Store your RBAC script in Git and rerun it when Jenkins is rebuilt
The Groovy RBAC script above is your source of truth for who has access to what. Commit it to your infrastructure repository alongside your Dockerfiles and Jenkinsfiles. When Jenkins is rebuilt from scratch, running the script restores the full permission model in seconds.
Remove access when people leave — immediately
Deactivate or delete the account the day someone leaves the team. If you're using LDAP or SSO, deactivating their company account handles this automatically. For Jenkins' own database, you need a process.
Teacher's Note
The RBAC script is your Jenkins permission model as code. Treat it like any other infrastructure code — review it, version it, run it in CI.
Practice Questions
1. What is the plugin ID of the Role-Based Authorization Strategy plugin that you install from the Jenkins Plugin Manager?
2. In the Groovy RBAC script, which role type constant do you use when creating a role that applies only to jobs matching a name pattern?
3. Which method on the RoleBasedAuthorizationStrategy object assigns a specific user to a named role?
Quiz
1. How do you restrict a developer so they can only see and build their own team's jobs in Jenkins RBAC?
2. What is the difference between a global role and an item role in the role-strategy plugin?
3. What is the most reliable way to ensure Jenkins access is revoked when someone leaves the company?
Up Next · Lesson 30
Securing Credentials
How Jenkins encrypts and protects secrets at rest, credential rotation, the common security mistakes teams make, and how to audit your credential store for risks.