@@ -116,7 +116,7 @@ public AuthenticationService(Settings settings, Realms realms, AuditTrailService
116
116
* a user was indeed associated with the request and the credentials were verified to be valid), the method returns
117
117
* the user and that user is then "attached" to the request's context.
118
118
*
119
- * @param request The request to be authenticated
119
+ * @param request The request to be authenticated
120
120
*/
121
121
public void authenticate (RestRequest request , ActionListener <Authentication > authenticationListener ) {
122
122
createAuthenticator (request , authenticationListener ).authenticateAsync ();
@@ -128,12 +128,12 @@ public void authenticate(RestRequest request, ActionListener<Authentication> aut
128
128
* the user and that user is then "attached" to the message's context. If no user was found to be attached to the given
129
129
* message, then the given fallback user will be returned instead.
130
130
*
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.
137
137
*/
138
138
public void authenticate (String action , TransportMessage message , User fallbackUser , ActionListener <Authentication > listener ) {
139
139
createAuthenticator (action , message , fallbackUser , listener ).authenticateAsync ();
@@ -226,23 +226,25 @@ private Authenticator(AuditableRequest auditableRequest, User fallbackUser, Acti
226
226
* these operations are:
227
227
*
228
228
* <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>
236
236
* </ol>
237
237
*/
238
238
private void authenticateAsync () {
239
239
if (defaultOrderedRealmList .isEmpty ()) {
240
240
// this happens when the license state changes between the call to authenticate and the actual invocation
241
241
// to get the realm list
242
+ logger .debug ("No realms available, failing authentication" );
242
243
listener .onResponse (null );
243
244
} else {
244
245
lookForExistingAuthentication ((authentication ) -> {
245
246
if (authentication != null ) {
247
+ logger .trace ("Found existing authentication [{}] in request [{}]" , authentication , request );
246
248
listener .onResponse (authentication );
247
249
} else {
248
250
tokenService .getAndValidateToken (threadContext , ActionListener .wrap (userToken -> {
@@ -252,6 +254,7 @@ private void authenticateAsync() {
252
254
checkForApiKey ();
253
255
}
254
256
}, e -> {
257
+ logger .debug (new ParameterizedMessage ("Failed to validate token authentication for request [{}]" , request ), e );
255
258
if (e instanceof ElasticsearchSecurityException &&
256
259
tokenService .isExpiredTokenException ((ElasticsearchSecurityException ) e ) == false ) {
257
260
// intentionally ignore the returned exception; we call this primarily
@@ -275,6 +278,7 @@ private void checkForApiKey() {
275
278
} else if (authResult .getStatus () == AuthenticationResult .Status .TERMINATE ) {
276
279
Exception e = (authResult .getException () != null ) ? authResult .getException ()
277
280
: Exceptions .authenticationError (authResult .getMessage ());
281
+ logger .debug (new ParameterizedMessage ("API key service terminated authentication for request [{}]" , request ), e );
278
282
listener .onFailure (e );
279
283
} else {
280
284
if (authResult .getMessage () != null ) {
@@ -308,7 +312,7 @@ private void lookForExistingAuthentication(Consumer<Authentication> authenticati
308
312
} catch (Exception e ) {
309
313
logger .error ((Supplier <?>)
310
314
() -> new ParameterizedMessage ("caught exception while trying to read authentication from request [{}]" , request ),
311
- e );
315
+ e );
312
316
action = () -> listener .onFailure (request .tamperedRequest ());
313
317
}
314
318
@@ -332,6 +336,8 @@ void extractToken(Consumer<AuthenticationToken> consumer) {
332
336
for (Realm realm : defaultOrderedRealmList ) {
333
337
final AuthenticationToken token = realm .token (threadContext );
334
338
if (token != null ) {
339
+ logger .trace ("Found authentication credentials [{}] for principal [{}] in request [{}]" ,
340
+ token .getClass ().getName (), token .principal (), request );
335
341
action = () -> consumer .accept (token );
336
342
break ;
337
343
}
@@ -358,12 +364,17 @@ private void consumeToken(AuthenticationToken token) {
358
364
} else {
359
365
authenticationToken = token ;
360
366
final List <Realm > realmsList = getRealmList (authenticationToken .principal ());
367
+ logger .trace ("Checking token of type [{}] against [{}] realm(s)" , token .getClass ().getName (), realmsList .size ());
361
368
final long startInvalidation = numInvalidation .get ();
362
369
final Map <Realm , Tuple <String , Exception >> messages = new LinkedHashMap <>();
363
370
final BiConsumer <Realm , ActionListener <User >> realmAuthenticatingConsumer = (realm , userListener ) -> {
364
371
if (realm .supports (authenticationToken )) {
372
+ logger .trace ("Trying to authenticate [{}] using realm [{}] with token [{}] " ,
373
+ token .principal (), realm , token .getClass ().getName ());
365
374
realm .authenticate (authenticationToken , ActionListener .wrap ((result ) -> {
366
375
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 );
367
378
if (result .getStatus () == AuthenticationResult .Status .SUCCESS ) {
368
379
// user was authenticated, populate the authenticated by information
369
380
authenticatedBy = new RealmRef (realm .name (), realm .type (), nodeName );
@@ -377,9 +388,9 @@ private void consumeToken(AuthenticationToken token) {
377
388
request .realmAuthenticationFailed (authenticationToken , realm .name ());
378
389
if (result .getStatus () == AuthenticationResult .Status .TERMINATE ) {
379
390
logger .info ("Authentication of [{}] was terminated by realm [{}] - {}" ,
380
- authenticationToken .principal (), realm .name (), result .getMessage ());
391
+ authenticationToken .principal (), realm .name (), result .getMessage ());
381
392
Exception e = (result .getException () != null ) ? result .getException ()
382
- : Exceptions .authenticationError (result .getMessage ());
393
+ : Exceptions .authenticationError (result .getMessage ());
383
394
userListener .onFailure (e );
384
395
} else {
385
396
if (result .getMessage () != null ) {
@@ -390,8 +401,8 @@ private void consumeToken(AuthenticationToken token) {
390
401
}
391
402
}, (ex ) -> {
392
403
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 );
395
406
userListener .onFailure (ex );
396
407
}));
397
408
} else {
@@ -407,6 +418,8 @@ private void consumeToken(AuthenticationToken token) {
407
418
try {
408
419
authenticatingListener .run ();
409
420
} catch (Exception e ) {
421
+ logger .debug (new ParameterizedMessage ("Authentication of [{}] with token [{}] failed" ,
422
+ token .principal (), token .getClass ().getName ()), e );
410
423
listener .onFailure (request .exceptionProcessingRequest (e , token ));
411
424
}
412
425
}
@@ -445,23 +458,25 @@ private List<Realm> getRealmList(String principal) {
445
458
* Handles failed extraction of an authentication token. This can happen in a few different scenarios:
446
459
*
447
460
* <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>
453
466
* </ul>
454
- *
467
+ * <p>
455
468
* Regardless of the scenario, this method will call the listener with either failure or success.
456
469
*/
457
470
// pkg-private for tests
458
471
void handleNullToken () {
459
472
final Authentication authentication ;
460
473
if (fallbackUser != null ) {
474
+ logger .trace ("No valid credentials found in request [{}], using fallback [{}]" , request , fallbackUser .principal ());
461
475
RealmRef authenticatedBy = new RealmRef ("__fallback" , "__fallback" , nodeName );
462
476
authentication = new Authentication (fallbackUser , authenticatedBy , null , Version .CURRENT , AuthenticationType .INTERNAL ,
463
477
Collections .emptyMap ());
464
478
} else if (isAnonymousUserEnabled ) {
479
+ logger .trace ("No valid credentials found in request [{}], using anonymous [{}]" , request , anonymousUser .principal ());
465
480
RealmRef authenticatedBy = new RealmRef ("__anonymous" , "__anonymous" , nodeName );
466
481
authentication = new Authentication (anonymousUser , authenticatedBy , null , Version .CURRENT , AuthenticationType .ANONYMOUS ,
467
482
Collections .emptyMap ());
@@ -473,7 +488,10 @@ void handleNullToken() {
473
488
if (authentication != null ) {
474
489
action = () -> writeAuthToContext (authentication );
475
490
} 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
+ };
477
495
}
478
496
479
497
// 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
501
519
Strings .collectionToCommaDelimitedString (defaultOrderedRealmList ),
502
520
Strings .collectionToCommaDelimitedString (unlicensedRealms ));
503
521
}
522
+ logger .trace ("Failed to authenticate request [{}]" , request );
504
523
listener .onFailure (request .authenticationFailed (authenticationToken ));
505
524
} else {
506
525
threadContext .putTransient (AuthenticationResult .THREAD_CONTEXT_KEY , authenticationResult );
@@ -514,7 +533,7 @@ private void consumeUser(User user, Map<Realm, Tuple<String, Exception>> message
514
533
assert runAsUsername .isEmpty () : "the run as username may not be empty" ;
515
534
logger .debug ("user [{}] attempted to runAs with an empty username" , user .principal ());
516
535
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 ));
518
537
}
519
538
} else {
520
539
finishAuthentication (user );
@@ -528,10 +547,12 @@ private void consumeUser(User user, Map<Realm, Tuple<String, Exception>> message
528
547
* names of users that exist using a timing attack
529
548
*/
530
549
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 ());
531
551
final RealmUserLookup lookup = new RealmUserLookup (getRealmList (runAsUsername ), threadContext );
532
552
final long startInvalidationNum = numInvalidation .get ();
533
553
lookup .lookup (runAsUsername , ActionListener .wrap (tuple -> {
534
554
if (tuple == null ) {
555
+ logger .debug ("Cannot find run-as user [{}] for authenticated user [{}]" , runAsUsername , user .principal ());
535
556
// the user does not exist, but we still create a User object, which will later be rejected by authz
536
557
userConsumer .accept (new User (runAsUsername , null , user ));
537
558
} else {
@@ -543,6 +564,7 @@ private void lookupRunAsUser(final User user, String runAsUsername, Consumer<Use
543
564
// this might provide a valid hint
544
565
lastSuccessfulAuthCache .computeIfAbsent (runAsUsername , s -> realm );
545
566
}
567
+ logger .trace ("Using run-as user [{}] with authenticated user [{}]" , foundUser , user .principal ());
546
568
userConsumer .accept (new User (foundUser , user ));
547
569
}
548
570
}, exception -> listener .onFailure (request .exceptionProcessingRequest (exception , authenticationToken ))));
@@ -569,11 +591,18 @@ void finishAuthentication(User finalUser) {
569
591
*/
570
592
void writeAuthToContext (Authentication authentication ) {
571
593
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
+ };
573
598
try {
574
599
authentication .writeToContext (threadContext );
575
600
} 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
+ };
577
606
}
578
607
579
608
// 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