@@ -116,7 +116,7 @@ public AuthenticationService(Settings settings, Realms realms, AuditTrailService
116116 * a user was indeed associated with the request and the credentials were verified to be valid), the method returns
117117 * the user and that user is then "attached" to the request's context.
118118 *
119- * @param request The request to be authenticated
119+ * @param request The request to be authenticated
120120 */
121121 public void authenticate (RestRequest request , ActionListener <Authentication > authenticationListener ) {
122122 createAuthenticator (request , authenticationListener ).authenticateAsync ();
@@ -128,12 +128,12 @@ public void authenticate(RestRequest request, ActionListener<Authentication> aut
128128 * the user and that user is then "attached" to the message's context. If no user was found to be attached to the given
129129 * message, then the given fallback user will be returned instead.
130130 *
131- * @param action The action of the message
132- * @param message The message to be authenticated
133- * @param fallbackUser The default user that will be assumed if no other user is attached to the message. Can be
134- * {@code null}, in which case there will be no fallback user and the success/failure of the
135- * authentication will be based on the whether there's an attached user to in the message and
136- * if there is, whether its credentials are valid.
131+ * @param action The action of the message
132+ * @param message The message to be authenticated
133+ * @param fallbackUser The default user that will be assumed if no other user is attached to the message. Can be
134+ * {@code null}, in which case there will be no fallback user and the success/failure of the
135+ * authentication will be based on the whether there's an attached user to in the message and
136+ * if there is, whether its credentials are valid.
137137 */
138138 public void authenticate (String action , TransportMessage message , User fallbackUser , ActionListener <Authentication > listener ) {
139139 createAuthenticator (action , message , fallbackUser , listener ).authenticateAsync ();
@@ -226,23 +226,25 @@ private Authenticator(AuditableRequest auditableRequest, User fallbackUser, Acti
226226 * these operations are:
227227 *
228228 * <ol>
229- * <li>look for existing authentication {@link #lookForExistingAuthentication(Consumer)}</li>
230- * <li>look for a user token</li>
231- * <li>token extraction {@link #extractToken(Consumer)}</li>
232- * <li>token authentication {@link #consumeToken(AuthenticationToken)}</li>
233- * <li>user lookup for run as if necessary {@link #consumeUser(User, Map)} and
234- * {@link #lookupRunAsUser(User, String, Consumer)}</li>
235- * <li>write authentication into the context {@link #finishAuthentication(User)}</li>
229+ * <li>look for existing authentication {@link #lookForExistingAuthentication(Consumer)}</li>
230+ * <li>look for a user token</li>
231+ * <li>token extraction {@link #extractToken(Consumer)}</li>
232+ * <li>token authentication {@link #consumeToken(AuthenticationToken)}</li>
233+ * <li>user lookup for run as if necessary {@link #consumeUser(User, Map)} and
234+ * {@link #lookupRunAsUser(User, String, Consumer)}</li>
235+ * <li>write authentication into the context {@link #finishAuthentication(User)}</li>
236236 * </ol>
237237 */
238238 private void authenticateAsync () {
239239 if (defaultOrderedRealmList .isEmpty ()) {
240240 // this happens when the license state changes between the call to authenticate and the actual invocation
241241 // to get the realm list
242+ logger .debug ("No realms available, failing authentication" );
242243 listener .onResponse (null );
243244 } else {
244245 lookForExistingAuthentication ((authentication ) -> {
245246 if (authentication != null ) {
247+ logger .trace ("Found existing authentication [{}] in request [{}]" , authentication , request );
246248 listener .onResponse (authentication );
247249 } else {
248250 tokenService .getAndValidateToken (threadContext , ActionListener .wrap (userToken -> {
@@ -252,6 +254,7 @@ private void authenticateAsync() {
252254 checkForApiKey ();
253255 }
254256 }, e -> {
257+ logger .debug (new ParameterizedMessage ("Failed to validate token authentication for request [{}]" , request ), e );
255258 if (e instanceof ElasticsearchSecurityException &&
256259 tokenService .isExpiredTokenException ((ElasticsearchSecurityException ) e ) == false ) {
257260 // intentionally ignore the returned exception; we call this primarily
@@ -275,6 +278,7 @@ private void checkForApiKey() {
275278 } else if (authResult .getStatus () == AuthenticationResult .Status .TERMINATE ) {
276279 Exception e = (authResult .getException () != null ) ? authResult .getException ()
277280 : Exceptions .authenticationError (authResult .getMessage ());
281+ logger .debug (new ParameterizedMessage ("API key service terminated authentication for request [{}]" , request ), e );
278282 listener .onFailure (e );
279283 } else {
280284 if (authResult .getMessage () != null ) {
@@ -308,7 +312,7 @@ private void lookForExistingAuthentication(Consumer<Authentication> authenticati
308312 } catch (Exception e ) {
309313 logger .error ((Supplier <?>)
310314 () -> new ParameterizedMessage ("caught exception while trying to read authentication from request [{}]" , request ),
311- e );
315+ e );
312316 action = () -> listener .onFailure (request .tamperedRequest ());
313317 }
314318
@@ -332,6 +336,8 @@ void extractToken(Consumer<AuthenticationToken> consumer) {
332336 for (Realm realm : defaultOrderedRealmList ) {
333337 final AuthenticationToken token = realm .token (threadContext );
334338 if (token != null ) {
339+ logger .trace ("Found authentication credentials [{}] for principal [{}] in request [{}]" ,
340+ token .getClass ().getName (), token .principal (), request );
335341 action = () -> consumer .accept (token );
336342 break ;
337343 }
@@ -358,12 +364,17 @@ private void consumeToken(AuthenticationToken token) {
358364 } else {
359365 authenticationToken = token ;
360366 final List <Realm > realmsList = getRealmList (authenticationToken .principal ());
367+ logger .trace ("Checking token of type [{}] against [{}] realm(s)" , token .getClass ().getName (), realmsList .size ());
361368 final long startInvalidation = numInvalidation .get ();
362369 final Map <Realm , Tuple <String , Exception >> messages = new LinkedHashMap <>();
363370 final BiConsumer <Realm , ActionListener <User >> realmAuthenticatingConsumer = (realm , userListener ) -> {
364371 if (realm .supports (authenticationToken )) {
372+ logger .trace ("Trying to authenticate [{}] using realm [{}] with token [{}] " ,
373+ token .principal (), realm , token .getClass ().getName ());
365374 realm .authenticate (authenticationToken , ActionListener .wrap ((result ) -> {
366375 assert result != null : "Realm " + realm + " produced a null authentication result" ;
376+ logger .debug ("Authentication of [{}] using realm [{}] with token [{}] was [{}]" ,
377+ token .principal (), realm , token .getClass ().getSimpleName (), result );
367378 if (result .getStatus () == AuthenticationResult .Status .SUCCESS ) {
368379 // user was authenticated, populate the authenticated by information
369380 authenticatedBy = new RealmRef (realm .name (), realm .type (), nodeName );
@@ -377,9 +388,9 @@ private void consumeToken(AuthenticationToken token) {
377388 request .realmAuthenticationFailed (authenticationToken , realm .name ());
378389 if (result .getStatus () == AuthenticationResult .Status .TERMINATE ) {
379390 logger .info ("Authentication of [{}] was terminated by realm [{}] - {}" ,
380- authenticationToken .principal (), realm .name (), result .getMessage ());
391+ authenticationToken .principal (), realm .name (), result .getMessage ());
381392 Exception e = (result .getException () != null ) ? result .getException ()
382- : Exceptions .authenticationError (result .getMessage ());
393+ : Exceptions .authenticationError (result .getMessage ());
383394 userListener .onFailure (e );
384395 } else {
385396 if (result .getMessage () != null ) {
@@ -390,8 +401,8 @@ private void consumeToken(AuthenticationToken token) {
390401 }
391402 }, (ex ) -> {
392403 logger .warn (new ParameterizedMessage (
393- "An error occurred while attempting to authenticate [{}] against realm [{}]" ,
394- authenticationToken .principal (), realm .name ()), ex );
404+ "An error occurred while attempting to authenticate [{}] against realm [{}]" ,
405+ authenticationToken .principal (), realm .name ()), ex );
395406 userListener .onFailure (ex );
396407 }));
397408 } else {
@@ -407,6 +418,8 @@ private void consumeToken(AuthenticationToken token) {
407418 try {
408419 authenticatingListener .run ();
409420 } catch (Exception e ) {
421+ logger .debug (new ParameterizedMessage ("Authentication of [{}] with token [{}] failed" ,
422+ token .principal (), token .getClass ().getName ()), e );
410423 listener .onFailure (request .exceptionProcessingRequest (e , token ));
411424 }
412425 }
@@ -445,23 +458,25 @@ private List<Realm> getRealmList(String principal) {
445458 * Handles failed extraction of an authentication token. This can happen in a few different scenarios:
446459 *
447460 * <ul>
448- * <li>this is an initial request from a client without preemptive authentication, so we must return an authentication
449- * challenge</li>
450- * <li>this is a request made internally within a node and there is a fallback user, which is typically the
451- * {@link SystemUser}</li>
452- * <li>anonymous access is enabled and this will be considered an anonymous request</li>
461+ * <li>this is an initial request from a client without preemptive authentication, so we must return an authentication
462+ * challenge</li>
463+ * <li>this is a request made internally within a node and there is a fallback user, which is typically the
464+ * {@link SystemUser}</li>
465+ * <li>anonymous access is enabled and this will be considered an anonymous request</li>
453466 * </ul>
454- *
467+ * <p>
455468 * Regardless of the scenario, this method will call the listener with either failure or success.
456469 */
457470 // pkg-private for tests
458471 void handleNullToken () {
459472 final Authentication authentication ;
460473 if (fallbackUser != null ) {
474+ logger .trace ("No valid credentials found in request [{}], using fallback [{}]" , request , fallbackUser .principal ());
461475 RealmRef authenticatedBy = new RealmRef ("__fallback" , "__fallback" , nodeName );
462476 authentication = new Authentication (fallbackUser , authenticatedBy , null , Version .CURRENT , AuthenticationType .INTERNAL ,
463477 Collections .emptyMap ());
464478 } else if (isAnonymousUserEnabled ) {
479+ logger .trace ("No valid credentials found in request [{}], using anonymous [{}]" , request , anonymousUser .principal ());
465480 RealmRef authenticatedBy = new RealmRef ("__anonymous" , "__anonymous" , nodeName );
466481 authentication = new Authentication (anonymousUser , authenticatedBy , null , Version .CURRENT , AuthenticationType .ANONYMOUS ,
467482 Collections .emptyMap ());
@@ -473,7 +488,10 @@ void handleNullToken() {
473488 if (authentication != null ) {
474489 action = () -> writeAuthToContext (authentication );
475490 } else {
476- action = () -> listener .onFailure (request .anonymousAccessDenied ());
491+ action = () -> {
492+ logger .debug ("No valid credentials found in request [{}], rejecting" , request );
493+ listener .onFailure (request .anonymousAccessDenied ());
494+ };
477495 }
478496
479497 // we assign the listener call to an action to avoid calling the listener within a try block and auditing the wrong thing when
@@ -501,6 +519,7 @@ private void consumeUser(User user, Map<Realm, Tuple<String, Exception>> message
501519 Strings .collectionToCommaDelimitedString (defaultOrderedRealmList ),
502520 Strings .collectionToCommaDelimitedString (unlicensedRealms ));
503521 }
522+ logger .trace ("Failed to authenticate request [{}]" , request );
504523 listener .onFailure (request .authenticationFailed (authenticationToken ));
505524 } else {
506525 threadContext .putTransient (AuthenticationResult .THREAD_CONTEXT_KEY , authenticationResult );
@@ -514,7 +533,7 @@ private void consumeUser(User user, Map<Realm, Tuple<String, Exception>> message
514533 assert runAsUsername .isEmpty () : "the run as username may not be empty" ;
515534 logger .debug ("user [{}] attempted to runAs with an empty username" , user .principal ());
516535 listener .onFailure (request .runAsDenied (
517- new Authentication (new User (runAsUsername , null , user ), authenticatedBy , lookedupBy ), authenticationToken ));
536+ new Authentication (new User (runAsUsername , null , user ), authenticatedBy , lookedupBy ), authenticationToken ));
518537 }
519538 } else {
520539 finishAuthentication (user );
@@ -528,10 +547,12 @@ private void consumeUser(User user, Map<Realm, Tuple<String, Exception>> message
528547 * names of users that exist using a timing attack
529548 */
530549 private void lookupRunAsUser (final User user , String runAsUsername , Consumer <User > userConsumer ) {
550+ logger .trace ("Looking up run-as user [{}] for authenticated user [{}]" , runAsUsername , user .principal ());
531551 final RealmUserLookup lookup = new RealmUserLookup (getRealmList (runAsUsername ), threadContext );
532552 final long startInvalidationNum = numInvalidation .get ();
533553 lookup .lookup (runAsUsername , ActionListener .wrap (tuple -> {
534554 if (tuple == null ) {
555+ logger .debug ("Cannot find run-as user [{}] for authenticated user [{}]" , runAsUsername , user .principal ());
535556 // the user does not exist, but we still create a User object, which will later be rejected by authz
536557 userConsumer .accept (new User (runAsUsername , null , user ));
537558 } else {
@@ -543,6 +564,7 @@ private void lookupRunAsUser(final User user, String runAsUsername, Consumer<Use
543564 // this might provide a valid hint
544565 lastSuccessfulAuthCache .computeIfAbsent (runAsUsername , s -> realm );
545566 }
567+ logger .trace ("Using run-as user [{}] with authenticated user [{}]" , foundUser , user .principal ());
546568 userConsumer .accept (new User (foundUser , user ));
547569 }
548570 }, exception -> listener .onFailure (request .exceptionProcessingRequest (exception , authenticationToken ))));
@@ -569,11 +591,18 @@ void finishAuthentication(User finalUser) {
569591 */
570592 void writeAuthToContext (Authentication authentication ) {
571593 request .authenticationSuccess (authentication .getAuthenticatedBy ().getName (), authentication .getUser ());
572- Runnable action = () -> listener .onResponse (authentication );
594+ Runnable action = () -> {
595+ logger .trace ("Established authentication [{}] for request [{}]" , authentication , request );
596+ listener .onResponse (authentication );
597+ };
573598 try {
574599 authentication .writeToContext (threadContext );
575600 } catch (Exception e ) {
576- action = () -> listener .onFailure (request .exceptionProcessingRequest (e , authenticationToken ));
601+ action = () -> {
602+ logger .debug (
603+ new ParameterizedMessage ("Failed to store authentication [{}] for request [{}]" , authentication , request ), e );
604+ listener .onFailure (request .exceptionProcessingRequest (e , authenticationToken ));
605+ };
577606 }
578607
579608 // we assign the listener call to an action to avoid calling the listener within a try block and auditing the wrong thing
0 commit comments