blob: 219310f0aab82c5c23db37c6065a8a0133cdc7ca [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.
*/
#include <future>
#include <iostream>
#include <thread>
#include <boost/log/trivial.hpp>
#include <gtest/gtest.h>
#include <geode/Cache.hpp>
#include <geode/CacheFactory.hpp>
#include <geode/RegionFactory.hpp>
#include <geode/RegionShortcut.hpp>
#include "framework/Cluster.h"
#include "framework/TestConfig.h"
namespace snitest {
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");
clientSslKeysDir = boost::filesystem::path(
getFrameworkString(FrameworkVariable::TestClientSslKeysDir));
currentWorkingDirectory = boost::filesystem::current_path();
sniConfigPath = boost::filesystem::path(
getFrameworkString(FrameworkVariable::TestSniConfigPath));
}
~SNITest() override = default;
void SetUp() override {
TearDown();
std::string dockerComposeCmd = "docker-compose -f " +
sniConfigPath.string() +
"/docker-compose.yml" + " up -d";
runProcess(dockerComposeCmd);
runProcess(
"docker exec -t geode gfsh run "
"--file=/geode/scripts/geode-starter.gfsh");
}
void TearDown() override { cleanupDocker(); }
void cleanupDocker() {
runProcess("docker stop geode");
runProcess("docker stop haproxy");
runProcess("docker container prune -f");
}
std::string runProcess(std::string command) {
const char* cstrCommand = command.c_str();
std::string commandOutput;
#if defined(_WIN32)
std::unique_ptr<FILE, decltype(&_pclose)> pipe(_popen(cstrCommand, "r"),
_pclose);
#else
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cStrCommand, "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 clientSslKeysDir;
boost::filesystem::path currentWorkingDirectory;
boost::filesystem::path sniConfigPath;
};
TEST_F(SNITest, connectViaProxy) {
const auto clientTruststore =
(clientSslKeysDir / boost::filesystem::path("/truststore_sni.pem"));
auto cache = CacheFactory()
.set("log-level", "debug")
.set("log-file", "SNITest.log")
.set("ssl-enabled", "true")
.set("ssl-truststore", clientTruststore.string())
.create();
auto portString = runProcess("docker port haproxy");
auto portNumber = parseProxyPort(portString);
cache.getPoolManager()
.createFactory()
.setSniProxy("localhost", portNumber)
.addLocator("locator-maeve", 10334)
.create("pool");
auto region = cache.createRegionFactory(RegionShortcut::PROXY)
.setPoolName("pool")
.create("jellyfish");
region->put("1", "one");
auto val = std::dynamic_pointer_cast<CacheableString>(region->get("1"));
EXPECT_EQ("one", val->value());
cache.close();
}
TEST_F(SNITest, connectWithoutProxyFails) {
const auto clientTruststore =
(clientSslKeysDir / boost::filesystem::path("/truststore_sni.pem"));
auto cache = CacheFactory()
.set("log-level", "DEBUG")
.set("ssl-enabled", "true")
.set("ssl-truststore", clientTruststore.string())
.create();
cache.getPoolManager()
.createFactory()
.setSniProxy("badProxyName", 40000)
.addLocator("locator-maeve", 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, dropSNIProxy) {
const auto clientTruststore =
(clientSslKeysDir / boost::filesystem::path("/truststore_sni.pem"));
auto cache = CacheFactory()
.set("log-level", "debug")
.set("log-file", "SNITest.log")
.set("ssl-enabled", "true")
.set("ssl-truststore", clientTruststore.string())
.create();
auto portString = runProcess("docker port haproxy");
auto proxyPort = parseProxyPort(portString);
cache.getPoolManager()
.createFactory()
.setSniProxy("localhost", proxyPort)
.addLocator("locator-maeve", 10334)
.create("pool");
auto region = cache.createRegionFactory(RegionShortcut::PROXY)
.setPoolName("pool")
.create("jellyfish");
region->put("1", "one");
auto val = std::dynamic_pointer_cast<CacheableString>(region->get("1"));
EXPECT_EQ("one", val->value());
runProcess("docker stop haproxy");
runProcess("docker container prune -f");
EXPECT_THROW(region->put("1", "one"),
apache::geode::client::NotConnectedException);
std::string startProxyArgs = "-f " + sniConfigPath.string() +
"/docker-compose.yml "
"run -d --name haproxy "
"--publish " +
std::to_string(proxyPort) + ":15443 haproxy";
runProcess("docker-compose " + startProxyArgs);
val = std::dynamic_pointer_cast<CacheableString>(region->get("1"));
EXPECT_EQ("one", val->value());
cache.close();
}
} // namespace snitest