You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by bb...@apache.org on 2020/06/19 13:43:56 UTC
[geode-native] branch develop updated: GEODE-8128: Add SNI tests
using new test framework (#616)
This is an automated email from the ASF dual-hosted git repository.
bbender pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode-native.git
The following commit(s) were added to refs/heads/develop by this push:
new 72459fd GEODE-8128: Add SNI tests using new test framework (#616)
72459fd is described below
commit 72459fdf95be96f46457672abe82a8abbfdc3c0d
Author: Michael Martell <mm...@pivotal.io>
AuthorDate: Fri Jun 19 06:43:46 2020 -0700
GEODE-8128: Add SNI tests using new test framework (#616)
* Update cluster to support propertiesFile, etc.
* Add new SNI test and config folder
* Make sni scripts executable
* Brought services up as daemons and stop them
* Add parsing of proxy port and a couple test cases.
* Inlined forever script and added gfsh script to start the cluster
* Disable the SNI test that requires a real gateway
Co-authored-by: Ernest Burghardt <eb...@pivotal.io>
Co-authored-by: Blake Bender <bb...@pivotal.io>
---
cppcache/integration/framework/Cluster.cpp | 22 ++-
cppcache/integration/framework/Cluster.h | 16 ++
cppcache/integration/framework/Gfsh.cpp | 38 ++++-
cppcache/integration/framework/Gfsh.h | 14 +-
cppcache/integration/test/CMakeLists.txt | 3 +
cppcache/integration/test/SNITest.cpp | 166 +++++++++++++++++++++
cppcache/integration/test/SslOneWayTest.cpp | 16 +-
cppcache/integration/test/SslTwoWayTest.cpp | 16 +-
.../test/sni-test-config/docker-compose.yml | 43 ++++++
.../geode-config/gemfire.properties | 19 +++
.../geode-config/gfsecurity.properties | 27 ++++
.../geode-config/locator-maeve-keystore.jks | Bin 0 -> 2048 bytes
.../geode-config/server-clementine-keystore.jks | Bin 0 -> 2059 bytes
.../geode-config/server-dolores-keystore.jks | Bin 0 -> 2050 bytes
.../sni-test-config/geode-config/truststore.jks | Bin 0 -> 8095 bytes
.../integration/test/sni-test-config/haproxy.cfg | 44 ++++++
.../test/sni-test-config/scripts/forever | 20 +++
.../sni-test-config/scripts/geode-starter-2.gfsh | 23 +++
.../sni-test-config/scripts/geode-starter.gfsh | 22 +++
19 files changed, 456 insertions(+), 33 deletions(-)
diff --git a/cppcache/integration/framework/Cluster.cpp b/cppcache/integration/framework/Cluster.cpp
index 78c621f..91ff454 100644
--- a/cppcache/integration/framework/Cluster.cpp
+++ b/cppcache/integration/framework/Cluster.cpp
@@ -89,7 +89,7 @@ void Locator::start() {
if (cluster_.useSsl()) {
locator.withConnect(false)
.withSslEnabledComponents("all")
- .withSslRquireAuthentication(cluster_.requireSslAuthentication())
+ .withSslRequireAuthentication(cluster_.requireSslAuthentication())
.withSslKeystore(cluster_.keystore())
.withSslTruststore(cluster_.truststore())
.withSslKeystorePassword(cluster_.keystorePassword())
@@ -455,6 +455,26 @@ void Cluster::useSsl(const bool requireSslAuthentication,
bool Cluster::useSsl() { return useSsl_; }
+void Cluster::usePropertiesFile(const std::string propertiesFile) {
+ usePropertiesFile_ = true;
+ propertiesFile_ = propertiesFile;
+}
+
+void Cluster::useSecurityPropertiesFile(const std::string securityPropertiesFile) {
+ useSecurityPropertiesFile_ = true;
+ securityPropertiesFile_ = securityPropertiesFile;
+}
+
+void Cluster::useHostNameForClients(
+ const std::string hostName) {
+ usePropertiesFile_ = true;
+ hostName_ = hostName;
+}
+
+bool Cluster::usePropertiesFile() { return usePropertiesFile_; }
+bool Cluster::useSecurityPropertiesFile() { return useSecurityPropertiesFile_; }
+bool Cluster::useHostNameForClients() { return useHostNameForClients_; }
+
bool Cluster::requireSslAuthentication() { return requireSslAuthentication_; }
std::string Cluster::keystore() { return keystore_; }
diff --git a/cppcache/integration/framework/Cluster.h b/cppcache/integration/framework/Cluster.h
index ee5ca70..bf17eb9 100644
--- a/cppcache/integration/framework/Cluster.h
+++ b/cppcache/integration/framework/Cluster.h
@@ -171,7 +171,15 @@ class Cluster {
const std::string truststorePassword);
bool useSsl();
+
+ void usePropertiesFile(const std::string propertiesFile);
+ void useSecurityPropertiesFile(const std::string securityPropertiesFile);
+ void useHostNameForClients(const std::string hostNameForClients);
+ bool usePropertiesFile();
+ bool useSecurityPropertiesFile();
+ bool useHostNameForClients();
bool requireSslAuthentication();
+
std::string keystore();
std::string truststore();
std::string keystorePassword();
@@ -214,11 +222,19 @@ class Cluster {
bool useSsl_ = false;
bool requireSslAuthentication_ = false;
+ bool usePropertiesFile_ = false;
+ bool useSecurityPropertiesFile_ = false;
+ bool useHostNameForClients_ = false;
+
std::string keystore_;
std::string keystorePassword_;
std::string truststore_;
std::string truststorePassword_;
+ std::string propertiesFile_;
+ std::string securityPropertiesFile_;
+ std::string hostName_;
+
bool useIPv6_ = false;
GfshExecute gfsh_;
diff --git a/cppcache/integration/framework/Gfsh.cpp b/cppcache/integration/framework/Gfsh.cpp
index a29e616..0373dce 100644
--- a/cppcache/integration/framework/Gfsh.cpp
+++ b/cppcache/integration/framework/Gfsh.cpp
@@ -156,13 +156,31 @@ Gfsh::Start::Locator &Gfsh::Start::Locator::withJmxManagerStart(
return *this;
}
-Gfsh::Start::Locator &Gfsh::Start::Locator::withSslRquireAuthentication(
+Gfsh::Start::Locator &Gfsh::Start::Locator::withSslRequireAuthentication(
const bool require) {
command_ += " --J=-Dgemfire.ssl-require-authentication=" +
std::string(require ? "true" : "false");
return *this;
}
+Gfsh::Start::Locator &Gfsh::Start::Locator::withPropertiesFile(
+ const std::string file) {
+ command_ += " --properties-file=" + file;
+ return *this;
+}
+
+Gfsh::Start::Locator &Gfsh::Start::Locator::withSecurityPropertiesFile(
+ const std::string file) {
+ command_ += " --security-properties-file=" + file;
+ return *this;
+}
+
+Gfsh::Start::Locator &Gfsh::Start::Locator::withHostNameForClients(
+ const std::string hostName) {
+ command_ += " --hostname-for-clients=" + hostName;
+ return *this;
+}
+
Gfsh::Start::Server::Server(Gfsh &gfsh) : Command(gfsh, "start server") {}
Gfsh::Start::Server &Gfsh::Start::Server::withName(const std::string &name) {
@@ -288,6 +306,24 @@ Gfsh::Start::Server &Gfsh::Start::Server::withSslRquireAuthentication(
return *this;
}
+Gfsh::Start::Server &Gfsh::Start::Server::withPropertiesFile(
+ const std::string file) {
+ command_ += " --properties-file=" + file;
+ return *this;
+}
+
+Gfsh::Start::Server &Gfsh::Start::Server::withSecurityPropertiesFile(
+ const std::string file) {
+ command_ += " --security-properties-file=" + file;
+ return *this;
+}
+
+Gfsh::Start::Server &Gfsh::Start::Server::withHostNameForClients(
+ const std::string hostName) {
+ command_ += " --hostname-for-clients=" + hostName;
+ return *this;
+}
+
Gfsh::Stop::Stop(Gfsh &gfsh) : gfsh_(gfsh) {}
Gfsh::Stop::Server Gfsh::Stop::server() { return Server{gfsh_}; }
diff --git a/cppcache/integration/framework/Gfsh.h b/cppcache/integration/framework/Gfsh.h
index b775493..4907137 100644
--- a/cppcache/integration/framework/Gfsh.h
+++ b/cppcache/integration/framework/Gfsh.h
@@ -125,7 +125,13 @@ class Gfsh {
Locator &withJmxManagerStart(const bool startJmxManager);
- Locator &withSslRquireAuthentication(const bool require);
+ Locator &withSslRequireAuthentication(const bool require);
+
+ Locator &withPropertiesFile(const std::string file);
+
+ Locator &withSecurityPropertiesFile(const std::string file);
+
+ Locator &withHostNameForClients(const std::string hostName);
};
class Server : public Command<void> {
@@ -169,6 +175,12 @@ class Gfsh {
Server &withSslTruststorePassword(const std::string &truststorePassword);
Server &withSslRquireAuthentication(const bool require);
+
+ Server &withPropertiesFile(const std::string file);
+
+ Server &withSecurityPropertiesFile(const std::string file);
+
+ Server &withHostNameForClients(const std::string hostName);
};
private:
diff --git a/cppcache/integration/test/CMakeLists.txt b/cppcache/integration/test/CMakeLists.txt
index a7554fd..e7be053 100644
--- a/cppcache/integration/test/CMakeLists.txt
+++ b/cppcache/integration/test/CMakeLists.txt
@@ -39,6 +39,7 @@ add_executable(cpp-integration-test
SimpleAuthInitialize.hpp
SimpleCqListener.cpp
SimpleCqListener.hpp
+ SNITest.cpp
SslOneWayTest.cpp
SslTwoWayTest.cpp
StructTest.cpp
@@ -92,6 +93,8 @@ configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/func_cacheserver2_pool.xml
${CMAKE_CURRENT_BINARY_DIR}/func_cacheserver2_pool.xml COPYONLY)
+ file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/sni-test-config DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
+
set_target_properties(cpp-integration-test PROPERTIES
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN ON
diff --git a/cppcache/integration/test/SNITest.cpp b/cppcache/integration/test/SNITest.cpp
new file mode 100644
index 0000000..490abe3
--- /dev/null
+++ b/cppcache/integration/test/SNITest.cpp
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+
+#include <iostream>
+#include <thread>
+
+#include <gtest/gtest.h>
+
+#include <geode/Cache.hpp>
+#include <geode/CacheFactory.hpp>
+#include <geode/RegionFactory.hpp>
+#include <geode/RegionShortcut.hpp>
+
+#include "framework/Cluster.h"
+
+namespace ssltest {
+
+using apache::geode::client::AuthenticationRequiredException;
+using apache::geode::client::CacheableString;
+using apache::geode::client::CacheFactory;
+using apache::geode::client::Exception;
+using apache::geode::client::RegionShortcut;
+
+class SNITest : public ::testing::Test {
+ protected:
+ SNITest() {
+ certificatePassword = std::string("apachegeode");
+ currentWorkingDirectory = boost::filesystem::current_path();
+ }
+
+ ~SNITest() override = default;
+
+ void SetUp() override {
+#if defined(_WIN32)
+ std::string sniDir(currentWorkingDirectory.string());
+ sniDir += "/../sni-test-config";
+ SetCurrentDirectory(sniDir.c_str());
+#else
+ chdir("./sni-test-config");
+#endif
+
+ std::system("docker-compose up -d");
+
+ std::system(
+ "docker exec -t geode gfsh run "
+ "--file=/geode/scripts/geode-starter.gfsh");
+ }
+
+ void TearDown() override { std::system("docker-compose stop"); }
+
+ std::string makeItSo(const char* command) {
+ std::string commandOutput;
+#if defined(_WIN32)
+ std::unique_ptr<FILE, decltype(&_pclose)> pipe(_popen(command, "r"),
+ _pclose);
+#else
+ std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(command, "r"), pclose);
+#endif
+ std::array<char, 128> charBuff;
+ if (!pipe) {
+ throw std::runtime_error("Failed on the POPEN");
+ }
+ while (fgets(charBuff.data(), charBuff.size(), pipe.get()) != nullptr) {
+ commandOutput += charBuff.data();
+ }
+ return commandOutput;
+ }
+
+ int parseProxyPort(std::string proxyString) {
+ // 15443/tcp -> 0.0.0.0:32787
+ std::size_t colonPosition = proxyString.find(":");
+ std::string portNumberString = proxyString.substr((colonPosition + 1));
+ return stoi(portNumberString);
+ }
+
+ std::string certificatePassword;
+ boost::filesystem::path currentWorkingDirectory;
+};
+
+TEST_F(SNITest, DISABLED_connectViaProxyTest) {
+ const auto clientTruststore =
+ (currentWorkingDirectory /
+ boost::filesystem::path("sni-test-config/geode-config/truststore.jks"));
+
+ auto cache = CacheFactory()
+ .set("log-level", "DEBUG")
+ .set("ssl-enabled", "true")
+ .set("ssl-truststore", clientTruststore.string())
+ .create();
+
+ auto portString = makeItSo("docker port haproxy");
+ auto portNumber = parseProxyPort(portString);
+
+ cache.getPoolManager()
+ .createFactory()
+ .addLocator("localhost", portNumber)
+ .create("pool");
+
+ auto region = cache.createRegionFactory(RegionShortcut::PROXY)
+ .setPoolName("pool")
+ .create("region");
+
+ region->put("1", "one");
+
+ cache.close();
+}
+
+TEST_F(SNITest, connectionFailsTest) {
+ const auto clientTruststore =
+ (currentWorkingDirectory /
+ boost::filesystem::path("sni-test-config/geode-config/truststore.jks"));
+
+ auto cache = CacheFactory()
+ .set("log-level", "DEBUG")
+ .set("ssl-enabled", "true")
+ .set("ssl-truststore", clientTruststore.string())
+ .create();
+
+ cache.getPoolManager()
+ .createFactory()
+ .addLocator("localhost", 10334)
+ .create("pool");
+
+ auto region = cache.createRegionFactory(RegionShortcut::PROXY)
+ .setPoolName("pool")
+ .create("region");
+ EXPECT_THROW(region->put("1", "one"),
+ apache::geode::client::NotConnectedException);
+
+ cache.close();
+}
+
+TEST_F(SNITest, doNothingTest) {
+ const auto clientTruststore =
+ (currentWorkingDirectory /
+ boost::filesystem::path("sni-test-config/geode-config/truststore.jks"));
+
+ auto cache = CacheFactory()
+ .set("log-level", "DEBUG")
+ .set("ssl-enabled", "true")
+ .set("ssl-truststore", clientTruststore.string())
+ .create();
+
+ cache.getPoolManager()
+ .createFactory()
+ .addLocator("localhost", 10334)
+ .create("pool");
+
+ cache.close();
+}
+
+} // namespace ssltest
diff --git a/cppcache/integration/test/SslOneWayTest.cpp b/cppcache/integration/test/SslOneWayTest.cpp
index 177e228..d7c10f1 100644
--- a/cppcache/integration/test/SslOneWayTest.cpp
+++ b/cppcache/integration/test/SslOneWayTest.cpp
@@ -36,11 +36,7 @@ using apache::geode::client::RegionShortcut;
class SslOneWayTest : public ::testing::Test {
protected:
- // You can remove any or all of the following functions if their bodies would
- // be empty.
-
SslOneWayTest() {
- // You can do set-up work for each test here.
certificatePassword = std::string("apachegeode");
serverSslKeysDir = boost::filesystem::path(
getFrameworkString(FrameworkVariable::TestServerSslKeysDir));
@@ -49,13 +45,8 @@ class SslOneWayTest : public ::testing::Test {
}
~SslOneWayTest() override = default;
- // You can do clean-up work that doesn't throw exceptions here.
- // If the constructor and destructor are not enough for setting up
- // and cleaning up each test, you can define the following methods:
void SetUp() override {
- // Code here will be called immediately after the constructor (right
- // before each test).
const auto clusterKeystore =
(serverSslKeysDir /
boost::filesystem::path("server_keystore_chained.p12"));
@@ -76,13 +67,8 @@ class SslOneWayTest : public ::testing::Test {
.execute();
}
- void TearDown() override {
- // Code here will be called immediately after each test (right
- // before the destructor).
- }
+ void TearDown() override {}
- // Class members declared here can be used by all tests in the test suite
- // for Ssl.
Cluster cluster = Cluster{LocatorCount{1}, ServerCount{1}};
std::string certificatePassword;
boost::filesystem::path serverSslKeysDir;
diff --git a/cppcache/integration/test/SslTwoWayTest.cpp b/cppcache/integration/test/SslTwoWayTest.cpp
index 01edc50..4cb1b41 100644
--- a/cppcache/integration/test/SslTwoWayTest.cpp
+++ b/cppcache/integration/test/SslTwoWayTest.cpp
@@ -36,11 +36,7 @@ using apache::geode::client::RegionShortcut;
class SslTwoWayTest : public ::testing::Test {
protected:
- // You can remove any or all of the following functions if their bodies would
- // be empty.
-
SslTwoWayTest() {
- // You can do set-up work for each test here.
certificatePassword = std::string("apachegeode");
serverSslKeysDir = boost::filesystem::path(
getFrameworkString(FrameworkVariable::TestServerSslKeysDir));
@@ -49,13 +45,8 @@ class SslTwoWayTest : public ::testing::Test {
}
~SslTwoWayTest() override = default;
- // You can do clean-up work that doesn't throw exceptions here.
- // If the constructor and destructor are not enough for setting up
- // and cleaning up each test, you can define the following methods:
void SetUp() override {
- // Code here will be called immediately after the constructor (right
- // before each test).
const auto clusterKeystore =
(serverSslKeysDir /
boost::filesystem::path("server_keystore_chained.p12"));
@@ -76,13 +67,8 @@ class SslTwoWayTest : public ::testing::Test {
.execute();
}
- void TearDown() override {
- // Code here will be called immediately after each test (right
- // before the destructor).
- }
+ void TearDown() override {}
- // Class members declared here can be used by all tests in the test suite
- // for Ssl.
Cluster cluster = Cluster{LocatorCount{1}, ServerCount{1}};
std::string certificatePassword;
boost::filesystem::path serverSslKeysDir;
diff --git a/cppcache/integration/test/sni-test-config/docker-compose.yml b/cppcache/integration/test/sni-test-config/docker-compose.yml
new file mode 100644
index 0000000..b0a6100
--- /dev/null
+++ b/cppcache/integration/test/sni-test-config/docker-compose.yml
@@ -0,0 +1,43 @@
+#
+# 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.
+#
+version: '3'
+services:
+ geode:
+ container_name: 'geode'
+ image: 'apachegeode/geode'
+ expose:
+ - '10334'
+ - '40404'
+ entrypoint: 'sh'
+ command: ["-c", "while true; do sleep 600; done"]
+ networks:
+ geode-sni-test:
+ volumes:
+ - ./geode-config:/geode/config:ro
+ - ./scripts:/geode/scripts
+ haproxy:
+ container_name: 'haproxy'
+ image: 'haproxy:2.1'
+ ports:
+ - "15443"
+ networks:
+ geode-sni-test:
+ volumes:
+ - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
+networks:
+ geode-sni-test:
+
diff --git a/cppcache/integration/test/sni-test-config/geode-config/gemfire.properties b/cppcache/integration/test/sni-test-config/geode-config/gemfire.properties
new file mode 100644
index 0000000..1f13fb0
--- /dev/null
+++ b/cppcache/integration/test/sni-test-config/geode-config/gemfire.properties
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+statistic-sampling-enabled=true
+statistic-archive-file=statArchive.gfs
diff --git a/cppcache/integration/test/sni-test-config/geode-config/gfsecurity.properties b/cppcache/integration/test/sni-test-config/geode-config/gfsecurity.properties
new file mode 100644
index 0000000..813d260
--- /dev/null
+++ b/cppcache/integration/test/sni-test-config/geode-config/gfsecurity.properties
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+
+security-log-level=info
+security-peer-verifymember-timeout=1000
+ssl-keystore-password=geode
+ssl-truststore=/geode/config/truststore.jks
+ssl-truststore-password=geode
+ssl-require-authentication=false
+ssl-web-require-authentication=false
+ssl-enabled-components=all
+ssl-endpoint-identification-enabled=false
+
diff --git a/cppcache/integration/test/sni-test-config/geode-config/locator-maeve-keystore.jks b/cppcache/integration/test/sni-test-config/geode-config/locator-maeve-keystore.jks
new file mode 100644
index 0000000..a29cf0f
Binary files /dev/null and b/cppcache/integration/test/sni-test-config/geode-config/locator-maeve-keystore.jks differ
diff --git a/cppcache/integration/test/sni-test-config/geode-config/server-clementine-keystore.jks b/cppcache/integration/test/sni-test-config/geode-config/server-clementine-keystore.jks
new file mode 100644
index 0000000..380de6c
Binary files /dev/null and b/cppcache/integration/test/sni-test-config/geode-config/server-clementine-keystore.jks differ
diff --git a/cppcache/integration/test/sni-test-config/geode-config/server-dolores-keystore.jks b/cppcache/integration/test/sni-test-config/geode-config/server-dolores-keystore.jks
new file mode 100644
index 0000000..cb2c4c5
Binary files /dev/null and b/cppcache/integration/test/sni-test-config/geode-config/server-dolores-keystore.jks differ
diff --git a/cppcache/integration/test/sni-test-config/geode-config/truststore.jks b/cppcache/integration/test/sni-test-config/geode-config/truststore.jks
new file mode 100644
index 0000000..ffcdaf3
Binary files /dev/null and b/cppcache/integration/test/sni-test-config/geode-config/truststore.jks differ
diff --git a/cppcache/integration/test/sni-test-config/haproxy.cfg b/cppcache/integration/test/sni-test-config/haproxy.cfg
new file mode 100644
index 0000000..c451ef6
--- /dev/null
+++ b/cppcache/integration/test/sni-test-config/haproxy.cfg
@@ -0,0 +1,44 @@
+#
+# 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.
+#
+
+defaults
+ timeout client 1000
+ timeout connect 1000
+ timeout server 1000
+
+frontend sniproxy
+ bind *:15443
+ mode tcp
+ tcp-request inspect-delay 5s
+ tcp-request content accept if { req_ssl_hello_type 1 }
+ use_backend locators-maeve if { req.ssl_sni -i locator-maeve }
+ use_backend servers-dolores if { req.ssl_sni -i server-dolores }
+ use_backend servers-clementine if { req.ssl_sni -i server-clementine }
+ default_backend locators-maeve
+ log stdout format raw local0 debug
+
+backend locators-maeve
+ mode tcp
+ server locator1 geode:10334
+
+backend servers-dolores
+ mode tcp
+ server server1 geode:40404
+
+backend servers-clementine
+ mode tcp
+ server server1 geode:40405
diff --git a/cppcache/integration/test/sni-test-config/scripts/forever b/cppcache/integration/test/sni-test-config/scripts/forever
new file mode 100755
index 0000000..4fecfa8
--- /dev/null
+++ b/cppcache/integration/test/sni-test-config/scripts/forever
@@ -0,0 +1,20 @@
+#!/usr/bin/env sh
+
+#
+# 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.
+#
+
+while true; do sleep 600; done
diff --git a/cppcache/integration/test/sni-test-config/scripts/geode-starter-2.gfsh b/cppcache/integration/test/sni-test-config/scripts/geode-starter-2.gfsh
new file mode 100755
index 0000000..38600aa
--- /dev/null
+++ b/cppcache/integration/test/sni-test-config/scripts/geode-starter-2.gfsh
@@ -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.
+#
+
+start locator --name=locator-maeve --hostname-for-clients=locator-maeve --properties-file=/geode/config/gemfire.properties --security-properties-file=/geode/config/gfsecurity.properties --J=-Dgemfire.ssl-keystore=/geode/config/locator-maeve-keystore.jks
+start server --name=server-dolores --group=group-dolores --hostname-for-clients=server-dolores --locators=localhost[10334] --properties-file=/geode/config/gemfire.properties --security-properties-file=/geode/config/gfsecurity.properties --J=-Dgemfire.ssl-keystore=/geode/config/server-dolores-keystore.jks
+start server --name=server-clementine --group=group-clementine --hostname-for-clients=server-clementine --server-port=40405 --locators=localhost[10334] --properties-file=/geode/config/gemfire.properties --security-properties-file=/geode/config/gfsecurity.properties --J=-Dgemfire.ssl-keystore=/geode/config/server-clementine-keystore.jks
+connect --locator=localhost[10334] --use-ssl=true --security-properties-file=/geode/config/gfsecurity.properties
+create region --name=region-dolores --group=group-dolores --type=REPLICATE
+create region --name=region-clementine --group=group-clementine --type=REPLICATE
diff --git a/cppcache/integration/test/sni-test-config/scripts/geode-starter.gfsh b/cppcache/integration/test/sni-test-config/scripts/geode-starter.gfsh
new file mode 100755
index 0000000..9ceecad
--- /dev/null
+++ b/cppcache/integration/test/sni-test-config/scripts/geode-starter.gfsh
@@ -0,0 +1,22 @@
+#
+# 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.
+#
+
+start locator --name=locator-maeve --hostname-for-clients=locator-maeve --properties-file=/geode/config/gemfire.properties --security-properties-file=/geode/config/gfsecurity.properties --J=-Dgemfire.ssl-keystore=/geode/config/locator-maeve-keystore.jks
+start server --name=server-dolores --max-heap=256m --hostname-for-clients=server-dolores --locators=localhost[10334] --properties-file=/geode/config/gemfire.properties --security-properties-file=/geode/config/gfsecurity.properties --J=-Dgemfire.ssl-keystore=/geode/config/server-dolores-keystore.jks
+connect --locator=localhost[10334] --use-ssl=true --security-properties-file=/geode/config/gfsecurity.properties
+create region --name=jellyfish --type=REPLICATE
+