99import org .elasticsearch .action .ActionListener ;
1010import org .elasticsearch .common .cache .Cache ;
1111import org .elasticsearch .common .cache .CacheBuilder ;
12+ import org .elasticsearch .common .cache .CacheLoader ;
1213import org .elasticsearch .common .settings .SecureString ;
1314import org .elasticsearch .common .util .concurrent .ListenableFuture ;
1415import org .elasticsearch .common .util .concurrent .ThreadContext ;
3233
3334public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm implements CachingRealm {
3435
35- private final Cache < String , ListenableFuture < CachedResult >> cache ;
36+ private final UserAuthenticationCache cache ;
3637 private final ThreadPool threadPool ;
3738 private final boolean authenticationEnabled ;
38- final Hasher cacheHasher ;
39+ protected final Hasher credentialHasher ;
3940
4041 protected CachingUsernamePasswordRealm (RealmConfig config , ThreadPool threadPool ) {
42+ this (config , threadPool , buildDefaultCache (config ));
43+ }
44+
45+ protected CachingUsernamePasswordRealm (RealmConfig config , ThreadPool threadPool , UserAuthenticationCache cache ) {
4146 super (config );
42- cacheHasher = Hasher .resolve (this .config .getSetting (CachingUsernamePasswordRealmSettings .CACHE_HASH_ALGO_SETTING ));
47+ credentialHasher = Hasher .resolve (this .config .getSetting (CachingUsernamePasswordRealmSettings .CACHE_HASH_ALGO_SETTING ));
4348 this .threadPool = threadPool ;
44- final TimeValue ttl = this .config .getSetting (CachingUsernamePasswordRealmSettings .CACHE_TTL_SETTING );
49+ this .authenticationEnabled = config .getSetting (CachingUsernamePasswordRealmSettings .AUTHC_ENABLED_SETTING );
50+ this .cache = cache ;
51+ }
52+
53+ private static UserAuthenticationCache buildDefaultCache (RealmConfig config ) {
54+ final TimeValue ttl = config .getSetting (CachingUsernamePasswordRealmSettings .CACHE_TTL_SETTING );
4555 if (ttl .getNanos () > 0 ) {
46- cache = CacheBuilder .<String , ListenableFuture <CachedResult >>builder ()
56+ final Cache < String , ListenableFuture < CachedResult >> cache = CacheBuilder .<String , ListenableFuture <CachedResult >>builder ()
4757 .setExpireAfterWrite (ttl )
48- .setMaximumWeight (this . config .getSetting (CachingUsernamePasswordRealmSettings .CACHE_MAX_USERS_SETTING ))
58+ .setMaximumWeight (config .getSetting (CachingUsernamePasswordRealmSettings .CACHE_MAX_USERS_SETTING ))
4959 .build ();
50- } else {
51- cache = null ;
60+ return new UserAuthenticationCache () {
61+ @ Override
62+ public void invalidate (String key ) {
63+ cache .invalidate (key );
64+ }
65+
66+ @ Override
67+ public void invalidate (String key , ListenableFuture <CachedResult > value ) {
68+ cache .invalidate (key , value );
69+ }
70+
71+ @ Override
72+ public void invalidateAll () {
73+ cache .invalidateAll ();
74+ }
75+
76+ @ Override
77+ public int count () {
78+ return cache .count ();
79+ }
80+
81+ @ Override
82+ public ListenableFuture <CachedResult > computeIfAbsent (
83+ String key ,
84+ CacheLoader <String , ListenableFuture <CachedResult >> loader
85+ ) throws ExecutionException {
86+ return cache .computeIfAbsent (key , loader );
87+ }
88+ };
5289 }
53- this .authenticationEnabled = config .getSetting (CachingUsernamePasswordRealmSettings .AUTHC_ENABLED_SETTING );
90+
91+ return null ;
5492 }
5593
5694 @ Override
@@ -122,6 +160,7 @@ public final void authenticate(AuthenticationToken authToken, ActionListener<Aut
122160 * @param listener to be called at completion
123161 */
124162 private void authenticateWithCache (UsernamePasswordToken token , ActionListener <AuthenticationResult <User >> listener ) {
163+ logger .info ("AUTH WITH CACHE" );
125164 assert cache != null ;
126165 try {
127166 final AtomicBoolean authenticationInCache = new AtomicBoolean (true );
@@ -130,6 +169,7 @@ private void authenticateWithCache(UsernamePasswordToken token, ActionListener<A
130169 return new ListenableFuture <>();
131170 });
132171 if (authenticationInCache .get ()) {
172+ logger .info ("IN CACHE" );
133173 // there is a cached or an inflight authenticate request
134174 listenableCacheEntry .addListener (ActionListener .wrap (cachedResult -> {
135175 final boolean credsMatch = cachedResult .verify (token .credentials ());
@@ -196,8 +236,10 @@ private void authenticateWithCache(UsernamePasswordToken token, ActionListener<A
196236 name (),
197237 token .principal ()
198238 );
239+ logger .info ("ATTEMPTING AUTH" );
199240 // attempt authentication against the authentication source
200241 doAuthenticate (token , ActionListener .wrap (authResult -> {
242+ logger .info ("GOT AUTH RESULT: " + authResult );
201243 if (authResult .isAuthenticated () == false ) {
202244 logger .trace ("realm [{}] did not authenticate user [{}] ([{}])" , name (), token .principal (), authResult );
203245 // a new request should trigger a new authentication
@@ -217,7 +259,9 @@ private void authenticateWithCache(UsernamePasswordToken token, ActionListener<A
217259 // notify any forestalled request listeners; they will not reach to the
218260 // authentication request and instead will use this result if they contain
219261 // the same credentials
220- listenableCacheEntry .onResponse (new CachedResult (authResult , cacheHasher , authResult .getValue (), token .credentials ()));
262+ listenableCacheEntry .onResponse (
263+ new CachedResult (authResult , credentialHasher , authResult .getValue (), token .credentials ())
264+ );
221265 listener .onResponse (authResult );
222266 }, e -> {
223267 cache .invalidate (token .principal (), listenableCacheEntry );
@@ -282,7 +326,7 @@ private void lookupWithCache(String username, ActionListener<User> listener) {
282326 if (false == lookupInCache .get ()) {
283327 // attempt lookup against the user directory
284328 doLookupUser (username , ActionListener .wrap (user -> {
285- final CachedResult result = new CachedResult (AuthenticationResult .notHandled (), cacheHasher , user , null );
329+ final CachedResult result = new CachedResult (AuthenticationResult .notHandled (), credentialHasher , user , null );
286330 if (user == null ) {
287331 // user not found, invalidate cache so that subsequent requests are forwarded to
288332 // the user directory
@@ -311,7 +355,20 @@ private void lookupWithCache(String username, ActionListener<User> listener) {
311355
312356 protected abstract void doLookupUser (String username , ActionListener <User > listener );
313357
314- private static class CachedResult {
358+ protected interface UserAuthenticationCache {
359+ void invalidate (String key );
360+
361+ void invalidate (String key , ListenableFuture <CachedResult > value );
362+
363+ void invalidateAll ();
364+
365+ int count ();
366+
367+ ListenableFuture <CachedResult > computeIfAbsent (String key , CacheLoader <String , ListenableFuture <CachedResult >> loader )
368+ throws ExecutionException ;
369+ }
370+
371+ protected static class CachedResult {
315372 private final AuthenticationResult <User > authenticationResult ;
316373 private final User user ;
317374 private final char [] hash ;
0 commit comments