blob: c79424783bf3b9ac5dae76edb39f53af7b822d31 [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.management.internal.cli.commands;
import static org.apache.geode.security.SecurableCommunicationChannels.ALL;
import static org.apache.geode.security.SecurableCommunicationChannels.JMX;
import static org.apache.geode.security.SecurableCommunicationChannels.LOCATOR;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Properties;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.apache.geode.cache.ssl.CertStores;
import org.apache.geode.cache.ssl.TestSSLUtils.CertificateBuilder;
import org.apache.geode.test.dunit.IgnoredException;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.rules.ClusterStartupRule;
import org.apache.geode.test.dunit.rules.MemberVM;
import org.apache.geode.test.junit.categories.GfshTest;
import org.apache.geode.test.junit.rules.GfshCommandRule;
@Category({GfshTest.class})
public class GfshHostNameVerificationDistributedTest {
private static MemberVM locator;
@Rule
public ClusterStartupRule cluster = new ClusterStartupRule();
@Rule
public GfshCommandRule gfsh = new GfshCommandRule();
private CertStores locatorStore;
private CertStores gfshStore;
@Before
public void setupCluster() throws Exception {
CertificateBuilder locatorCertificate = new CertificateBuilder()
.commonName("locator")
.sanDnsName(InetAddress.getLoopbackAddress().getHostName())
.sanDnsName(InetAddress.getLocalHost().getHostName())
.sanIpAddress(InetAddress.getLocalHost())
.sanIpAddress(InetAddress.getByName("0.0.0.0")); // to pass on windows
CertificateBuilder gfshCertificate = new CertificateBuilder()
.commonName("gfsh");
locatorStore = CertStores.locatorStore();
gfshStore = CertStores.clientStore();
locatorStore.withCertificate(locatorCertificate);
gfshStore.withCertificate(gfshCertificate);
locatorStore
.trustSelf()
.trust(gfshStore.alias(), gfshStore.certificate());
gfshStore
.trust(locatorStore.alias(), locatorStore.certificate());
}
private File gfshSecurityProperties(Properties clientSSLProps) throws IOException {
File sslConfigFile = File.createTempFile("gfsh-ssl", "properties");
FileOutputStream out = new FileOutputStream(sslConfigFile);
clientSSLProps.store(out, null);
return sslConfigFile;
}
@Test
public void gfshConnectsToLocator() throws Exception {
Properties locatorSSLProps = locatorStore.propertiesWith(LOCATOR);
Properties gfshSSLProps = gfshStore.propertiesWith(LOCATOR);
// create a cluster
locator = cluster.startLocatorVM(0, locatorSSLProps);
// connect gfsh
File sslConfigFile = gfshSecurityProperties(gfshSSLProps);
gfsh.connectAndVerify(locator.getPort(), GfshCommandRule.PortType.locator,
"security-properties-file", sslConfigFile.getAbsolutePath());
gfsh.executeAndAssertThat("list members").statusIsSuccess();
}
@Test
public void expectConnectionFailureWhenNoHostNameInLocatorKey() throws Exception {
CertificateBuilder locatorCertificate = new CertificateBuilder()
.commonName("locator");
validateGfshConnection(locatorCertificate);
}
@Test
public void expectConnectionFailureWhenWrongHostNameInLocatorKey() throws Exception {
CertificateBuilder locatorCertificate = new CertificateBuilder()
.commonName("locator")
.sanDnsName("example.com");
validateGfshConnection(locatorCertificate);
}
private void validateGfshConnection(CertificateBuilder locatorCertificate)
throws Exception {
CertificateBuilder gfshCertificate = new CertificateBuilder().commonName("gfsh");
CertStores lstore = CertStores.locatorStore();
CertStores gstore = CertStores.clientStore();
lstore.withCertificate(locatorCertificate);
gstore.withCertificate(gfshCertificate);
lstore.trustSelf().trust(gstore.alias(), gstore.certificate());
gstore.trust(lstore.alias(), lstore.certificate());
Properties locatorSSLProps = lstore.propertiesWith(ALL, false, false);
Properties gfshSSLProps = gstore.propertiesWith(ALL, false, true);
// create a cluster
locator = cluster.startLocatorVM(0, locatorSSLProps);
// connect gfsh
File sslConfigFile = gfshSecurityProperties(gfshSSLProps);
IgnoredException.addIgnoredException("javax.net.ssl.SSLHandshakeException");
IgnoredException.addIgnoredException("java.net.SocketException");
String connectCommand =
"connect --locator=" + locator.getVM().getHost().getHostName() + "[" + locator.getPort()
+ "] --security-properties-file=" + sslConfigFile.getAbsolutePath();
gfsh.executeAndAssertThat(connectCommand).statusIsError()
.containsOutput("Unable to form SSL connection");
IgnoredException.removeAllExpectedExceptions();
}
@Test
public void gfshConnectsToLocatorOnJMX() throws Exception {
Properties locatorSSLProps = locatorStore.propertiesWith(JMX);
Properties gfshSSLProps = gfshStore.propertiesWith(JMX);
validateGfshConnectOnJMX(locatorSSLProps, gfshSSLProps);
}
@Test
public void gfshConnectsToLocatorOnJMXWhenALL() throws Exception {
Properties locatorSSLProps = locatorStore.propertiesWith(ALL);
Properties gfshSSLProps = gfshStore.propertiesWith(ALL);
validateGfshConnectOnJMX(locatorSSLProps, gfshSSLProps);
}
private void validateGfshConnectOnJMX(Properties locatorSSLProps, Properties gfshSSLProps)
throws IOException {
// create a cluster
locator = cluster.startLocatorVM(0, locatorSSLProps);
// connect gfsh on jmx
File sslConfigFile = gfshSecurityProperties(gfshSSLProps);
final int jmxPort = locator.getJmxPort();
final String sslConfigFilePath = sslConfigFile.getAbsolutePath();
VM vm = cluster.getVM(1);
vm.invoke(() -> {
GfshCommandRule rule = new GfshCommandRule();
rule.connectAndVerify(jmxPort, GfshCommandRule.PortType.jmxManager,
"security-properties-file", sslConfigFilePath);
rule.executeAndAssertThat("list members").statusIsSuccess();
rule.close();
});
vm.bounce(); // to clear the system properties set by JmxOperationInvoker
}
}