Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 4A574200C16 for ; Thu, 9 Feb 2017 21:09:29 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 48E72160B4B; Thu, 9 Feb 2017 20:09:29 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id D1F38160B50 for ; Thu, 9 Feb 2017 21:09:27 +0100 (CET) Received: (qmail 42162 invoked by uid 500); 9 Feb 2017 20:09:21 -0000 Mailing-List: contact commits-help@lucene.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@lucene.apache.org Delivered-To: mailing list commits@lucene.apache.org Received: (qmail 39048 invoked by uid 99); 9 Feb 2017 20:09:19 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 09 Feb 2017 20:09:19 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id B1E24DFEEA; Thu, 9 Feb 2017 20:09:19 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: ab@apache.org To: commits@lucene.apache.org Date: Thu, 09 Feb 2017 20:09:57 -0000 Message-Id: <4b73ddeaf475413baf418047b4ffe309@git.apache.org> In-Reply-To: <9b0e05b8e5d946029493091ea69be581@git.apache.org> References: <9b0e05b8e5d946029493091ea69be581@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [40/50] lucene-solr:jira/solr-9858: SOLR-9997: Enable configuring SolrHttpClientBuilder via java system property. archived-at: Thu, 09 Feb 2017 20:09:29 -0000 SOLR-9997: Enable configuring SolrHttpClientBuilder via java system property. Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/e1a57764 Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/e1a57764 Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/e1a57764 Branch: refs/heads/jira/solr-9858 Commit: e1a577645756addc8ed060024e4af7ccd15c2321 Parents: 37b75be Author: markrmiller Authored: Tue Feb 7 13:15:51 2017 -0500 Committer: markrmiller Committed: Tue Feb 7 13:15:51 2017 -0500 ---------------------------------------------------------------------- solr/CHANGES.txt | 1 + solr/bin/solr | 31 ++++- solr/bin/solr.cmd | 37 +++++- solr/bin/solr.in.cmd | 4 +- solr/bin/solr.in.sh | 4 +- .../apache/solr/security/HadoopAuthPlugin.java | 37 ++++++ .../src/java/org/apache/solr/util/SolrCLI.java | 39 ------ .../solr/client/solrj/impl/HttpClientUtil.java | 37 ++++-- .../solrj/impl/Krb5HttpClientBuilder.java | 5 +- .../solr/client/solrj/impl/PreemptiveAuth.java | 59 +++++++++ ...PreemptiveBasicAuthClientBuilderFactory.java | 132 +++++++++++++++++++ 11 files changed, 330 insertions(+), 56 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/CHANGES.txt ---------------------------------------------------------------------- diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index a93bb00..96b06a6 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -128,6 +128,7 @@ New Features * SOLR-10087: StreamHandler now supports registering custom streaming expressions from the blob store (Kevin Risden) +* SOLR-9997: Enable configuring SolrHttpClientBuilder via java system property. (Hrishikesh Gadre via Mark Miller) Bug Fixes ---------------------- http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/bin/solr ---------------------------------------------------------------------- diff --git a/solr/bin/solr b/solr/bin/solr index cf9765d..cd9db0f 100755 --- a/solr/bin/solr +++ b/solr/bin/solr @@ -232,12 +232,39 @@ else fi # Authentication options +if [ -z "$SOLR_AUTH_TYPE" ] && [ -n "$SOLR_AUTHENTICATION_OPTS" ]; then + echo "WARNING: SOLR_AUTHENTICATION_OPTS environment variable configured without associated SOLR_AUTH_TYPE variable" + echo " Please configure SOLR_AUTH_TYPE environment variable with the authentication type to be used." + echo " Currently supported authentication types are [kerberos, basic]" +fi + +if [ -n "$SOLR_AUTH_TYPE" ] && [ -n "$SOLR_AUTHENTICATION_CLIENT_BUILDER" ]; then + echo "WARNING: SOLR_AUTHENTICATION_CLIENT_BUILDER and SOLR_AUTH_TYPE environment variables are configured together." + echo " Use SOLR_AUTH_TYPE environment variable to configure authentication type to be used. " + echo " Currently supported authentication types are [kerberos, basic]" + echo " The value of SOLR_AUTHENTICATION_CLIENT_BUILDER environment variable will be ignored" +fi + +if [ -n "$SOLR_AUTH_TYPE" ]; then + case "$(echo $SOLR_AUTH_TYPE | awk '{print tolower($0)}')" in + basic) + SOLR_AUTHENTICATION_CLIENT_BUILDER="org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory" + ;; + kerberos) + SOLR_AUTHENTICATION_CLIENT_BUILDER="org.apache.solr.client.solrj.impl.Krb5HttpClientBuilder" + ;; + *) + echo "ERROR: Value specified for SOLR_AUTH_TYPE environment variable is invalid." + exit 1 + esac +fi + if [ "$SOLR_AUTHENTICATION_CLIENT_CONFIGURER" != "" ]; then echo "WARNING: Found unsupported configuration variable SOLR_AUTHENTICATION_CLIENT_CONFIGURER" - echo " Please start using SOLR_AUTHENTICATION_CLIENT_BUILDER instead" + echo " Please start using SOLR_AUTH_TYPE instead" fi if [ "$SOLR_AUTHENTICATION_CLIENT_BUILDER" != "" ]; then - AUTHC_CLIENT_BUILDER_ARG="-Dsolr.authentication.httpclient.builder=$SOLR_AUTHENTICATION_CLIENT_BUILDER" + AUTHC_CLIENT_BUILDER_ARG="-Dsolr.httpclient.builder.factory=$SOLR_AUTHENTICATION_CLIENT_BUILDER" fi AUTHC_OPTS="$AUTHC_CLIENT_BUILDER_ARG $SOLR_AUTHENTICATION_OPTS" http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/bin/solr.cmd ---------------------------------------------------------------------- diff --git a/solr/bin/solr.cmd b/solr/bin/solr.cmd index 6cd0096..29422f3 100644 --- a/solr/bin/solr.cmd +++ b/solr/bin/solr.cmd @@ -117,12 +117,43 @@ IF DEFINED SOLR_SSL_KEY_STORE ( ) REM Authentication options + +IF NOT DEFINED SOLR_AUTH_TYPE ( + IF DEFINED SOLR_AUTHENTICATION_OPTS ( + echo WARNING: SOLR_AUTHENTICATION_OPTS variable configured without associated SOLR_AUTH_TYPE variable + echo Please configure SOLR_AUTH_TYPE variable with the authentication type to be used. + echo Currently supported authentication types are [kerberos, basic] + ) +) + +IF DEFINED SOLR_AUTH_TYPE ( + IF DEFINED SOLR_AUTHENTICATION_CLIENT_BUILDER ( + echo WARNING: SOLR_AUTHENTICATION_CLIENT_BUILDER and SOLR_AUTH_TYPE variables are configured together + echo Use SOLR_AUTH_TYPE variable to configure authentication type to be used + echo Currently supported authentication types are [kerberos, basic] + echo The value of SOLR_AUTHENTICATION_CLIENT_BUILDER configuration variable will be ignored + ) +) + +IF DEFINED SOLR_AUTH_TYPE ( + IF /I "%SOLR_AUTH_TYPE%" == "basic" ( + set SOLR_AUTHENTICATION_CLIENT_BUILDER="org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory" + ) ELSE ( + IF /I "%SOLR_AUTH_TYPE%" == "kerberos" ( + set SOLR_AUTHENTICATION_CLIENT_BUILDER="org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory" + ) ELSE ( + echo ERROR: Value specified for SOLR_AUTH_TYPE configuration variable is invalid. + goto err + ) + ) +) + IF DEFINED SOLR_AUTHENTICATION_CLIENT_CONFIGURER ( echo WARNING: Found unsupported configuration variable SOLR_AUTHENTICATION_CLIENT_CONFIGURER - echo Please start using SOLR_AUTHENTICATION_CLIENT_BUILDER instead + echo Please start using SOLR_AUTH_TYPE instead ) IF DEFINED SOLR_AUTHENTICATION_CLIENT_BUILDER ( - set AUTHC_CLIENT_BUILDER_ARG="-Dsolr.authentication.httpclient.builder=%SOLR_AUTHENTICATION_CLIENT_BUILDER%" + set AUTHC_CLIENT_BUILDER_ARG="-Dsolr.httpclient.builder.factory=%SOLR_AUTHENTICATION_CLIENT_BUILDER%" ) set "AUTHC_OPTS=%AUTHC_CLIENT_BUILDER_ARG% %SOLR_AUTHENTICATION_OPTS%" @@ -1154,7 +1185,7 @@ for /f "usebackq" %%i in (`dir /b "%SOLR_TIP%\bin" ^| findstr /i "^solr-.*\.port @echo. set has_info=1 echo Found Solr process %%k running on port !SOME_SOLR_PORT! - "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ -Dlog4j.configuration="file:%DEFAULT_SERVER_DIR%\scripts\cloud-scripts\log4j.properties" ^ -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ org.apache.solr.util.SolrCLI status -solr !SOLR_URL_SCHEME!://%SOLR_TOOL_HOST%:!SOME_SOLR_PORT!/solr http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/bin/solr.in.cmd ---------------------------------------------------------------------- diff --git a/solr/bin/solr.in.cmd b/solr/bin/solr.in.cmd index e565c02..279e03e 100644 --- a/solr/bin/solr.in.cmd +++ b/solr/bin/solr.in.cmd @@ -108,7 +108,9 @@ REM set SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD= REM set SOLR_SSL_CLIENT_TRUST_STORE_TYPE= REM Settings for authentication -REM set SOLR_AUTHENTICATION_CLIENT_BUILDER= +REM Please configure only one of SOLR_AUTHENTICATION_CLIENT_BUILDER or SOLR_AUTH_TYPE parameters +REM set SOLR_AUTHENTICATION_CLIENT_BUILDER=org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory +REM set SOLR_AUTH_TYPE=basic REM set SOLR_AUTHENTICATION_OPTS="-Dbasicauth=solr:SolrRocks" REM Settings for ZK ACL http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/bin/solr.in.sh ---------------------------------------------------------------------- diff --git a/solr/bin/solr.in.sh b/solr/bin/solr.in.sh index 5a9f807..878702f 100644 --- a/solr/bin/solr.in.sh +++ b/solr/bin/solr.in.sh @@ -120,7 +120,9 @@ #SOLR_SSL_CLIENT_TRUST_STORE_TYPE= # Settings for authentication -#SOLR_AUTHENTICATION_CLIENT_BUILDER= +# Please configure only one of SOLR_AUTHENTICATION_CLIENT_BUILDER or SOLR_AUTH_TYPE parameters +#SOLR_AUTHENTICATION_CLIENT_BUILDER="org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory" +#SOLR_AUTH_TYPE="basic" #SOLR_AUTHENTICATION_OPTS="-Dbasicauth=solr:SolrRocks" # Settings for ZK ACL http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/core/src/java/org/apache/solr/security/HadoopAuthPlugin.java ---------------------------------------------------------------------- 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 1f0d5ad..fa59d38 100644 --- a/solr/core/src/java/org/apache/solr/security/HadoopAuthPlugin.java +++ b/solr/core/src/java/org/apache/solr/security/HadoopAuthPlugin.java @@ -34,6 +34,7 @@ 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.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; @@ -112,6 +113,12 @@ public class HadoopAuthPlugin extends AuthenticationPlugin { */ public static final String PROXY_USER_CONFIGS = "proxyUserConfigs"; + /** + * This parameter is used to debug the authentication related issues during development. + * This should not be used in production. + */ + private static final boolean TRACE_HTTP = Boolean.getBoolean("hadoopauth.tracehttp"); + private AuthenticationFilter authFilter; protected final CoreContainer coreContainer; @@ -204,6 +211,23 @@ public class HadoopAuthPlugin extends AuthenticationPlugin { throws Exception { final HttpServletResponse frsp = (HttpServletResponse)response; + if (TRACE_HTTP) { + HttpServletRequest req = (HttpServletRequest) request; + log.info("----------HTTP Request---------"); + log.info("{} : {}", req.getMethod(), req.getRequestURI()); + log.info("Query : {}", req.getQueryString()); + log.info("Headers :"); + Enumeration headers = req.getHeaderNames(); + while (headers.hasMoreElements()) { + String name = headers.nextElement(); + Enumeration hvals = req.getHeaders(name); + while (hvals.hasMoreElements()) { + log.info("{} : {}", name, hvals.nextElement()); + } + } + log.info("-------------------------------"); + } + // Workaround until HADOOP-13346 is fixed. HttpServletResponse rspCloseShield = new HttpServletResponseWrapper(frsp) { @SuppressForbidden(reason = "Hadoop DelegationTokenAuthenticationFilter uses response writer, this" + @@ -219,6 +243,19 @@ public class HadoopAuthPlugin extends AuthenticationPlugin { }; authFilter.doFilter(request, rspCloseShield, filterChain); + if (TRACE_HTTP) { + log.info("----------HTTP Response---------"); + log.info("Status : {}", frsp.getStatus()); + log.info("Headers :"); + for (String name : frsp.getHeaderNames()) { + for (String value : frsp.getHeaders(name)) { + log.info("{} : {}", name, value); + } + } + log.info("-------------------------------"); + } + + if (authFilter instanceof HadoopAuthFilter) { // delegation token mgmt. String requestContinuesAttr = (String)request.getAttribute(REQUEST_CONTINUES_ATTR); if (requestContinuesAttr == null) { http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/core/src/java/org/apache/solr/util/SolrCLI.java ---------------------------------------------------------------------- diff --git a/solr/core/src/java/org/apache/solr/util/SolrCLI.java b/solr/core/src/java/org/apache/solr/util/SolrCLI.java index bb2d554..4f6cf8d 100644 --- a/solr/core/src/java/org/apache/solr/util/SolrCLI.java +++ b/solr/core/src/java/org/apache/solr/util/SolrCLI.java @@ -60,7 +60,6 @@ import org.apache.commons.cli.Option; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; -import org.apache.commons.codec.binary.Base64; import org.apache.commons.exec.DefaultExecuteResultHandler; import org.apache.commons.exec.DefaultExecutor; import org.apache.commons.exec.Executor; @@ -80,7 +79,6 @@ import org.apache.http.client.methods.HttpHead; import org.apache.http.client.utils.URIBuilder; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.message.BasicHeader; import org.apache.http.util.EntityUtils; import org.apache.lucene.util.Version; import org.apache.solr.client.solrj.SolrClient; @@ -90,7 +88,6 @@ import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.impl.HttpClientUtil; import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.client.solrj.impl.HttpSolrClient.Builder; -import org.apache.solr.client.solrj.impl.SolrHttpClientBuilder; import org.apache.solr.client.solrj.impl.ZkClientClusterStateProvider; import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest; import org.apache.solr.client.solrj.response.QueryResponse; @@ -106,7 +103,6 @@ import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.util.ContentStreamBase; import org.apache.solr.common.util.NamedList; -import org.apache.solr.common.util.StrUtils; import org.noggit.CharArr; import org.noggit.JSONParser; import org.noggit.JSONWriter; @@ -153,7 +149,6 @@ public class SolrCLI { int toolExitStatus = 0; try { - setBasicAuth(); runImpl(cli); } catch (Exception exc) { // since this is a CLI, spare the user the stacktrace @@ -261,20 +256,6 @@ public class SolrCLI { } public static CommandLine parseCmdLine(String[] args, Option[] toolOptions) throws Exception { - - String builderClassName = System.getProperty("solr.authentication.httpclient.builder"); - if (builderClassName!=null) { - try { - Class c = Class.forName(builderClassName); - SolrHttpClientBuilder builder = (SolrHttpClientBuilder)c.newInstance(); - HttpClientUtil.setHttpClientBuilder(builder); - log.info("Set SolrHttpClientBuilder from: "+builderClassName); - } catch (Exception ex) { - log.error(ex.getMessage()); - throw new RuntimeException("Error during loading of builder '"+builderClassName+"'.", ex); - } - } - // the parser doesn't like -D props List toolArgList = new ArrayList(); List dashDList = new ArrayList(); @@ -532,25 +513,6 @@ public class SolrCLI { } /** - * Inspects system property basicauth and enables authentication for HttpClient - * @throws Exception if the basicauth SysProp has wrong format - */ - protected static void setBasicAuth() throws Exception { - String basicauth = System.getProperty("basicauth", null); - if (basicauth != null) { - List ss = StrUtils.splitSmart(basicauth, ':'); - if (ss.size() != 2) - throw new Exception("Please provide 'basicauth' in the 'user:password' format"); - - HttpClientUtil.addRequestInterceptor((httpRequest, httpContext) -> { - String pair = ss.get(0) + ":" + ss.get(1); - byte[] encodedBytes = Base64.encodeBase64(pair.getBytes(UTF_8)); - httpRequest.addHeader(new BasicHeader("Authorization", "Basic " + new String(encodedBytes, UTF_8))); - }); - } - } - - /** * Determine if a request to Solr failed due to a communication error, * which is generally retry-able. */ @@ -3341,7 +3303,6 @@ public class SolrCLI { int toolExitStatus = 0; try { - setBasicAuth(); toolExitStatus = runAssert(cli); } catch (Exception exc) { // since this is a CLI, spare the user the stacktrace http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientUtil.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientUtil.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientUtil.java index decd5e8..7ee90e1 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientUtil.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientUtil.java @@ -22,6 +22,7 @@ import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.zip.GZIPInputStream; @@ -111,28 +112,46 @@ public class HttpClientUtil { // cannot be established within x ms. with a // java.net.SocketTimeoutException: Connection timed out public static final String PROP_CONNECTION_TIMEOUT = "connTimeout"; - + + /** + * A Java system property to select the {@linkplain HttpClientBuilderFactory} used for + * configuring the {@linkplain HttpClientBuilder} instance by default. + */ + public static final String SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY = "solr.httpclient.builder.factory"; + static final DefaultHttpRequestRetryHandler NO_RETRY = new DefaultHttpRequestRetryHandler( 0, false); private static volatile SolrHttpClientBuilder httpClientBuilder; - + private static SolrHttpClientContextBuilder httpClientRequestContextBuilder = new SolrHttpClientContextBuilder(); - + + private static volatile SchemaRegistryProvider schemaRegistryProvider; + private static volatile String cookiePolicy; + private static final List interceptors = Collections.synchronizedList(new ArrayList()); + + static { resetHttpClientBuilder(); + + // Configure the HttpClientBuilder if user has specified the factory type. + String factoryClassName = System.getProperty(SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY); + if (factoryClassName != null) { + logger.debug ("Using " + factoryClassName); + try { + HttpClientBuilderFactory factory = (HttpClientBuilderFactory)Class.forName(factoryClassName).newInstance(); + httpClientBuilder = factory.getHttpClientBuilder(Optional.of(SolrHttpClientBuilder.create())); + } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { + throw new RuntimeException("Unable to instantiate Solr HttpClientBuilderFactory", e); + } + } } public static abstract class SchemaRegistryProvider { /** Must be non-null */ public abstract Registry getSchemaRegistry(); } - - private static volatile SchemaRegistryProvider schemaRegistryProvider; - private static volatile String cookiePolicy; - private static final List interceptors = Collections.synchronizedList(new ArrayList()); - private static class DynamicInterceptor implements HttpRequestInterceptor { @Override @@ -151,7 +170,7 @@ public class HttpClientUtil { } } - + public static void setHttpClientBuilder(SolrHttpClientBuilder newHttpClientBuilder) { httpClientBuilder = newHttpClientBuilder; } http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientBuilder.java ---------------------------------------------------------------------- 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 7f3cf29..1bcf96b 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 @@ -138,8 +138,11 @@ public class Krb5HttpClientBuilder implements HttpClientBuilderFactory { }); HttpClientUtil.addRequestInterceptor(bufferedEntityInterceptor); } + } else { + logger.warn("{} is configured without specifying system property '{}'", + getClass().getName(), LOGIN_CONFIG_PROP); } - + return builder; } http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveAuth.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveAuth.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveAuth.java new file mode 100644 index 0000000..3334d9f --- /dev/null +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveAuth.java @@ -0,0 +1,59 @@ +/* + * 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 java.io.IOException; + +import org.apache.http.HttpException; +import org.apache.http.HttpRequest; +import org.apache.http.HttpRequestInterceptor; +import org.apache.http.auth.AuthScheme; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.AuthState; +import org.apache.http.auth.Credentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.protocol.ClientContext; +import org.apache.http.protocol.HttpContext; + +/** + * This HTTP request interceptor adds HTTP authentication credentials to every outgoing + * request. This implementation is required since Solr client is not capable of performing + * non preemptive authentication. By adding the Http authentication credentials to every request, + * this interceptor enables "preemptive" authentication. + */ +public class PreemptiveAuth implements HttpRequestInterceptor { + private AuthScheme authScheme = null; + + public PreemptiveAuth(AuthScheme authScheme) { + this.authScheme = authScheme; + } + + @Override + public void process(final HttpRequest request, final HttpContext context) throws HttpException, + IOException { + + AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE); + // If no auth scheme available yet, try to initialize it preemptively + if (authState.getAuthScheme() == null) { + CredentialsProvider credsProvider = (CredentialsProvider) context + .getAttribute(ClientContext.CREDS_PROVIDER); + Credentials creds = credsProvider.getCredentials(AuthScope.ANY); + authState.update(authScheme, creds); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthClientBuilderFactory.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthClientBuilderFactory.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthClientBuilderFactory.java new file mode 100644 index 0000000..76ce990 --- /dev/null +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthClientBuilderFactory.java @@ -0,0 +1,132 @@ +/* + * 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 java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import java.util.Properties; + +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.impl.auth.BasicScheme; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.solr.client.solrj.impl.SolrHttpClientBuilder.CredentialsProviderProvider; +import org.apache.solr.common.params.MapSolrParams; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.common.util.StrUtils; + +/** + * HttpClientConfigurer implementation providing support for preemptive Http Basic authentication + * scheme. + */ +@SuppressWarnings({"rawtypes", "unchecked"}) +public class PreemptiveBasicAuthClientBuilderFactory implements HttpClientBuilderFactory { + /** + * A system property used to specify a properties file containing default parameters used for + * creating a HTTP client. This is specifically useful for configuring the HTTP basic auth + * credentials (i.e. username/password). The name of the property must match the relevant + * Solr config property name. + */ + public static final String SYS_PROP_HTTP_CLIENT_CONFIG = "solr.httpclient.config"; + + /** + * A system property to configure the Basic auth credentials via a java system property. + * Since this will expose the password on the command-line, it is not very secure. But + * this mechanism is added for backwards compatibility. + */ + public static final String SYS_PROP_BASIC_AUTH_CREDENTIALS = "basicauth"; + + private static SolrParams defaultParams; + private static PreemptiveAuth requestInterceptor = new PreemptiveAuth(new BasicScheme()); + + static { + String credentials = System.getProperty(SYS_PROP_BASIC_AUTH_CREDENTIALS); + String configFile = System.getProperty(SYS_PROP_HTTP_CLIENT_CONFIG); + + if (credentials != null && configFile != null) { + throw new RuntimeException("Basic authentication credentials passed via a configuration file" + + " as well as java system property. Please choose one mechanism!"); + } + + if (credentials != null) { + List ss = StrUtils.splitSmart(credentials, ':'); + if (ss.size() != 2) { + throw new RuntimeException("Please provide 'basicauth' in the 'user:password' format"); + } + Properties defaultProps = new Properties(); + defaultProps.setProperty(HttpClientUtil.PROP_BASIC_AUTH_USER, ss.get(0)); + defaultProps.setProperty(HttpClientUtil.PROP_BASIC_AUTH_PASS, ss.get(1)); + defaultParams = new MapSolrParams(new HashMap(defaultProps)); + } + + if(configFile != null) { + try { + Properties defaultProps = new Properties(); + defaultProps.load(new InputStreamReader(new FileInputStream(configFile), StandardCharsets.UTF_8)); + defaultParams = new MapSolrParams(new HashMap(defaultProps)); + } catch (IOException e) { + throw new IllegalArgumentException("Unable to read the Http client config file", e); + } + } + } + + /** + * This method enables configuring system wide defaults (apart from using a config file based approach). + */ + public static void setDefaultSolrParams(SolrParams params) { + defaultParams = params; + } + + @Override + public void close() throws IOException { + HttpClientUtil.removeRequestInterceptor(requestInterceptor); + } + + @Override + public SolrHttpClientBuilder getHttpClientBuilder(Optional builder) { + return builder.isPresent() ? + initHttpClientBuilder(builder.get()) + : initHttpClientBuilder(SolrHttpClientBuilder.create()); + } + + private SolrHttpClientBuilder initHttpClientBuilder(SolrHttpClientBuilder builder) { + final String basicAuthUser = defaultParams.get(HttpClientUtil.PROP_BASIC_AUTH_USER); + final String basicAuthPass = defaultParams.get(HttpClientUtil.PROP_BASIC_AUTH_PASS); + if(basicAuthUser == null || basicAuthPass == null) { + throw new IllegalArgumentException("username & password must be specified with " + getClass().getName()); + } + + builder.setDefaultCredentialsProvider(new CredentialsProviderProvider() { + @Override + public CredentialsProvider getCredentialsProvider() { + CredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(basicAuthUser, basicAuthPass)); + return credsProvider; + } + }); + + HttpClientUtil.addRequestInterceptor(requestInterceptor); + return builder; + } +} \ No newline at end of file