You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by yo...@apache.org on 2016/11/17 21:39:45 UTC
[1/5] lucene-solr:branch_6x: SOLR-9460: Fully fix test setup
Repository: lucene-solr
Updated Branches:
refs/heads/branch_6x 722e77a69 -> f084e658b
SOLR-9460: Fully fix test setup
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/6428772a
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/6428772a
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/6428772a
Branch: refs/heads/branch_6x
Commit: 6428772aa2cd3a1c344cfcaeec7c30fd46071134
Parents: 225198a
Author: Uwe Schindler <us...@apache.org>
Authored: Sat Sep 3 20:30:30 2016 +0200
Committer: yonik <yo...@apache.org>
Committed: Thu Nov 17 15:05:46 2016 -0500
----------------------------------------------------------------------
.../TestSolrCloudWithSecureImpersonation.java | 22 ++++++++++++--------
1 file changed, 13 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6428772a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java b/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
index 3727620..ef41e4d 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
@@ -58,16 +58,18 @@ public class TestSolrCloudWithSecureImpersonation extends SolrTestCaseJ4 {
private static SolrClient solrClient;
private static String getUsersFirstGroup() throws Exception {
- org.apache.hadoop.security.Groups hGroups =
- new org.apache.hadoop.security.Groups(new Configuration());
String group = "*"; // accept any group if a group can't be found
- try {
- List<String> g = hGroups.getGroups(System.getProperty("user.name"));
- if (g != null && g.size() > 0) {
- group = g.get(0);
+ if (!Constants.WINDOWS) { // does not work on Windows!
+ org.apache.hadoop.security.Groups hGroups =
+ new org.apache.hadoop.security.Groups(new Configuration());
+ try {
+ List<String> g = hGroups.getGroups(System.getProperty("user.name"));
+ if (g != null && g.size() > 0) {
+ group = g.get(0);
+ }
+ } catch (NullPointerException npe) {
+ // if user/group doesn't exist on test box
}
- } catch (NullPointerException npe) {
- // if user/group doesn't exist on test box
}
return group;
}
@@ -154,7 +156,9 @@ public class TestSolrCloudWithSecureImpersonation extends SolrTestCaseJ4 {
miniCluster.shutdown();
}
miniCluster = null;
- solrClient.close();
+ if (solrClient != null) {
+ solrClient.close();
+ }
solrClient = null;
System.clearProperty("authenticationPlugin");
System.clearProperty(KerberosPlugin.DELEGATION_TOKEN_ENABLED);
[4/5] lucene-solr:branch_6x: SOLR-9324: Fix local host test
assumptions
Posted by yo...@apache.org.
SOLR-9324: Fix local host test assumptions
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/8659fe1c
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/8659fe1c
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/8659fe1c
Branch: refs/heads/branch_6x
Commit: 8659fe1cce3f49f37f50f9a74d0eb79ad8d1bf58
Parents: f78f698
Author: Gregory Chanan <gc...@cloudera.com>
Authored: Sat Aug 6 00:04:58 2016 -0400
Committer: yonik <yo...@apache.org>
Committed: Thu Nov 17 15:05:46 2016 -0500
----------------------------------------------------------------------
.../TestSolrCloudWithSecureImpersonation.java | 23 +++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8659fe1c/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java b/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
index 1839d32..71107ee 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
@@ -18,6 +18,7 @@ package org.apache.solr.cloud;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
+import java.net.InetAddress;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
@@ -42,6 +43,7 @@ import org.apache.solr.security.HttpParamDelegationTokenPlugin;
import org.apache.solr.security.KerberosPlugin;
import org.apache.solr.servlet.SolrRequestParsers;
import org.junit.AfterClass;
+import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -57,8 +59,16 @@ public class TestSolrCloudWithSecureImpersonation extends SolrTestCaseJ4 {
private static String getUsersFirstGroup() throws Exception {
org.apache.hadoop.security.Groups hGroups =
new org.apache.hadoop.security.Groups(new Configuration());
- List<String> g = hGroups.getGroups(System.getProperty("user.name"));
- return g.get(0);
+ String group = "*"; // accept any group if a group can't be found
+ try {
+ List<String> g = hGroups.getGroups(System.getProperty("user.name"));
+ if (g != null && g.size() > 0) {
+ group = g.get(0);
+ }
+ } catch (NullPointerException npe) {
+ // if user/group doesn't exist on test box
+ }
+ return group;
}
private static Map<String, String> getImpersonatorSettings() throws Exception {
@@ -70,7 +80,9 @@ public class TestSolrCloudWithSecureImpersonation extends SolrTestCaseJ4 {
filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "wrongHost.groups", "*");
filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "noHosts.groups", "*");
filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "localHostAnyGroup.groups", "*");
- filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "localHostAnyGroup.hosts", "127.0.0.1");
+ InetAddress loopback = InetAddress.getLoopbackAddress();
+ filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "localHostAnyGroup.hosts",
+ loopback.getCanonicalHostName() + "," + loopback.getHostName() + "," + loopback.getHostAddress());
filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "anyHostUsersGroup.groups", getUsersFirstGroup());
filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "anyHostUsersGroup.hosts", "*");
filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "bogusGroup.groups", "__some_bogus_group");
@@ -128,6 +140,11 @@ public class TestSolrCloudWithSecureImpersonation extends SolrTestCaseJ4 {
}
}
+ @Before
+ public void clearCalledIndicator() throws Exception {
+ ImpersonatorCollectionsHandler.called.set(false);
+ }
+
@AfterClass
public static void shutdown() throws Exception {
if (miniCluster != null) {
[3/5] lucene-solr:branch_6x: SOLR-9324: Support Secure Impersonation
/ Proxy User for solr authentication
Posted by yo...@apache.org.
SOLR-9324: Support Secure Impersonation / Proxy User for solr authentication
Conflicts:
solr/CHANGES.txt
solr/core/src/java/org/apache/solr/security/KerberosPlugin.java
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/f78f698a
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/f78f698a
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/f78f698a
Branch: refs/heads/branch_6x
Commit: f78f698ab0a919e4923f0cbf061dfa254e177555
Parents: 722e77a
Author: Gregory Chanan <gc...@cloudera.com>
Authored: Mon Jul 25 14:15:48 2016 -0400
Committer: yonik <yo...@apache.org>
Committed: Thu Nov 17 15:05:46 2016 -0500
----------------------------------------------------------------------
.../security/DelegationTokenKerberosFilter.java | 46 ++-
.../apache/solr/security/KerberosPlugin.java | 205 ++++++-----
.../TestSolrCloudWithDelegationTokens.java | 9 +-
.../TestSolrCloudWithSecureImpersonation.java | 340 +++++++++++++++++++
...ramDelegationTokenAuthenticationHandler.java | 109 ------
.../HttpParamDelegationTokenPlugin.java | 272 +++++++++++++++
6 files changed, 776 insertions(+), 205 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f78f698a/solr/core/src/java/org/apache/solr/security/DelegationTokenKerberosFilter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/security/DelegationTokenKerberosFilter.java b/solr/core/src/java/org/apache/solr/security/DelegationTokenKerberosFilter.java
index a96605d..421de52 100644
--- a/solr/core/src/java/org/apache/solr/security/DelegationTokenKerberosFilter.java
+++ b/solr/core/src/java/org/apache/solr/security/DelegationTokenKerberosFilter.java
@@ -18,6 +18,7 @@ package org.apache.solr.security;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
+import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
@@ -36,8 +37,11 @@ import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.ACLProvider;
import org.apache.curator.retry.ExponentialBackoffRetry;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authentication.server.AuthenticationHandler;
import org.apache.hadoop.security.token.delegation.web.DelegationTokenAuthenticationFilter;
+import org.apache.hadoop.security.token.delegation.web.HttpUserGroupInformation;
import org.apache.solr.common.cloud.SecurityAwareZkACLProvider;
import org.apache.solr.common.cloud.SolrZkClient;
import org.apache.solr.common.cloud.ZkACLProvider;
@@ -67,6 +71,27 @@ public class DelegationTokenKerberosFilter extends DelegationTokenAuthentication
super.init(conf);
}
+ /**
+ * Return the ProxyUser Configuration. FilterConfig properties beginning with
+ * "solr.impersonator.user.name" will be added to the configuration.
+ */
+ @Override
+ protected Configuration getProxyuserConfiguration(FilterConfig filterConf)
+ throws ServletException {
+ Configuration conf = new Configuration(false);
+
+ Enumeration<?> names = filterConf.getInitParameterNames();
+ while (names.hasMoreElements()) {
+ String name = (String) names.nextElement();
+ if (name.startsWith(KerberosPlugin.IMPERSONATOR_PREFIX)) {
+ String value = filterConf.getInitParameter(name);
+ conf.set(PROXYUSER_PREFIX + "." + name.substring(KerberosPlugin.IMPERSONATOR_PREFIX.length()), value);
+ conf.set(name, value);
+ }
+ }
+ return conf;
+ }
+
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
@@ -81,7 +106,26 @@ public class DelegationTokenKerberosFilter extends DelegationTokenAuthentication
return nonNullQueryString;
}
};
- super.doFilter(requestNonNullQueryString, response, filterChain);
+
+ // include Impersonator User Name in case someone (e.g. logger) wants it
+ FilterChain filterChainWrapper = new FilterChain() {
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse)
+ throws IOException, ServletException {
+ HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
+
+ UserGroupInformation ugi = HttpUserGroupInformation.get();
+ if (ugi != null && ugi.getAuthenticationMethod() == UserGroupInformation.AuthenticationMethod.PROXY) {
+ UserGroupInformation realUserUgi = ugi.getRealUser();
+ if (realUserUgi != null) {
+ httpRequest.setAttribute(KerberosPlugin.IMPERSONATOR_USER_NAME, realUserUgi.getShortUserName());
+ }
+ }
+ filterChain.doFilter(servletRequest, servletResponse);
+ }
+ };
+
+ super.doFilter(requestNonNullQueryString, response, filterChainWrapper);
}
@Override
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f78f698a/solr/core/src/java/org/apache/solr/security/KerberosPlugin.java
----------------------------------------------------------------------
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 0eac9ae..b04ea49 100644
--- a/solr/core/src/java/org/apache/solr/security/KerberosPlugin.java
+++ b/solr/core/src/java/org/apache/solr/security/KerberosPlugin.java
@@ -53,17 +53,21 @@ import org.apache.commons.collections.iterators.IteratorEnumeration;
import org.apache.hadoop.security.authentication.client.AuthenticationException;
import org.apache.hadoop.security.authentication.server.AuthenticationHandler;
import org.apache.hadoop.security.authentication.server.AuthenticationToken;
+import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.solr.client.solrj.impl.HttpClientConfigurer;
import org.apache.solr.client.solrj.impl.Krb5HttpClientConfigurer;
import org.apache.solr.cloud.ZkController;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.cloud.SecurityAwareZkACLProvider;
+import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.util.SuppressForbidden;
import org.apache.solr.core.CoreContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.annotations.VisibleForTesting;
+
public class KerberosPlugin extends AuthenticationPlugin implements HttpClientInterceptorPlugin {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@@ -77,6 +81,7 @@ public class KerberosPlugin extends AuthenticationPlugin implements HttpClientIn
public static final String KEYTAB_PARAM = "solr.kerberos.keytab";
public static final String TOKEN_VALID_PARAM = "solr.kerberos.token.valid";
public static final String COOKIE_PORT_AWARE_PARAM = "solr.kerberos.cookie.portaware";
+ public static final String IMPERSONATOR_PREFIX = "solr.kerberos.impersonator.user.";
public static final String DELEGATION_TOKEN_ENABLED = "solr.kerberos.delegation.token.enabled";
public static final String DELEGATION_TOKEN_KIND = "solr.kerberos.delegation.token.kind";
public static final String DELEGATION_TOKEN_VALIDITY = "solr.kerberos.delegation.token.validity";
@@ -85,8 +90,11 @@ public class KerberosPlugin extends AuthenticationPlugin implements HttpClientIn
"solr.kerberos.delegation.token.signer.secret.provider.zookeper.path";
public static final String DELEGATION_TOKEN_SECRET_MANAGER_ZNODE_WORKING_PATH =
"solr.kerberos.delegation.token.secret.manager.znode.working.path";
+
public static final String DELEGATION_TOKEN_TYPE_DEFAULT = "solr-dt";
-
+ public static final String IMPERSONATOR_DO_AS_HTTP_PARAM = "doAs";
+ public static final String IMPERSONATOR_USER_NAME = "solr.impersonator.user.name";
+
// filled in by Plugin/Filter
static final String REQUEST_CONTINUES_ATTR =
"org.apache.solr.security.kerberosplugin.requestcontinues";
@@ -105,107 +113,121 @@ public class KerberosPlugin extends AuthenticationPlugin implements HttpClientIn
@Override
public void init(Map<String, Object> pluginConfig) {
try {
- Map<String, String> params = new HashMap();
- putParam(params, "type", AUTH_HANDLER_PARAM, "kerberos");
- putParam(params, "kerberos.name.rules", NAME_RULES_PARAM, "DEFAULT");
- putParam(params, "token.valid", TOKEN_VALID_PARAM, "30");
- putParam(params, "cookie.path", COOKIE_PATH_PARAM, "/");
- if ("kerberos".equals(params.get("type"))) {
- putParam(params, "kerberos.principal", PRINCIPAL_PARAM, null);
- putParam(params, "kerberos.keytab", KEYTAB_PARAM, null);
- } else {
- // allow tests which specify AUTH_HANDLER_PARAM to avoid specifying kerberos principal/keytab
- putParamOptional(params, "kerberos.principal", PRINCIPAL_PARAM);
- putParamOptional(params, "kerberos.keytab", KEYTAB_PARAM);
- }
+ FilterConfig conf = getInitFilterConfig(pluginConfig, false);
+ kerberosFilter.init(conf);
+ } catch (ServletException e) {
+ throw new SolrException(ErrorCode.SERVER_ERROR, "Error initializing kerberos authentication plugin: "+e);
+ }
+ }
- String delegationTokenStr = System.getProperty(DELEGATION_TOKEN_ENABLED, null);
- boolean delegationTokenEnabled =
- (delegationTokenStr == null) ? false : Boolean.parseBoolean(delegationTokenStr);
- ZkController controller = coreContainer.getZkController();
-
- if (delegationTokenEnabled) {
- putParam(params, "delegation-token.token-kind", DELEGATION_TOKEN_KIND, DELEGATION_TOKEN_TYPE_DEFAULT);
- if (coreContainer.isZooKeeperAware()) {
- putParam(params, "signer.secret.provider", DELEGATION_TOKEN_SECRET_PROVIDER, "zookeeper");
- if ("zookeeper".equals(params.get("signer.secret.provider"))) {
- String zkHost = controller.getZkServerAddress();
- putParam(params, "token.validity", DELEGATION_TOKEN_VALIDITY, "36000");
- params.put("zk-dt-secret-manager.enable", "true");
-
- String chrootPath = zkHost.contains("/")? zkHost.substring(zkHost.indexOf("/")): "";
- String znodeWorkingPath = chrootPath + SecurityAwareZkACLProvider.SECURITY_ZNODE_PATH + "/zkdtsm";
- // Note - Curator complains if the znodeWorkingPath starts with /
- znodeWorkingPath = znodeWorkingPath.startsWith("/")? znodeWorkingPath.substring(1): znodeWorkingPath;
- putParam(params, "zk-dt-secret-manager.znodeWorkingPath",
- DELEGATION_TOKEN_SECRET_MANAGER_ZNODE_WORKING_PATH, znodeWorkingPath);
- putParam(params, "signer.secret.provider.zookeeper.path",
- DELEGATION_TOKEN_SECRET_PROVIDER_ZK_PATH, "/token");
- // need to ensure krb5 is setup properly before running curator;
- // the coreContainer should take care of this by calling configure on the
- // kerberosConfigurer.
- }
- } else {
- log.info("CoreContainer is not ZooKeeperAware, not setting ZK-related delegation token properties");
+ @VisibleForTesting
+ protected FilterConfig getInitFilterConfig(Map<String, Object> pluginConfig, boolean skipKerberosChecking) {
+ Map<String, String> params = new HashMap();
+ params.put("type", "kerberos");
+ putParam(params, "kerberos.name.rules", NAME_RULES_PARAM, "DEFAULT");
+ putParam(params, "token.valid", TOKEN_VALID_PARAM, "30");
+ putParam(params, "cookie.path", COOKIE_PATH_PARAM, "/");
+ if (!skipKerberosChecking) {
+ putParam(params, "kerberos.principal", PRINCIPAL_PARAM, null);
+ putParam(params, "kerberos.keytab", KEYTAB_PARAM, null);
+ } else {
+ putParamOptional(params, "kerberos.principal", PRINCIPAL_PARAM);
+ putParamOptional(params, "kerberos.keytab", KEYTAB_PARAM);
+ }
+
+ String delegationTokenStr = System.getProperty(DELEGATION_TOKEN_ENABLED, null);
+ boolean delegationTokenEnabled =
+ (delegationTokenStr == null) ? false : Boolean.parseBoolean(delegationTokenStr);
+ ZkController controller = coreContainer.getZkController();
+
+ if (delegationTokenEnabled) {
+ putParam(params, "delegation-token.token-kind", DELEGATION_TOKEN_KIND, DELEGATION_TOKEN_TYPE_DEFAULT);
+ if (coreContainer.isZooKeeperAware()) {
+ putParam(params, "signer.secret.provider", DELEGATION_TOKEN_SECRET_PROVIDER, "zookeeper");
+ if ("zookeeper".equals(params.get("signer.secret.provider"))) {
+ String zkHost = controller.getZkServerAddress();
+ putParam(params, "token.validity", DELEGATION_TOKEN_VALIDITY, "36000");
+ params.put("zk-dt-secret-manager.enable", "true");
+ // Note - Curator complains if the znodeWorkingPath starts with /
+ String chrootPath = zkHost.substring(zkHost.indexOf("/"));
+ String relativePath = chrootPath.startsWith("/") ? chrootPath.substring(1) : chrootPath;
+ putParam(params, "zk-dt-secret-manager.znodeWorkingPath",
+ DELEGATION_TOKEN_SECRET_MANAGER_ZNODE_WORKING_PATH,
+ relativePath + SecurityAwareZkACLProvider.SECURITY_ZNODE_PATH + "/zkdtsm");
+ putParam(params, "signer.secret.provider.zookeeper.path",
+ DELEGATION_TOKEN_SECRET_PROVIDER_ZK_PATH, "/token");
+ // ensure krb5 is setup properly before running curator
+ kerberosConfigurer.configure(new DefaultHttpClient(), new ModifiableSolrParams());
}
+ } else {
+ log.info("CoreContainer is not ZooKeeperAware, not setting ZK-related delegation token properties");
}
+ }
- // Special handling for the "cookie.domain" based on whether port should be
- // appended to the domain. Useful for situations where multiple solr nodes are
- // on the same host.
- String usePortStr = System.getProperty(COOKIE_PORT_AWARE_PARAM, null);
- boolean needPortAwareCookies = (usePortStr == null) ? false: Boolean.parseBoolean(usePortStr);
-
- if (!needPortAwareCookies || !coreContainer.isZooKeeperAware()) {
- putParam(params, "cookie.domain", COOKIE_DOMAIN_PARAM, null);
- } else { // we need port aware cookies and we are in SolrCloud mode.
- String host = System.getProperty(COOKIE_DOMAIN_PARAM, null);
- if (host==null) {
- throw new SolrException(ErrorCode.SERVER_ERROR, "Missing required parameter '"+COOKIE_DOMAIN_PARAM+"'.");
- }
- int port = controller.getHostPort();
- params.put("cookie.domain", host + ":" + port);
+ // Special handling for the "cookie.domain" based on whether port should be
+ // appended to the domain. Useful for situations where multiple solr nodes are
+ // on the same host.
+ String usePortStr = System.getProperty(COOKIE_PORT_AWARE_PARAM, null);
+ boolean needPortAwareCookies = (usePortStr == null) ? false: Boolean.parseBoolean(usePortStr);
+
+ if (!needPortAwareCookies || !coreContainer.isZooKeeperAware()) {
+ putParam(params, "cookie.domain", COOKIE_DOMAIN_PARAM, null);
+ } else { // we need port aware cookies and we are in SolrCloud mode.
+ String host = System.getProperty(COOKIE_DOMAIN_PARAM, null);
+ if (host==null) {
+ throw new SolrException(ErrorCode.SERVER_ERROR, "Missing required parameter '"+COOKIE_DOMAIN_PARAM+"'.");
}
+ int port = controller.getHostPort();
+ params.put("cookie.domain", host + ":" + port);
+ }
- final ServletContext servletContext = new AttributeOnlyServletContext();
- if (delegationTokenEnabled) {
- kerberosFilter = new DelegationTokenKerberosFilter();
- // pass an attribute-enabled context in order to pass the zkClient
- // and because the filter may pass a curator instance.
- if (controller != null) {
- servletContext.setAttribute(DELEGATION_TOKEN_ZK_CLIENT, controller.getZkClient());
+ // check impersonator config
+ for (Enumeration e = System.getProperties().propertyNames(); e.hasMoreElements();) {
+ String key = e.nextElement().toString();
+ if (key.startsWith(IMPERSONATOR_PREFIX)) {
+ if (!delegationTokenEnabled) {
+ throw new SolrException(ErrorCode.SERVER_ERROR,
+ "Impersonator configuration requires delegation tokens to be enabled: " + key);
}
- } else {
- kerberosFilter = new KerberosFilter();
+ params.put(key, System.getProperty(key));
}
- log.info("Params: "+params);
+ }
+ final ServletContext servletContext = new AttributeOnlyServletContext();
+ if (controller != null) {
+ servletContext.setAttribute(DELEGATION_TOKEN_ZK_CLIENT, controller.getZkClient());
+ }
+ if (delegationTokenEnabled) {
+ kerberosFilter = new DelegationTokenKerberosFilter();
+ // pass an attribute-enabled context in order to pass the zkClient
+ // and because the filter may pass a curator instance.
+ } else {
+ kerberosFilter = new KerberosFilter();
+ }
+ log.info("Params: "+params);
- FilterConfig conf = new FilterConfig() {
- @Override
- public ServletContext getServletContext() {
- return servletContext;
- }
+ FilterConfig conf = new FilterConfig() {
+ @Override
+ public ServletContext getServletContext() {
+ return servletContext;
+ }
- @Override
- public Enumeration<String> getInitParameterNames() {
- return new IteratorEnumeration(params.keySet().iterator());
- }
+ @Override
+ public Enumeration<String> getInitParameterNames() {
+ return new IteratorEnumeration(params.keySet().iterator());
+ }
- @Override
- public String getInitParameter(String param) {
- return params.get(param);
- }
+ @Override
+ public String getInitParameter(String param) {
+ return params.get(param);
+ }
- @Override
- public String getFilterName() {
- return "KerberosFilter";
- }
- };
+ @Override
+ public String getFilterName() {
+ return "KerberosFilter";
+ }
+ };
- kerberosFilter.init(conf);
- } catch (ServletException e) {
- throw new SolrException(ErrorCode.SERVER_ERROR, "Error initializing kerberos authentication plugin: "+e);
- }
+ return conf;
}
private void putParam(Map<String, String> params, String internalParamName, String externalParamName, String defaultValue) {
@@ -260,10 +282,15 @@ public class KerberosPlugin extends AuthenticationPlugin implements HttpClientIn
return kerberosConfigurer;
}
+ @Override
public void close() {
kerberosFilter.destroy();
}
+ protected Filter getKerberosFilter() { return kerberosFilter; }
+
+ protected void setKerberosFilter(Filter kerberosFilter) { this.kerberosFilter = kerberosFilter; }
+
protected static class AttributeOnlyServletContext implements ServletContext {
private Map<String, Object> attributes = new HashMap<String, Object>();
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f78f698a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithDelegationTokens.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithDelegationTokens.java b/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithDelegationTokens.java
index 364f004..053cea8 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithDelegationTokens.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithDelegationTokens.java
@@ -33,10 +33,10 @@ import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.cloud.SolrZkClient;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.params.ModifiableSolrParams;
-import static org.apache.solr.security.HttpParamDelegationTokenAuthenticationHandler.USER_PARAM;
+import static org.apache.solr.security.HttpParamDelegationTokenPlugin.USER_PARAM;
import org.apache.http.HttpStatus;
-import org.apache.solr.security.HttpParamDelegationTokenAuthenticationHandler;
+import org.apache.solr.security.HttpParamDelegationTokenPlugin;
import org.apache.solr.security.KerberosPlugin;
import org.junit.AfterClass;
import org.junit.BeforeClass;
@@ -63,10 +63,8 @@ public class TestSolrCloudWithDelegationTokens extends SolrTestCaseJ4 {
@BeforeClass
public static void startup() throws Exception {
- System.setProperty("authenticationPlugin", KerberosPlugin.class.getName());
+ System.setProperty("authenticationPlugin", HttpParamDelegationTokenPlugin.class.getName());
System.setProperty(KerberosPlugin.DELEGATION_TOKEN_ENABLED, "true");
- System.setProperty(KerberosPlugin.AUTH_HANDLER_PARAM,
- HttpParamDelegationTokenAuthenticationHandler.class.getName());
System.setProperty("solr.kerberos.cookie.domain", "127.0.0.1");
miniCluster = new MiniSolrCloudCluster(NUM_SERVERS, createTempDir(), buildJettyConfig("/solr"));
@@ -92,7 +90,6 @@ public class TestSolrCloudWithDelegationTokens extends SolrTestCaseJ4 {
solrClientSecondary = null;
System.clearProperty("authenticationPlugin");
System.clearProperty(KerberosPlugin.DELEGATION_TOKEN_ENABLED);
- System.clearProperty(KerberosPlugin.AUTH_HANDLER_PARAM);
System.clearProperty("solr.kerberos.cookie.domain");
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f78f698a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java b/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
new file mode 100644
index 0000000..1839d32
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
@@ -0,0 +1,340 @@
+/*
+ * 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.cloud;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.client.solrj.SolrClient;
+import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.embedded.JettySolrRunner;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.response.CollectionAdminResponse;
+import org.apache.solr.common.cloud.ZkStateReader;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.handler.admin.CollectionsHandler;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.security.HttpParamDelegationTokenPlugin;
+import org.apache.solr.security.KerberosPlugin;
+import org.apache.solr.servlet.SolrRequestParsers;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.apache.solr.security.HttpParamDelegationTokenPlugin.USER_PARAM;
+import static org.apache.solr.security.HttpParamDelegationTokenPlugin.REMOTE_HOST_PARAM;
+import static org.apache.solr.security.HttpParamDelegationTokenPlugin.REMOTE_ADDRESS_PARAM;
+
+public class TestSolrCloudWithSecureImpersonation extends SolrTestCaseJ4 {
+ private static final int NUM_SERVERS = 2;
+ private static MiniSolrCloudCluster miniCluster;
+ private static SolrClient solrClient;
+
+ private static String getUsersFirstGroup() throws Exception {
+ org.apache.hadoop.security.Groups hGroups =
+ new org.apache.hadoop.security.Groups(new Configuration());
+ List<String> g = hGroups.getGroups(System.getProperty("user.name"));
+ return g.get(0);
+ }
+
+ private static Map<String, String> getImpersonatorSettings() throws Exception {
+ Map<String, String> filterProps = new TreeMap<String, String>();
+ filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "noGroups.hosts", "*");
+ filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "anyHostAnyUser.groups", "*");
+ filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "anyHostAnyUser.hosts", "*");
+ filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "wrongHost.hosts", "1.1.1.1.1.1");
+ filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "wrongHost.groups", "*");
+ filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "noHosts.groups", "*");
+ filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "localHostAnyGroup.groups", "*");
+ filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "localHostAnyGroup.hosts", "127.0.0.1");
+ filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "anyHostUsersGroup.groups", getUsersFirstGroup());
+ filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "anyHostUsersGroup.hosts", "*");
+ filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "bogusGroup.groups", "__some_bogus_group");
+ filterProps.put(KerberosPlugin.IMPERSONATOR_PREFIX + "bogusGroup.hosts", "*");
+ return filterProps;
+ }
+
+ @BeforeClass
+ public static void startup() throws Exception {
+ System.setProperty("authenticationPlugin", HttpParamDelegationTokenPlugin.class.getName());
+ System.setProperty(KerberosPlugin.DELEGATION_TOKEN_ENABLED, "true");
+
+ System.setProperty("solr.kerberos.cookie.domain", "127.0.0.1");
+ Map<String, String> impSettings = getImpersonatorSettings();
+ for (Map.Entry<String, String> entry : impSettings.entrySet()) {
+ System.setProperty(entry.getKey(), entry.getValue());
+ }
+ System.setProperty("solr.test.sys.prop1", "propone");
+ System.setProperty("solr.test.sys.prop2", "proptwo");
+
+ SolrRequestParsers.DEFAULT.setAddRequestHeadersToContext(true);
+ String solrXml = MiniSolrCloudCluster.DEFAULT_CLOUD_SOLR_XML.replace("</solr>",
+ " <str name=\"collectionsHandler\">" + ImpersonatorCollectionsHandler.class.getName() + "</str>\n" +
+ "</solr>");
+
+ miniCluster = new MiniSolrCloudCluster(NUM_SERVERS, createTempDir(), solrXml, buildJettyConfig("/solr"));
+ JettySolrRunner runner = miniCluster.getJettySolrRunners().get(0);
+ solrClient = new HttpSolrClient.Builder(runner.getBaseUrl().toString()).build();
+ }
+
+ /**
+ * Verify that impersonator info is preserved in the request
+ */
+ public static class ImpersonatorCollectionsHandler extends CollectionsHandler {
+ public static AtomicBoolean called = new AtomicBoolean(false);
+
+ public ImpersonatorCollectionsHandler() { super(); }
+
+ public ImpersonatorCollectionsHandler(final CoreContainer coreContainer) {
+ super(coreContainer);
+ }
+
+ @Override
+ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
+ called.set(true);
+ super.handleRequestBody(req, rsp);
+ String doAs = req.getParams().get(KerberosPlugin.IMPERSONATOR_DO_AS_HTTP_PARAM);
+ if (doAs != null) {
+ HttpServletRequest httpRequest = (HttpServletRequest)req.getContext().get("httpRequest");
+ assertNotNull(httpRequest);
+ String user = (String)httpRequest.getAttribute(USER_PARAM);
+ assertNotNull(user);
+ assertEquals(user, httpRequest.getAttribute(KerberosPlugin.IMPERSONATOR_USER_NAME));
+ }
+ }
+ }
+
+ @AfterClass
+ public static void shutdown() throws Exception {
+ if (miniCluster != null) {
+ miniCluster.shutdown();
+ }
+ miniCluster = null;
+ solrClient.close();
+ solrClient = null;
+ System.clearProperty("authenticationPlugin");
+ System.clearProperty(KerberosPlugin.DELEGATION_TOKEN_ENABLED);
+ System.clearProperty("solr.kerberos.cookie.domain");
+ Map<String, String> impSettings = getImpersonatorSettings();
+ for (Map.Entry<String, String> entry : impSettings.entrySet()) {
+ System.clearProperty(entry.getKey());
+ }
+ System.clearProperty("solr.test.sys.prop1");
+ System.clearProperty("solr.test.sys.prop2");
+ SolrRequestParsers.DEFAULT.setAddRequestHeadersToContext(false);
+ }
+
+ private void create1ShardCollection(String name, String config, MiniSolrCloudCluster solrCluster) throws Exception {
+ CollectionAdminResponse response;
+ CollectionAdminRequest.Create create = new CollectionAdminRequest.Create() {
+ @Override
+ public SolrParams getParams() {
+ ModifiableSolrParams msp = new ModifiableSolrParams(super.getParams());
+ msp.set(USER_PARAM, "user");
+ return msp;
+ }
+ };
+ create.setConfigName(config);
+ create.setCollectionName(name);
+ create.setNumShards(1);
+ create.setReplicationFactor(1);
+ create.setMaxShardsPerNode(1);
+ response = create.process(solrCluster.getSolrClient());
+
+ if (response.getStatus() != 0 || response.getErrorMessages() != null) {
+ fail("Could not create collection. Response" + response.toString());
+ }
+ ZkStateReader zkStateReader = solrCluster.getSolrClient().getZkStateReader();
+ AbstractDistribZkTestBase.waitForRecoveriesToFinish(name, zkStateReader, false, true, 100);
+ }
+
+ private SolrRequest getProxyRequest(String user, String doAs) {
+ return getProxyRequest(user, doAs, null);
+ }
+
+ private SolrRequest getProxyRequest(String user, String doAs, String remoteHost) {
+ return getProxyRequest(user, doAs, remoteHost, null);
+ }
+
+ private SolrRequest getProxyRequest(String user, String doAs, String remoteHost, String remoteAddress) {
+ return new CollectionAdminRequest.List() {
+ @Override
+ public SolrParams getParams() {
+ ModifiableSolrParams params = new ModifiableSolrParams(super.getParams());
+ params.set(USER_PARAM, user);
+ params.set(KerberosPlugin.IMPERSONATOR_DO_AS_HTTP_PARAM, doAs);
+ if (remoteHost != null) params.set(REMOTE_HOST_PARAM, remoteHost);
+ if (remoteAddress != null) params.set(REMOTE_ADDRESS_PARAM, remoteAddress);
+ return params;
+ }
+ };
+ }
+
+ private String getExpectedGroupExMsg(String user, String doAs) {
+ return "User: " + user + " is not allowed to impersonate " + doAs;
+ }
+
+ private String getExpectedHostExMsg(String user) {
+ return "Unauthorized connection for super-user: " + user;
+ }
+
+ @Test
+ public void testProxyNoConfigGroups() throws Exception {
+ try {
+ solrClient.request(getProxyRequest("noGroups","bar"));
+ fail("Expected RemoteSolrException");
+ }
+ catch (HttpSolrClient.RemoteSolrException ex) {
+ assertTrue(ex.getMessage().contains(getExpectedGroupExMsg("noGroups", "bar")));
+ }
+ }
+
+ @Test
+ public void testProxyWrongHost() throws Exception {
+ try {
+ solrClient.request(getProxyRequest("wrongHost","bar"));
+ fail("Expected RemoteSolrException");
+ }
+ catch (HttpSolrClient.RemoteSolrException ex) {
+ assertTrue(ex.getMessage().contains(getExpectedHostExMsg("wrongHost")));
+ }
+ }
+
+ @Test
+ public void testProxyNoConfigHosts() throws Exception {
+ try {
+ solrClient.request(getProxyRequest("noHosts","bar"));
+ fail("Expected RemoteSolrException");
+ }
+ catch (HttpSolrClient.RemoteSolrException ex) {
+ // FixMe: this should return an exception about the host being invalid,
+ // but a bug (HADOOP-11077) causes an NPE instead.
+ //assertTrue(ex.getMessage().contains(getExpectedHostExMsg("noHosts")));
+ }
+ }
+
+ @Test
+ public void testProxyValidateAnyHostAnyUser() throws Exception {
+ solrClient.request(getProxyRequest("anyHostAnyUser", "bar", null));
+ assertTrue(ImpersonatorCollectionsHandler.called.get());
+ }
+
+ @Test
+ public void testProxyInvalidProxyUser() throws Exception {
+ try {
+ // wrong direction, should fail
+ solrClient.request(getProxyRequest("bar","anyHostAnyUser"));
+ fail("Expected RemoteSolrException");
+ }
+ catch (HttpSolrClient.RemoteSolrException ex) {
+ assertTrue(ex.getMessage().contains(getExpectedGroupExMsg("bar", "anyHostAnyUser")));
+ }
+ }
+
+ @Test
+ public void testProxyValidateHost() throws Exception {
+ solrClient.request(getProxyRequest("localHostAnyGroup", "bar"));
+ assertTrue(ImpersonatorCollectionsHandler.called.get());
+ }
+
+
+
+ @Test
+ public void testProxyValidateGroup() throws Exception {
+ solrClient.request(getProxyRequest("anyHostUsersGroup", System.getProperty("user.name"), null));
+ assertTrue(ImpersonatorCollectionsHandler.called.get());
+ }
+
+ @Test
+ public void testProxyUnknownRemote() throws Exception {
+ try {
+ // Use a reserved ip address
+ String nonProxyUserConfiguredIpAddress = "255.255.255.255";
+ solrClient.request(getProxyRequest("localHostAnyGroup", "bar", "unknownhost.bar.foo", nonProxyUserConfiguredIpAddress));
+ fail("Expected RemoteSolrException");
+ }
+ catch (HttpSolrClient.RemoteSolrException ex) {
+ assertTrue(ex.getMessage().contains(getExpectedHostExMsg("localHostAnyGroup")));
+ }
+ }
+
+ @Test
+ public void testProxyInvalidRemote() throws Exception {
+ try {
+ String invalidIpAddress = "-127.-128";
+ solrClient.request(getProxyRequest("localHostAnyGroup","bar", "[ff01::114]", invalidIpAddress));
+ fail("Expected RemoteSolrException");
+ }
+ catch (HttpSolrClient.RemoteSolrException ex) {
+ assertTrue(ex.getMessage().contains(getExpectedHostExMsg("localHostAnyGroup")));
+ }
+ }
+
+ @Test
+ public void testProxyInvalidGroup() throws Exception {
+ try {
+ solrClient.request(getProxyRequest("bogusGroup","bar", null));
+ fail("Expected RemoteSolrException");
+ }
+ catch (HttpSolrClient.RemoteSolrException ex) {
+ assertTrue(ex.getMessage().contains(getExpectedGroupExMsg("bogusGroup", "bar")));
+ }
+ }
+
+ @Test
+ public void testProxyNullProxyUser() throws Exception {
+ try {
+ solrClient.request(getProxyRequest("","bar"));
+ fail("Expected RemoteSolrException");
+ }
+ catch (HttpSolrClient.RemoteSolrException ex) {
+ // this exception is specific to our implementation, don't check a specific message.
+ }
+ }
+
+ @Test
+ public void testForwarding() throws Exception {
+ String collectionName = "forwardingCollection";
+ File configDir = getFile("solr").toPath().resolve("collection1/conf").toFile();
+ miniCluster.uploadConfigDir(configDir, "conf1");
+ create1ShardCollection(collectionName, "conf1", miniCluster);
+
+ // try a command to each node, one of them must be forwarded
+ for (JettySolrRunner jetty : miniCluster.getJettySolrRunners()) {
+ HttpSolrClient client =
+ new HttpSolrClient.Builder(jetty.getBaseUrl().toString() + "/" + collectionName).build();
+ try {
+ ModifiableSolrParams params = new ModifiableSolrParams();
+ params.set("q", "*:*");
+ params.set(USER_PARAM, "user");
+ client.query(params);
+ } finally {
+ client.close();
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f78f698a/solr/core/src/test/org/apache/solr/security/HttpParamDelegationTokenAuthenticationHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/security/HttpParamDelegationTokenAuthenticationHandler.java b/solr/core/src/test/org/apache/solr/security/HttpParamDelegationTokenAuthenticationHandler.java
deleted file mode 100644
index 7c5c94a..0000000
--- a/solr/core/src/test/org/apache/solr/security/HttpParamDelegationTokenAuthenticationHandler.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * 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.security;
-
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.hadoop.security.authentication.client.AuthenticationException;
-import org.apache.hadoop.security.authentication.server.AuthenticationHandler;
-import org.apache.hadoop.security.authentication.server.AuthenticationToken;
-import org.apache.hadoop.security.token.delegation.web.DelegationTokenAuthenticationHandler;
-
-import org.apache.http.NameValuePair;
-import org.apache.http.client.utils.URLEncodedUtils;
-
-/**
- * AuthenticationHandler that supports delegation tokens and simple
- * authentication via the "user" http parameter
- */
-public class HttpParamDelegationTokenAuthenticationHandler extends
- DelegationTokenAuthenticationHandler {
-
- public static final String USER_PARAM = "user";
-
- public HttpParamDelegationTokenAuthenticationHandler() {
- super(new HttpParamAuthenticationHandler());
- }
-
- @Override
- public void init(Properties config) throws ServletException {
- Properties conf = new Properties();
- for (Map.Entry entry : config.entrySet()) {
- conf.setProperty((String) entry.getKey(), (String) entry.getValue());
- }
- conf.setProperty(TOKEN_KIND, KerberosPlugin.DELEGATION_TOKEN_TYPE_DEFAULT);
- super.init(conf);
- }
-
- private static String getHttpParam(HttpServletRequest request, String param) {
- List<NameValuePair> pairs =
- URLEncodedUtils.parse(request.getQueryString(), Charset.forName("UTF-8"));
- for (NameValuePair nvp : pairs) {
- if(param.equals(nvp.getName())) {
- return nvp.getValue();
- }
- }
- return null;
- }
-
- private static class HttpParamAuthenticationHandler
- implements AuthenticationHandler {
-
- @Override
- public String getType() {
- return "dummy";
- }
-
- @Override
- public void init(Properties config) throws ServletException {
- }
-
- @Override
- public void destroy() {
- }
-
- @Override
- public boolean managementOperation(AuthenticationToken token,
- HttpServletRequest request, HttpServletResponse response)
- throws IOException, AuthenticationException {
- return false;
- }
-
- @Override
- public AuthenticationToken authenticate(HttpServletRequest request,
- HttpServletResponse response)
- throws IOException, AuthenticationException {
- AuthenticationToken token = null;
- String userName = getHttpParam(request, USER_PARAM);
- if (userName != null) {
- return new AuthenticationToken(userName, userName, "test");
- } else {
- response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
- response.setHeader("WWW-Authenticate", "dummy");
- }
- return token;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f78f698a/solr/core/src/test/org/apache/solr/security/HttpParamDelegationTokenPlugin.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/security/HttpParamDelegationTokenPlugin.java b/solr/core/src/test/org/apache/solr/security/HttpParamDelegationTokenPlugin.java
new file mode 100644
index 0000000..7a4f69f
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/security/HttpParamDelegationTokenPlugin.java
@@ -0,0 +1,272 @@
+/*
+ * 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.security;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.security.Principal;
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.hadoop.security.authentication.client.AuthenticationException;
+import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
+import org.apache.hadoop.security.authentication.server.AuthenticationHandler;
+import org.apache.hadoop.security.authentication.server.AuthenticationToken;
+import org.apache.hadoop.security.token.delegation.web.DelegationTokenAuthenticationHandler;
+
+import org.apache.http.HttpException;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpRequestInterceptor;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.utils.URLEncodedUtils;
+import org.apache.http.protocol.HttpContext;
+import org.apache.solr.client.solrj.impl.HttpClientUtil;
+import org.apache.solr.client.solrj.impl.SolrHttpClientBuilder;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.util.ExecutorUtil;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.request.SolrRequestInfo;
+
+/**
+ * AuthenticationHandler that supports delegation tokens and simple
+ * authentication via the "user" http parameter
+ */
+public class HttpParamDelegationTokenPlugin extends KerberosPlugin {
+ public static final String USER_PARAM = "user"; // http parameter for user authentication
+ public static final String REMOTE_HOST_PARAM = "remoteHost"; // http parameter for indicating remote host
+ public static final String REMOTE_ADDRESS_PARAM = "remoteAddress"; // http parameter for indicating remote address
+ public static final String INTERNAL_REQUEST_HEADER = "internalRequest"; // http header for indicating internal request
+
+ boolean isSolrThread() {
+ return ExecutorUtil.isSolrServerThread();
+ }
+
+ private final HttpRequestInterceptor interceptor = new HttpRequestInterceptor() {
+ @Override
+ public void process(HttpRequest httpRequest, HttpContext httpContext) throws HttpException, IOException {
+ SolrRequestInfo reqInfo = SolrRequestInfo.getRequestInfo();
+ String usr;
+ if (reqInfo != null) {
+ Principal principal = reqInfo.getReq().getUserPrincipal();
+ if (principal == null) {
+ //this had a request but not authenticated
+ //so we don't not need to set a principal
+ return;
+ } else {
+ usr = principal.getName();
+ }
+ } else {
+ if (!isSolrThread()) {
+ //if this is not running inside a Solr threadpool (as in testcases)
+ // then no need to add any header
+ return;
+ }
+ //this request seems to be originated from Solr itself
+ usr = "$"; //special name to denote the user is the node itself
+ }
+ httpRequest.setHeader(INTERNAL_REQUEST_HEADER, usr);
+ }
+ };
+
+ public HttpParamDelegationTokenPlugin(CoreContainer coreContainer) {
+ super(coreContainer);
+ }
+
+ @Override
+ public void init(Map<String, Object> pluginConfig) {
+ try {
+ final FilterConfig initConf = getInitFilterConfig(pluginConfig, true);
+
+ FilterConfig conf = new FilterConfig() {
+ @Override
+ public ServletContext getServletContext() {
+ return initConf.getServletContext();
+ }
+
+ @Override
+ public Enumeration<String> getInitParameterNames() {
+ return initConf.getInitParameterNames();
+ }
+
+ @Override
+ public String getInitParameter(String param) {
+ if (AuthenticationFilter.AUTH_TYPE.equals(param)) {
+ return HttpParamDelegationTokenAuthenticationHandler.class.getName();
+ }
+ return initConf.getInitParameter(param);
+ }
+
+ @Override
+ public String getFilterName() {
+ return "HttpParamFilter";
+ }
+ };
+ Filter kerberosFilter = new HttpParamToRequestFilter();
+ kerberosFilter.init(conf);
+ setKerberosFilter(kerberosFilter);
+ } catch (ServletException e) {
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
+ "Error initializing kerberos authentication plugin: "+e);
+ }
+ }
+
+ @Override
+ public SolrHttpClientBuilder getHttpClientBuilder(SolrHttpClientBuilder builder) {
+ HttpClientUtil.addRequestInterceptor(interceptor);
+ return super.getHttpClientBuilder(builder);
+ }
+
+ @Override
+ public void close() {
+ HttpClientUtil.removeRequestInterceptor(interceptor);
+ super.close();
+ }
+
+ private static String getHttpParam(HttpServletRequest request, String param) {
+ List<NameValuePair> pairs = URLEncodedUtils.parse(request.getQueryString(), Charset.forName("UTF-8"));
+ for (NameValuePair nvp : pairs) {
+ if (param.equals(nvp.getName())) {
+ return nvp.getValue();
+ }
+ }
+ return null;
+ }
+
+ public static class HttpParamDelegationTokenAuthenticationHandler extends
+ DelegationTokenAuthenticationHandler {
+
+ public HttpParamDelegationTokenAuthenticationHandler() {
+ super(new HttpParamAuthenticationHandler());
+ }
+
+ @Override
+ public void init(Properties config) throws ServletException {
+ Properties conf = new Properties();
+ for (Map.Entry entry : config.entrySet()) {
+ conf.setProperty((String) entry.getKey(), (String) entry.getValue());
+ }
+ conf.setProperty(TOKEN_KIND, KerberosPlugin.DELEGATION_TOKEN_TYPE_DEFAULT);
+ super.init(conf);
+ }
+
+ private static class HttpParamAuthenticationHandler implements AuthenticationHandler {
+ @Override
+ public String getType() {
+ return "dummy";
+ }
+
+ @Override
+ public void init(Properties config) throws ServletException {
+ }
+
+ @Override
+ public void destroy() {
+ }
+
+ @Override
+ public boolean managementOperation(AuthenticationToken token,
+ HttpServletRequest request, HttpServletResponse response)
+ throws IOException, AuthenticationException {
+ return false;
+ }
+
+ @Override
+ public AuthenticationToken authenticate(HttpServletRequest request,
+ HttpServletResponse response)
+ throws IOException, AuthenticationException {
+ AuthenticationToken token = null;
+ String userName = getHttpParam(request, USER_PARAM);
+ if (userName == null) {
+ //check if this is an internal request
+ userName = request.getHeader(INTERNAL_REQUEST_HEADER);
+ }
+ if (userName != null) {
+ return new AuthenticationToken(userName, userName, "test");
+ } else {
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ response.setHeader("WWW-Authenticate", "dummy");
+ }
+ return token;
+ }
+ }
+ }
+
+ /**
+ * Filter that converts http params to HttpServletRequest params
+ */
+ private static class HttpParamToRequestFilter extends DelegationTokenKerberosFilter {
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ final HttpServletRequest httpRequest = (HttpServletRequest) request;
+ final HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(httpRequest) {
+ @Override
+ public String getRemoteHost() {
+ String param = getHttpParam(httpRequest, REMOTE_HOST_PARAM);
+ return param != null ? param : httpRequest.getRemoteHost();
+ }
+
+ @Override
+ public String getRemoteAddr() {
+ String param = getHttpParam(httpRequest, REMOTE_ADDRESS_PARAM);
+ return param != null ? param : httpRequest.getRemoteAddr();
+ }
+ };
+
+ super.doFilter(requestWrapper, response, chain);
+ }
+
+ @Override
+ protected void doFilter(FilterChain filterChain, HttpServletRequest request,
+ HttpServletResponse response) throws IOException, ServletException {
+ // remove the filter-specific authentication information, so it doesn't get accidentally forwarded.
+ List<NameValuePair> newPairs = new LinkedList<NameValuePair>();
+ List<NameValuePair> pairs = URLEncodedUtils.parse(request.getQueryString(), Charset.forName("UTF-8"));
+ for (NameValuePair nvp : pairs) {
+ if (!USER_PARAM.equals(nvp.getName())) {
+ newPairs.add(nvp);
+ }
+ else {
+ request.setAttribute(USER_PARAM, nvp.getValue());
+ }
+ }
+ final String queryStringNoUser = URLEncodedUtils.format(newPairs, StandardCharsets.UTF_8);
+ HttpServletRequest requestWrapper = new HttpServletRequestWrapper(request) {
+ @Override
+ public String getQueryString() {
+ return queryStringNoUser;
+ }
+ };
+ super.doFilter(filterChain, requestWrapper, response);
+ }
+ }
+}
[5/5] lucene-solr:branch_6x: SOLR-9324 Fix
TestSolrCloudWithSecureImpersonation#testForwarding
Posted by yo...@apache.org.
SOLR-9324 Fix TestSolrCloudWithSecureImpersonation#testForwarding
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/f084e658
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/f084e658
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/f084e658
Branch: refs/heads/branch_6x
Commit: f084e658b77e1ec98021146318cc37772b73de51
Parents: 6428772
Author: Hrishikesh Gadre <hg...@cloudera.com>
Authored: Tue Nov 15 16:32:21 2016 -0800
Committer: yonik <yo...@apache.org>
Committed: Thu Nov 17 15:05:47 2016 -0500
----------------------------------------------------------------------
.../cloud/TestSolrCloudWithSecureImpersonation.java | 2 +-
.../security/HttpParamDelegationTokenPlugin.java | 15 +++++++++++----
2 files changed, 12 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f084e658/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java b/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
index ef41e4d..8d7a1a6 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
@@ -343,7 +343,7 @@ public class TestSolrCloudWithSecureImpersonation extends SolrTestCaseJ4 {
@Test
public void testForwarding() throws Exception {
String collectionName = "forwardingCollection";
- File configDir = getFile("solr").toPath().resolve("collection1/conf").toFile();
+ File configDir = TEST_PATH().resolve("collection1/conf").toFile();
miniCluster.uploadConfigDir(configDir, "conf1");
create1ShardCollection(collectionName, "conf1", miniCluster);
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f084e658/solr/core/src/test/org/apache/solr/security/HttpParamDelegationTokenPlugin.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/security/HttpParamDelegationTokenPlugin.java b/solr/core/src/test/org/apache/solr/security/HttpParamDelegationTokenPlugin.java
index 7a4f69f..42d99a2 100644
--- a/solr/core/src/test/org/apache/solr/security/HttpParamDelegationTokenPlugin.java
+++ b/solr/core/src/test/org/apache/solr/security/HttpParamDelegationTokenPlugin.java
@@ -49,8 +49,9 @@ import org.apache.http.HttpRequestInterceptor;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.protocol.HttpContext;
+import org.apache.solr.client.solrj.impl.HttpClientConfigurer;
import org.apache.solr.client.solrj.impl.HttpClientUtil;
-import org.apache.solr.client.solrj.impl.SolrHttpClientBuilder;
+import org.apache.solr.client.solrj.impl.Krb5HttpClientConfigurer;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.core.CoreContainer;
@@ -97,6 +98,13 @@ public class HttpParamDelegationTokenPlugin extends KerberosPlugin {
}
};
+ private final HttpClientConfigurer configurer = new Krb5HttpClientConfigurer() {
+ public void configure(org.apache.http.impl.client.DefaultHttpClient httpClient, org.apache.solr.common.params.SolrParams config) {
+ super.configure(httpClient, config);
+ httpClient.addRequestInterceptor(interceptor);
+ };
+ };
+
public HttpParamDelegationTokenPlugin(CoreContainer coreContainer) {
super(coreContainer);
}
@@ -140,9 +148,8 @@ public class HttpParamDelegationTokenPlugin extends KerberosPlugin {
}
@Override
- public SolrHttpClientBuilder getHttpClientBuilder(SolrHttpClientBuilder builder) {
- HttpClientUtil.addRequestInterceptor(interceptor);
- return super.getHttpClientBuilder(builder);
+ public HttpClientConfigurer getClientConfigurer() {
+ return configurer;
}
@Override
[2/5] lucene-solr:branch_6x: SOLR-9460: Disable test that does not
work with Windows
Posted by yo...@apache.org.
SOLR-9460: Disable test that does not work with Windows
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/225198a2
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/225198a2
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/225198a2
Branch: refs/heads/branch_6x
Commit: 225198a2b754783d485b2cee7d1aa4741f65e5a3
Parents: 8659fe1
Author: Uwe Schindler <us...@apache.org>
Authored: Sat Sep 3 10:48:01 2016 +0200
Committer: yonik <yo...@apache.org>
Committed: Thu Nov 17 15:05:46 2016 -0500
----------------------------------------------------------------------
.../apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java | 3 +++
1 file changed, 3 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/225198a2/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java b/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
index 71107ee..3727620 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithSecureImpersonation.java
@@ -25,6 +25,7 @@ import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.hadoop.conf.Configuration;
+import org.apache.lucene.util.Constants;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrRequest;
@@ -92,6 +93,8 @@ public class TestSolrCloudWithSecureImpersonation extends SolrTestCaseJ4 {
@BeforeClass
public static void startup() throws Exception {
+ assumeFalse("Hadoop does not work on Windows", Constants.WINDOWS);
+
System.setProperty("authenticationPlugin", HttpParamDelegationTokenPlugin.class.getName());
System.setProperty(KerberosPlugin.DELEGATION_TOKEN_ENABLED, "true");