Skip to content

Commit fb222ad

Browse files
authored
Merge pull request #273 from riptano/CPP-798
* CPP-798 Configure auth/SSL from secure connection bundle configuration Also, * CPP-797 Events need to map from affected node address to `host_id` * CPP-800 Node discovery should use the `host_id` (and endpoint address) instead of the node's `rpc_address`
2 parents b906e55 + bacce8e commit fb222ad

52 files changed

Lines changed: 939 additions & 507 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

cpp-driver/gtests/src/integration/driver_utils.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ unsigned int test::driver::internals::Utils::connect_timeout(CassCluster* cluste
5050

5151
std::string test::driver::internals::Utils::contact_points(CassCluster* cluster) {
5252
std::string contact_points;
53-
const ContactPointList& contact_points_list = cluster->config().contact_points();
54-
for (ContactPointList::const_iterator it = contact_points_list.begin();
55-
it != contact_points_list.end(); ++it) {
53+
const AddressVec& contact_points_list = cluster->config().contact_points();
54+
for (AddressVec::const_iterator it = contact_points_list.begin(); it != contact_points_list.end();
55+
++it) {
5656
if (contact_points.size() > 0) {
5757
contact_points.push_back(',');
5858
}
59-
contact_points.append((*it).c_str());
59+
contact_points.append((*it).hostname_or_address().c_str());
6060
}
6161
return contact_points;
6262
}
@@ -73,7 +73,7 @@ std::string test::driver::internals::Utils::host(CassFuture* future) {
7373
if (future) {
7474
Future* cass_future = static_cast<Future*>(future);
7575
if (cass_future->type() == Future::FUTURE_TYPE_RESPONSE) {
76-
return static_cast<ResponseFuture*>(cass_future)->address().to_string().c_str();
76+
return static_cast<ResponseFuture*>(cass_future)->address().hostname_or_address().c_str();
7777
}
7878
}
7979
return "";

cpp-driver/gtests/src/unit/tests/test_address.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,41 @@ TEST(AddressUnitTest, ToInetIPv6) {
9797
EXPECT_EQ(expected, actual);
9898
}
9999

100+
TEST(AddressUnitTest, ToString) {
101+
// Only hostname/address
102+
EXPECT_EQ(Address("127.0.0.1", 9042).hostname_or_address(), "127.0.0.1");
103+
EXPECT_EQ(Address("::1", 9042).hostname_or_address(), "::1");
104+
EXPECT_EQ(Address("0:0:0:0:0:0:0:1", 9042).hostname_or_address(), "::1"); // IPv6 normalization
105+
EXPECT_EQ(Address("0:0:0:0:0:0:0:0", 9042).hostname_or_address(), "::"); // IPv6 normalization
106+
EXPECT_EQ(Address("datastax.com", 9042).hostname_or_address(), "datastax.com");
107+
108+
// w/o port
109+
EXPECT_EQ(Address("127.0.0.1", 9042).to_string(), "127.0.0.1");
110+
EXPECT_EQ(Address("::1", 9042).to_string(), "::1");
111+
EXPECT_EQ(Address("datastax.com", 9042).to_string(), "datastax.com");
112+
113+
// w/ port
114+
EXPECT_EQ(Address("127.0.0.1", 9042).to_string(true), "127.0.0.1:9042");
115+
EXPECT_EQ(Address("::1", 9042).to_string(true), "[::1]:9042");
116+
EXPECT_EQ(Address("datastax.com", 9042).to_string(true), "datastax.com:9042");
117+
118+
// w/ servername
119+
EXPECT_EQ(Address("127.0.0.1", 9042, "d1f1884b-6e05-4b3f-9e88-8a93904bb0e5").to_string(),
120+
"127.0.0.1 (d1f1884b-6e05-4b3f-9e88-8a93904bb0e5)");
121+
EXPECT_EQ(Address("::1", 9042, "d1f1884b-6e05-4b3f-9e88-8a93904bb0e5").to_string(),
122+
"::1 (d1f1884b-6e05-4b3f-9e88-8a93904bb0e5)");
123+
EXPECT_EQ(Address("datastax.com", 9042, "d1f1884b-6e05-4b3f-9e88-8a93904bb0e5").to_string(),
124+
"datastax.com (d1f1884b-6e05-4b3f-9e88-8a93904bb0e5)");
125+
126+
// w/ servername and port
127+
EXPECT_EQ(Address("127.0.0.1", 9042, "d1f1884b-6e05-4b3f-9e88-8a93904bb0e5").to_string(true),
128+
"127.0.0.1:9042 (d1f1884b-6e05-4b3f-9e88-8a93904bb0e5)");
129+
EXPECT_EQ(Address("::1", 9042, "d1f1884b-6e05-4b3f-9e88-8a93904bb0e5").to_string(true),
130+
"[::1]:9042 (d1f1884b-6e05-4b3f-9e88-8a93904bb0e5)");
131+
EXPECT_EQ(Address("datastax.com", 9042, "d1f1884b-6e05-4b3f-9e88-8a93904bb0e5").to_string(true),
132+
"datastax.com:9042 (d1f1884b-6e05-4b3f-9e88-8a93904bb0e5)");
133+
}
134+
100135
TEST(AddressUnitTest, Hash) {
101136
AddressSet set;
102137

cpp-driver/gtests/src/unit/tests/test_cloud_secure_connect_config.cpp

Lines changed: 115 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "unit.hpp"
2121

2222
#include "cloud_secure_connection_config.hpp"
23+
#include "config.hpp"
2324
#include "json.hpp"
2425
#include "string.hpp"
2526

@@ -33,28 +34,8 @@
3334
#define CERTIFICATE_FILE "cert"
3435
#define KEY_FILE "key"
3536

36-
#define CERTIFICATE_AUTHORITY "This would be a PEM file"
37-
#define CERTIFICATE "This would also be a PEM file"
38-
#define KEY "This would be yet another PEM file"
39-
4037
#define CREDS_V1_ZIP_FILE "creds-v1.zip"
4138

42-
#define FULL_CONFIG_CREDSV1 \
43-
StringBuffer buffer; \
44-
Writer<StringBuffer> writer(buffer); \
45-
writer.StartObject(); \
46-
writer.Key("username"); \
47-
writer.String("DataStax"); \
48-
writer.Key("password"); \
49-
writer.String("Constellation"); \
50-
writer.Key("host"); \
51-
writer.String("cloud.datastax.com"); \
52-
writer.Key("port"); \
53-
writer.Int(1443); \
54-
writer.Key("keyspace"); \
55-
writer.String("database_as_a_service"); \
56-
writer.EndObject()
57-
5839
#ifdef _WIN32
5940
#define PATH_SEPARATOR '\\'
6041
#else
@@ -63,18 +44,33 @@
6344

6445
using datastax::String;
6546
using datastax::internal::core::CloudSecureConnectionConfig;
47+
using datastax::internal::core::Config;
48+
using datastax::internal::enterprise::DsePlainTextAuthProvider;
6649
using datastax::internal::json::StringBuffer;
6750
using datastax::internal::json::Writer;
6851

52+
using mockssandra::Ssl;
53+
6954
class CloudSecureConnectionConfigTest : public Unit {
7055
public:
56+
const String& ca_cert() const { return ca_cert_; }
57+
void set_invalid_ca_cert() { ca_cert_ = "!!!!!INVALID!!!!!"; }
58+
const String& cert() const { return cert_; }
59+
void set_invalid_cert() { cert_ = "!!!!!INVALID!!!!!"; }
60+
const String& key() const { return key_; }
61+
void set_invalid_key() { key_ = "!!!!!INVALID!!!!!"; }
62+
7163
void SetUp() {
7264
Unit::SetUp();
7365
char tmp[260] = { 0 }; // Note: 260 is the maximum path on Windows
7466
size_t tmp_length = 260;
7567
uv_os_tmpdir(tmp, &tmp_length);
7668

7769
tmp_zip_file_ = String(tmp, tmp_length) + PATH_SEPARATOR + CREDS_V1_ZIP_FILE;
70+
71+
ca_cert_ = Ssl::generate_cert(Ssl::generate_key());
72+
key_ = Ssl::generate_key();
73+
cert_ = Ssl::generate_cert(key_, "localhost");
7874
}
7975

8076
const String& creds_zip_file() const { return tmp_zip_file_; }
@@ -88,21 +84,37 @@ class CloudSecureConnectionConfigTest : public Unit {
8884
zipCloseFileInZip(zip_file);
8985
}
9086
if (is_ca && add_zip_file_entry(zip_file, CERTIFICATE_AUTHORITY_FILE)) {
91-
zipWriteInFileInZip(zip_file, CERTIFICATE_AUTHORITY, strlen(CERTIFICATE_AUTHORITY));
87+
zipWriteInFileInZip(zip_file, ca_cert_.c_str(), ca_cert_.length());
9288
zipCloseFileInZip(zip_file);
9389
}
9490
if (is_cert && add_zip_file_entry(zip_file, CERTIFICATE_FILE)) {
95-
zipWriteInFileInZip(zip_file, CERTIFICATE, strlen(CERTIFICATE));
91+
zipWriteInFileInZip(zip_file, cert_.c_str(), cert_.length());
9692
zipCloseFileInZip(zip_file);
9793
}
9894
if (is_key && add_zip_file_entry(zip_file, KEY_FILE)) {
99-
zipWriteInFileInZip(zip_file, KEY, strlen(KEY));
95+
zipWriteInFileInZip(zip_file, key_.c_str(), key_.length());
10096
zipCloseFileInZip(zip_file);
10197
}
10298

10399
zipClose(zip_file, NULL);
104100
}
105101

102+
static void full_config_credsv1(StringBuffer& buffer) {
103+
Writer<StringBuffer> writer(buffer);
104+
writer.StartObject();
105+
writer.Key("username");
106+
writer.String("DataStax");
107+
writer.Key("password");
108+
writer.String("Constellation");
109+
writer.Key("host");
110+
writer.String("cloud.datastax.com");
111+
writer.Key("port");
112+
writer.Int(1443);
113+
writer.Key("keyspace");
114+
writer.String("database_as_a_service");
115+
writer.EndObject();
116+
}
117+
106118
private:
107119
bool add_zip_file_entry(zipFile zip_file, const String& zip_filename) {
108120
zip_fileinfo file_info;
@@ -124,27 +136,36 @@ class CloudSecureConnectionConfigTest : public Unit {
124136

125137
private:
126138
String tmp_zip_file_;
139+
String ca_cert_;
140+
String cert_;
141+
String key_;
127142
};
128143

129144
TEST_F(CloudSecureConnectionConfigTest, CredsV1) {
130-
CloudSecureConnectionConfig config;
145+
Config config;
146+
CloudSecureConnectionConfig cloud_config;
131147

132-
FULL_CONFIG_CREDSV1;
148+
StringBuffer buffer;
149+
full_config_credsv1(buffer);
133150
create_zip_file(buffer.GetString());
134151

135-
EXPECT_TRUE(config.load(creds_zip_file()));
136-
EXPECT_EQ("DataStax", config.username());
137-
EXPECT_EQ("Constellation", config.password());
138-
EXPECT_EQ("cloud.datastax.com", config.host());
139-
EXPECT_EQ(1443, config.port());
140-
EXPECT_EQ("database_as_a_service", config.keyspace());
141-
EXPECT_EQ(CERTIFICATE_AUTHORITY, config.ca_cert());
142-
EXPECT_EQ(CERTIFICATE, config.cert());
143-
EXPECT_EQ(KEY, config.key());
152+
EXPECT_TRUE(cloud_config.load(creds_zip_file(), &config));
153+
EXPECT_EQ("DataStax", cloud_config.username());
154+
EXPECT_EQ("Constellation", cloud_config.password());
155+
EXPECT_EQ("cloud.datastax.com", cloud_config.host());
156+
EXPECT_EQ(1443, cloud_config.port());
157+
EXPECT_EQ("database_as_a_service", cloud_config.keyspace());
158+
EXPECT_EQ(ca_cert(), cloud_config.ca_cert());
159+
EXPECT_EQ(cert(), cloud_config.cert());
160+
EXPECT_EQ(key(), cloud_config.key());
161+
162+
EXPECT_TRUE(config.ssl_context());
163+
EXPECT_TRUE(dynamic_cast<DsePlainTextAuthProvider*>(config.auth_provider().get()) != NULL);
144164
}
145165

146166
TEST_F(CloudSecureConnectionConfigTest, CredsV1WithoutCreds) {
147-
CloudSecureConnectionConfig config;
167+
Config config;
168+
CloudSecureConnectionConfig cloud_config;
148169

149170
StringBuffer buffer;
150171
Writer<StringBuffer> writer(buffer);
@@ -158,15 +179,19 @@ TEST_F(CloudSecureConnectionConfigTest, CredsV1WithoutCreds) {
158179
writer.EndObject();
159180
create_zip_file(buffer.GetString());
160181

161-
EXPECT_TRUE(config.load(creds_zip_file()));
162-
EXPECT_EQ("", config.username());
163-
EXPECT_EQ("", config.password());
164-
EXPECT_EQ("bigdata.datastax.com", config.host());
165-
EXPECT_EQ(2443, config.port());
166-
EXPECT_EQ("datastax", config.keyspace());
167-
EXPECT_EQ(CERTIFICATE_AUTHORITY, config.ca_cert());
168-
EXPECT_EQ(CERTIFICATE, config.cert());
169-
EXPECT_EQ(KEY, config.key());
182+
EXPECT_TRUE(cloud_config.load(creds_zip_file(), &config));
183+
EXPECT_EQ("", cloud_config.username());
184+
EXPECT_EQ("", cloud_config.password());
185+
EXPECT_EQ("bigdata.datastax.com", cloud_config.host());
186+
EXPECT_EQ(2443, cloud_config.port());
187+
EXPECT_EQ("datastax", cloud_config.keyspace());
188+
EXPECT_EQ(ca_cert(), cloud_config.ca_cert());
189+
EXPECT_EQ(cert(), cloud_config.cert());
190+
EXPECT_EQ(key(), cloud_config.key());
191+
192+
EXPECT_TRUE(config.ssl_context());
193+
EXPECT_TRUE(dynamic_cast<DsePlainTextAuthProvider*>(config.auth_provider().get()) ==
194+
NULL); // Not configured
170195
}
171196

172197
TEST_F(CloudSecureConnectionConfigTest, InvalidCredsV1ConfigMissingHost) {
@@ -245,24 +270,67 @@ TEST_F(CloudSecureConnectionConfigTest, InvalidCredsV1MissingConfigJson) {
245270
TEST_F(CloudSecureConnectionConfigTest, InvalidCredsV1MissingCA) {
246271
CloudSecureConnectionConfig config;
247272

248-
FULL_CONFIG_CREDSV1;
273+
StringBuffer buffer;
274+
full_config_credsv1(buffer);
249275
create_zip_file(buffer.GetString(), true, false);
250276
EXPECT_FALSE(config.load(creds_zip_file()));
251277
}
252278

253279
TEST_F(CloudSecureConnectionConfigTest, InvalidCredsV1MissingCert) {
254280
CloudSecureConnectionConfig config;
255281

256-
FULL_CONFIG_CREDSV1;
282+
StringBuffer buffer;
283+
full_config_credsv1(buffer);
257284
create_zip_file(buffer.GetString(), true, true, false);
258285
EXPECT_FALSE(config.load(creds_zip_file()));
259286
}
260287

261288
TEST_F(CloudSecureConnectionConfigTest, InvalidCredsV1MissingKey) {
262289
CloudSecureConnectionConfig config;
263290

264-
FULL_CONFIG_CREDSV1;
291+
StringBuffer buffer;
292+
full_config_credsv1(buffer);
293+
create_zip_file(buffer.GetString(), true, true, false);
265294
create_zip_file(buffer.GetString(), true, true, true, false);
266295
EXPECT_FALSE(config.load(creds_zip_file()));
267296
}
297+
298+
TEST_F(CloudSecureConnectionConfigTest, InvalidCredsV1SslCaCert) {
299+
Config config;
300+
CloudSecureConnectionConfig cloud_config;
301+
302+
StringBuffer buffer;
303+
full_config_credsv1(buffer);
304+
set_invalid_ca_cert();
305+
create_zip_file(buffer.GetString());
306+
307+
EXPECT_FALSE(cloud_config.load(creds_zip_file(), &config));
308+
EXPECT_FALSE(config.ssl_context());
309+
}
310+
311+
TEST_F(CloudSecureConnectionConfigTest, InvalidCredsV1SslCert) {
312+
Config config;
313+
CloudSecureConnectionConfig cloud_config;
314+
315+
StringBuffer buffer;
316+
full_config_credsv1(buffer);
317+
set_invalid_cert();
318+
create_zip_file(buffer.GetString());
319+
320+
EXPECT_FALSE(cloud_config.load(creds_zip_file(), &config));
321+
EXPECT_FALSE(config.ssl_context());
322+
}
323+
324+
TEST_F(CloudSecureConnectionConfigTest, InvalidCredsV1SslKey) {
325+
Config config;
326+
CloudSecureConnectionConfig cloud_config;
327+
328+
StringBuffer buffer;
329+
full_config_credsv1(buffer);
330+
set_invalid_key();
331+
create_zip_file(buffer.GetString());
332+
333+
EXPECT_FALSE(cloud_config.load(creds_zip_file(), &config));
334+
EXPECT_FALSE(config.ssl_context());
335+
}
268336
#endif

0 commit comments

Comments
 (0)