Jenkins Security Architecture: How ACL, Permission, AuthorizationStrategy, and SecurityRealm Work Together

Jenkins separates authentication from authorization through a layered architecture built around SecurityRealm, AuthorizationStrategy, ACL, and Permission, with all permission checks ultimately delegating to the root ACL provided by the active authorization strategy.

The jenkinsci/jenkins repository implements a robust security model that keeps authentication and authorization decoupled, making it possible to plug in diverse identity providers and access policies. At the heart of the Jenkins security architecture are four coordinated components: SecurityRealm, AuthorizationStrategy, ACL, and Permission. Administrators who understand how these classes interact can configure fine-grained access control and troubleshoot authorization failures with precision.

SecurityRealm: The Jenkins Authentication Layer

SecurityRealm is the extension point that handles the authentication side of the Jenkins security architecture. Defined in core/src/main/java/hudson/security/SecurityRealm.java, it provides the Spring Security filter chain, a UserDetailsService, and optional remember-me support. Concrete implementations such as LDAP, GitHub OAuth, and the private internal database plug into this framework by supplying their own login logic while reusing the standard filter sequence.

How SecurityRealm Creates the Authentication Pipeline

Every SecurityRealm implementation assembles SecurityComponents via createSecurityComponents(). This method returns an authentication manager, a user-details service, and a remember-me service. The realm then wires these components into a servlet filter chain through createFilter(), which typically includes session context integration, basic authentication, form login, remember-me, anonymous access, and logout handling.

Built-in Authentication Features

Beyond primary login logic, SecurityRealm handles logout routing, self-registration pages, and CAPTCHA support. These capabilities are defined in the base class so that individual realms inherit consistent behavior for session termination and user signup flows.

AuthorizationStrategy: The Jenkins Authorization Layer

AuthorizationStrategy is the extension point for the authorization side. Defined in core/src/main/java/hudson/security/AuthorizationStrategy.java, its primary responsibility is supplying the root ACL through getRootACL(). Every other ACL in the system ultimately delegates to this root ACL, establishing a single authority for access decisions.

Root ACL as the Single Authority

The default implementation, AuthorizationStrategy.Unsecured, grants every permission to everyone. Production implementations such as Matrix-based, Project-based, and Role-Based strategies return a custom ACL object that enforces explicit grants. When Jenkins needs to authorize an action, it consults the root ACL via AuthorizationStrategy.getRootACL() and then calls ACL.hasPermission2(Authentication, Permission).

Per-Object ACLs for Fine-Grained Control

Concrete strategies may expose additional ACLs tailored to specific objects. Methods such as getACL(Job), getACL(View), and getACL(User) allow strategies to return specialized access control lists. Even when these per-object ACLs exist, they typically delegate upward to the root ACL, ensuring a single, consistent authority for all permission decisions.

ACL: The Core Permission-Checking Interface

hudson.security.ACL, located in core/src/main/java/hudson/security/ACL.java, is the engine that answers the question "is this user allowed to perform this action?". Implementations are usually created by an AuthorizationStrategy; for example, MatrixACL and the ACLs returned by ProjectBasedMatrixAuthorizationStrategy evaluate whether a given authentication holds the requested permission.

hasPermission2 and the Lambda Helper

The interface defines hasPermission(User, Permission) and hasPermission2(Authentication, Permission). For trivial cases, the lambda-based helper ACL.lambda2 provides a lightweight predicate. The unsecured strategy uses this helper to unconditionally return true, bypassing all authorization checks.

How Authentication and Authorization Interact

The Jenkins security architecture processes every request through a coordinated pipeline. First, the filter chain created by the active SecurityRealm authenticates the user and stores the resulting Authentication object in the Spring Security SecurityContextHolder.

When code asks whether a user may perform an action --- for example, Job.CONFIGURE --- Jenkins retrieves the current authentication and calls AuthorizationStrategy.getRootACL(). The root ACL's hasPermission2(Authentication, Permission) method then evaluates the request. If the ACL grants the permission, the request proceeds; if denied, Jenkins delegates to the AccessDeniedHandler, which returns an HTTP 403 response. This design guarantees that authentication is established once per request and reused consistently across all subsequent authorization checks.

Configuring Jenkins Security Programmatically

Administrators can script the Jenkins security architecture directly via Groovy console snippets or init hooks. The following examples demonstrate registering an LDAP realm, applying a matrix strategy, and checking permissions in Java.

Register an LDAP SecurityRealm

import hudson.security.*
import jenkins.model.Jenkins

def realm = new LDAPSecurityRealm(
    "ldap://ldap.example.com",
    "dc=example,dc=com",
    null,                     // manager DN (optional)
    null,                     // manager password (optional)
    null,                     // user search base (optional)
    null,                     // user search filter (optional)
    null,                     // group search base (optional)
    null,                     // group search filter (optional)
    false,                    // disable mail address resolver
    null,                     // bind name
    null,                     // bind password
    false                     // use caching
)
Jenkins.instance.setSecurityRealm(realm)
Jenkins.instance.save()

Apply a Matrix-Based AuthorizationStrategy

import hudson.security.*
import jenkins.model.Jenkins

def strategy = new GlobalMatrixAuthorizationStrategy()
strategy.add(Jenkins.ADMINISTER, "admin")       // admin gets all rights
strategy.add(Permission.fromId("Job.Build"), "developer")
Jenkins.instance.setAuthorizationStrategy(strategy)
Jenkins.instance.save()

Verify Permissions Against the Root ACL

import hudson.security.*; 
import jenkins.model.Jenkins;

ACL acl = Jenkins.get().getAuthorizationStrategy().getRootACL();
boolean canConfigure = acl.hasPermission2(
    Jenkins.getAuthentication(),
    Jenkins.get().getPermission("Job.Configure")
);
System.out.println("User can configure jobs? " + canConfigure);

Summary

  • SecurityRealm (hudson.security.SecurityRealm) manages authentication by assembling SecurityComponents and exposing a Spring Security filter chain via createFilter().
  • AuthorizationStrategy (hudson.security.AuthorizationStrategy) manages authorization by supplying a root ACL through getRootACL(), which serves as the final authority for every permission decision.
  • ACL (hudson.security.ACL) performs the actual permission checks through hasPermission2(Authentication, Permission), with concrete implementations provided by the active authorization strategy.
  • All permission checks in Jenkins ultimately flow through the root ACL, ensuring centralized, consistent access control across jobs, views, nodes, and users.

Frequently Asked Questions

What is the difference between SecurityRealm and AuthorizationStrategy in Jenkins?

SecurityRealm handles authentication by verifying who the user is, typically through a Spring Security filter chain and a UserDetailsService. AuthorizationStrategy handles authorization by deciding what that authenticated user is allowed to do, using an ACL to grant or deny specific permissions. They are separate extension points so that administrators can mix any identity provider with any access policy.

How does Jenkins check if a user has a specific permission?

When code requests a permission check, Jenkins retrieves the current Authentication from the security context and calls AuthorizationStrategy.getRootACL(). It then invokes ACL.hasPermission2(Authentication, Permission) on that root ACL. If the ACL returns true, the action is permitted; otherwise, Jenkins raises an access-denied exception and returns HTTP 403.

What is the root ACL in Jenkins?

The root ACL is the top-level ACL object returned by AuthorizationStrategy.getRootACL(). It is the single authority that evaluates every permission request in the system. Even when strategies supply per-object ACLs via methods like getACL(Job), those ACLs typically delegate to the root ACL to ensure consistent policy enforcement.

Can I combine LDAP authentication with role-based authorization in Jenkins?

Yes. Because SecurityRealm and AuthorizationStrategy are independent extension points, you can configure an LDAPSecurityRealm for authentication while using the Role-Based Authorization Strategy plugin for authorization. LDAP provides the user and group identities, and the authorization strategy maps those identities to Jenkins permissions through its ACL implementation.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →