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

> Understand Jenkins security architecture. Learn how SecurityRealm, AuthorizationStrategy, ACL, and Permission enable robust access control and protect your CI/CD pipelines.

- Repository: [Jenkins/jenkins](https://github.com/jenkinsci/jenkins)
- Tags: architecture
- Published: 2026-07-28

---

**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`](https://github.com/jenkinsci/jenkins/blob/main/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`](https://github.com/jenkinsci/jenkins/blob/main/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`](https://github.com/jenkinsci/jenkins/blob/main/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

```groovy
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

```groovy
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

```java
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.