Setup LDAP based authentication in JBoss EAP 8 / 7.1+ using Elytron

Solution Verified - Updated

Environment

  • Red Hat JBoss Enterprise Application Platform (EAP)
    • 8.x
    • 7.1+
  • Elytron
  • LDAP
  • RBAC (Role-based Access Control) for Management Console

Issue

  • How to configure including the management interface
  • Setup RBAC (Role-based Access Control)
  • Setup authentication for Admin console

Resolution

Standalone setup:

  1. Create the directory context. Be sure to replace the URL, principal and credential to match the LDAP server.

     /subsystem=elytron/dir-context=ldap-dir-context:add(url="ldap[s]://example.com",principal="CN=<service_account_user>,CN=Users,DC=EXAMPLE,DC=COM",credential-reference={clear-text="secret"}, referral-mode=follow)
    
  2. Create a LDAP realm and security domain. Be sure to replace the search-base-dn and filter-base-dn to match the LDAP server. Also, this example is specific to Active Directory. Other vendors may require changes like modifying rdn-identifier, modifying attribute-mapping's from attribute, adding a filter-name or other changes. use-recursive-search may need to be true depending on the LDAP configuration. Also note role-recursion="5", which means that if a LDAP group, contains other groups it will recurse up to 5 times to resolve composite groups.

     /subsystem=elytron/ldap-realm=ldap-realm:add(dir-context=ldap-dir-context,direct-verification="true",identity-mapping={rdn-identifier="sAMAccountName", attribute-mapping=[{filter-base-dn="CN=Users,DC=Example,DC=COM",filter="(& (objectClass=group)(member={1}))",from="cn",to="Roles",role-recursion="5"}], search-base-dn="CN=Users,DC=Example,DC=COM", use-recursive-search="true"})
    
     /subsystem=elytron/simple-role-decoder=from-roles-attribute:add(attribute=Roles)
    
     # if the permission set and the default permission mapper don't exist
     /subsystem=elytron/permission-set=login-permission:add(permissions=[{class-name="org.wildfly.security.auth.permission.LoginPermission"}])
     /subsystem=elytron/simple-permission-mapper=default-permission-mapper:add(mapping-mode=first,permission-mappings=[{match-all=true,permission-sets=[{permission-set=login-permission}]}])
     # if the permission set and the default permission mapper exist, ignore the above
    
    
     /subsystem=elytron/security-domain=ldap-security-domain:add(realms=[{realm=ldap-realm,role-decoder=from-roles-attribute}],default-realm=ldap-realm,permission-mapper=default-permission-mapper)
    
  3. For LDAPS to connect, if the LDAP server's certificate is not signed by a root certificate authority, a custom truststore needs to be configured. The JKS file ldap-truststore.jks should contain the LDAP server's certificate

     /subsystem=elytron/key-store=ldaps-truststore:add(path=ldap-truststore.jks,relative-to=jboss.server.config.dir,credential-reference={clear-text="secret"},type=JKS)
     /subsystem=elytron/trust-manager=ldaps-trustmanager:add(key-store=ldaps-truststore,algorithm="PKIX")
     /subsystem=elytron/client-ssl-context=ldaps-context:add(trust-manager=ldaps-trustmanager)
     /subsystem=elytron/dir-context=ldap-dir-context:write-attribute(name=ssl-context,value=ldaps-context)
    

    Additionally, if the LDAP server requires client certificate authentication, also knows as two-way SSL, client certificate must be provided in keystore. The JKS file ldap-keystore.jks should contain the client certificate and private key:

     /subsystem=elytron/key-store=ldaps-keystore:add(path=ldap-keystore.jks,relative-to=jboss.server.config.dir,credential-reference={clear-text="secret"},type=JKS) 
     /subsystem=elytron/key-manager=ldaps-keymanager:add(key-store=ldaps-keystore,algorithm="SunX509",credential-reference={clear-text="secret"}
     /subsystem=elytron/client-ssl-context=ldaps-context:write-attribute(name=key-manager,value=ldaps-keymanager)
    
  4. Create a http-authentication-factory and enable BASIC & FORM mechanism.

     /subsystem=elytron/http-authentication-factory=ldap-http-auth:add(http-server-mechanism-factory=global,security-domain=ldap-security-domain,mechanism-configurations=[{mechanism-name=BASIC,mechanism-realm-configurations=[{realm-name=ldap-realm}]}])
    
  5. Create a sasl-authentication-factory for cli and remoting-connectorand set the authentication mechanism to PLAIN

     /subsystem=elytron/configurable-sasl-server-factory=ldap-sasl-server-factory:add(sasl-server-factory=elytron)
     /subsystem=elytron/sasl-authentication-factory=ldap-sasl-authentication:add(sasl-server-factory=ldap-sasl-server-factory,security-domain=ldap-security-domain,mechanism-configurations=[{mechanism-name=PLAIN,mechanism-realm-configurations=[{realm-name=ldap-realm}]}])
    
  6. Optional Add a new filter-pattern PLAIN in the filters of configurable-sasl-server-factory. Note if it was already added as PLAIN pattern filter for another configuration skip this step. This is done if there's a client connecting that prefers DIGEST security, which would fail with LDAP. If planning on adding local auth, this will require another filter.

     /subsystem=elytron/configurable-sasl-server-factory=ldap-sasl-server-factory:list-add(name=filters, value={pattern-filter=PLAIN})
    
  7. Optional Change the management interface to use the configured LDAP method and enable http-upgrade:

     /core-service=management/management-interface=http-interface:write-attribute(name=http-authentication-factory,value=ldap-http-auth)
     /core-service=management/management-interface=http-interface:write-attribute(name=http-upgrade,value={sasl-authentication-factory=ldap-sasl-authentication})
     /core-service=management/management-interface=http-interface:write-attribute(name=http-upgrade-enabled, value=true)
    
  8. Optional Changing the management interface in the last step may be required to add support for local authentication.

    This exists by default, but the later entries depend on it:

     /subsystem=elytron/identity-realm=local:add(identity="$local")
    

    This enables the local auth in the ldap security-domain

     /subsystem=elytron/security-domain=ldap-security-domain:list-add(name=realms, index=0, value={realm=local} )
     /subsystem=elytron/sasl-authentication-factory=ldap-sasl-authentication:list-add(name=mechanism-configurations, index=0, value={mechanism-name="JBOSS-LOCAL-USER", realm-mapper="local"})
    
     /subsystem=elytron/configurable-sasl-server-factory=ldap-sasl-server-factory:write-attribute(name="properties",value={"wildfly.sasl.local-user.default-user" => "$local"}) 
    

    If added the PLAIN filter above, add this filter. Warning, If it wasn't done then adding this line will actually break the LDAP authentication because the filters are combined with "OR" logic.

     /subsystem=elytron/configurable-sasl-server-factory=ldap-sasl-server-factory:list-add(name=filters, value={pattern-filter=JBOSS-LOCAL-USER})
    
  9. Enabling RBAC in the management interface:

     /core-service=management/access=authorization:write-attribute(name=provider,value=rbac)
    

    Then add roles with a list of users/groups for each role.

     /core-service=management/access=authorization/role-mapping=SuperUser/include=user-exampleuser:add(name=exampleuser,type=USER)
     /core-service=management/access=authorization/role-mapping=SuperUser/include=group-examplegroup:add(name=examplegroup,type=GROUP)
     /core-service=management/access=authorization/role-mapping=Monitor:add
     /core-service=management/access=authorization/role-mapping=Monitor/include=user-anotheruser:add(name=anotheruser,type=USER)
    

    Note Do NOT add the realm= attribute to the role-mapping. See Management Console Authentication Fails with Elytron and RBAC, Displays "Connect to Management Interface" in JBoss EAP 7.1 or Later

    See Enabling RBAC roles in JBoss EAP 6/7.

  10. For enabling the application to authenticate using the same security-domain, configure application-security-domains like below

     /subsystem=undertow/application-security-domain=exampleLdapSD:add(http-authentication-factory=ldap-http-auth)
    

    Or

     .......
     <filters>
         <application-security-domains>
             <application-security-domain name="exampleLdapSD" http-authentication-factory="ldap-http-auth"/>
         </application-security-domains>
         </subsystem>
    
  11. Set the realm name as exampleLdapSD in application's web.xml and set security-domain as exampleLdapSD in jboss-web.xml

    • web.xml:

        <login-config>
            <auth-method>FORM</auth-method>
            <realm-name>exampleLdapSD</realm-name>
        </login-config>
      
    • jboss-web.xml:

        <jboss-web>
            <context-root>/APP</context-root>
            <security-domain>exampleLdapSD</security-domain>
        </jboss-web>
      

Domain mode "Application" setup:

For Domain mode the commands are similar to the ones above, except one must add the profile, for instance:

  1. Create the directory context. Be sure to replace the URL, principal, and credential to match the LDAP server.

     /profile=default/subsystem=elytron/dir-context=ldap-dir-context:add(url="ldap://localhost:10389",principal="uid=admin,ou=system",credential-reference={clear-text="secret"}, referral-mode=follow)
    
  2. Create an LDAP realm and security domain. Be sure to replace the search-base-dn and filter-base-dn to match the LDAP server. Also, this example is specific to Active Directory. Other vendors may require changes like modifying rdn-identifier, modifying attribute mappings from attribute, adding a filter-name or other changes. use-recursive-search may need to be true depending on the LDAP configuration. Also note role-recursion="5", which means that if an LDAP group, contains other groups it will recurse up to 5 times to resolve composite groups.

     /profile=default/subsystem=elytron/ldap-realm=ldap-realm:add(dir-context=ldap-dir-context,direct-verification="true",identity-mapping={rdn-identifier="sAMAccountName", attribute-mapping=[{filter-base-dn="CN=Users,DC=Example,DC=COM",filter="(& (objectClass=group)(member={1}))",from="cn",to="Roles",role-recursion="5"}], search-base-dn="CN=Users,DC=Example,DC=COM", use-recursive-search="true"})
     /profile=default/subsystem=elytron/simple-role-decoder=from-roles-attribute:add(attribute=Roles)
     /profile=default/subsystem=elytron/security-domain=ldap-security-domain:add(realms=[{realm=ldap-realm,role-decoder=from-roles-attribute}],default-realm=ldap-realm,permission-mapper=default-permission-mapper)
    
  3. For LDAPS to connect, if the LDAP server's certificate is not signed by a root certificate authority, a custom truststore needs to be configured. The JKS file ldap-truststore.jks should contain the LDAP server's certificate

     /profile=default//subsystem=elytron/key-store=ldaps-truststore:add(path=ldap-truststore.jks,relative-to=jboss.server.config.dir,credential-reference={clear-text="secret"},type=JKS)
     /profile=default//subsystem=elytron/trust-manager=ldaps-trustmanager:add(key-store=ldaps-truststore,algorithm="PKIX")
     /profile=default//subsystem=elytron/client-ssl-context=ldaps-context:add(trust-manager=ldaps-trustmanager)
     /profile=default//subsystem=elytron/dir-context=ldap-dir-context:write-attribute(name=ssl-context,value=ldaps-context)
    

    Additionally, if the LDAP server requires client certificate authentication, also knows as two-way SSL, the client certificate must be provided in keystore. The JKS file ldap-keystore.jks should contain the client certificate and private key:

     /subsystem=elytron/key-store=ldaps-keystore:add(path=ldap-keystore.jks,relative-to=jboss.server.config.dir,credential-reference={clear-text="secret"},type=JKS) 
     /subsystem=elytron/key-manager=ldaps-keymanager:add(key-store=ldaps-keystore,algorithm="SunX509",credential-reference={clear-text="secret"}
     /subsystem=elytron/client-ssl-context=ldaps-context:write-attribute(name=key-manager,value=ldaps-keymanager)
    
  4. Create an http-authentication-factory and enable BASIC & FORM mechanism.

     /profile=default/subsystem=elytron/http-authentication-factory=ldap-http-auth:add(http-server-mechanism-factory=global,security-domain=ldap-security-domain,mechanism-configurations=[{mechanism-name=BASIC,mechanism-realm-configurations=[{realm-name=ldap-realm}]}])
    
  5. Create a sasl-authentication-factory for CLI and remoting-connectorand set the authentication mechanism to PLAIN

     /profile=default/subsystem=elytron/configurable-sasl-server-factory=ldap-sasl-server-factory:add(sasl-server-factory=elytron)
     /profile=default/subsystem=elytron/sasl-authentication-factory=ldap-sasl-authentication:add(sasl-server-factory=ldap-sasl-server-factory,security-domain=ldap-security-domain,mechanism-configurations=[{mechanism-name=PLAIN,mechanism-realm-configurations=[{realm-name=ldap-realm}]}])
    

Domain mode "Management" setup:

  1. Create the directory context. Be sure to replace the URL, principal, and credential to match the LDAP server.

     /host=master/subsystem=elytron/dir-context=ldap-dir-context:add(url="ldap://127.0.0.1:10389",principal="uid=admin,ou=system",credential-reference={clear-text="secret"}, referral-mode=follow)
    
  2. Create an LDAP realm and security domain. Be sure to replace the search-base-dn and filter-base-dn to match the LDAP server. Also, this example is specific to Active Directory. Other vendors may require changes like modifying rdn-identifier, modifying attribute mappings from attribute, adding a filter-name or other changes. use-recursive-search may need to be true depending on the LDAP configuration. Also note role-recursion="5", which means that if an LDAP group, contains other groups it will recurse up to 5 times to resolve composite groups.

     /host=master/subsystem=elytron/ldap-realm=ldap-realm:add(dir-context=ldap-dir-context,direct-verification="true",identity-mapping={rdn-identifier="sAMAccountName", attribute-mapping=[{filter-base-dn="CN=Users,DC=Example,DC=COM",filter="(& (objectClass=group)(member={1}))",from="cn",to="Roles",role-recursion="5"}], search-base-dn="CN=Users,DC=Example,DC=COM", use-recursive-search="true"})
     
     /host=master/subsystem=elytron/simple-role-decoder=from-roles-attribute:add(attribute=Roles)
     
     /host=master/subsystem=elytron/security-domain=ldap-security-domain:add(realms=[{realm=ldap-realm,role-decoder=from-roles-attribute}],default-realm=ldap-realm,permission-mapper=default-permission-mapper)
    
  3. For LDAPS to connect, if the LDAP server's certificate is not signed by a root certificate authority, a custom truststore needs to be configured. The JKS file ldap-truststore.jks should contain the LDAP server's certificate.

     /host=master/subsystem=elytron/key-store=ldaps-truststore:add(path=ldap-truststore.jks,relative-to=jboss.server.config.dir,credential-reference={clear-text="secret"},type=JKS)
     /host=master/subsystem=elytron/trust-manager=ldaps-trustmanager:add(key-store=ldaps-truststore,algorithm="PKIX")
     /host=master/subsystem=elytron/client-ssl-context=ldaps-context:add(trust-manager=ldaps-trustmanager)
     /host=master/subsystem=elytron/dir-context=ldap-dir-context:write-attribute(name=ssl-context,value=ldaps-context)
    

    Additionally, if the LDAP server requires client certificate authentication, also knows as two-way SSL, the client certificate must be provided in keystore. The JKS file ldap-keystore.jks should contain the client certificate and private key:

     /host=master/subsystem=elytron/key-store=ldaps-keystore:add(path=ldap-keystore.jks,relative-to=jboss.server.config.dir,credential-reference={clear-text="secret"},type=JKS) 
     /host=master/subsystem=elytron/key-manager=ldaps-keymanager:add(key-store=ldaps-keystore,algorithm="SunX509",credential-reference={clear-text="secret"}
     /host=master/subsystem=elytron/client-ssl-context=ldaps-context:write-attribute(name=key-manager,value=ldaps-keymanager)
    
  4. Create an http-authentication-factory and enable BASIC & FORM mechanism.

     /host=master/subsystem=elytron/http-authentication-factory=ldap-http-auth:add(http-server-mechanism-factory=global,security-domain=ldap-security-domain,mechanism-configurations=[{mechanism-name=BASIC,mechanism-realm-configurations=[{realm-name=ldap-realm}]}])
    
  5. Create a sasl-authentication-factory for CLI and remoting-connectorand set the authentication mechanism to PLAIN

     /host=master/subsystem=elytron/configurable-sasl-server-factory=ldap-sasl-server-factory:add(sasl-server-factory=elytron)
     /host=master/subsystem=elytron/sasl-authentication-factory=ldap-sasl-authentication:add(sasl-server-factory=ldap-sasl-server-factory,security-domain=ldap-security-domain,mechanism-configurations=[{mechanism-name=PLAIN,mechanism-realm-configurations=[{realm-name=ldap-realm}]}])
    
  6. Change the management interface to use the configured LDAP method and enable http-upgrade:

     /host=master/core-service=management/management-interface=http-interface:write-attribute(name=http-authentication-factory,value=ldap-http-auth)
     /host=master/core-service=management/management-interface=http-interface:write-attribute(name=http-upgrade,value={sasl-authentication-factory=ldap-sasl-authentication})
     /host=master/core-service=management/management-interface=http-interface:write-attribute(name=http-upgrade-enabled, value=true)
    
  7. Optional: Changing the management interface in the last step may be required to add support for local authentication.

     /host=master/subsystem=elytron/identity-realm=local:add(identity="$local")
    

    This enables the local auth in the ldap security-domain

     /host=master/subsystem=elytron/security-domain=ldap-security-domain:list-add(name=realms, index=0, value={realm=local} )
     /host=master/subsystem=elytron/sasl-authentication-factory=ldap-sasl-authentication:list-add(name=mechanism-configurations, index=0, value={mechanism-name="JBOSS-LOCAL-USER", realm-mapper="local"})
    
     /host=master/subsystem=elytron/configurable-sasl-server-factory=ldap-sasl-server-factory:write-attribute(name="properties",value={"wildfly.sasl.local-user.default-user" => "$local"}) 
    

So, to connect using the LDAP users:

    sh bin/jboss-cli.sh --connect --no-local-auth

to connect using $local users.

    sh bin/jboss-cli.sh --connect

Diagnostic Steps

Components
Category

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.