Using failover realm in Elytron
With a failover realm you can configure an alternative realm that will be used if primary realm is not available. A common use case is to fail over to a local file based realm if an LDAP or database server has gone down allowing administrators to retain access to the server.
Add a failover realm
You can add a failover-realm
to the Elytron subsystem by specifying the following attributes:
-
delegate-realm
primary security realm -
failover-realm
alternative realm that will be used when primary realm is not available[1] -
emit-events
configures whether this failover realm should emit SecurityRealmUnavailableEvent security event to the corresponding SecurityDomain when it fails over[2].
/subsystem=elytron/failover-realm=failoverRealmExample:add(
delegate-realm=LdapRealm,failover-realm=LocalRealm,emit-events=false)
If the delegate throws a RealmUnavailableException during RealmIdentity lookup, it will be caught and failover realm will be used instead.
[1] Realm is unavailable when it throws a RealmUnavailableException during lookup. This exception occurs when the connection to the realm was unsuccessful.
[2] Security events are captured by security event listeners and can be used for audit logging
Example
Below is an example of adding a failover-realm
with primary LDAP realm and fail over filesystem realm.
To make this example simple, we are going to use containerised version of OpenLdap. You can use docker
and run the following:
$ docker run --env LDAP_ORGANISATION="wildfly" --env LDAP_DOMAIN="wildfly.org" --env LDAP_ADMIN_PASSWORD="admin" --detach osixia/openldap
You can check its IP address with the following command:
$ docker inspect --format '{{ .NetworkSettings.IPAddress }}' $(docker ps -q)
172.17.0.2
Use any LDAP browser to check that the connection is working and to import a sample ldif
file containing a single user named "user" which is granted the Role “Admin”.
dn: ou=Users,dc=wildfly,dc=org
objectClass: organizationalUnit
objectClass: top
ou: Users
dn: uid=user,ou=Users,dc=wildfly,dc=org
objectClass: top
objectClass: person
objectClass: inetOrgPerson
cn: Jane
sn: user
uid: user
userPassword: secret123
dn: ou=Roles,dc=wildfly,dc=org
objectclass: top
objectclass: organizationalUnit
ou: Roles
dn: cn=Admin,ou=Roles,dc=wildfly,dc=org
objectClass: top
objectClass: groupOfNames
cn: Admin
member: uid=user,ou=Users,dc=wildfly,dc=org
Next, configure the LDAP realm in the elytron subsystem with appropriate identity and attribute mappings.
/subsystem=elytron/dir-context=exampleDC:add(url="ldap://172.17.0.2:389",principal="cn=admin,dc=wildfly,dc=org",credential-reference={clear-text="admin"})
/subsystem=elytron/ldap-realm=exampleLdapRealm:add(dir-context=exampleDC,identity-mapping={search-base-dn="ou=Users,dc=wildfly,dc=org",rdn-identifier="uid",user-password-mapper={from="userPassword"},attribute-mapping=[{filter-base-dn="ou=Roles,dc=wildfly,dc=org",filter="(&(objectClass=groupOfNames)(member={1}))",from="cn",to="Roles"}]})
Add filesystem realm with identity user
and role Admin
as well.
/subsystem=elytron/filesystem-realm=exampleFSRealm:add(path=demofs-realm-users,relative-to=jboss.server.config.dir)
/subsystem=elytron/filesystem-realm=exampleFSRealm:add-identity(identity=user)
/subsystem=elytron/filesystem-realm=exampleFSRealm:set-password(identity=user,clear={password="secret123"})
/subsystem=elytron/filesystem-realm=exampleFSRealm:add-identity-attribute(identity=user,name=Roles, value=["Admin"])
Configure failover-realm
to use the file system realm as a failover when LDAP realm is not available.
/subsystem=elytron/failover-realm=failoverRealm:add(delegate-realm=exampleLdapRealm,failover-realm=exampleFSRealm)
Add a security domain that uses this failover realm and role decoder that decodes roles from the Roles
attribute.
/subsystem=elytron/simple-role-decoder=from-roles-attribute:add(attribute=Roles)
/subsystem=elytron/security-domain=failoverSD:add(default-realm=failoverRealm,permission-mapper=default-permission-mapper,realms=[{realm=failoverRealm,role-decoder="from-roles-attribute"}])
Add HTTP authentication factory with this new security domain and BASIC
authentication mechanism. Finally, configure undertow to use this HTTP authentication factory.
/subsystem=elytron/http-authentication-factory=example-failover-http-auth:add(http-server-mechanism-factory="global",mechanism-configurations=[{mechanism-name="BASIC",mechanism-realm-configurations=[{realm-name="RealmUsersRoles"}]}],security-domain=failoverSD)
/subsystem=undertow/application-security-domain=httpSD:add(http-authentication-factory=example-failover-http-auth)
Clone the example from this link https://github.com/wildfly-security-incubator/elytron-examples/tree/master/failover-realm and deploy it to the running WildFly instance.
mvn clean install wildfly:deploy
After the application was successfully deployed you can access the http://localhost:8080/failover-realm-demo/secure in your browser. You will be prompted to authenticate. Provide username user
and password secret123
.
The security domain is configured to use the failover realm. Since the LDAP realm is configured to be the delegate realm, the authentication request was handled by the LDAP realm.
Use docker to pause the OpenLDAP container:
$ docker pause ${CONTAINER}
The docker pause command suspends all processes in the specified container. This will make the LDAP realm unable to establish the connection to the OpenLDAP running in the container.
When you access the http://localhost:8080/failover-realm-demo/secure and try to authenticate again, the LDAP realm will try to establish the connection. You might notice a slight delay in your authentication. After a certain timeout is exceeded, the failover filesystem realm will be used for authentication instead. Since the user is present in the filesystem realm as well, you will be able to connect successfully.
To use ldap-realm
instead of the filesystem-realm
again, you can unpause the container.
$ docker unpause ${CONTAINER}
Summary
This blog post has given an overview of failover-realm
usage in the Elytron subsystem.
You can take a look at a following example https://github.com/wildfly-security-incubator/elytron-examples/tree/master/failover-realm for more information.