From fd24abc17105bbf4a35c43b54a12b92266086869 Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Fri, 22 Nov 2024 08:24:51 -0500 Subject: [PATCH] Remove Kerberos specific functions from HttpSolrClient --- .../impl/DelegationTokenHttpSolrClient.java | 46 --- .../client/solrj/impl/HttpSolrClient.java | 27 +- .../solrj/impl/Krb5HttpClientBuilder.java | 263 ------------------ .../solrj/impl/BasicHttpSolrClientTest.java | 18 -- 4 files changed, 1 insertion(+), 353 deletions(-) delete mode 100644 solr/solrj/src/java/org/apache/solr/client/solrj/impl/DelegationTokenHttpSolrClient.java delete mode 100644 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/DelegationTokenHttpSolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/DelegationTokenHttpSolrClient.java deleted file mode 100644 index 8aad9ee6ef8..00000000000 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/DelegationTokenHttpSolrClient.java +++ /dev/null @@ -1,46 +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.client.solrj.impl; - -import java.io.IOException; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.solr.client.solrj.SolrRequest; -import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.common.params.SolrParams; - -public class DelegationTokenHttpSolrClient extends HttpSolrClient { - public static final String DELEGATION_TOKEN_PARAM = "delegation"; - - /** - * Constructor for use by {@linkplain org.apache.solr.client.solrj.impl.HttpSolrClient.Builder}. - * - * @lucene.internal - */ - protected DelegationTokenHttpSolrClient(Builder builder) { - super(builder); - } - - @Override - protected HttpRequestBase createMethod(final SolrRequest request, String collection) - throws IOException, SolrServerException { - SolrParams params = request.getParams(); - if (params != null && params.getParams(DELEGATION_TOKEN_PARAM) != null) { - throw new IllegalArgumentException(DELEGATION_TOKEN_PARAM + " parameter not supported"); - } - return super.createMethod(request, collection); - } -} diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java index 9c1ed46d7b5..bff1a819407 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java @@ -34,7 +34,6 @@ import java.util.Base64; import java.util.Collection; import java.util.Collections; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -870,17 +869,6 @@ public Builder allowCompression(boolean compression) { return this; } - /** Use a delegation token for authenticating via the KerberosPlugin */ - public Builder withKerberosDelegationToken(String delegationToken) { - if (this.invariantParams.get(DelegationTokenHttpSolrClient.DELEGATION_TOKEN_PARAM) != null) { - throw new IllegalStateException( - DelegationTokenHttpSolrClient.DELEGATION_TOKEN_PARAM + " is already defined!"); - } - this.invariantParams.add( - DelegationTokenHttpSolrClient.DELEGATION_TOKEN_PARAM, delegationToken); - return this; - } - /** * Adds to the set of params that the created {@link HttpSolrClient} will add on all requests * @@ -907,20 +895,7 @@ public HttpSolrClient build() { "Cannot create HttpSolrClient without a valid baseSolrUrl!"); } - if (this.invariantParams.get(DelegationTokenHttpSolrClient.DELEGATION_TOKEN_PARAM) == null) { - return new HttpSolrClient(this); - } else { - urlParamNames = - urlParamNames == null - ? Set.of(DelegationTokenHttpSolrClient.DELEGATION_TOKEN_PARAM) - : urlParamNames; - if (!urlParamNames.contains(DelegationTokenHttpSolrClient.DELEGATION_TOKEN_PARAM)) { - urlParamNames = new HashSet<>(urlParamNames); - urlParamNames.add(DelegationTokenHttpSolrClient.DELEGATION_TOKEN_PARAM); - } - urlParamNames = Set.copyOf(urlParamNames); - return new DelegationTokenHttpSolrClient(this); - } + return new HttpSolrClient(this); } @Override 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 deleted file mode 100644 index 0355c1a1b75..00000000000 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientBuilder.java +++ /dev/null @@ -1,263 +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.client.solrj.impl; - -import java.lang.invoke.MethodHandles; -import java.net.URI; -import java.nio.file.Paths; -import java.security.Principal; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import javax.security.auth.login.AppConfigurationEntry; -import javax.security.auth.login.Configuration; -import org.apache.http.HttpEntity; -import org.apache.http.HttpEntityEnclosingRequest; -import org.apache.http.HttpRequestInterceptor; -import org.apache.http.auth.AuthSchemeProvider; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.Credentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.config.AuthSchemes; -import org.apache.http.config.Lookup; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.cookie.CookieSpecProvider; -import org.apache.http.entity.BufferedHttpEntity; -import org.apache.http.impl.auth.SPNegoSchemeFactory; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.eclipse.jetty.client.HttpAuthenticationStore; -import org.eclipse.jetty.client.WWWAuthenticationProtocolHandler; -import org.eclipse.jetty.client.util.SPNEGOAuthentication; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** Kerberos-enabled SolrHttpClientBuilder */ -public class Krb5HttpClientBuilder implements HttpClientBuilderFactory { - - public static final String LOGIN_CONFIG_PROP = "java.security.auth.login.config"; - private static final String SPNEGO_OID = "1.3.6.1.5.5.2"; - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - private static Configuration jaasConfig = new SolrJaasConfiguration(); - - public Krb5HttpClientBuilder() {} - - /** - * The jaasConfig is static, which makes it problematic for testing in the same jvm. Call this - * function to regenerate the static config (this is not thread safe). Note: only used for tests - */ - public static void regenerateJaasConfiguration() { - jaasConfig = new SolrJaasConfiguration(); - } - - public SolrHttpClientBuilder getBuilder() { - return getBuilder(HttpClientUtil.getHttpClientBuilder()); - } - - @Override - public void close() { - HttpClientUtil.removeRequestInterceptor(bufferedEntityInterceptor); - } - - @Override - public SolrHttpClientBuilder getHttpClientBuilder(SolrHttpClientBuilder builder) { - return builder == null ? getBuilder() : getBuilder(builder); - } - - private SPNEGOAuthentication createSPNEGOAuthentication() { - SPNEGOAuthentication authentication = - new SPNEGOAuthentication(null) { - - @Override - public boolean matches(String type, URI uri, String realm) { - return this.getType().equals(type); - } - }; - String clientAppName = System.getProperty("solr.kerberos.jaas.appname", "Client"); - AppConfigurationEntry[] entries = jaasConfig.getAppConfigurationEntry(clientAppName); - if (entries == null) { - log.warn( - "Could not find login configuration entry for {}. SPNego authentication may not be successful.", - (Object) clientAppName); - return authentication; - } - if (entries.length != 1) { - log.warn("Multiple login modules are specified in the configuration file"); - return authentication; - } - - Map options = entries[0].getOptions(); - setAuthenticationOptions(authentication, options, (String) options.get("principal")); - return authentication; - } - - static void setAuthenticationOptions( - SPNEGOAuthentication authentication, Map options, String username) { - String keyTab = (String) options.get("keyTab"); - if (keyTab != null) { - authentication.setUserKeyTabPath(Paths.get(keyTab)); - } - authentication.setServiceName("HTTP"); - authentication.setUserName(username); - if ("true".equalsIgnoreCase((String) options.get("useTicketCache"))) { - authentication.setUseTicketCache(true); - String ticketCachePath = (String) options.get("ticketCache"); - if (ticketCachePath != null) { - authentication.setTicketCachePath(Paths.get(ticketCachePath)); - } - authentication.setRenewTGT("true".equalsIgnoreCase((String) options.get("renewTGT"))); - } - } - - @Override - public void setup(Http2SolrClient http2Client) { - HttpAuthenticationStore authenticationStore = new HttpAuthenticationStore(); - authenticationStore.addAuthentication(createSPNEGOAuthentication()); - http2Client.setAuthenticationStore(authenticationStore); - http2Client - .getProtocolHandlers() - .put(new WWWAuthenticationProtocolHandler(http2Client.getHttpClient())); - } - - public SolrHttpClientBuilder getBuilder(SolrHttpClientBuilder builder) { - if (System.getProperty(LOGIN_CONFIG_PROP) != null) { - String configValue = System.getProperty(LOGIN_CONFIG_PROP); - - if (configValue != null) { - log.info("Setting up SPNego auth with config: {}", configValue); - final String useSubjectCredsProp = "javax.security.auth.useSubjectCredsOnly"; - String useSubjectCredsVal = System.getProperty(useSubjectCredsProp); - - // "javax.security.auth.useSubjectCredsOnly" should be false so that the underlying - // authentication mechanism can load the credentials from the JAAS configuration. - if (useSubjectCredsVal == null) { - System.setProperty(useSubjectCredsProp, "false"); - } else if (!useSubjectCredsVal.toLowerCase(Locale.ROOT).equals("false")) { - // Don't overwrite the prop value if it's already been written to something else, - // but log because it is likely the Credentials won't be loaded correctly. - log.warn( - "System Property: {} set to: {} not false. SPNego authentication may not be successful.", - useSubjectCredsProp, - useSubjectCredsVal); - } - - javax.security.auth.login.Configuration.setConfiguration(jaasConfig); - // Enable only SPNEGO authentication scheme. - - builder.setAuthSchemeRegistryProvider( - () -> { - Lookup authProviders = - RegistryBuilder.create() - .register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory(true, false)) - .build(); - return authProviders; - }); - // Get the credentials from the JAAS configuration rather than here - Credentials useJaasCreds = - new Credentials() { - @Override - public String getPassword() { - return null; - } - - @Override - public Principal getUserPrincipal() { - return null; - } - }; - - HttpClientUtil.setCookiePolicy(SolrPortAwareCookieSpecFactory.POLICY_NAME); - - builder.setCookieSpecRegistryProvider( - () -> { - SolrPortAwareCookieSpecFactory cookieFactory = new SolrPortAwareCookieSpecFactory(); - - Lookup cookieRegistry = - RegistryBuilder.create() - .register(SolrPortAwareCookieSpecFactory.POLICY_NAME, cookieFactory) - .build(); - - return cookieRegistry; - }); - - builder.setDefaultCredentialsProvider( - () -> { - CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(AuthScope.ANY, useJaasCreds); - return credentialsProvider; - }); - HttpClientUtil.addRequestInterceptor(bufferedEntityInterceptor); - } - } else { - log.warn( - "{} is configured without specifying system property '{}'", - getClass().getName(), - LOGIN_CONFIG_PROP); - } - - return builder; - } - - // Set a buffered entity based request interceptor - private HttpRequestInterceptor bufferedEntityInterceptor = - (request, context) -> { - if (request instanceof HttpEntityEnclosingRequest enclosingRequest) { - HttpEntity requestEntity = enclosingRequest.getEntity(); - enclosingRequest.setEntity(new BufferedHttpEntity(requestEntity)); - } - }; - - public static class SolrJaasConfiguration extends javax.security.auth.login.Configuration { - - private javax.security.auth.login.Configuration baseConfig; - - // the com.sun.security.jgss appNames - private Set initiateAppNames = - new HashSet<>( - Arrays.asList("com.sun.security.jgss.krb5.initiate", "com.sun.security.jgss.initiate")); - - public SolrJaasConfiguration() { - try { - - this.baseConfig = javax.security.auth.login.Configuration.getConfiguration(); - } catch (SecurityException e) { - this.baseConfig = null; - } - } - - @Override - public AppConfigurationEntry[] getAppConfigurationEntry(String appName) { - if (baseConfig == null) return null; - - if (log.isDebugEnabled()) { - log.debug("Login prop: {}", System.getProperty(LOGIN_CONFIG_PROP)); - } - - String clientAppName = System.getProperty("solr.kerberos.jaas.appname", "Client"); - if (initiateAppNames.contains(appName)) { - log.debug( - "Using AppConfigurationEntry for appName '{}' instead of: '{}'", - clientAppName, - appName); - return baseConfig.getAppConfigurationEntry(clientAppName); - } - return baseConfig.getAppConfigurationEntry(appName); - } - } -} diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java index 30299f0b572..2074a4c8a48 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java @@ -890,23 +890,5 @@ public void testInvariantParams() throws IOException { .build()) { assertEquals(2, createdClient.getInvariantParams().getParams("fq").length); } - - try (SolrClient createdClient = - new HttpSolrClient.Builder() - .withBaseSolrUrl(getBaseUrl()) - .withKerberosDelegationToken("mydt") - .withInvariantParams( - SolrTestCaseJ4.params(DelegationTokenHttpSolrClient.DELEGATION_TOKEN_PARAM, "mydt")) - .build()) { - fail(); - } catch (Exception ex) { - if (!ex.getMessage() - .equals( - "parameter " - + DelegationTokenHttpSolrClient.DELEGATION_TOKEN_PARAM - + " is redefined.")) { - throw ex; - } - } } }