Accessing Security Realm Cache in Wildfly 26

57 views
Skip to first unread message

Laura Schanno

unread,
Aug 1, 2025, 6:34:20 PMAug 1
to WildFly

Hello,


I’m looking for information on how to programmatically interact with the cache in a cacheable security realm so that individual Principals can be ejected from the cache as desired. Some background information: I’m attempting to move from Wildfly 17 to Wildfly 21. We currently have a cached credentials service that is intended to synchronize the evicting, flushing, and searching of user credentials between two caches: the underlying Wildfly cache, and a separate application-wide cache maintained by a separate user service.


For wildfly 17, we created a cacheable security domain as follows:

/subsystem=security/security-domain=datawave:add(cache-type=infinispan)

/subsystem=security/security-domain=datawave/authentication=classic:add

/subsystem=security/security-domain=datawave/authentication=classic/login-module=Remoting:add( \

   code=Remoting, \

   flag=optional, \

   module-options={password-stacking=useFirstPass})

/subsystem=security/security-domain=datawave/authentication=classic/login-module=RunAs:add( \

   code=RunAs, \

   flag=required, \

   module-options={roleName=InternalUser})

/subsystem=security/security-domain=datawave/authentication=classic/login-module=Datawave:add( \

   code=datawave.security.login.DatawavePrincipalLoginModule, \

   flag=required, \

   module-options={ \

       principalClass=datawave.security.authorization.DatawavePrincipal, \

       verifier=datawave.security.login.DatawaveCertVerifier, \

       ocspLevel=off, \

       allowUserProxying=false, \

       trustedHeaderLogin="${dw.trusted.header.authentication:false}"})

/subsystem=security/security-domain=datawave/jsse=classic:add( \

   keystore={type="${KEYSTORE_TYPE}", \

   password="${KEYSTORE_PASSWORD}", \

   url="file://${KEYSTORE}"}, \

   truststore={type="${TRUSTSTORE_TYPE}", \

   password="${TRUSTSTORE_PASSWORD}", \

   url="file://${TRUSTSTORE}"})


We then have a method that produces the underlying cache (as a CacheableManager from picketbox) so it can be injected in other EJBs:

@Resource(name = "java:jboss/jaas/datawave")

private AuthenticationManager authenticationManager;


@Produces

@AuthorizationCache

@SuppressWarnings("unchecked")

public CacheableManager<Object,Principal> produceAuthManager() {

   return (authenticationManager instanceof CacheableManager) ? (CacheableManager<Object,Principal>) authenticationManager : null;

}


This then gets injected into our credentials cache service where we can evict Principals as needed.


   @Inject

   @AuthorizationCache

   private CacheableManager<?,Principal> authManager;


   @Inject

   private Instance<CachedDatawaveUserService> cachedDatawaveUserServiceInstance;


   /**

    * Removes all cached {@link DatawaveUser}s. There are potentially two caches in use. First, Wildfly uses a security cache that stores {@link Principal}s

    * under the incoming credential key. This is normally a very short-lived cache (5-30 minutes). Second, a {@link CachedDatawaveUserService} may be in use,

    * which means that it caches according to its own rules. This method attempts to clear both caches.

    *

    * @return a string indicating cache flush was successful

    */

   @GET

   @Path("/flushAll")

   @JmxManaged

   public String flushAll() {

       try {

           // Remove principals from the Wildfly cached authentication manager, if we have one in use.

           authManager.flushCache();

           if (!cachedDatawaveUserServiceInstance.isUnsatisfied()) {

               cachedDatawaveUserServiceInstance.get().evictAll();

           }

           return "All credentials caches cleared.";

       } catch (Exception e) {

           GenericResponse<String> response = new GenericResponse<>();

           response.addException(new QueryException(UNKNOWN_SERVER_ERROR, e));

           throw new DatawaveWebApplicationException(e, response);

       }

   }


Our authentication will need to be migrated over to a custom security realm in Wildfly 26, and from my understanding, it will need to be embedded into a caching-realm if we want to continue to have a cache of the Principals via Wildfly. Something that will probably look similar to the following:


/subsystem=elytron/custom-realm=datawaveRealm:add( \

   class-name=datawave.security.realm.DatawavePrincipalSecurityRealm, \

   module="datawave.elytron", \

   configuration={ \

       verifier="datawave.security.realm.DatawaveCertVerifier", \

       ocspLevel="off", \

       allowUserProxying="false", \

       trustedHeaderLogin="${trusted.header.login}"})

/subsystem=elytron/caching-realm=cachedDatawaveRealm:add( \

   realm=datawaveRealm)

/subsystem=elytron/security-domain=datawave:add(default-realm=cachedDatawaveRealm,realms=[{realm=cachedDatawaveRealm}])

 

What would be the best way to inject the cache in use by the SecurityRealm elsewhere so that we can evict Principals as needed? I assume I need to access and inject the realm’s RealmIdentityCache instance. If this isn’t supported, what is the recommended way to programmatically interact with a security realm’s cache?


Laura Schanno

unread,
Aug 2, 2025, 3:19:13 PMAug 2
to WildFly
Alternatively, if a cached SecurityRealm or its cache cannot be injected, is there a way to interact or configure the security realm to make it possible to evict specific Principals or list its contents?

Laura Schanno

unread,
Aug 4, 2025, 5:54:04 PMAug 4
to WildFly
Looking into this a bit further, it appears that the ModifiableSecurityRealm interface exposes methods for managing the identities associated with the realm. When the identities are modified in a modifiable security realm, does this modification persist throughout the application lifespan, or only within the lifespan of a single authentication session?

Diana Krepinska

unread,
Aug 6, 2025, 7:30:22 AMAug 6
to WildFly
The modification is persisted in the realm. One example that contains modification of the realm identity is here: https://github.com/wildfly-security-incubator/elytron-examples/blob/main/self-service/src/main/java/Identity.java . Not every security realm supports modifying identities though, only those that extend the  ModifiableSecurityRealm or CachingModifiableSecurityRealm. The caching-realm uses LRU strategy, you can't choose which principal to evict, that would be a feature request. Now this has to be implemented as a custom realm.

Laura Schanno

unread,
Aug 6, 2025, 11:17:54 AMAug 6
to WildFly
Thanks for the info, I'll take a look at that example along with CachingModifiableSecurityRealm to investigate using a custom realm. Is there a recommended way to programmatically get the security realm(s) from the current security domain? I understand the SecurityDomain exposes some methods for getting the current security identity, but I didn't see anything for security realms.

Diana Krepinska

unread,
Aug 27, 2025, 6:57:59 AMAug 27
to WildFly
There is no recommended way, as the methods to obtain realms information from the SecurityDomain are not public. There is a separation between a server configuration and a deployment. Why/where do you need the security realms?

Laura Schanno

unread,
Aug 27, 2025, 10:30:07 AMAug 27
to WildFly
At the time that I asked the question, I believed I would need to access the security realms programmatically in order to directly update the cache manually where needed. My understanding  of how to inject and manage the cache since then has changed, so I don't think I need to be able to directly access the security realms anymore.
Reply all
Reply to author
Forward
0 new messages