Setup LDAP based authentication in JBoss EAP 8 / 7.1+ using Elytron
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:
-
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) -
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-searchmay need to be true depending on the LDAP configuration. Also noterole-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) -
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.jksshould 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.jksshould 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) -
Create a
http-authentication-factoryand enableBASIC&FORMmechanism./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}]}]) -
Create a
sasl-authentication-factoryforcliandremoting-connectorand set the authentication mechanism toPLAIN/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}]}]) -
Optional Add a new filter-pattern
PLAINin the filters ofconfigurable-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}) -
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) -
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
PLAINfilter 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}) -
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 -
For enabling the application to authenticate using the same security-domain, configure
application-security-domainslike 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> -
Set the
realmname asexampleLdapSDin application'sweb.xmland setsecurity-domainasexampleLdapSDinjboss-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:
-
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) -
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) -
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.jksshould 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) -
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}]}]) -
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:
-
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) -
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) -
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) -
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}]}]) -
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}]}]) -
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) -
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
- Enable TRACE level logging on
org.wildfly.securityandorg.jboss.remoting(SASL). - Turn on LDAP tracing in the JVM by setting system property com.sun.jndi.ldap.connect.pool.debug=all. The value "fine" also works.
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.