blob: 0681ecf3e15610debe14b1b529b2d9197545d85b [file] [log] [blame]
/*
* 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.geode.internal.net;
import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_ENABLED;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_CIPHERS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_CLUSTER_ALIAS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_DEFAULT_ALIAS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_ENABLED_COMPONENTS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_GATEWAY_ALIAS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_JMX_ALIAS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE_PASSWORD;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE_TYPE;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_LOCATOR_ALIAS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_PROTOCOLS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_SERVER_ALIAS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_TRUSTSTORE;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_TRUSTSTORE_PASSWORD;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_WEB_ALIAS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_WEB_SERVICE_REQUIRE_AUTHENTICATION;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.security.KeyStore;
import java.util.Properties;
import org.apache.commons.lang3.StringUtils;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.RestoreSystemProperties;
import org.junit.experimental.categories.Category;
import org.apache.geode.GemFireConfigException;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.distributed.internal.DistributionConfigImpl;
import org.apache.geode.internal.admin.SSLConfig;
import org.apache.geode.internal.security.SecurableCommunicationChannel;
import org.apache.geode.test.junit.categories.MembershipTest;
@Category(MembershipTest.class)
public class SSLConfigurationFactoryJUnitTest {
@Rule
public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
@After
public void tearDownTest() {
SSLConfigurationFactory.close();
}
@Test
public void getNonSSLConfiguration() {
Properties properties = new Properties();
DistributionConfigImpl distributionConfig = new DistributionConfigImpl(properties);
SSLConfigurationFactory.setDistributionConfig(distributionConfig);
for (SecurableCommunicationChannel securableComponent : SecurableCommunicationChannel
.values()) {
assertSSLConfig(properties,
SSLConfigurationFactory.getSSLConfigForComponent(securableComponent), securableComponent,
distributionConfig);
}
}
@Test
public void getSSLConfigForComponentShouldThrowExceptionForUnknownComponents() {
Properties properties = new Properties();
properties.setProperty(SSL_ENABLED_COMPONENTS, "none");
assertThatThrownBy(() -> new DistributionConfigImpl(properties))
.isInstanceOf(IllegalArgumentException.class)
.hasCauseInstanceOf(GemFireConfigException.class)
.hasMessageContaining("There is no registered component for the name: none");
}
@Test
public void getSSLConfigWithCommaDelimitedProtocols() {
Properties properties = new Properties();
properties.setProperty(SSL_ENABLED_COMPONENTS, "all");
properties.setProperty(SSL_KEYSTORE, "someKeyStore");
properties.setProperty(SSL_KEYSTORE_PASSWORD, "keystorePassword");
properties.setProperty(SSL_KEYSTORE_TYPE, "JKS");
properties.setProperty(SSL_TRUSTSTORE, "someKeyStore");
properties.setProperty(SSL_TRUSTSTORE_PASSWORD, "keystorePassword");
properties.setProperty(SSL_DEFAULT_ALIAS, "defaultAlias");
properties.setProperty(SSL_CIPHERS, "Cipher1,Cipher2");
properties.setProperty(SSL_PROTOCOLS, "Protocol1,Protocol2");
DistributionConfigImpl distributionConfig = new DistributionConfigImpl(properties);
SSLConfigurationFactory.setDistributionConfig(distributionConfig);
assertSSLConfigForChannels(properties, distributionConfig);
}
@Test
public void getSSLConfigWithCommaDelimitedCiphers() {
Properties properties = new Properties();
properties.setProperty(SSL_ENABLED_COMPONENTS, "all");
properties.setProperty(SSL_KEYSTORE, "someKeyStore");
properties.setProperty(SSL_KEYSTORE_PASSWORD, "keystorePassword");
properties.setProperty(SSL_KEYSTORE_TYPE, "JKS");
properties.setProperty(SSL_TRUSTSTORE, "someKeyStore");
properties.setProperty(SSL_TRUSTSTORE_PASSWORD, "keystorePassword");
properties.setProperty(SSL_DEFAULT_ALIAS, "defaultAlias");
properties.setProperty(SSL_CIPHERS, "Cipher1,Cipher2");
properties.setProperty(SSL_PROTOCOLS, "any");
DistributionConfigImpl distributionConfig = new DistributionConfigImpl(properties);
SSLConfigurationFactory.setDistributionConfig(distributionConfig);
assertSSLConfigForChannels(properties, distributionConfig);
}
@Test
public void getSSLConfigForComponentALL() {
Properties properties = new Properties();
properties.setProperty(SSL_ENABLED_COMPONENTS, "all");
properties.setProperty(SSL_KEYSTORE, "someKeyStore");
properties.setProperty(SSL_KEYSTORE_PASSWORD, "keystorePassword");
properties.setProperty(SSL_KEYSTORE_TYPE, "JKS");
properties.setProperty(SSL_TRUSTSTORE, "someKeyStore");
properties.setProperty(SSL_TRUSTSTORE_PASSWORD, "keystorePassword");
properties.setProperty(SSL_DEFAULT_ALIAS, "defaultAlias");
properties.setProperty(SSL_CIPHERS, "any");
properties.setProperty(SSL_PROTOCOLS, "any");
DistributionConfigImpl distributionConfig = new DistributionConfigImpl(properties);
SSLConfigurationFactory.setDistributionConfig(distributionConfig);
assertSSLConfigForChannels(properties, distributionConfig);
}
@Test
public void getSSLConfigForComponentHTTPService() {
Properties properties = new Properties();
properties.setProperty(SSL_ENABLED_COMPONENTS, SecurableCommunicationChannel.WEB.getConstant());
properties.setProperty(SSL_KEYSTORE, "someKeyStore");
properties.setProperty(SSL_KEYSTORE_PASSWORD, "keystorePassword");
properties.setProperty(SSL_KEYSTORE_TYPE, "JKS");
properties.setProperty(SSL_TRUSTSTORE, "someKeyStore");
properties.setProperty(SSL_TRUSTSTORE_PASSWORD, "keystorePassword");
properties.setProperty(SSL_DEFAULT_ALIAS, "defaultAlias");
properties.setProperty(SSL_CIPHERS, "any");
properties.setProperty(SSL_PROTOCOLS, "any");
DistributionConfigImpl distributionConfig = new DistributionConfigImpl(properties);
SSLConfigurationFactory.setDistributionConfig(distributionConfig);
assertSSLConfigForChannels(properties, distributionConfig);
}
@Test
public void getSSLConfigForComponentHTTPServiceWithAlias() {
Properties properties = new Properties();
properties.setProperty(SSL_ENABLED_COMPONENTS, SecurableCommunicationChannel.WEB.getConstant());
properties.setProperty(SSL_KEYSTORE, "someKeyStore");
properties.setProperty(SSL_KEYSTORE_PASSWORD, "keystorePassword");
properties.setProperty(SSL_KEYSTORE_TYPE, "JKS");
properties.setProperty(SSL_TRUSTSTORE, "someKeyStore");
properties.setProperty(SSL_TRUSTSTORE_PASSWORD, "keystorePassword");
properties.setProperty(SSL_DEFAULT_ALIAS, "defaultAlias");
properties.setProperty(SSL_WEB_ALIAS, "httpAlias");
properties.setProperty(SSL_CIPHERS, "any");
properties.setProperty(SSL_PROTOCOLS, "any");
DistributionConfigImpl distributionConfig = new DistributionConfigImpl(properties);
SSLConfigurationFactory.setDistributionConfig(distributionConfig);
assertSSLConfigForChannels(properties, distributionConfig);
}
@Test
public void getSSLConfigForComponentHTTPServiceWithMutualAuth() {
Properties properties = new Properties();
properties.setProperty(SSL_ENABLED_COMPONENTS, SecurableCommunicationChannel.WEB.getConstant());
properties.setProperty(SSL_KEYSTORE, "someKeyStore");
properties.setProperty(SSL_KEYSTORE_PASSWORD, "keystorePassword");
properties.setProperty(SSL_KEYSTORE_TYPE, "JKS");
properties.setProperty(SSL_TRUSTSTORE, "someKeyStore");
properties.setProperty(SSL_TRUSTSTORE_PASSWORD, "keystorePassword");
properties.setProperty(SSL_DEFAULT_ALIAS, "defaultAlias");
properties.setProperty(SSL_WEB_ALIAS, "httpAlias");
properties.setProperty(SSL_WEB_SERVICE_REQUIRE_AUTHENTICATION, "true");
properties.setProperty(SSL_CIPHERS, "any");
properties.setProperty(SSL_PROTOCOLS, "any");
DistributionConfigImpl distributionConfig = new DistributionConfigImpl(properties);
SSLConfigurationFactory.setDistributionConfig(distributionConfig);
assertSSLConfigForChannels(properties, distributionConfig);
}
@Test
public void getSSLConfigUsingJavaProperties() {
Properties properties = new Properties();
properties.setProperty(CLUSTER_SSL_ENABLED, "true");
properties.setProperty(MCAST_PORT, "0");
System.setProperty(SSLConfigurationFactory.JAVAX_KEYSTORE, "keystore");
System.setProperty(SSLConfigurationFactory.JAVAX_KEYSTORE_TYPE, KeyStore.getDefaultType());
System.setProperty(SSLConfigurationFactory.JAVAX_KEYSTORE_PASSWORD, "keystorePassword");
System.setProperty(SSLConfigurationFactory.JAVAX_TRUSTSTORE, "truststore");
System.setProperty(SSLConfigurationFactory.JAVAX_TRUSTSTORE_PASSWORD, "truststorePassword");
System.setProperty(SSLConfigurationFactory.JAVAX_TRUSTSTORE_TYPE, KeyStore.getDefaultType());
DistributionConfigImpl distributionConfig = new DistributionConfigImpl(properties);
SSLConfigurationFactory.setDistributionConfig(distributionConfig);
SSLConfig sslConfig =
SSLConfigurationFactory.getSSLConfigForComponent(SecurableCommunicationChannel.CLUSTER);
assertThat(sslConfig.isEnabled()).isTrue();
assertThat(sslConfig.getKeystore())
.isEqualTo(System.getProperty(SSLConfigurationFactory.JAVAX_KEYSTORE));
assertThat(sslConfig.getKeystorePassword())
.isEqualTo(System.getProperty(SSLConfigurationFactory.JAVAX_KEYSTORE_PASSWORD));
assertThat(sslConfig.getKeystoreType())
.isEqualTo(System.getProperty(SSLConfigurationFactory.JAVAX_KEYSTORE_TYPE));
assertThat(sslConfig.getTruststore())
.isEqualTo(System.getProperty(SSLConfigurationFactory.JAVAX_TRUSTSTORE));
assertThat(sslConfig.getTruststorePassword())
.isEqualTo(System.getProperty(SSLConfigurationFactory.JAVAX_TRUSTSTORE_PASSWORD));
assertThat(sslConfig.getTruststoreType())
.isEqualTo(System.getProperty(SSLConfigurationFactory.JAVAX_TRUSTSTORE_TYPE));
assertThat(sslConfig.isEnabled()).isTrue();
assertThat(sslConfig.getKeystore())
.isEqualTo(System.getProperty(SSLConfigurationFactory.JAVAX_KEYSTORE));
assertThat(sslConfig.getKeystorePassword())
.isEqualTo(System.getProperty(SSLConfigurationFactory.JAVAX_KEYSTORE_PASSWORD));
assertThat(sslConfig.getKeystoreType())
.isEqualTo(System.getProperty(SSLConfigurationFactory.JAVAX_KEYSTORE_TYPE));
assertThat(sslConfig.getTruststore())
.isEqualTo(System.getProperty(SSLConfigurationFactory.JAVAX_TRUSTSTORE));
assertThat(sslConfig.getTruststorePassword())
.isEqualTo(System.getProperty(SSLConfigurationFactory.JAVAX_TRUSTSTORE_PASSWORD));
assertThat(sslConfig.getTruststoreType())
.isEqualTo(System.getProperty(SSLConfigurationFactory.JAVAX_TRUSTSTORE_TYPE));
}
@Test
public void getSSLHTTPMutualAuthenticationOffWithDefaultConfiguration() {
Properties properties = new Properties();
properties.setProperty(CLUSTER_SSL_ENABLED, "true");
properties.setProperty(MCAST_PORT, "0");
DistributionConfigImpl distributionConfig = new DistributionConfigImpl(properties);
SSLConfigurationFactory.setDistributionConfig(distributionConfig);
SSLConfig sslConfig =
SSLConfigurationFactory.getSSLConfigForComponent(SecurableCommunicationChannel.WEB);
assertThat(sslConfig.isRequireAuth()).isFalse();
assertThat(sslConfig.isEnabled()).isTrue();
sslConfig =
SSLConfigurationFactory.getSSLConfigForComponent(SecurableCommunicationChannel.CLUSTER);
assertThat(sslConfig.isRequireAuth()).isTrue();
assertThat(sslConfig.isEnabled()).isTrue();
sslConfig =
SSLConfigurationFactory.getSSLConfigForComponent(SecurableCommunicationChannel.GATEWAY);
assertThat(sslConfig.isRequireAuth()).isTrue();
assertThat(sslConfig.isEnabled()).isTrue();
sslConfig =
SSLConfigurationFactory.getSSLConfigForComponent(SecurableCommunicationChannel.SERVER);
assertThat(sslConfig.isRequireAuth()).isTrue();
assertThat(sslConfig.isEnabled()).isTrue();
sslConfig = SSLConfigurationFactory.getSSLConfigForComponent(SecurableCommunicationChannel.JMX);
assertThat(sslConfig.isRequireAuth()).isTrue();
assertThat(sslConfig.isEnabled()).isTrue();
}
@Test
public void setDistributionConfig() {
Properties properties = new Properties();
properties.setProperty(SSL_ENABLED_COMPONENTS, "all");
properties.setProperty(SSL_KEYSTORE, "someKeyStore");
DistributionConfigImpl distributionConfig = new DistributionConfigImpl(properties);
SSLConfigurationFactory.setDistributionConfig(distributionConfig);
SSLConfig sslConfig =
SSLConfigurationFactory.getSSLConfigForComponent(SecurableCommunicationChannel.LOCATOR);
assertThat(sslConfig.isEnabled()).isTrue();
assertThat(sslConfig.getKeystore()).isEqualTo("someKeyStore");
properties.setProperty(SSL_ENABLED_COMPONENTS, SecurableCommunicationChannel.JMX.getConstant());
properties.setProperty(SSL_KEYSTORE, "someOtherKeyStore");
sslConfig = SSLConfigurationFactory.getSSLConfigForComponent(properties,
SecurableCommunicationChannel.LOCATOR);
assertThat(sslConfig.isEnabled()).isFalse();
assertThat(sslConfig.getKeystore()).isEqualTo("someOtherKeyStore");
}
private void assertSSLConfig(final Properties properties, final SSLConfig sslConfig,
final SecurableCommunicationChannel expectedSecurableComponent,
final DistributionConfigImpl distributionConfig) {
assertThat(sslConfig.isEnabled()).isEqualTo(isSSLComponentEnabled(expectedSecurableComponent,
distributionConfig.getSecurableCommunicationChannels()));
if (sslConfig.isEnabled()) {
assertThat(sslConfig.getKeystore()).isEqualTo(properties.getProperty(SSL_KEYSTORE));
assertThat(sslConfig.getKeystorePassword())
.isEqualTo(properties.getProperty(SSL_KEYSTORE_PASSWORD));
assertThat(sslConfig.getKeystoreType()).isEqualTo(properties.getProperty(SSL_KEYSTORE_TYPE));
assertThat(sslConfig.getTruststore()).isEqualTo(properties.getProperty(SSL_TRUSTSTORE));
assertThat(sslConfig.getTruststorePassword())
.isEqualTo(properties.getProperty(SSL_TRUSTSTORE_PASSWORD));
assertThat(sslConfig.getCiphers())
.isEqualTo(properties.getProperty(SSL_CIPHERS).replace(",", " "));
assertThat(sslConfig.getProtocols())
.isEqualTo(properties.getProperty(SSL_PROTOCOLS).replace(",", " "));
assertThat(sslConfig.getAlias())
.isEqualTo(getCorrectAlias(expectedSecurableComponent, properties));
assertThat(sslConfig.isRequireAuth())
.isEqualTo(requiresAuthentication(properties, expectedSecurableComponent));
assertThat(sslConfig.getSecuredCommunicationChannel()).isEqualTo(expectedSecurableComponent);
}
}
private void assertSSLConfigForChannels(final Properties distributionConfigProperties,
final DistributionConfigImpl distributionConfig) {
for (SecurableCommunicationChannel securableComponent : SecurableCommunicationChannel
.values()) {
assertSSLConfig(distributionConfigProperties,
SSLConfigurationFactory.getSSLConfigForComponent(securableComponent), securableComponent,
distributionConfig);
}
}
private boolean requiresAuthentication(final Properties properties,
final SecurableCommunicationChannel expectedSecurableComponent) {
boolean defaultAuthentication =
expectedSecurableComponent.equals(SecurableCommunicationChannel.WEB)
? DistributionConfig.DEFAULT_SSL_WEB_SERVICE_REQUIRE_AUTHENTICATION
: DistributionConfig.DEFAULT_SSL_REQUIRE_AUTHENTICATION;
String httpRequiresAuthentication =
properties.getProperty(SSL_WEB_SERVICE_REQUIRE_AUTHENTICATION);
return httpRequiresAuthentication == null ? defaultAuthentication
: Boolean.parseBoolean(httpRequiresAuthentication);
}
private String getCorrectAlias(final SecurableCommunicationChannel expectedSecurableComponent,
final Properties properties) {
switch (expectedSecurableComponent) {
case ALL:
return properties.getProperty(SSL_DEFAULT_ALIAS);
case CLUSTER:
return getAliasForComponent(properties, SSL_CLUSTER_ALIAS);
case GATEWAY:
return getAliasForComponent(properties, SSL_GATEWAY_ALIAS);
case WEB:
return getAliasForComponent(properties, SSL_WEB_ALIAS);
case JMX:
return getAliasForComponent(properties, SSL_JMX_ALIAS);
case LOCATOR:
return getAliasForComponent(properties, SSL_LOCATOR_ALIAS);
case SERVER:
return getAliasForComponent(properties, SSL_SERVER_ALIAS);
default:
return properties.getProperty(SSL_DEFAULT_ALIAS);
}
}
private String getAliasForComponent(final Properties properties,
final String componentAliasProperty) {
String aliasProperty = properties.getProperty(componentAliasProperty);
return !StringUtils.isEmpty(aliasProperty) ? aliasProperty
: properties.getProperty(SSL_DEFAULT_ALIAS);
}
private boolean isSSLComponentEnabled(
final SecurableCommunicationChannel expectedSecurableComponent,
final SecurableCommunicationChannel[] securableComponents) {
for (SecurableCommunicationChannel securableCommunicationChannel : securableComponents) {
if (SecurableCommunicationChannel.ALL.equals(securableCommunicationChannel)
|| securableCommunicationChannel.equals(expectedSecurableComponent)) {
return true;
}
}
return false;
}
}