This is an automated email from the ASF dual-hosted git repository.
mdrob pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/main by this push:
new def7f47 SOLR-15233: Set doAs in ConfigurableInternodeAuthHadoopPlugin
def7f47 is described below
commit def7f47a4d2389ce8362ce7215095c5e43afe5c0
Author: Mike Drob <[email protected]>
AuthorDate: Fri Apr 2 11:37:51 2021 -0500
SOLR-15233: Set doAs in ConfigurableInternodeAuthHadoopPlugin
Additional-Author: Jason Gerlowski <[email protected]>
Additional-Author: Geza Nagy <gezan>
---
solr/CHANGES.txt | 2 +
.../ConfigurableInternodeAuthHadoopPlugin.java | 67 ++++++++++++++++++++--
.../org/apache/solr/security/HadoopAuthPlugin.java | 13 +++--
.../org/apache/solr/security/KerberosPlugin.java | 22 +++----
.../security/hadoop_kerberos_authz_config.json | 15 +++--
.../client/solrj/impl/Krb5HttpClientUtils.java | 66 +++++++++++++++++++++
.../apache/solr/security/hadoop/KerberosUtils.java | 3 +-
.../TestRuleBasedAuthorizationWithKerberos.java | 51 ++++++++++++++--
.../hadoop/TestSolrCloudWithHadoopAuthPlugin.java | 7 ++-
.../src/hadoop-authentication-plugin.adoc | 10 ++++
.../client/solrj/impl/Krb5HttpClientBuilder.java | 13 +++--
11 files changed, 227 insertions(+), 42 deletions(-)
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 7ad7907..fbc6f57 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -252,6 +252,8 @@ Bug Fixes
* SOLR-15162: Allow readOnly parameter to be used with v2 modify collection
command (Eric Pugh)
+* SOLR-15233: Set doAs param in ConfigurableInternodeAuthHadoopPlugin (Geza
Nagy, Jason Gerlowski, Mike Drob)
+
================== 8.9.0 ==================
Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this
release.
diff --git
a/solr/core/src/java/org/apache/solr/security/ConfigurableInternodeAuthHadoopPlugin.java
b/solr/core/src/java/org/apache/solr/security/ConfigurableInternodeAuthHadoopPlugin.java
index 010fa16..8ad112d 100644
---
a/solr/core/src/java/org/apache/solr/security/ConfigurableInternodeAuthHadoopPlugin.java
+++
b/solr/core/src/java/org/apache/solr/security/ConfigurableInternodeAuthHadoopPlugin.java
@@ -16,20 +16,34 @@
*/
package org.apache.solr.security;
-import java.io.IOException;
-import java.util.Map;
-import java.util.Objects;
-
+import org.apache.http.HttpRequest;
+import org.apache.http.client.methods.HttpRequestWrapper;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.protocol.HttpContext;
import org.apache.solr.client.solrj.impl.Http2SolrClient;
import org.apache.solr.client.solrj.impl.HttpClientBuilderFactory;
import org.apache.solr.client.solrj.impl.SolrHttpClientBuilder;
import org.apache.solr.core.CoreContainer;
+import org.apache.solr.request.SolrRequestInfo;
+import org.apache.solr.servlet.SolrDispatchFilter;
+import org.eclipse.jetty.client.api.Request;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.net.URISyntaxException;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.BiConsumer;
/**
* This class extends {@linkplain HadoopAuthPlugin} by enabling configuration
of
* authentication mechanism for Solr internal communication.
**/
public class ConfigurableInternodeAuthHadoopPlugin extends HadoopAuthPlugin
implements HttpClientBuilderPlugin {
+ private static final Logger log =
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
/**
* A property specifying the {@linkplain HttpClientBuilderFactory} used for
the Solr internal
@@ -37,6 +51,8 @@ public class ConfigurableInternodeAuthHadoopPlugin extends
HadoopAuthPlugin impl
*/
private static final String HTTPCLIENT_BUILDER_FACTORY =
"clientBuilderFactory";
+ private static final String DO_AS = "doAs";
+
private HttpClientBuilderFactory factory = null;
public ConfigurableInternodeAuthHadoopPlugin(CoreContainer coreContainer) {
@@ -44,10 +60,10 @@ public class ConfigurableInternodeAuthHadoopPlugin extends
HadoopAuthPlugin impl
}
@Override
- public void init(Map<String,Object> pluginConfig) {
+ public void init(Map<String, Object> pluginConfig) {
super.init(pluginConfig);
- String httpClientBuilderFactory =
(String)Objects.requireNonNull(pluginConfig.get(HTTPCLIENT_BUILDER_FACTORY),
+ String httpClientBuilderFactory = (String)
Objects.requireNonNull(pluginConfig.get(HTTPCLIENT_BUILDER_FACTORY),
"Please specify clientBuilderFactory to be used for Solr internal
communication.");
factory =
this.coreContainer.getResourceLoader().newInstance(httpClientBuilderFactory,
HttpClientBuilderFactory.class);
}
@@ -70,4 +86,43 @@ public class ConfigurableInternodeAuthHadoopPlugin extends
HadoopAuthPlugin impl
factory.close();
}
}
+
+ @Override
+ public boolean interceptInternodeRequest(HttpRequest httpRequest,
HttpContext httpContext) {
+ if (! (httpRequest instanceof HttpRequestWrapper)) {
+ log.warn("Unable to add doAs to forwarded/distributed request - unknown
request type");
+ return false;
+ }
+ AtomicBoolean success = new AtomicBoolean(false);
+ return intercept((key, value) -> {
+ HttpRequestWrapper request = (HttpRequestWrapper) httpRequest;
+ URIBuilder uriBuilder = new URIBuilder(request.getURI());
+ uriBuilder.setParameter(key, value);
+ try {
+ request.setURI(uriBuilder.build());
+ success.set(true);
+ } catch (URISyntaxException e) {
+ log.warn("Unable to add doAs to forwarded/distributed request - bad
URI");
+ }
+ }) && success.get();
+ }
+
+ @Override
+ protected boolean interceptInternodeRequest(Request request) {
+ return intercept(request::param);
+ }
+
+ private boolean intercept(BiConsumer<String, String> setParam) {
+ SolrRequestInfo info = SolrRequestInfo.getRequestInfo();
+ if (info != null && (info.getAction() == SolrDispatchFilter.Action.FORWARD
||
+ info.getAction() == SolrDispatchFilter.Action.REMOTEQUERY)) {
+ if (info.getUserPrincipal() != null) {
+ String name = info.getUserPrincipal().getName();
+ log.debug("Setting doAs={} to forwarded/remote request", name);
+ setParam.accept(DO_AS, name);
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/solr/core/src/java/org/apache/solr/security/HadoopAuthPlugin.java
b/solr/core/src/java/org/apache/solr/security/HadoopAuthPlugin.java
index f625c93..2a68ee3 100644
--- a/solr/core/src/java/org/apache/solr/security/HadoopAuthPlugin.java
+++ b/solr/core/src/java/org/apache/solr/security/HadoopAuthPlugin.java
@@ -51,11 +51,11 @@ import org.slf4j.LoggerFactory;
/**
* This class implements a generic plugin which can use authentication schemes
exposed by the
* Hadoop framework. This plugin supports following features
- * - integration with authentication mehcanisms (e.g. kerberos)
+ * - integration with authentication mechanisms (e.g. kerberos)
* - Delegation token support
* - Proxy users (or secure impersonation) support
*
- * This plugin enables defining configuration parameters required by the
undelying Hadoop authentication
+ * This plugin enables defining configuration parameters required by the
underlying Hadoop authentication
* mechanism. These configuration parameters can either be specified as a Java
system property or the default
* value can be specified as part of the plugin configuration.
*
@@ -121,6 +121,7 @@ public class HadoopAuthPlugin extends AuthenticationPlugin {
private AuthenticationFilter authFilter;
private final Locale defaultLocale = Locale.getDefault();
protected final CoreContainer coreContainer;
+ private boolean delegationTokenEnabled;
public HadoopAuthPlugin(CoreContainer coreContainer) {
this.coreContainer = coreContainer;
@@ -129,8 +130,8 @@ public class HadoopAuthPlugin extends AuthenticationPlugin {
@Override
public void init(Map<String,Object> pluginConfig) {
try {
- String delegationTokenEnabled =
(String)pluginConfig.getOrDefault(DELEGATION_TOKEN_ENABLED_PROPERTY, "false");
- authFilter = (Boolean.parseBoolean(delegationTokenEnabled)) ? new
HadoopAuthFilter() : new AuthenticationFilter() {
+ delegationTokenEnabled = Boolean.parseBoolean((String)
pluginConfig.get(DELEGATION_TOKEN_ENABLED_PROPERTY));
+ authFilter = delegationTokenEnabled ? new HadoopAuthFilter() : new
AuthenticationFilter() {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
// A hack until HADOOP-15681 get committed
@@ -183,6 +184,10 @@ public class HadoopAuthPlugin extends AuthenticationPlugin
{
params.put(configName, configVal);
}
}
+ if (delegationTokenEnabled) {
+ // This is the only kind we support right now anyway
+ params.putIfAbsent("delegation-token.token-kind",
KerberosPlugin.DELEGATION_TOKEN_TYPE_DEFAULT);
+ }
// Configure proxy user settings.
params.putAll(proxyUserConfigs);
diff --git a/solr/core/src/java/org/apache/solr/security/KerberosPlugin.java
b/solr/core/src/java/org/apache/solr/security/KerberosPlugin.java
index 42d6491..804566c 100644
--- a/solr/core/src/java/org/apache/solr/security/KerberosPlugin.java
+++ b/solr/core/src/java/org/apache/solr/security/KerberosPlugin.java
@@ -21,6 +21,7 @@ import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
+import java.util.function.BiConsumer;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
@@ -244,23 +245,16 @@ public class KerberosPlugin extends AuthenticationPlugin
implements HttpClientBu
}
@Override
- protected boolean interceptInternodeRequest(HttpRequest httpRequest,
HttpContext httpContext) {
- SolrRequestInfo info = SolrRequestInfo.getRequestInfo();
- if (info != null && (info.getAction() == SolrDispatchFilter.Action.FORWARD
||
- info.getAction() == SolrDispatchFilter.Action.REMOTEQUERY)) {
- if (info.getUserPrincipal() != null) {
- if (log.isInfoEnabled()) {
- log.info("Setting original user principal: {}",
info.getUserPrincipal().getName());
- }
- httpRequest.setHeader(ORIGINAL_USER_PRINCIPAL_HEADER,
info.getUserPrincipal().getName());
- return true;
- }
- }
- return false;
+ public boolean interceptInternodeRequest(HttpRequest httpRequest,
HttpContext httpContext) {
+ return intercept(httpRequest::setHeader);
}
@Override
protected boolean interceptInternodeRequest(Request request) {
+ return intercept(request::header);
+ }
+
+ private boolean intercept(BiConsumer<String, String> header) {
SolrRequestInfo info = SolrRequestInfo.getRequestInfo();
if (info != null && (info.getAction() == SolrDispatchFilter.Action.FORWARD
||
info.getAction() == SolrDispatchFilter.Action.REMOTEQUERY)) {
@@ -268,7 +262,7 @@ public class KerberosPlugin extends AuthenticationPlugin
implements HttpClientBu
if (log.isInfoEnabled()) {
log.info("Setting original user principal: {}",
info.getUserPrincipal().getName());
}
- request.header(ORIGINAL_USER_PRINCIPAL_HEADER,
info.getUserPrincipal().getName());
+ header.accept(ORIGINAL_USER_PRINCIPAL_HEADER,
info.getUserPrincipal().getName());
return true;
}
}
diff --git
a/solr/core/src/test-files/solr/security/hadoop_kerberos_authz_config.json
b/solr/core/src/test-files/solr/security/hadoop_kerberos_authz_config.json
index 92081b7..660418e 100644
--- a/solr/core/src/test-files/solr/security/hadoop_kerberos_authz_config.json
+++ b/solr/core/src/test-files/solr/security/hadoop_kerberos_authz_config.json
@@ -4,6 +4,7 @@
"sysPropPrefix": "solr.",
"type": "kerberos",
"clientBuilderFactory":
"org.apache.solr.client.solrj.impl.Krb5HttpClientBuilder",
+ "enableDelegationToken": "true",
"initKerberosZk": "true",
"authConfigs": [
"kerberos.principal",
@@ -11,6 +12,10 @@
"kerberos.name.rules"
],
"defaultConfigs": {
+ },
+ "proxyUserConfigs": {
+ "proxyuser.solr.hosts": "*",
+ "proxyuser.solr.groups": "*"
}
},
"authorization":{
@@ -18,8 +23,9 @@
"useShortName": "true",
"permissions":[
{
- "name":"collection-admin-edit",
- "role":"admin"
+ "name": "read",
+ "role": "alt_role",
+ "collection": "public"
},
{
"name":"read",
@@ -30,8 +36,9 @@
"role":"admin"
}
],
- "user-role":{
- "solr":"admin"
+ "user-role": {
+ "solr":"admin",
+ "solr_alt": "alt_role"
}
}
}
diff --git
a/solr/core/src/test/org/apache/solr/client/solrj/impl/Krb5HttpClientUtils.java
b/solr/core/src/test/org/apache/solr/client/solrj/impl/Krb5HttpClientUtils.java
new file mode 100644
index 0000000..d2917b7
--- /dev/null
+++
b/solr/core/src/test/org/apache/solr/client/solrj/impl/Krb5HttpClientUtils.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.client.solrj.impl;
+
+import org.eclipse.jetty.client.HttpAuthenticationStore;
+import org.eclipse.jetty.client.WWWAuthenticationProtocolHandler;
+import org.eclipse.jetty.client.util.SPNEGOAuthentication;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+import java.lang.invoke.MethodHandles;
+import java.net.URI;
+
+/**
+ * All of this is a clone of Krb5HttpClientBuilder to hardcode the
user-principal for a unit test
+ */
+public class Krb5HttpClientUtils {
+ private static final Logger log =
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ private static Configuration jaasConfig = new
Krb5HttpClientBuilder.SolrJaasConfiguration();
+
+
+ public static void setup(Http2SolrClient http2Client, String principalName) {
+ HttpAuthenticationStore authenticationStore = new
HttpAuthenticationStore();
+
authenticationStore.addAuthentication(createSPNEGOAuthentication(principalName));
+ http2Client.getHttpClient().setAuthenticationStore(authenticationStore);
+ http2Client.getProtocolHandlers().put(new
WWWAuthenticationProtocolHandler(http2Client.getHttpClient()));
+ }
+
+ private static SPNEGOAuthentication createSPNEGOAuthentication(String
principalName) {
+ SPNEGOAuthentication authentication = new SPNEGOAuthentication(null){
+
+ public boolean matches(String type, URI uri, String realm) {
+ return this.getType().equals(type);
+ }
+ };
+ String clientAppName = System.getProperty("solr.kerberos.jaas.appname",
"Client");
+ AppConfigurationEntry[] entries =
jaasConfig.getAppConfigurationEntry(clientAppName);
+ if (entries == null) {
+ log.warn("Could not find login configuration entry for {}. SPNego
authentication may not be successful.", (Object)clientAppName);
+ return authentication;
+ }
+ if (entries.length != 1) {
+ log.warn("Multiple login modules are specified in the configuration
file");
+ return authentication;
+ }
+
+ Krb5HttpClientBuilder.setAuthenticationOptions(authentication,
entries[0].getOptions(), principalName);
+ return authentication;
+ }
+}
diff --git
a/solr/core/src/test/org/apache/solr/security/hadoop/KerberosUtils.java
b/solr/core/src/test/org/apache/solr/security/hadoop/KerberosUtils.java
index 4d1b4b4..ac3077b 100644
--- a/solr/core/src/test/org/apache/solr/security/hadoop/KerberosUtils.java
+++ b/solr/core/src/test/org/apache/solr/security/hadoop/KerberosUtils.java
@@ -38,6 +38,7 @@ public class KerberosUtils {
System.setProperty("solr.jaas.debug", "true");
Path kdcDir = baseDir.resolve("minikdc");
String solrClientPrincipal = "solr";
+ String solrAltClientPrincipal = "solr_alt"; // An alternate principal that
can be handled differently by authz tests
File keytabFile = kdcDir.resolve("keytabs").toFile();
KerberosTestServices tmp = KerberosTestServices.builder()
.withKdc(kdcDir.toFile())
@@ -45,7 +46,7 @@ public class KerberosUtils {
.build();
String solrServerPrincipal = "HTTP/127.0.0.1";
tmp.start();
- tmp.getKdc().createPrincipal(keytabFile, solrServerPrincipal,
solrClientPrincipal);
+ tmp.getKdc().createPrincipal(keytabFile, solrServerPrincipal,
solrAltClientPrincipal, solrClientPrincipal);
String appName = "SolrClient";
String jaas = appName + " {\n"
diff --git
a/solr/core/src/test/org/apache/solr/security/hadoop/TestRuleBasedAuthorizationWithKerberos.java
b/solr/core/src/test/org/apache/solr/security/hadoop/TestRuleBasedAuthorizationWithKerberos.java
index 0020e54..fa89891 100644
---
a/solr/core/src/test/org/apache/solr/security/hadoop/TestRuleBasedAuthorizationWithKerberos.java
+++
b/solr/core/src/test/org/apache/solr/security/hadoop/TestRuleBasedAuthorizationWithKerberos.java
@@ -18,23 +18,32 @@ package org.apache.solr.security.hadoop;
import org.apache.lucene.util.Constants;
import org.apache.solr.client.solrj.SolrQuery;
+import org.apache.solr.client.solrj.embedded.JettySolrRunner;
+import org.apache.solr.client.solrj.impl.BaseHttpSolrClient;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.Http2SolrClient;
+import org.apache.solr.client.solrj.impl.Krb5HttpClientUtils;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.cloud.AbstractDistribZkTestBase;
import org.apache.solr.cloud.KerberosTestServices;
import org.apache.solr.cloud.SolrCloudTestCase;
import org.apache.solr.common.SolrInputDocument;
+import org.apache.solr.util.LogLevel;
import org.junit.AfterClass;
+import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+@LogLevel("org.apache.solr.security=DEBUG")
public class TestRuleBasedAuthorizationWithKerberos extends SolrCloudTestCase {
- protected static final int NUM_SERVERS = 1;
+ protected static final int NUM_SERVERS = 2;
protected static final int NUM_SHARDS = 1;
protected static final int REPLICATION_FACTOR = 1;
private static KerberosTestServices kerberosTestServices;
+ private String collectionName;
+
@BeforeClass
public static void setupClass() throws Exception {
assumeFalse("Hadoop does not work on Windows", Constants.WINDOWS);
@@ -53,15 +62,45 @@ public class TestRuleBasedAuthorizationWithKerberos extends
SolrCloudTestCase {
kerberosTestServices = null;
}
- @Test
- public void testCollectionCreateSearchDelete() throws Exception {
- CloudSolrClient solrClient = cluster.getSolrClient();
- String collectionName = "testkerberoscollection_authz";
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ collectionName = getSaferTestName();
// create collection
CollectionAdminRequest.Create create =
CollectionAdminRequest.createCollection(collectionName, "conf1",
NUM_SHARDS, REPLICATION_FACTOR);
- create.process(solrClient);
+ create.process(cluster.getSolrClient());
+ cluster.waitForActiveCollection(collectionName, 1, 1);
+ }
+
+ @Test
+ public void testReadsAltUser() throws Exception {
+ String authorizedColl = "public";
+
+ // create collection
+ CollectionAdminRequest.createCollection(authorizedColl, "conf1",
NUM_SHARDS, REPLICATION_FACTOR)
+ .process(cluster.getSolrClient());
+ cluster.waitForActiveCollection(authorizedColl, 1, 1);
+
+ final SolrQuery q = new SolrQuery("*:*");
+
+ for (JettySolrRunner jsr : cluster.getJettySolrRunners()) {
+ final String baseUrl = jsr.getBaseUrl().toString();
+ try (Http2SolrClient client = new
Http2SolrClient.Builder(baseUrl).build()) {
+ Krb5HttpClientUtils.setup(client, "solr_alt");
+ assertEquals(0, client.query(authorizedColl, q).getStatus());
+ BaseHttpSolrClient.RemoteSolrException e =
assertThrows(BaseHttpSolrClient.RemoteSolrException.class,
+ () -> client.query(collectionName, q));
+ assertEquals(403, e.code());
+ }
+ }
+ }
+
+ @Test
+ public void testCollectionCreateSearchDelete() throws Exception {
+ CloudSolrClient solrClient = cluster.getSolrClient();
SolrInputDocument doc = new SolrInputDocument();
doc.setField("id", "1");
diff --git
a/solr/core/src/test/org/apache/solr/security/hadoop/TestSolrCloudWithHadoopAuthPlugin.java
b/solr/core/src/test/org/apache/solr/security/hadoop/TestSolrCloudWithHadoopAuthPlugin.java
index 6538fd5..36520be 100644
---
a/solr/core/src/test/org/apache/solr/security/hadoop/TestSolrCloudWithHadoopAuthPlugin.java
+++
b/solr/core/src/test/org/apache/solr/security/hadoop/TestSolrCloudWithHadoopAuthPlugin.java
@@ -70,13 +70,13 @@ public class TestSolrCloudWithHadoopAuthPlugin extends
SolrCloudAuthTestCase {
NUM_SHARDS, REPLICATION_FACTOR);
create.process(solrClient);
// The metrics counter for wrong credentials here really just means
- assertAuthMetricsMinimums(4, 2, 0, 2, 0, 0);
+ assertAuthMetricsMinimums(2, 1, 0, 1, 0, 0);
SolrInputDocument doc = new SolrInputDocument();
doc.setField("id", "1");
solrClient.add(collectionName, doc);
solrClient.commit(collectionName);
- assertAuthMetricsMinimums(8, 4, 0, 4, 0, 0);
+ assertAuthMetricsMinimums(4, 2, 0, 2, 0, 0);
SolrQuery query = new SolrQuery();
query.setQuery("*:*");
@@ -88,5 +88,6 @@ public class TestSolrCloudWithHadoopAuthPlugin extends
SolrCloudAuthTestCase {
AbstractDistribZkTestBase.waitForCollectionToDisappear(collectionName,
solrClient.getZkStateReader(), true, 330);
// cookie was used to avoid re-authentication
- assertAuthMetricsMinimums(11, 7, 0, 4, 0, 0); }
+ assertAuthMetricsMinimums(6, 4, 0, 2, 0, 0);
+ }
}
diff --git a/solr/solr-ref-guide/src/hadoop-authentication-plugin.adoc
b/solr/solr-ref-guide/src/hadoop-authentication-plugin.adoc
index 96609c0..82cd87a 100644
--- a/solr/solr-ref-guide/src/hadoop-authentication-plugin.adoc
+++ b/solr/solr-ref-guide/src/hadoop-authentication-plugin.adoc
@@ -77,6 +77,8 @@ After consulting the Hadoop authentication library's
documentation, you can supp
Please note that this example uses `ConfigurableInternodeAuthHadoopPlugin`,
and hence you must provide the `clientBuilderFactory` implementation. As a
result, all internode communication will use the Kerberos mechanism, instead of
PKI authentication.
+This configuration assumes that your servers are using the `solr` principal,
and will be allowed to impersonate any other user with requests coming from any
other host. For additional security, consider setting the host list to match
your cluster nodes. The Hadoop
https://hadoop.apache.org/docs/r3.2.2/hadoop-project-dist/hadoop-common/Superusers.html[proxy
users] documentation contains more detail about available configuration
options.
+
To setup this plugin, use the following in your `security.json` file.
[source,json]
@@ -88,17 +90,25 @@ To setup this plugin, use the following in your
`security.json` file.
"type": "kerberos",
"clientBuilderFactory":
"org.apache.solr.client.solrj.impl.Krb5HttpClientBuilder",
"initKerberosZk": "true",
+ "enableDelegationToken": "true",
"authConfigs": [
"kerberos.principal",
"kerberos.keytab",
"kerberos.name.rules"
],
"defaultConfigs": {
+ },
+ "proxyUserConfigs": {
+ "proxyuser.solr.hosts": "*",
+ "proxyuser.solr.groups": "*"
}
}
}
----
+[WARNING]
+For the `ConfigurableInternodeAuthHadoopPlugin`, user credential proxying
relies on delegation token support. Without it, forwarded requests will
authenticate as Solr server credentials instead of real-user credentials, and
likely allowing authenticated-but-unauthorized users to query and index
documents into your collections.
+
=== Simple Authentication with Delegation Tokens
Similar to the previous example, this is an example of setting up a Solr
cluster that uses delegation tokens. Refer to the parameters in the Hadoop
authentication library's
https://hadoop.apache.org/docs/stable/hadoop-auth/Configuration.html[documentation]
or refer to the section <<kerberos-authentication-plugin.adoc#,Kerberos
Authentication Plugin>> for further details. Please note that this example does
not use Kerberos and the requests made to Solr must contain valid delegation
tokens.
diff --git
a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientBuilder.java
b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientBuilder.java
index aa3eb85..43ca73e 100644
---
a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientBuilder.java
+++
b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientBuilder.java
@@ -102,13 +102,19 @@ public class Krb5HttpClientBuilder implements
HttpClientBuilderFactory {
log.warn("Multiple login modules are specified in the configuration
file");
return authentication;
}
+
Map<String, ?> options = entries[0].getOptions();
+ setAuthenticationOptions(authentication, options, (String)
options.get("principal"));
+ return authentication;
+ }
+
+ static void setAuthenticationOptions(SPNEGOAuthentication authentication,
Map<String, ?> options, String username) {
String keyTab = (String)options.get("keyTab");
if (keyTab != null) {
- authentication.setUserKeyTabPath(Paths.get(keyTab, new String[0]));
+ authentication.setUserKeyTabPath(Paths.get(keyTab));
}
authentication.setServiceName("HTTP");
- authentication.setUserName((String)options.get("principal"));
+ authentication.setUserName(username);
if ("true".equalsIgnoreCase((String)options.get("useTicketCache"))) {
authentication.setUseTicketCache(true);
String ticketCachePath = (String)options.get("ticketCache");
@@ -117,7 +123,6 @@ public class Krb5HttpClientBuilder implements
HttpClientBuilderFactory {
}
authentication.setRenewTGT("true".equalsIgnoreCase((String)options.get("renewTGT")));
}
- return authentication;
}
@Override
@@ -202,7 +207,7 @@ public class Krb5HttpClientBuilder implements
HttpClientBuilderFactory {
}
};
- private static class SolrJaasConfiguration extends
javax.security.auth.login.Configuration {
+ public static class SolrJaasConfiguration extends
javax.security.auth.login.Configuration {
private javax.security.auth.login.Configuration baseConfig;