-
Notifications
You must be signed in to change notification settings - Fork 24.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Unify AuthC chain - 1. Authenticator extraction (#77293)
This PR is a first step to refactor and unify the authentication chain. An Authenticator interface is extracted for following concrete Authenticators (listed in decreasing priority): * Service token * OAuth2 token * API key * Realms Before runnning the above authenticators, existing authentication from ThreadContext is always checked first. After running the authenticators, fallback, anonymous and lookup users are checked more consistently. Failed authentication with either OAuth2 token or API key now reports the attempted and failed credentials instead of "missing credentials". In above authenticators, the RealmsAuthenticator has its own sub-chain. Technically, this sub-chain can also be flattend and be part of the main chain. But it's impractical to do so without also changing the existing behaviour. Though the change makes sense imo, it adds a lot complexities of the PR. So it is better to be left as future work. Relates: #75607 Co-authored-by: Tim Vernum <tim@adjective.org>
- Loading branch information
Showing
19 changed files
with
2,086 additions
and
823 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 76 additions & 0 deletions
76
...in/security/src/main/java/org/elasticsearch/xpack/security/authc/ApiKeyAuthenticator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
package org.elasticsearch.xpack.security.authc; | ||
|
||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
import org.apache.logging.log4j.message.ParameterizedMessage; | ||
import org.elasticsearch.action.ActionListener; | ||
import org.elasticsearch.xpack.core.security.authc.Authentication; | ||
import org.elasticsearch.xpack.core.security.authc.AuthenticationResult; | ||
import org.elasticsearch.xpack.core.security.authc.AuthenticationToken; | ||
import org.elasticsearch.xpack.core.security.support.Exceptions; | ||
import org.elasticsearch.xpack.security.authc.ApiKeyService.ApiKeyCredentials; | ||
|
||
class ApiKeyAuthenticator implements Authenticator { | ||
|
||
private static final Logger logger = LogManager.getLogger(ApiKeyAuthenticator.class); | ||
|
||
private final ApiKeyService apiKeyService; | ||
private final String nodeName; | ||
|
||
ApiKeyAuthenticator(ApiKeyService apiKeyService, String nodeName) { | ||
this.apiKeyService = apiKeyService; | ||
this.nodeName = nodeName; | ||
} | ||
|
||
@Override | ||
public String name() { | ||
return "API key"; | ||
} | ||
|
||
@Override | ||
public AuthenticationToken extractCredentials(Context context) { | ||
return apiKeyService.getCredentialsFromHeader(context.getThreadContext()); | ||
} | ||
|
||
@Override | ||
public void authenticate(Context context, ActionListener<Result> listener) { | ||
final AuthenticationToken authenticationToken = context.getMostRecentAuthenticationToken(); | ||
if (false == authenticationToken instanceof ApiKeyCredentials) { | ||
listener.onResponse(Authenticator.Result.notHandled()); | ||
return; | ||
} | ||
ApiKeyCredentials apiKeyCredentials = (ApiKeyCredentials) authenticationToken; | ||
apiKeyService.tryAuthenticate(context.getThreadContext(), apiKeyCredentials, ActionListener.wrap(authResult -> { | ||
if (authResult.isAuthenticated()) { | ||
final Authentication authentication = apiKeyService.createApiKeyAuthentication(authResult, nodeName); | ||
listener.onResponse(Authenticator.Result.success(authentication)); | ||
} else if (authResult.getStatus() == AuthenticationResult.Status.TERMINATE) { | ||
Exception e = (authResult.getException() != null) ? | ||
authResult.getException() : | ||
Exceptions.authenticationError(authResult.getMessage()); | ||
logger.debug(new ParameterizedMessage("API key service terminated authentication for request [{}]", context.getRequest()), | ||
e); | ||
listener.onFailure(e); | ||
} else { | ||
if (authResult.getMessage() != null) { | ||
if (authResult.getException() != null) { | ||
logger.warn(new ParameterizedMessage("Authentication using apikey failed - {}", authResult.getMessage()), | ||
authResult.getException()); | ||
} else { | ||
logger.warn("Authentication using apikey failed - {}", authResult.getMessage()); | ||
} | ||
} | ||
listener.onResponse(Authenticator.Result.unsuccessful( | ||
authResult.getMessage(), | ||
authResult.getException())); | ||
} | ||
}, e -> listener.onFailure(context.getRequest().exceptionProcessingRequest(e, null)))); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.