This is an automated email from the ASF dual-hosted git repository.
gerlowskija pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/branch_9x by this push:
new f74b5e85e02 SOLR-16720: Defer PKI header creation to send-time (#1666)
f74b5e85e02 is described below
commit f74b5e85e0274ec9b6460f111bbc0af2d8e17228
Author: Alex <[email protected]>
AuthorDate: Fri May 26 08:29:44 2023 -0700
SOLR-16720: Defer PKI header creation to send-time (#1666)
---
.../solr/security/PKIAuthenticationPlugin.java | 74 ++++++++++++++--------
1 file changed, 48 insertions(+), 26 deletions(-)
diff --git
a/solr/core/src/java/org/apache/solr/security/PKIAuthenticationPlugin.java
b/solr/core/src/java/org/apache/solr/security/PKIAuthenticationPlugin.java
index 6a005559f9b..cfd4436dac7 100644
--- a/solr/core/src/java/org/apache/solr/security/PKIAuthenticationPlugin.java
+++ b/solr/core/src/java/org/apache/solr/security/PKIAuthenticationPlugin.java
@@ -368,6 +368,8 @@ public class PKIAuthenticationPlugin extends
AuthenticationPlugin
public void setup(Http2SolrClient client) {
final HttpListenerFactory.RequestResponseListener listener =
new HttpListenerFactory.RequestResponseListener() {
+ private static final String CACHED_REQUEST_USER_KEY =
"cachedRequestUser";
+
@Override
public void onQueued(Request request) {
log.trace("onQueued: {}", request);
@@ -379,11 +381,12 @@ public class PKIAuthenticationPlugin extends
AuthenticationPlugin
if (log.isDebugEnabled()) {
log.debug("{} secures this internode request",
this.getClass().getSimpleName());
}
- if ("v1".equals(System.getProperty(SEND_VERSION))) {
- generateToken().ifPresent(s -> request.header(HEADER, s));
- } else {
- generateTokenV2().ifPresent(s -> request.header(HEADER_V2, s));
- }
+
+ // The onBegin hook below (potentially) runs in a separate Jetty
thread than was
+ // used to submit the request. While we're still in the
submitting thread, fetch
+ // the user information from the SolrRequestInfo thread local
and cache it on the
+ // Request so it can be accessed accurately in onBegin
+ cachePreFetchedUserOnJettyRequest(request);
} else {
if (log.isDebugEnabled()) {
log.debug(
@@ -392,6 +395,31 @@ public class PKIAuthenticationPlugin extends
AuthenticationPlugin
}
}
}
+
+ @Override
+ public void onBegin(Request request) {
+ log.trace("onBegin: {}", request);
+
+ final Optional<String> preFetchedUser =
getUserFromJettyRequest(request);
+ if ("v1".equals(System.getProperty(SEND_VERSION))) {
+ preFetchedUser
+ .map(PKIAuthenticationPlugin.this::generateToken)
+ .ifPresent(token -> request.header(HEADER, token));
+ } else {
+ preFetchedUser
+ .map(PKIAuthenticationPlugin.this::generateTokenV2)
+ .ifPresent(token -> request.header(HEADER_V2, token));
+ }
+ }
+
+ private void cachePreFetchedUserOnJettyRequest(Request request) {
+ getUser().ifPresent(user ->
request.attribute(CACHED_REQUEST_USER_KEY, user));
+ }
+
+ private Optional<String> getUserFromJettyRequest(Request request) {
+ return Optional.ofNullable(
+ (String) request.getAttributes().get(CACHED_REQUEST_USER_KEY));
+ }
};
client.addListenerFactory(() -> listener);
}
@@ -432,7 +460,7 @@ public class PKIAuthenticationPlugin extends
AuthenticationPlugin
}
}
- private String getUser() {
+ private Optional<String> getUser() {
SolrRequestInfo reqInfo = getRequestInfo();
if (reqInfo != null && !reqInfo.useServerToken()) {
Principal principal = reqInfo.getUserPrincipal();
@@ -440,57 +468,51 @@ public class PKIAuthenticationPlugin extends
AuthenticationPlugin
log.debug("generateToken: principal is null");
// this had a request but not authenticated
// so we don't not need to set a principal
- return null;
+ return Optional.empty();
} else {
assert principal.getName() != null;
- return principal.getName();
+ return Optional.of(principal.getName());
}
} else {
if (!isSolrThread()) {
// if this is not running inside a Solr threadpool (as in testcases)
// then no need to add any header
log.debug("generateToken: not a solr (server) thread");
- return null;
+ return Optional.empty();
}
// this request seems to be originated from Solr itself
- return "$"; // special name to denote the user is the node itself
+ return Optional.of(NODE_IS_USER); // special name to denote the user is
the node itself
}
}
@SuppressForbidden(reason = "Needs currentTimeMillis to set current time in
header")
- private Optional<String> generateToken() {
- String usr = getUser();
- if (usr == null) {
- return Optional.empty();
- }
-
+ private String generateToken(String usr) {
+ assert usr != null;
String s = usr + " " + System.currentTimeMillis();
byte[] payload = s.getBytes(UTF_8);
byte[] payloadCipher =
publicKeyHandler.getKeyPair().encrypt(ByteBuffer.wrap(payload));
String base64Cipher = Base64.getEncoder().encodeToString(payloadCipher);
log.trace("generateToken: usr={} token={}", usr, base64Cipher);
- return Optional.of(myNodeName + " " + base64Cipher);
+ return myNodeName + " " + base64Cipher;
}
- private Optional<String> generateTokenV2() {
- String user = getUser();
- if (user == null) {
- return Optional.empty();
- }
-
+ private String generateTokenV2(String user) {
+ assert user != null;
String s = myNodeName + " " + user + " " + Instant.now().toEpochMilli();
byte[] payload = s.getBytes(UTF_8);
byte[] signature = publicKeyHandler.getKeyPair().signSha256(payload);
String base64Signature = Base64.getEncoder().encodeToString(signature);
- return Optional.of(s + " " + base64Signature);
+ return s + " " + base64Signature;
}
void setHeader(HttpRequest httpRequest) {
if ("v1".equals(System.getProperty(SEND_VERSION))) {
- generateToken().ifPresent(s -> httpRequest.setHeader(HEADER, s));
+ getUser().map(this::generateToken).ifPresent(token ->
httpRequest.setHeader(HEADER, token));
} else {
- generateTokenV2().ifPresent(s -> httpRequest.setHeader(HEADER_V2, s));
+ getUser()
+ .map(this::generateTokenV2)
+ .ifPresent(token -> httpRequest.setHeader(HEADER_V2, token));
}
}