Jenkins users are authenticated against your existing LDAP or Active Directory infrastructure, meaning you don’t have to manage separate credentials for Jenkins.

Let’s say you’ve got a Jenkins instance and you want to tie its user authentication into your company’s Active Directory (AD). Instead of every developer having a separate Jenkins login, they can just use their AD credentials. This is super common for security and management reasons.

Here’s a peek at what a basic LDAP configuration looks like in Jenkins. This isn’t the full picture, but it shows the core parameters you’ll be wrestling with:

jenkins.model.Jenkins.instance.security.configure(
    new hudson.security.HudsonPrivateSecurityRealm(false), // Using the built-in security realm initially
    new hudson.security.LDAPSecurityRealm("ldap://your-ad-server.your-domain.com:389/dc=your-domain,dc=com"),
    null, // No authorization strategy here for now
    true, // Enable security
    false // Disable fallback to Jenkins own user database
)

This snippet, executed via the Jenkins Script Console, would start the process of integrating LDAP. You’d first set up Jenkins to use its own internal user database, then swap it out for the LDAP realm. The LDAPSecurityRealm is the key piece, pointing to your LDAP server.

The problem this solves is straightforward: eliminating duplicate user management. Every time a new employee joins or an old one leaves, you’d otherwise have to update Jenkins separately. By integrating with AD, user lifecycle management is centralized.

Internally, Jenkins acts as an LDAP client. When a user tries to log in, Jenkins queries your LDAP server. It sends the username and password provided by the user. The LDAP server then validates these credentials against its directory. If the LDAP server confirms the credentials are valid, Jenkins grants access. If not, access is denied.

Here’s a more detailed look at the key configuration levers:

  • Server URL: This is the address of your LDAP server. It typically includes the protocol (e.g., ldap:// or ldaps://), hostname, and port (default is 389 for LDAP, 636 for LDAPS). For AD, it might look like ldap://dc1.mycompany.local:389.
  • Bind DN and Password: Jenkins needs credentials to connect to the LDAP server itself to perform searches and lookups. This isn’t the user’s password, but an account Jenkins uses. A common pattern is to use a dedicated service account. For example, cn=jenkins_bind,ou=Service Accounts,dc=mycompany,dc=local with its associated password.
  • User Search Base: This is the starting point in your LDAP directory where Jenkins should look for users. For AD, this is often your domain’s root Distinguished Name (DN), like dc=mycompany,dc=local. Jenkins will then search within this base.
  • User Search Filter: This is a crucial part that tells Jenkins how to find a user. It’s an LDAP filter. For AD, a common filter is (&(objectClass=user)(sAMAccountName={0})). {0} is a placeholder that Jenkins replaces with the username the user typed into the login form. This filter finds objects that are users and whose sAMAccountName attribute matches the provided username.
  • Group or Role Name Attributes: You can map LDAP groups to Jenkins roles. You’ll specify which LDAP attribute contains the group memberships. For AD, this is often memberOf.
  • Manager DN and Password (for group membership caching): If you want Jenkins to cache group memberships for performance, it might need a separate bind DN and password with read access to group data.

Let’s see a more complete configuration in Jenkins’ config.xml (which is what the Groovy script above modifies):

<securityRealm class="hudson.security.LDAPSecurityRealm">
  <server>ldap://dc1.mycompany.local:389</server>
  <bindDn>cn=jenkins_bind,ou=Service Accounts,dc=mycompany,dc=local</bindDn>
  <bindPassword>cHJvZ3JhbW1lcnMgb25seQ==</bindPassword> <!-- This is base64 encoded -->
  <userSearchBase>dc=mycompany,dc=local</userSearchBase>
  <userSearchFilter>(&amp;(objectClass=user)(sAMAccountName={0}))</userSearchFilter>
  <groupSearchBase>ou=Groups,dc=mycompany,dc=local</groupSearchBase> <!-- Optional, for group lookups -->
  <groupSearchFilter>(&amp;(objectClass=group)(memberOf={0}))</groupSearchFilter> <!-- Example filter -->
  <managerDn>cn=jenkins_manager,ou=Service Accounts,dc=mycompany,dc=local</managerDn> <!-- Optional -->
  <managerPassword>YW5vdGhlcnBhc3N3b3Jk</managerPassword> <!-- Optional, base64 encoded -->
  <disableGroupMembershipLookup>false</disableGroupMembershipLookup>
  <cacheEntries>true</cacheEntries>
  <cacheTimeout>600</cacheTimeout>
</securityRealm>

Notice the bindPassword and managerPassword are base64 encoded. Jenkins does this for a little bit of obfuscation, though it’s not true encryption. You can decode them to see the plain text password.

The most surprising thing about integrating Jenkins with LDAP/AD is how often the user search filter is the culprit for login failures, even when the server details and bind credentials are correct. People often get the base DN right but then use a filter that’s too restrictive or doesn’t account for AD’s specific object classes or attribute names (like sAMAccountName vs. uid).

If you’re using LDAPS (LDAP over SSL/TLS), you’ll need to import your LDAP server’s certificate into Jenkins’ Java trust store. Otherwise, Jenkins won’t trust the connection, and you’ll see SSL handshake errors. This is a common oversight when moving from plain LDAP to LDAPS for security.

Once you have LDAP authentication working, the next logical step is to configure authorization, mapping your LDAP groups to Jenkins roles.

Want structured learning?

Take the full Jenkins course →