You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ja...@apache.org on 2018/10/03 14:18:53 UTC

[6/6] lucene-solr:solr12799-auth-forward: Forward the user principal on inter-node requests

Forward the user principal on inter-node requests


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/c1851096
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/c1851096
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/c1851096

Branch: refs/heads/solr12799-auth-forward
Commit: c1851096f67c1722ed92439d38d62149d4827b9d
Parents: 4c32559
Author: Jan Høydahl <ja...@apache.org>
Authored: Wed Oct 3 15:57:16 2018 +0200
Committer: Jan Høydahl <ja...@apache.org>
Committed: Wed Oct 3 15:57:16 2018 +0200

----------------------------------------------------------------------
 .../handler/component/HttpShardHandler.java     |  7 +++++++
 .../apache/solr/security/BasicAuthPlugin.java   |  1 -
 .../solr/security/PKIAuthenticationPlugin.java  |  4 ++--
 .../apache/solr/update/SolrCmdDistributor.java  |  4 ++++
 .../solr/security/BasicAuthIntegrationTest.java | 20 ++++++++++++++++++--
 .../apache/solr/client/solrj/SolrRequest.java   | 11 +++++++++++
 .../solr/client/solrj/impl/HttpSolrClient.java  | 13 ++++++++++---
 7 files changed, 52 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c1851096/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java
index a548031..3068a36 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java
@@ -18,6 +18,7 @@ package org.apache.solr.handler.component;
 
 import java.lang.invoke.MethodHandles;
 import java.net.ConnectException;
+import java.security.Principal;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -56,6 +57,7 @@ import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.StrUtils;
 import org.apache.solr.core.CoreDescriptor;
 import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrRequestInfo;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.MDC;
@@ -136,6 +138,10 @@ public class HttpShardHandler extends ShardHandler {
     // do this outside of the callable for thread safety reasons
     final List<String> urls = getURLs(shard);
 
+    // If request has a Principal (authenticated user), extract it for passing on to the new shard request
+    SolrRequestInfo requestInfo = SolrRequestInfo.getRequestInfo();
+    final Principal userPrincipal = requestInfo == null ? null : requestInfo.getReq().getUserPrincipal();
+
     Callable<ShardResponse> task = () -> {
 
       ShardResponse srsp = new ShardResponse();
@@ -154,6 +160,7 @@ public class HttpShardHandler extends ShardHandler {
 
         QueryRequest req = makeQueryRequest(sreq, params, shard);
         req.setMethod(SolrRequest.METHOD.POST);
+        req.setUserPrincipal(userPrincipal);
 
         // no need to set the response parser as binary is the default
         // req.setResponseParser(new BinaryResponseParser());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c1851096/solr/core/src/java/org/apache/solr/security/BasicAuthPlugin.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/security/BasicAuthPlugin.java b/solr/core/src/java/org/apache/solr/security/BasicAuthPlugin.java
index dc97828..4087600 100644
--- a/solr/core/src/java/org/apache/solr/security/BasicAuthPlugin.java
+++ b/solr/core/src/java/org/apache/solr/security/BasicAuthPlugin.java
@@ -197,7 +197,6 @@ public class BasicAuthPlugin extends AuthenticationPlugin implements ConfigEdita
     if (forwardCredentials) {
       if (httpContext instanceof HttpClientContext) {
         HttpClientContext httpClientContext = (HttpClientContext) httpContext;
-        log.info("*** HttpClientContext token={}", httpClientContext.getUserToken());
         if (httpClientContext.getUserToken() instanceof BasicAuthUserPrincipal) {
           BasicAuthUserPrincipal principal = (BasicAuthUserPrincipal) httpClientContext.getUserToken();
           String userPassBase64 = Base64.encodeBase64String((principal.getName() + ":" + principal.getPassword()).getBytes(StandardCharsets.UTF_8));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c1851096/solr/core/src/java/org/apache/solr/security/PKIAuthenticationPlugin.java
----------------------------------------------------------------------
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 2a8e216..5245afc 100644
--- a/solr/core/src/java/org/apache/solr/security/PKIAuthenticationPlugin.java
+++ b/solr/core/src/java/org/apache/solr/security/PKIAuthenticationPlugin.java
@@ -239,10 +239,10 @@ public class PKIAuthenticationPlugin extends AuthenticationPlugin implements Htt
         return;
       }
       if (!cores.getAuthenticationPlugin().interceptInternodeRequest(httpRequest, httpContext)) {
-        log.debug("PKIAuthenticationPlugin secures this internode request");
+        log.debug("{} secures this internode request", this.getClass().getSimpleName());
         setHeader(httpRequest);
       } else {
-        log.debug("{} secures this internode request", cores.getAuthenticationPlugin().getClass().getName());
+        log.debug("{} secures this internode request", cores.getAuthenticationPlugin().getClass().getSimpleName());
       }
     }
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c1851096/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java b/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java
index cb7f9cb..af2b5aa 100644
--- a/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java
+++ b/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java
@@ -47,6 +47,7 @@ import org.apache.solr.common.cloud.ZkStateReader;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.core.Diagnostics;
+import org.apache.solr.request.SolrRequestInfo;
 import org.apache.solr.update.processor.DistributedUpdateProcessor;
 import org.apache.solr.update.processor.DistributedUpdateProcessor.LeaderRequestReplicationTracker;
 import org.apache.solr.update.processor.DistributedUpdateProcessor.RollupRequestReplicationTracker;
@@ -282,6 +283,9 @@ public class SolrCmdDistributor implements Closeable {
   }
 
   private void submit(final Req req, boolean isCommit) {
+    // Copy user principal from the original request to the new update request, for later authentication interceptor use
+    req.uReq.setUserPrincipal(SolrRequestInfo.getRequestInfo().getReq().getUserPrincipal());
+
     if (req.synchronous) {
       blockAndDoRetries();
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c1851096/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
index 581f4cf..0066914 100644
--- a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
@@ -46,9 +46,11 @@ import org.apache.solr.client.solrj.impl.HttpClientUtil;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.request.GenericSolrRequest;
+import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.request.RequestWriter.StringPayloadContentWriter;
 import org.apache.solr.client.solrj.request.UpdateRequest;
 import org.apache.solr.client.solrj.request.V2Request;
+import org.apache.solr.client.solrj.response.QueryResponse;
 import org.apache.solr.cloud.SolrCloudTestCase;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.cloud.DocCollection;
@@ -221,13 +223,18 @@ public class BasicAuthIntegrationTest extends SolrCloudTestCase {
         log.error("RunExampleTool failed due to: " + e +
             "; stdout from tool prior to failure: " + baos.toString(StandardCharsets.UTF_8.name()));
       }
-      executeCommand(baseUrl + authcPrefix, cl, "{set-property : { blockUnknown: false}}", "harry", "HarryIsUberCool");
       
       addDocument("harry","HarryIsUberCool","id", "5");
 
+      // Validate forwardCredentials
+      assertEquals(1, executeQuery(params("q", "id:5"), "harry", "HarryIsUberCool").getResults().getNumFound());
+      // TODO: Validate that this requests were handled by PKI plugin
       executeCommand(baseUrl + authcPrefix, cl, "{set-property : { forwardCredentials: true}}", "harry", "HarryIsUberCool");
       verifySecurityStatus(cl, baseUrl + authcPrefix, "authentication/forwardCredentials", "true", 20, "harry", "HarryIsUberCool");
-      assertEquals(1, cluster.getSolrClient().query(COLLECTION, params("q", "id:5")).getResults().getNumFound());
+      assertEquals(1, executeQuery(params("q", "id:5"), "harry", "HarryIsUberCool").getResults().getNumFound());
+      // NOCOMMIT: Validate that sub requests were handled by BasicAuth plugin
+      
+      executeCommand(baseUrl + authcPrefix, cl, "{set-property : { blockUnknown: false}}", "harry", "HarryIsUberCool");
     } finally {
       if (cl != null) {
         HttpClientUtil.close(cl);
@@ -235,6 +242,15 @@ public class BasicAuthIntegrationTest extends SolrCloudTestCase {
     }
   }
 
+  private QueryResponse executeQuery(ModifiableSolrParams params, String user, String pass) throws IOException, SolrServerException {
+    SolrRequest req = new QueryRequest(params);
+    req.setBasicAuthCredentials(user, pass);
+    QueryResponse resp = (QueryResponse) req.process(cluster.getSolrClient(), COLLECTION);
+    assertNull(resp.getException());
+    assertEquals(0, resp.getStatus());
+    return resp;
+  }
+
   private void addDocument(String user, String pass, String... fields) throws IOException, SolrServerException {
     SolrInputDocument doc = new SolrInputDocument();
     boolean isKey = true;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c1851096/solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java b/solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java
index 7dbaab9..04b94f7 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java
@@ -18,6 +18,7 @@ package org.apache.solr.client.solrj;
 
 import java.io.IOException;
 import java.io.Serializable;
+import java.security.Principal;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
@@ -36,6 +37,16 @@ import static java.util.Collections.unmodifiableSet;
  * @since solr 1.3
  */
 public abstract class SolrRequest<T extends SolrResponse> implements Serializable {
+  // This user principal is typically used by Auth plugins during distributed/sharded search
+  private Principal userPrincipal;
+
+  public void setUserPrincipal(Principal userPrincipal) {
+    this.userPrincipal = userPrincipal;
+  }
+
+  public Principal getUserPrincipal() {
+    return userPrincipal;
+  }
 
   public enum METHOD {
     GET,

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c1851096/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java
index 2b60e33..057122e 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java
@@ -24,6 +24,7 @@ import java.lang.invoke.MethodHandles;
 import java.net.ConnectException;
 import java.net.SocketTimeoutException;
 import java.nio.charset.StandardCharsets;
+import java.security.Principal;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -252,7 +253,7 @@ public class HttpSolrClient extends SolrClient {
       throws SolrServerException, IOException {
     HttpRequestBase method = createMethod(request, collection);
     setBasicAuthHeader(request, method);
-    return executeMethod(method, processor, isV2ApiRequest(request));
+    return executeMethod(method, request.getUserPrincipal(), processor, isV2ApiRequest(request));
   }
 
   private boolean isV2ApiRequest(final SolrRequest request) {
@@ -296,7 +297,7 @@ public class HttpSolrClient extends SolrClient {
     ExecutorService pool = ExecutorUtil.newMDCAwareFixedThreadPool(1, new SolrjNamedThreadFactory("httpUriRequest"));
     try {
       MDC.put("HttpSolrClient.url", baseUrl);
-      mrr.future = pool.submit(() -> executeMethod(method, processor, isV2ApiRequest(request)));
+      mrr.future = pool.submit(() -> executeMethod(method, request.getUserPrincipal(), processor, isV2ApiRequest(request)));
  
     } finally {
       pool.shutdown();
@@ -517,7 +518,7 @@ public class HttpSolrClient extends SolrClient {
 
   private static final List<String> errPath = Arrays.asList("metadata", "error-class");//Utils.getObjectByPath(err, false,"metadata/error-class")
 
-  protected NamedList<Object> executeMethod(HttpRequestBase method, final ResponseParser processor, final boolean isV2Api) throws SolrServerException {
+  protected NamedList<Object> executeMethod(HttpRequestBase method, Principal userPrincipal, final ResponseParser processor, final boolean isV2Api) throws SolrServerException {
     method.addHeader("User-Agent", AGENT);
  
     org.apache.http.client.config.RequestConfig.Builder requestConfigBuilder = HttpClientUtil.createDefaultRequestConfigBuilder();
@@ -539,6 +540,12 @@ public class HttpSolrClient extends SolrClient {
     try {
       // Execute the method.
       HttpClientContext httpClientRequestContext = HttpClientUtil.createNewHttpClientRequestContext();
+      if (userPrincipal != null) {
+        // Normally the context contains a static userToken to enable reuse resources.
+        // However, if a personal Principal object exists, we use that instead, also as a means
+        // to transfer authentication information to Auth plugins that wish to intercept the request later
+        httpClientRequestContext.setUserToken(userPrincipal);
+      }
       final HttpResponse response = httpClient.execute(method, httpClientRequestContext);
 
       int httpStatus = response.getStatusLine().getStatusCode();