SOLR-10783: Add support for Hadoop Credential Provider as SSL/TLS store password source.

This commit is contained in:
Mark Miller 2018-04-09 21:38:07 -05:00
parent 1d8c58eb6d
commit 5e2a5a5b8c
20 changed files with 967 additions and 59 deletions

View File

@ -80,6 +80,9 @@ New Features
* SOLR-12139: The "eq" (equals) function query now works with string fields, string literals, and perhaps anything.
(Andrey Kudryavtsev, David Smiley)
* SOLR-10783: Add support for Hadoop Credential Provider as SSL/TLS store password source.
(Mano Kovacs via Mark Miller)
Bug Fixes
----------------------

View File

@ -163,6 +163,11 @@ fi
SOLR_URL_SCHEME=http
SOLR_JETTY_CONFIG=()
SOLR_SSL_OPTS=""
if [ -n "$SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH" ]; then
SOLR_SSL_OPTS+=" -Dhadoop.security.credential.provider.path=$SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH"
fi
if [ -z "$SOLR_SSL_ENABLED" ]; then
if [ -n "$SOLR_SSL_KEY_STORE" ]; then
SOLR_SSL_ENABLED="true" # implicitly from earlier behaviour
@ -172,6 +177,7 @@ if [ -z "$SOLR_SSL_ENABLED" ]; then
fi
if [ "$SOLR_SSL_ENABLED" == "true" ]; then
SOLR_JETTY_CONFIG+=("--module=https")
SOLR_JETTY_CONFIG+=("--lib=$DEFAULT_SERVER_DIR/solr-webapp/webapp/WEB-INF/lib/*")
SOLR_URL_SCHEME=https
if [ -n "$SOLR_SSL_KEY_STORE" ]; then
SOLR_SSL_OPTS+=" -Dsolr.jetty.keystore=$SOLR_SSL_KEY_STORE"

View File

@ -38,11 +38,17 @@ REM command line args
IF "%SOLR_INCLUDE%"=="" set "SOLR_INCLUDE=%SOLR_TIP%\bin\solr.in.cmd"
IF EXIST "%SOLR_INCLUDE%" CALL "%SOLR_INCLUDE%"
set "DEFAULT_SERVER_DIR=%SOLR_TIP%\server"
REM Select HTTP OR HTTPS related configurations
set SOLR_URL_SCHEME=http
set "SOLR_JETTY_CONFIG=--module=http"
set "SOLR_SSL_OPTS= "
IF DEFINED SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dhadoop.security.credential.provider.path=%SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH%"
)
IF NOT DEFINED SOLR_SSL_ENABLED (
IF DEFINED SOLR_SSL_KEY_STORE (
set "SOLR_SSL_ENABLED=true"
@ -50,8 +56,9 @@ IF NOT DEFINED SOLR_SSL_ENABLED (
set "SOLR_SSL_ENABLED=false"
)
)
IF "%SOLR_SSL_ENABLED%"=="true" (
set "SOLR_JETTY_CONFIG=--module=https"
set "SOLR_JETTY_CONFIG=--lib="%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*" --module=https"
set SOLR_URL_SCHEME=https
IF DEFINED SOLR_SSL_KEY_STORE (
set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.keystore=%SOLR_SSL_KEY_STORE%"
@ -182,8 +189,6 @@ IF !JAVA_MAJOR_VERSION! LSS 8 (
goto err
)
set "DEFAULT_SERVER_DIR=%SOLR_TIP%\server"
set FIRST_ARG=%1
IF [%1]==[] goto usage
@ -1008,7 +1013,7 @@ IF "%SCRIPT_CMD%"=="stop" (
set found_it=1
@echo Stopping Solr process %%N running on port %SOLR_PORT%
IF "%STOP_PORT%"=="" set /A STOP_PORT=%SOLR_PORT% - 1000
"%JAVA%" %SOLR_SSL_OPTS% -Djetty.home="%SOLR_SERVER_DIR%" -jar "%SOLR_SERVER_DIR%\start.jar" "%SOLR_JETTY_CONFIG%" STOP.PORT=!STOP_PORT! STOP.KEY=%STOP_KEY% --stop
"%JAVA%" %SOLR_SSL_OPTS% -Djetty.home="%SOLR_SERVER_DIR%" -jar "%SOLR_SERVER_DIR%\start.jar" %SOLR_JETTY_CONFIG% STOP.PORT=!STOP_PORT! STOP.KEY=%STOP_KEY% --stop
del "%SOLR_TIP%"\bin\solr-%SOLR_PORT%.port
timeout /T 5
REM Kill it if it is still running after the graceful shutdown
@ -1260,7 +1265,7 @@ IF "%FG%"=="1" (
-Dlog4j.configurationFile="%LOG4J_CONFIG%" -DSTOP.PORT=!STOP_PORT! -DSTOP.KEY=%STOP_KEY% ^
-Dsolr.solr.home="%SOLR_HOME%" -Dsolr.install.dir="%SOLR_TIP%" -Dsolr.default.confdir="%DEFAULT_CONFDIR%" ^
-Djetty.host=%SOLR_JETTY_HOST% -Djetty.port=%SOLR_PORT% -Djetty.home="%SOLR_SERVER_DIR%" ^
-Djava.io.tmpdir="%SOLR_SERVER_DIR%\tmp" -jar start.jar "%SOLR_JETTY_CONFIG%" "%SOLR_JETTY_ADDL_CONFIG%"
-Djava.io.tmpdir="%SOLR_SERVER_DIR%\tmp" -jar start.jar %SOLR_JETTY_CONFIG% "%SOLR_JETTY_ADDL_CONFIG%"
) ELSE (
START /B "Solr-%SOLR_PORT%" /D "%SOLR_SERVER_DIR%" ^
"%JAVA%" %SERVEROPT% %SOLR_JAVA_MEM% %START_OPTS% ^
@ -1268,7 +1273,7 @@ IF "%FG%"=="1" (
-Dsolr.log.muteconsole ^
-Dsolr.solr.home="%SOLR_HOME%" -Dsolr.install.dir="%SOLR_TIP%" -Dsolr.default.confdir="%DEFAULT_CONFDIR%" ^
-Djetty.host=%SOLR_JETTY_HOST% -Djetty.port=%SOLR_PORT% -Djetty.home="%SOLR_SERVER_DIR%" ^
-Djava.io.tmpdir="%SOLR_SERVER_DIR%\tmp" -jar start.jar "%SOLR_JETTY_CONFIG%" "%SOLR_JETTY_ADDL_CONFIG%" > "!SOLR_LOGS_DIR!\solr-%SOLR_PORT%-console.log"
-Djava.io.tmpdir="%SOLR_SERVER_DIR%\tmp" -jar start.jar %SOLR_JETTY_CONFIG% "%SOLR_JETTY_ADDL_CONFIG%" > "!SOLR_LOGS_DIR!\solr-%SOLR_PORT%-console.log"
echo %SOLR_PORT%>"%SOLR_TIP%"\bin\solr-%SOLR_PORT%.port
REM now wait to see Solr come online ...

View File

@ -119,6 +119,17 @@ REM set SOLR_SSL_CLIENT_TRUST_STORE=
REM set SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD=
REM set SOLR_SSL_CLIENT_TRUST_STORE_TYPE=
REM Sets path of Hadoop credential provider (hadoop.security.credential.provider.path property) and
REM enables usage of credential store.
REM Credential provider should store the following keys:
REM * solr.jetty.keystore.password
REM * solr.jetty.truststore.password
REM Set the two below if you want to set specific store passwords for HTTP client
REM * javax.net.ssl.keyStorePassword
REM * javax.net.ssl.trustStorePassword
REM More info: https://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/CredentialProviderAPI.html
REM set SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH=localjceks://file/home/solr/hadoop-credential-provider.jceks
REM Settings for authentication
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

View File

@ -136,6 +136,17 @@
#SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD=
#SOLR_SSL_CLIENT_TRUST_STORE_TYPE=
# Sets path of Hadoop credential provider (hadoop.security.credential.provider.path property) and
# enables usage of credential store.
# Credential provider should store the following keys:
# * solr.jetty.keystore.password
# * solr.jetty.truststore.password
# Set the two below if you want to set specific store passwords for HTTP client
# * javax.net.ssl.keyStorePassword
# * javax.net.ssl.trustStorePassword
# More info: https://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/CredentialProviderAPI.html
#SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH=localjceks://file/home/solr/hadoop-credential-provider.jceks
# Settings for authentication
# 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"

View File

@ -18,7 +18,7 @@
package org.apache.solr.util.configuration;
import java.lang.invoke.MethodHandles;
import java.util.Map;
import java.util.List;
import org.apache.solr.common.StringUtils;
import org.slf4j.Logger;
@ -28,48 +28,94 @@ import org.slf4j.LoggerFactory;
* Dedicated object to handle Solr configurations
*/
public class SSLConfigurations {
private final Map<String, String> envVars;
public static final String DEFAULT_STORE_PASSWORD = "secret";
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
public static class SysProps {
public static final String SSL_KEY_STORE_PASSWORD = "javax.net.ssl.keyStorePassword";
public static final String SSL_TRUST_STORE_PASSWORD = "javax.net.ssl.trustStorePassword";
}
protected final List<SSLCredentialProvider> credentialProviders;
public static class EnvVars {
public static final String SOLR_SSL_CLIENT_KEY_STORE_PASSWORD = "SOLR_SSL_CLIENT_KEY_STORE_PASSWORD";
public static final String SOLR_SSL_KEY_STORE_PASSWORD = "SOLR_SSL_KEY_STORE_PASSWORD";
public static final String SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD = "SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD";
public static final String SOLR_SSL_TRUST_STORE_PASSWORD = "SOLR_SSL_TRUST_STORE_PASSWORD";
public static class SysProps {
public static final String SSL_KEY_STORE_PASSWORD = "solr.jetty.keystore.password";
public static final String SSL_TRUST_STORE_PASSWORD = "solr.jetty.truststore.password";
public static final String SSL_CLIENT_KEY_STORE_PASSWORD = "javax.net.ssl.keyStorePassword";
public static final String SSL_CLIENT_TRUST_STORE_PASSWORD = "javax.net.ssl.trustStorePassword";
}
/**
* @param envVars Map of environment variables to use
* @param sslCredentialProviderFactory Credential provider factory to use for providers
*/
public SSLConfigurations(Map<String, String> envVars) {
this.envVars = envVars;
public SSLConfigurations(SSLCredentialProviderFactory sslCredentialProviderFactory) {
credentialProviders = sslCredentialProviderFactory.getProviders();
}
/** Initiates javax.net.ssl.* system properties from the proper sources. */
/**
* @param credentialProviders Explicit list of credential providers to use
*/
public SSLConfigurations(List<SSLCredentialProvider> credentialProviders) {
this.credentialProviders = credentialProviders;
}
/**
* Initiates javax.net.ssl.* system properties from the proper sources.
*/
public void init() {
String clientKeystorePassword = envVars.get(EnvVars.SOLR_SSL_CLIENT_KEY_STORE_PASSWORD);
String keystorePassword = envVars.get(EnvVars.SOLR_SSL_KEY_STORE_PASSWORD);
String clientKeystorePassword = getClientKeyStorePassword();
String keystorePassword = getKeyStorePassword();
String clientTruststorePassword = envVars.get(EnvVars.SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD);
String truststorePassword = envVars.get(EnvVars.SOLR_SSL_TRUST_STORE_PASSWORD);
String clientTruststorePassword = getClientTrustStorePassword();
String truststorePassword = getTrustStorePassword();
if (isEmpty(System.getProperty(SysProps.SSL_KEY_STORE_PASSWORD))
if (isEmpty(System.getProperty(SysProps.SSL_CLIENT_KEY_STORE_PASSWORD))
&& !(isEmpty(clientKeystorePassword) && isEmpty(keystorePassword))) {
log.debug("Setting {} based on env var", SysProps.SSL_KEY_STORE_PASSWORD);
System.setProperty(SysProps.SSL_KEY_STORE_PASSWORD, clientKeystorePassword != null ? clientKeystorePassword : keystorePassword);
log.info("Setting {}", SysProps.SSL_CLIENT_KEY_STORE_PASSWORD);
System.setProperty(SysProps.SSL_CLIENT_KEY_STORE_PASSWORD, clientKeystorePassword != null ? clientKeystorePassword : keystorePassword);
}
if (isEmpty(System.getProperty(SysProps.SSL_TRUST_STORE_PASSWORD))
if (isEmpty(System.getProperty(SysProps.SSL_CLIENT_TRUST_STORE_PASSWORD))
&& !(isEmpty(clientTruststorePassword) && isEmpty(truststorePassword))) {
log.debug("Setting {} based on env var", SysProps.SSL_TRUST_STORE_PASSWORD);
System.setProperty(SysProps.SSL_TRUST_STORE_PASSWORD, clientTruststorePassword != null ? clientTruststorePassword : truststorePassword);
log.info("Setting {}", SysProps.SSL_CLIENT_TRUST_STORE_PASSWORD);
System.setProperty(SysProps.SSL_CLIENT_TRUST_STORE_PASSWORD, clientTruststorePassword != null ? clientTruststorePassword : truststorePassword);
}
}
/**
* @return password for keystore used for SSL connections
*/
public String getKeyStorePassword() {
String keyStorePassword = getPassword(SSLCredentialProvider.CredentialType.SSL_KEY_STORE_PASSWORD);
return keyStorePassword;
}
/**
* @return password for truststore used for SSL connections
*/
public String getTrustStorePassword() {
String trustStorePassword = getPassword(SSLCredentialProvider.CredentialType.SSL_TRUST_STORE_PASSWORD);
return trustStorePassword;
}
/**
* @return password for keystore used for SSL client connections
*/
public String getClientKeyStorePassword() {
String keyStorePassword = getPassword(SSLCredentialProvider.CredentialType.SSL_CLIENT_KEY_STORE_PASSWORD);
return keyStorePassword;
}
/**
* @return password for truststore used for SSL client connections
*/
public String getClientTrustStorePassword() {
String trustStorePassword = getPassword(SSLCredentialProvider.CredentialType.SSL_CLIENT_TRUST_STORE_PASSWORD);
return trustStorePassword;
}
protected String getPassword(SSLCredentialProvider.CredentialType type) {
for(SSLCredentialProvider provider: credentialProviders){
String credential = provider.getCredential(type);
if(credential != null) return credential;
}
return null;
}
private boolean isEmpty(String str) {

View File

@ -39,7 +39,7 @@ public class SSLConfigurationsFactory {
}
private static SSLConfigurations getInstance() {
return new SSLConfigurations(System.getenv());
return new SSLConfigurations(new SSLCredentialProviderFactory());
}
@VisibleForTesting

View File

@ -0,0 +1,36 @@
/*
* 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.util.configuration;
/**
* Interface for different source of SSL configurations.
*/
public interface SSLCredentialProvider {
enum CredentialType {
SSL_KEY_STORE_PASSWORD,
SSL_TRUST_STORE_PASSWORD,
SSL_CLIENT_KEY_STORE_PASSWORD,
SSL_CLIENT_TRUST_STORE_PASSWORD
}
/**
* @return Credential for the given credential type
*/
String getCredential(CredentialType type);
}

View File

@ -0,0 +1,93 @@
/*
* 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.util.configuration;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import com.google.common.collect.ImmutableMap;
import org.apache.solr.util.configuration.providers.EnvSSLCredentialProvider;
import org.apache.solr.util.configuration.providers.HadoopSSLCredentialProvider;
import org.apache.solr.util.configuration.providers.SysPropSSLCredentialProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Class responsible to build SSL credential providers
*/
public class SSLCredentialProviderFactory {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
public static final String DEFAULT_PROVIDER_CHAIN = "env;sysprop";
public static final String PROVIDER_CHAIN_KEY = "solr.ssl.credential.provider.chain";
private final static ImmutableMap<String, Class> defaultProviders = ImmutableMap.of(
"env", EnvSSLCredentialProvider.class,
"sysprop", SysPropSSLCredentialProvider.class,
"hadoop", HadoopSSLCredentialProvider.class
);
private String providerChain;
public SSLCredentialProviderFactory() {
this.providerChain = System.getProperty(PROVIDER_CHAIN_KEY, DEFAULT_PROVIDER_CHAIN);
}
public SSLCredentialProviderFactory(String providerChain) {
this.providerChain = providerChain;
}
public List<SSLCredentialProvider> getProviders() {
ArrayList<SSLCredentialProvider> providers = new ArrayList<>();
log.info(String.format(Locale.ROOT, "Processing SSL Credential Provider chain: %s", providerChain));
String classPrefix = "class://";
for (String provider : providerChain.split(";")) {
if (defaultProviders.containsKey(provider)) {
providers.add(getDefaultProvider(defaultProviders.get(provider)));
} else if (provider.startsWith(classPrefix)) {
providers.add(getProviderByClassName(provider.substring(classPrefix.length())));
} else {
throw new RuntimeException("Unable to parse credential provider: " + provider);
}
}
return providers;
}
private SSLCredentialProvider getProviderByClassName(String clazzName) {
try {
return (SSLCredentialProvider) Class.forName(clazzName).getConstructor().newInstance();
} catch (InstantiationException | ClassNotFoundException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
String msg = String.format(Locale.ROOT, "Could not instantiate %s credential provider", clazzName);
log.error(msg);
throw new RuntimeException(msg, e);
}
}
private SSLCredentialProvider getDefaultProvider(Class aClass) {
try {
return (SSLCredentialProvider) aClass.getConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
String msg = String.format(Locale.ROOT, "Could not instantiate %s credential provider", aClass.getName());
log.error(msg);
throw new RuntimeException(msg, e);
}
}
}

View File

@ -0,0 +1,56 @@
/*
* 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.util.configuration.providers;
import java.util.EnumMap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import org.apache.solr.util.configuration.SSLCredentialProvider;
import static org.apache.solr.util.configuration.SSLCredentialProvider.CredentialType.SSL_CLIENT_KEY_STORE_PASSWORD;
import static org.apache.solr.util.configuration.SSLCredentialProvider.CredentialType.SSL_CLIENT_TRUST_STORE_PASSWORD;
import static org.apache.solr.util.configuration.SSLCredentialProvider.CredentialType.SSL_KEY_STORE_PASSWORD;
import static org.apache.solr.util.configuration.SSLCredentialProvider.CredentialType.SSL_TRUST_STORE_PASSWORD;
/**
* Abstract provider with default implementation
*/
abstract public class AbstractSSLCredentialProvider implements SSLCredentialProvider {
public static final EnumMap<CredentialType, String> DEFAULT_CREDENTIAL_KEY_MAP = Maps.newEnumMap(ImmutableMap.of(
SSL_KEY_STORE_PASSWORD, "solr.jetty.keystore.password",
SSL_TRUST_STORE_PASSWORD, "solr.jetty.truststore.password",
SSL_CLIENT_KEY_STORE_PASSWORD, "javax.net.ssl.keyStorePassword",
SSL_CLIENT_TRUST_STORE_PASSWORD, "javax.net.ssl.trustStorePassword"
));
private final EnumMap<CredentialType, String> credentialKeyMap;
public AbstractSSLCredentialProvider() {
credentialKeyMap = getCredentialKeyMap();
}
abstract protected String getCredential(String key);
abstract protected EnumMap<CredentialType, String> getCredentialKeyMap();
@Override
public String getCredential(CredentialType type) {
return getCredential(credentialKeyMap.get(type));
}
}

View File

@ -0,0 +1,72 @@
/*
* 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.util.configuration.providers;
import java.util.EnumMap;
import java.util.Map;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import static org.apache.solr.util.configuration.SSLCredentialProvider.CredentialType.SSL_CLIENT_KEY_STORE_PASSWORD;
import static org.apache.solr.util.configuration.SSLCredentialProvider.CredentialType.SSL_CLIENT_TRUST_STORE_PASSWORD;
import static org.apache.solr.util.configuration.SSLCredentialProvider.CredentialType.SSL_KEY_STORE_PASSWORD;
import static org.apache.solr.util.configuration.SSLCredentialProvider.CredentialType.SSL_TRUST_STORE_PASSWORD;
/**
* Environment variable based SSL configuration provider
*/
public class EnvSSLCredentialProvider extends AbstractSSLCredentialProvider {
public static class EnvVars {
public static final String SOLR_SSL_CLIENT_KEY_STORE_PASSWORD = "SOLR_SSL_CLIENT_KEY_STORE_PASSWORD";
public static final String SOLR_SSL_KEY_STORE_PASSWORD = "SOLR_SSL_KEY_STORE_PASSWORD";
public static final String SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD = "SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD";
public static final String SOLR_SSL_TRUST_STORE_PASSWORD = "SOLR_SSL_TRUST_STORE_PASSWORD";
}
private Map<String, String> envVars;
public EnvSSLCredentialProvider() {
this.envVars = System.getenv();
}
protected EnumMap<CredentialType, String> getCredentialKeyMap() {
return Maps.newEnumMap(ImmutableMap.of(
SSL_KEY_STORE_PASSWORD, EnvVars.SOLR_SSL_KEY_STORE_PASSWORD,
SSL_TRUST_STORE_PASSWORD, EnvVars.SOLR_SSL_TRUST_STORE_PASSWORD,
SSL_CLIENT_KEY_STORE_PASSWORD, EnvVars.SOLR_SSL_CLIENT_KEY_STORE_PASSWORD,
SSL_CLIENT_TRUST_STORE_PASSWORD, EnvVars.SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD
));
}
protected String getCredential(String envKey) {
if (envVars.containsKey(envKey)) {
return envVars.get(envKey);
} else {
return null;
}
}
@VisibleForTesting
public void setEnvVars(Map<String, String> envVars) {
this.envVars = envVars;
}
}

View File

@ -0,0 +1,66 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.util.configuration.providers;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.EnumMap;
import org.apache.hadoop.conf.Configuration;
import org.apache.solr.common.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.apache.hadoop.security.alias.CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH;
/**
* System property based SSL configuration provider
*/
public class HadoopSSLCredentialProvider extends AbstractSSLCredentialProvider {
private Configuration hadoopConfigurationProvider;
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
public HadoopSSLCredentialProvider() {
this(new Configuration());
}
public HadoopSSLCredentialProvider(Configuration hadoopConfigurationProvider) {
if (StringUtils.isEmpty(System.getProperty(CREDENTIAL_PROVIDER_PATH))) {
throw new RuntimeException("Cannot initialize Hadoop configuration provider without credential provider path. Use " + CREDENTIAL_PROVIDER_PATH + " system property to configure.");
}
this.hadoopConfigurationProvider = hadoopConfigurationProvider;
hadoopConfigurationProvider.set(CREDENTIAL_PROVIDER_PATH, System.getProperty(CREDENTIAL_PROVIDER_PATH));
}
@Override
protected EnumMap<CredentialType, String> getCredentialKeyMap() {
return DEFAULT_CREDENTIAL_KEY_MAP;
}
protected String getCredential(String keystoreKey) {
try {
char[] password = hadoopConfigurationProvider.getPassword(keystoreKey);
return password == null ? null : String.valueOf(password);
} catch (IOException e) {
log.error("Could not read password from Hadoop Credential Store: " + keystoreKey, e);
return null;
}
}
}

View File

@ -0,0 +1,38 @@
/*
* 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.util.configuration.providers;
import java.util.EnumMap;
/**
* System property based SSL configuration provider
*/
public class SysPropSSLCredentialProvider extends AbstractSSLCredentialProvider {
@Override
protected EnumMap<CredentialType, String> getCredentialKeyMap() {
return DEFAULT_CREDENTIAL_KEY_MAP;
}
protected String getCredential(String syspropKey) {
if (System.getProperty(syspropKey) != null) {
return System.getProperty(syspropKey);
} else {
return null;
}
}
}

View File

@ -0,0 +1,23 @@
/*
* 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.
*/
/**
* TODO
*/
package org.apache.solr.util.configuration.providers;

View File

@ -17,17 +17,27 @@
package org.apache.solr.util.configuration;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.apache.hadoop.conf.Configuration;
import org.apache.lucene.util.TestRuleRestoreSystemProperties;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.util.configuration.providers.EnvSSLCredentialProvider;
import org.apache.solr.util.configuration.providers.HadoopSSLCredentialProvider;
import org.apache.solr.util.configuration.providers.SysPropSSLCredentialProvider;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.mockito.Mockito;
import static org.apache.hadoop.security.alias.CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;
public class SSLConfigurationsTest {
private Map<String, String> envs;
@ -38,11 +48,16 @@ public class SSLConfigurationsTest {
public static final String SAMPLE_PW3 = "pw789";
public static final String KEY_STORE_PASSWORD = SSLConfigurations.SysProps.SSL_KEY_STORE_PASSWORD;
public static final String TRUST_STORE_PASSWORD = SSLConfigurations.SysProps.SSL_TRUST_STORE_PASSWORD;
public static final String CLIENT_KEY_STORE_PASSWORD = SSLConfigurations.SysProps.SSL_CLIENT_KEY_STORE_PASSWORD;
public static final String CLIENT_TRUST_STORE_PASSWORD = SSLConfigurations.SysProps.SSL_CLIENT_TRUST_STORE_PASSWORD;
@Rule
public TestRule syspropRestore = new TestRuleRestoreSystemProperties(
SSLConfigurations.SysProps.SSL_KEY_STORE_PASSWORD,
SSLConfigurations.SysProps.SSL_TRUST_STORE_PASSWORD
SSLConfigurations.SysProps.SSL_TRUST_STORE_PASSWORD,
SSLConfigurations.SysProps.SSL_CLIENT_KEY_STORE_PASSWORD,
SSLConfigurations.SysProps.SSL_CLIENT_TRUST_STORE_PASSWORD,
CREDENTIAL_PROVIDER_PATH
);
@Before
@ -50,72 +65,204 @@ public class SSLConfigurationsTest {
envs = new HashMap<>();
}
private SSLConfigurations createSut(Configuration mockHadoopConfiguration) {
EnvSSLCredentialProvider envSSLCredentialProvider = new EnvSSLCredentialProvider();
envSSLCredentialProvider.setEnvVars(envs);
sut = new SSLConfigurations(Arrays.asList(
new HadoopSSLCredentialProvider(mockHadoopConfiguration),
envSSLCredentialProvider,
new SysPropSSLCredentialProvider())
);
return sut;
}
private SSLConfigurations createSut() {
sut = new SSLConfigurations(envs);
EnvSSLCredentialProvider envSSLCredentialProvider = new EnvSSLCredentialProvider();
envSSLCredentialProvider.setEnvVars(envs);
sut = new SSLConfigurations(Arrays.asList(envSSLCredentialProvider, new SysPropSSLCredentialProvider()));
return sut;
}
@Test
public void testSslConfigKeystorePwFromKeystoreEnvVar() {
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_KEY_STORE_PASSWORD, SAMPLE_PW1);
envs.put(EnvSSLCredentialProvider.EnvVars.SOLR_SSL_KEY_STORE_PASSWORD, SAMPLE_PW1);
createSut().init();
assertThat(System.getProperty(KEY_STORE_PASSWORD), is(SAMPLE_PW1));
assertThat(System.getProperty(CLIENT_KEY_STORE_PASSWORD), is(SAMPLE_PW1));
}
@Test
public void testSslConfigKeystorePwFromClientKeystoreEnvVar() {
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_CLIENT_KEY_STORE_PASSWORD, SAMPLE_PW2);
envs.put(EnvSSLCredentialProvider.EnvVars.SOLR_SSL_CLIENT_KEY_STORE_PASSWORD, SAMPLE_PW2);
createSut().init();
assertThat(System.getProperty(KEY_STORE_PASSWORD), is(SAMPLE_PW2));
assertThat(System.getProperty(CLIENT_KEY_STORE_PASSWORD), is(SAMPLE_PW2));
}
@Test
public void testSslConfigKeystorePwFromBothEnvVars() {
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_KEY_STORE_PASSWORD, SAMPLE_PW1);
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_CLIENT_KEY_STORE_PASSWORD, SAMPLE_PW2);
envs.put(EnvSSLCredentialProvider.EnvVars.SOLR_SSL_KEY_STORE_PASSWORD, SAMPLE_PW1);
envs.put(EnvSSLCredentialProvider.EnvVars.SOLR_SSL_CLIENT_KEY_STORE_PASSWORD, SAMPLE_PW2);
createSut().init();
assertThat(System.getProperty(KEY_STORE_PASSWORD), is(SAMPLE_PW2));
assertThat(System.getProperty(CLIENT_KEY_STORE_PASSWORD), is(SAMPLE_PW2));
}
@Test
public void testSslConfigKeystorePwFromKeystoreHadoopCredentialProvider() throws IOException {
getSutWithMockedHadoopCredentialProvider(SSLConfigurations.SysProps.SSL_KEY_STORE_PASSWORD, SAMPLE_PW1)
.init();
assertThat(System.getProperty(CLIENT_KEY_STORE_PASSWORD), is(SAMPLE_PW1));
}
@Test
public void testSslConfigKeystorePwFromClientKeystoreHadoopCredentialProvider() throws IOException {
getSutWithMockedHadoopCredentialProvider(SSLConfigurations.SysProps.SSL_CLIENT_KEY_STORE_PASSWORD, SAMPLE_PW2)
.init();
assertThat(System.getProperty(CLIENT_KEY_STORE_PASSWORD), is(SAMPLE_PW2));
}
@Test
public void testSslConfigKeystorePwNotOverwrittenIfExists() {
System.setProperty(KEY_STORE_PASSWORD, SAMPLE_PW3);
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_KEY_STORE_PASSWORD, SAMPLE_PW1);
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_CLIENT_KEY_STORE_PASSWORD, SAMPLE_PW2);
System.setProperty(CLIENT_KEY_STORE_PASSWORD, SAMPLE_PW3);
envs.put(EnvSSLCredentialProvider.EnvVars.SOLR_SSL_KEY_STORE_PASSWORD, SAMPLE_PW1);
envs.put(EnvSSLCredentialProvider.EnvVars.SOLR_SSL_CLIENT_KEY_STORE_PASSWORD, SAMPLE_PW2);
createSut().init();
assertThat(System.getProperty(KEY_STORE_PASSWORD), is(SAMPLE_PW3)); // unchanged
assertThat(System.getProperty(CLIENT_KEY_STORE_PASSWORD), is(SAMPLE_PW3)); // unchanged
}
@Test
public void testSslConfigTruststorePwFromKeystoreEnvVar() {
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_TRUST_STORE_PASSWORD, SAMPLE_PW1);
envs.put(EnvSSLCredentialProvider.EnvVars.SOLR_SSL_TRUST_STORE_PASSWORD, SAMPLE_PW1);
createSut().init();
assertThat(System.getProperty(TRUST_STORE_PASSWORD), is(SAMPLE_PW1));
assertThat(System.getProperty(CLIENT_TRUST_STORE_PASSWORD), is(SAMPLE_PW1));
}
@Test
public void testSslConfigTruststorePwFromClientKeystoreEnvVar() {
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD, SAMPLE_PW2);
envs.put(EnvSSLCredentialProvider.EnvVars.SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD, SAMPLE_PW2);
createSut().init();
assertThat(System.getProperty(TRUST_STORE_PASSWORD), is(SAMPLE_PW2));
assertThat(System.getProperty(CLIENT_TRUST_STORE_PASSWORD), is(SAMPLE_PW2));
}
@Test
public void testSslConfigTruststorePwFromBothEnvVars() {
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_TRUST_STORE_PASSWORD, SAMPLE_PW1);
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD, SAMPLE_PW2);
envs.put(EnvSSLCredentialProvider.EnvVars.SOLR_SSL_TRUST_STORE_PASSWORD, SAMPLE_PW1);
envs.put(EnvSSLCredentialProvider.EnvVars.SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD, SAMPLE_PW2);
createSut().init();
assertThat(System.getProperty(TRUST_STORE_PASSWORD), is(SAMPLE_PW2));
assertThat(System.getProperty(CLIENT_TRUST_STORE_PASSWORD), is(SAMPLE_PW2));
}
@Test
public void testSslConfigTruststorePwNotOverwrittenIfExists() {
System.setProperty(TRUST_STORE_PASSWORD, SAMPLE_PW3);
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_TRUST_STORE_PASSWORD, SAMPLE_PW1);
envs.put(SSLConfigurations.EnvVars.SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD, SAMPLE_PW2);
System.setProperty(CLIENT_TRUST_STORE_PASSWORD, SAMPLE_PW3);
envs.put(EnvSSLCredentialProvider.EnvVars.SOLR_SSL_TRUST_STORE_PASSWORD, SAMPLE_PW1);
envs.put(EnvSSLCredentialProvider.EnvVars.SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD, SAMPLE_PW2);
createSut().init();
assertThat(System.getProperty(TRUST_STORE_PASSWORD), is(SAMPLE_PW3)); // unchanged
assertThat(System.getProperty(CLIENT_TRUST_STORE_PASSWORD), is(SAMPLE_PW3)); // unchanged
}
@Test
public void testGetKeyStorePasswordFromProperty() {
System.setProperty(KEY_STORE_PASSWORD, SAMPLE_PW1);
assertThat(createSut().getKeyStorePassword(), is(SAMPLE_PW1));
}
@Test
public void testGetKeyStorePasswordFromEnv() {
envs.put(EnvSSLCredentialProvider.EnvVars.SOLR_SSL_KEY_STORE_PASSWORD, SAMPLE_PW2);
assertThat(createSut().getKeyStorePassword(), is(SAMPLE_PW2));
}
@Test
public void testGetKeyStorePasswordFromHadoopCredentialProvider() throws IOException {
SSLConfigurations sut = getSutWithMockedHadoopCredentialProvider(SSLConfigurations.SysProps.SSL_KEY_STORE_PASSWORD, SAMPLE_PW3);
assertThat(sut.getKeyStorePassword(), is(SAMPLE_PW3));
}
@Test
public void testGetTrustStorePasswordFromProperty() {
System.setProperty(TRUST_STORE_PASSWORD, SAMPLE_PW1);
assertThat(createSut().getTrustStorePassword(), is(SAMPLE_PW1));
}
@Test
public void testGetTrustStorePasswordFromEnv() {
envs.put(EnvSSLCredentialProvider.EnvVars.SOLR_SSL_TRUST_STORE_PASSWORD, SAMPLE_PW2);
assertThat(createSut().getTrustStorePassword(), is(SAMPLE_PW2));
}
@Test
public void testGetTruststorePasswordFromHadoopCredentialProvider() throws IOException {
SSLConfigurations sut = getSutWithMockedHadoopCredentialProvider(SSLConfigurations.SysProps.SSL_TRUST_STORE_PASSWORD, SAMPLE_PW3);
assertThat(sut.getTrustStorePassword(), is(SAMPLE_PW3));
}
@Test
public void testGetClientKeyStorePasswordFromProperty() {
System.setProperty(CLIENT_KEY_STORE_PASSWORD, SAMPLE_PW1);
assertThat(createSut().getClientKeyStorePassword(), is(SAMPLE_PW1));
}
@Test
public void testGetClientKeyStorePasswordFromEnv() {
envs.put(EnvSSLCredentialProvider.EnvVars.SOLR_SSL_CLIENT_KEY_STORE_PASSWORD, SAMPLE_PW2);
assertThat(createSut().getClientKeyStorePassword(), is(SAMPLE_PW2));
}
@Test
public void testGetClientKeyStorePasswordFromHadoopCredentialProvider() throws IOException {
SSLConfigurations sut = getSutWithMockedHadoopCredentialProvider(SSLConfigurations.SysProps.SSL_CLIENT_KEY_STORE_PASSWORD, SAMPLE_PW3);
assertThat(sut.getClientKeyStorePassword(), is(SAMPLE_PW3));
}
@Test
public void testGetClientTrustStorePasswordFromProperty() {
System.setProperty(CLIENT_TRUST_STORE_PASSWORD, SAMPLE_PW1);
assertThat(createSut().getClientTrustStorePassword(), is(SAMPLE_PW1));
}
@Test
public void testGetClientTrustStorePasswordFromEnv() {
envs.put(EnvSSLCredentialProvider.EnvVars.SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD, SAMPLE_PW2);
assertThat(createSut().getClientTrustStorePassword(), is(SAMPLE_PW2));
}
@Test
public void testGetClientTruststorePasswordFromHadoopCredentialProvider() throws IOException {
SSLConfigurations sut = getSutWithMockedHadoopCredentialProvider(SSLConfigurations.SysProps.SSL_CLIENT_TRUST_STORE_PASSWORD, SAMPLE_PW3);
assertThat(sut.getClientTrustStorePassword(), is(SAMPLE_PW3));
}
@Test
public void testSystemPropertyPriorityOverEnvVar() throws IOException {
envs.put(EnvSSLCredentialProvider.EnvVars.SOLR_SSL_KEY_STORE_PASSWORD, SAMPLE_PW2);
assertThat(createSut().getKeyStorePassword(), is(SAMPLE_PW2));
System.setProperty(KEY_STORE_PASSWORD, SAMPLE_PW1);
assertThat(createSut().getKeyStorePassword(), is(SAMPLE_PW2));
}
@Test
public void testHadoopCredentialProviderPrioritySysPropAndEnvVars() throws IOException {
envs.put(EnvSSLCredentialProvider.EnvVars.SOLR_SSL_KEY_STORE_PASSWORD, SAMPLE_PW2);
assertThat(createSut().getKeyStorePassword(), is(SAMPLE_PW2));
System.setProperty(KEY_STORE_PASSWORD, SAMPLE_PW1);
assertThat(createSut().getKeyStorePassword(), is(SAMPLE_PW2));
SSLConfigurations sut = getSutWithMockedHadoopCredentialProvider(KEY_STORE_PASSWORD, SAMPLE_PW3);
assertThat(sut.getKeyStorePassword(), is(SAMPLE_PW3));
}
private SSLConfigurations getSutWithMockedHadoopCredentialProvider(String key, String pw) throws IOException {
Configuration mockHadoopConfiguration = getMockHadoopConfiguration();
when(mockHadoopConfiguration.getPassword(key))
.then(invocationOnMock -> invocationOnMock.getArguments()[0].equals(key) ? pw.toCharArray() : null);
System.setProperty(CREDENTIAL_PROVIDER_PATH, "/some/path"); // enables HCP
return createSut(mockHadoopConfiguration);
}
private Configuration getMockHadoopConfiguration() {
SolrTestCaseJ4.assumeWorkingMockito();
return Mockito.mock(Configuration.class);
}
}

View File

@ -0,0 +1,90 @@
/*
* 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.util.configuration;
import java.util.List;
import org.apache.lucene.util.TestRuleRestoreSystemProperties;
import org.apache.solr.util.configuration.providers.EnvSSLCredentialProvider;
import org.apache.solr.util.configuration.providers.SysPropSSLCredentialProvider;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
/**
*/
public class SSLCredentialProviderFactoryTest {
@Rule
public TestRule syspropRestore = new TestRuleRestoreSystemProperties(
SSLCredentialProviderFactory.PROVIDER_CHAIN_KEY
);
@Test
public void testGetProvidersOrder() {
SSLCredentialProviderFactory sut = getSut("sysprop;env");
List<SSLCredentialProvider> providers = sut.getProviders();
assertThat(providers.get(0), is(SysPropSSLCredentialProvider.class));
assertThat(providers.get(1), is(EnvSSLCredentialProvider.class));
sut = getSut("env;sysprop");
providers = sut.getProviders();
assertThat(providers.get(0), is(EnvSSLCredentialProvider.class));
assertThat(providers.get(1), is(SysPropSSLCredentialProvider.class));
}
@Test
public void testGetProvidersWithCustomProvider() {
SSLCredentialProviderFactory sut = getSut("sysprop;class://" + CustomSSLCredentialProvider.class.getName() + ";env");
List<SSLCredentialProvider> providers = sut.getProviders();
assertThat(providers.get(0), is(SysPropSSLCredentialProvider.class));
assertThat(providers.get(1), is(CustomSSLCredentialProvider.class));
assertThat(providers.get(2), is(EnvSSLCredentialProvider.class));
}
@Test(expected = RuntimeException.class)
public void testGetProvidersInvalidProvider() {
getSut("sysprop;DoesNotExists").getProviders();
}
@Test
public void testGetProvidersBySysprop() {
String chain = "sysprop;class://" + CustomSSLCredentialProvider.class.getName() + ";env";
System.setProperty(SSLCredentialProviderFactory.PROVIDER_CHAIN_KEY, chain);
SSLCredentialProviderFactory sut = new SSLCredentialProviderFactory();
List<SSLCredentialProvider> providers = sut.getProviders();
assertThat(providers.get(0), is(SysPropSSLCredentialProvider.class));
assertThat(providers.get(1), is(CustomSSLCredentialProvider.class));
assertThat(providers.get(2), is(EnvSSLCredentialProvider.class));
}
private SSLCredentialProviderFactory getSut(String providerChain) {
return new SSLCredentialProviderFactory(providerChain);
}
static public class CustomSSLCredentialProvider implements SSLCredentialProvider {
@Override
public String getCredential(CredentialType type) {
return null;
}
}
}

View File

@ -0,0 +1,61 @@
/*
* 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.util.configuration.providers;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import org.apache.solr.util.configuration.SSLCredentialProvider;
import org.junit.Test;
import static org.apache.solr.util.configuration.providers.AbstractSSLCredentialProvider.DEFAULT_CREDENTIAL_KEY_MAP;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
/**
*/
public class EnvSSLCredentialProviderTest {
@Test
public void testGetCredentials() throws Exception {
int cnt = 0;
Map<String, String> envvars = ImmutableMap.of(
EnvSSLCredentialProvider.EnvVars.SOLR_SSL_KEY_STORE_PASSWORD, "pw" + ++cnt,
EnvSSLCredentialProvider.EnvVars.SOLR_SSL_TRUST_STORE_PASSWORD, "pw" + ++cnt,
EnvSSLCredentialProvider.EnvVars.SOLR_SSL_CLIENT_KEY_STORE_PASSWORD, "pw" + ++cnt,
EnvSSLCredentialProvider.EnvVars.SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD, "pw" + ++cnt
);
EnvSSLCredentialProvider sut = new EnvSSLCredentialProvider();
sut.setEnvVars(envvars);
cnt = 0;
for (Map.Entry<SSLCredentialProvider.CredentialType, String> set : DEFAULT_CREDENTIAL_KEY_MAP.entrySet()) {
String expectedpw = "pw" + ++cnt;
assertThat(sut.getCredential(set.getKey()), is(expectedpw));
}
}
@Test
public void testGetCredentialsWithEnvVars() throws Exception {
EnvSSLCredentialProvider sut = new EnvSSLCredentialProvider();
// assuming not to fail
sut.getCredential(SSLCredentialProvider.CredentialType.SSL_KEY_STORE_PASSWORD);
sut.getCredential(SSLCredentialProvider.CredentialType.SSL_CLIENT_KEY_STORE_PASSWORD);
sut.getCredential(SSLCredentialProvider.CredentialType.SSL_TRUST_STORE_PASSWORD);
sut.getCredential(SSLCredentialProvider.CredentialType.SSL_CLIENT_TRUST_STORE_PASSWORD);
}
}

View File

@ -0,0 +1,74 @@
/*
* 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.util.configuration.providers;
import java.io.IOException;
import java.util.Map;
import org.apache.hadoop.conf.Configuration;
import org.apache.lucene.util.TestRuleRestoreSystemProperties;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.util.configuration.SSLCredentialProvider;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.mockito.Mockito;
import static org.apache.hadoop.security.alias.CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH;
import static org.apache.solr.util.configuration.providers.AbstractSSLCredentialProvider.DEFAULT_CREDENTIAL_KEY_MAP;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;
/**
*/
public class HadoopSSLCredentialProviderTest {
@Rule
public TestRule syspropRestore = new TestRuleRestoreSystemProperties(
CREDENTIAL_PROVIDER_PATH
);
@Test(expected = RuntimeException.class)
public void testConstructorRequiresCredPath() {
new HadoopSSLCredentialProvider(getMockHadoopConfiguration());
}
@Test
public void testGetCredentials() throws Exception {
int cnt = 0;
for (Map.Entry<SSLCredentialProvider.CredentialType, String> set : DEFAULT_CREDENTIAL_KEY_MAP.entrySet()) {
String pw = "pw" + ++cnt;
HadoopSSLCredentialProvider sut = new HadoopSSLCredentialProvider(getMockedHadoopCredentialProvider(set.getValue(), pw));
assertThat(sut.getCredential(set.getKey()), is(pw));
}
}
private Configuration getMockedHadoopCredentialProvider(String key, String pw) throws IOException {
Configuration mockHadoopConfiguration = getMockHadoopConfiguration();
when(mockHadoopConfiguration.getPassword(key))
.then(invocationOnMock -> invocationOnMock.getArguments()[0].equals(key) ? pw.toCharArray() : null);
System.setProperty(CREDENTIAL_PROVIDER_PATH, "/some/path"); // enables HCP
return mockHadoopConfiguration;
}
private Configuration getMockHadoopConfiguration() {
SolrTestCaseJ4.assumeWorkingMockito();
return Mockito.mock(Configuration.class);
}
}

View File

@ -0,0 +1,66 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.util.configuration.providers;
import java.util.Map;
import org.apache.lucene.util.TestRuleRestoreSystemProperties;
import org.apache.solr.util.configuration.SSLConfigurations;
import org.apache.solr.util.configuration.SSLCredentialProvider;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import static org.apache.solr.util.configuration.providers.AbstractSSLCredentialProvider.DEFAULT_CREDENTIAL_KEY_MAP;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
/**
*/
public class SysPropSSLCredentialProviderTest {
@Rule
public TestRule syspropRestore = new TestRuleRestoreSystemProperties(
SSLConfigurations.SysProps.SSL_KEY_STORE_PASSWORD,
SSLConfigurations.SysProps.SSL_TRUST_STORE_PASSWORD,
SSLConfigurations.SysProps.SSL_CLIENT_KEY_STORE_PASSWORD,
SSLConfigurations.SysProps.SSL_CLIENT_TRUST_STORE_PASSWORD
);
@Test
public void testGetCredentials() throws Exception {
int cnt = 0;
SysPropSSLCredentialProvider sut = new SysPropSSLCredentialProvider();
for (Map.Entry<SSLCredentialProvider.CredentialType, String> set : DEFAULT_CREDENTIAL_KEY_MAP.entrySet()) {
String pw = "pw" + ++cnt;
System.setProperty(set.getValue(), pw);
assertThat(sut.getCredential(set.getKey()), is(pw));
}
}
@Test
public void testGetCredentialsWithoutSetup() throws Exception {
SysPropSSLCredentialProvider sut = new SysPropSSLCredentialProvider();
// assuming not to fail
sut.getCredential(SSLCredentialProvider.CredentialType.SSL_KEY_STORE_PASSWORD);
sut.getCredential(SSLCredentialProvider.CredentialType.SSL_CLIENT_KEY_STORE_PASSWORD);
sut.getCredential(SSLCredentialProvider.CredentialType.SSL_TRUST_STORE_PASSWORD);
sut.getCredential(SSLCredentialProvider.CredentialType.SSL_CLIENT_TRUST_STORE_PASSWORD);
}
}

View File

@ -7,10 +7,14 @@
<!-- and either jetty-https.xml or jetty-spdy.xml (but not both) -->
<!-- ============================================================= -->
<Configure id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
<Call class="org.apache.solr.util.configuration.SSLConfigurationsFactory" name="current">
<Get name="keyStorePassword" id="keyStorePassword"/>
<Get name="trustStorePassword" id="trustStorePassword"/>
</Call>
<Set name="KeyStorePath"><Property name="solr.jetty.keystore" default="./etc/solr-ssl.keystore.jks"/></Set>
<Set name="KeyStorePassword"><Env name="SOLR_SSL_KEY_STORE_PASSWORD" default="secret"/></Set>
<Set name="KeyStorePassword"><Ref refid="keyStorePassword"/></Set>
<Set name="TrustStorePath"><Property name="solr.jetty.truststore" default="./etc/solr-ssl.keystore.jks"/></Set>
<Set name="TrustStorePassword"><Env name="SOLR_SSL_TRUST_STORE_PASSWORD" default="secret"/></Set>
<Set name="TrustStorePassword"><Ref refid="trustStorePassword"/></Set>
<Set name="NeedClientAuth"><Property name="solr.jetty.ssl.needClientAuth" default="false"/></Set>
<Set name="WantClientAuth"><Property name="solr.jetty.ssl.wantClientAuth" default="false"/></Set>
<Set name="KeyStoreType"><Property name="solr.jetty.keystore.type" default="JKS"/></Set>