1 //
2 // Copyright 2020 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h"
18
19 #include <gmock/gmock.h>
20 #include <grpc/support/alloc.h>
21 #include <grpc/support/string_util.h>
22 #include <gtest/gtest.h>
23
24 #include <deque>
25 #include <list>
26
27 #include "absl/log/check.h"
28 #include "absl/status/status.h"
29 #include "src/core/lib/slice/slice_internal.h"
30 #include "src/core/util/crash.h"
31 #include "src/core/util/tmpfile.h"
32 #include "test/core/test_util/test_config.h"
33 #include "test/core/test_util/tls_utils.h"
34
35 #define CA_CERT_PATH "src/core/tsi/test_creds/ca.pem"
36 #define SERVER_CERT_PATH "src/core/tsi/test_creds/server1.pem"
37 #define SERVER_KEY_PATH "src/core/tsi/test_creds/server1.key"
38 #define CA_CERT_PATH_2 "src/core/tsi/test_creds/multi-domain.pem"
39 #define SERVER_CERT_PATH_2 "src/core/tsi/test_creds/server0.pem"
40 #define SERVER_KEY_PATH_2 "src/core/tsi/test_creds/server0.key"
41 #define INVALID_PATH "invalid/path"
42 #define MALFORMED_CERT_PATH "src/core/tsi/test_creds/malformed-cert.pem"
43 #define MALFORMED_KEY_PATH "src/core/tsi/test_creds/malformed-key.pem"
44
45 namespace grpc_core {
46
47 namespace testing {
48
49 constexpr const char* kCertName = "cert_name";
50 constexpr const char* kRootError = "Unable to get latest root certificates.";
51 constexpr const char* kIdentityError =
52 "Unable to get latest identity certificates.";
53
54 class GrpcTlsCertificateProviderTest : public ::testing::Test {
55 protected:
56 // Forward declaration.
57 class TlsCertificatesTestWatcher;
58
59 // CredentialInfo contains the parameters when calling OnCertificatesChanged
60 // of a watcher. When OnCertificatesChanged is invoked, we will push a
61 // CredentialInfo to the cert_update_queue of state_, and check in each test
62 // if the status updates are correct.
63 struct CredentialInfo {
64 std::string root_certs;
65 PemKeyCertPairList key_cert_pairs;
CredentialInfogrpc_core::testing::GrpcTlsCertificateProviderTest::CredentialInfo66 CredentialInfo(std::string root, PemKeyCertPairList key_cert)
67 : root_certs(std::move(root)), key_cert_pairs(std::move(key_cert)) {}
operator ==grpc_core::testing::GrpcTlsCertificateProviderTest::CredentialInfo68 bool operator==(const CredentialInfo& other) const {
69 return root_certs == other.root_certs &&
70 key_cert_pairs == other.key_cert_pairs;
71 }
72 };
73
74 // ErrorInfo contains the parameters when calling OnError of a watcher. When
75 // OnError is invoked, we will push a ErrorInfo to the error_queue of state_,
76 // and check in each test if the status updates are correct.
77 struct ErrorInfo {
78 std::string root_cert_str;
79 std::string identity_cert_str;
ErrorInfogrpc_core::testing::GrpcTlsCertificateProviderTest::ErrorInfo80 ErrorInfo(std::string root, std::string identity)
81 : root_cert_str(std::move(root)),
82 identity_cert_str(std::move(identity)) {}
operator ==grpc_core::testing::GrpcTlsCertificateProviderTest::ErrorInfo83 bool operator==(const ErrorInfo& other) const {
84 return root_cert_str == other.root_cert_str &&
85 identity_cert_str == other.identity_cert_str;
86 }
87 };
88
89 struct WatcherState {
90 TlsCertificatesTestWatcher* watcher = nullptr;
91 std::deque<CredentialInfo> cert_update_queue;
92 std::deque<ErrorInfo> error_queue;
93 Mutex mu;
94
GetCredentialQueuegrpc_core::testing::GrpcTlsCertificateProviderTest::WatcherState95 std::deque<CredentialInfo> GetCredentialQueue() {
96 // We move the data member value so the data member will be re-initiated
97 // with size 0, and ready for the next check.
98 MutexLock lock(&mu);
99 return std::move(cert_update_queue);
100 }
GetErrorQueuegrpc_core::testing::GrpcTlsCertificateProviderTest::WatcherState101 std::deque<ErrorInfo> GetErrorQueue() {
102 // We move the data member value so the data member will be re-initiated
103 // with size 0, and ready for the next check.
104 MutexLock lock(&mu);
105 return std::move(error_queue);
106 }
107 };
108
109 class TlsCertificatesTestWatcher : public grpc_tls_certificate_distributor::
110 TlsCertificatesWatcherInterface {
111 public:
112 // ctor sets state->watcher to this.
TlsCertificatesTestWatcher(WatcherState * state)113 explicit TlsCertificatesTestWatcher(WatcherState* state) : state_(state) {
114 state_->watcher = this;
115 }
116
117 // dtor sets state->watcher to nullptr.
~TlsCertificatesTestWatcher()118 ~TlsCertificatesTestWatcher() override { state_->watcher = nullptr; }
119
OnCertificatesChanged(absl::optional<absl::string_view> root_certs,absl::optional<PemKeyCertPairList> key_cert_pairs)120 void OnCertificatesChanged(
121 absl::optional<absl::string_view> root_certs,
122 absl::optional<PemKeyCertPairList> key_cert_pairs) override {
123 MutexLock lock(&state_->mu);
124 std::string updated_root;
125 if (root_certs.has_value()) {
126 updated_root = std::string(*root_certs);
127 }
128 PemKeyCertPairList updated_identity;
129 if (key_cert_pairs.has_value()) {
130 updated_identity = std::move(*key_cert_pairs);
131 }
132 state_->cert_update_queue.emplace_back(std::move(updated_root),
133 std::move(updated_identity));
134 }
135
OnError(grpc_error_handle root_cert_error,grpc_error_handle identity_cert_error)136 void OnError(grpc_error_handle root_cert_error,
137 grpc_error_handle identity_cert_error) override {
138 MutexLock lock(&state_->mu);
139 CHECK(!root_cert_error.ok() || !identity_cert_error.ok());
140 std::string root_error_str;
141 std::string identity_error_str;
142 if (!root_cert_error.ok()) {
143 CHECK(grpc_error_get_str(
144 root_cert_error, StatusStrProperty::kDescription, &root_error_str));
145 }
146 if (!identity_cert_error.ok()) {
147 CHECK(grpc_error_get_str(identity_cert_error,
148 StatusStrProperty::kDescription,
149 &identity_error_str));
150 }
151 state_->error_queue.emplace_back(std::move(root_error_str),
152 std::move(identity_error_str));
153 }
154
155 private:
156 WatcherState* state_;
157 };
158
SetUp()159 void SetUp() override {
160 root_cert_ = GetFileContents(CA_CERT_PATH);
161 cert_chain_ = GetFileContents(SERVER_CERT_PATH);
162 private_key_ = GetFileContents(SERVER_KEY_PATH);
163 root_cert_2_ = GetFileContents(CA_CERT_PATH_2);
164 cert_chain_2_ = GetFileContents(SERVER_CERT_PATH_2);
165 private_key_2_ = GetFileContents(SERVER_KEY_PATH_2);
166 malformed_cert_ = GetFileContents(MALFORMED_CERT_PATH);
167 malformed_key_ = GetFileContents(MALFORMED_KEY_PATH);
168 }
169
MakeWatcher(RefCountedPtr<grpc_tls_certificate_distributor> distributor,absl::optional<std::string> root_cert_name,absl::optional<std::string> identity_cert_name)170 WatcherState* MakeWatcher(
171 RefCountedPtr<grpc_tls_certificate_distributor> distributor,
172 absl::optional<std::string> root_cert_name,
173 absl::optional<std::string> identity_cert_name) {
174 MutexLock lock(&mu_);
175 distributor_ = distributor;
176 watchers_.emplace_back();
177 // TlsCertificatesTestWatcher ctor takes a pointer to the WatcherState.
178 // It sets WatcherState::watcher to point to itself.
179 // The TlsCertificatesTestWatcher dtor will set WatcherState::watcher back
180 // to nullptr to indicate that it's been destroyed.
181 auto watcher =
182 std::make_unique<TlsCertificatesTestWatcher>(&watchers_.back());
183 distributor_->WatchTlsCertificates(std::move(watcher),
184 std::move(root_cert_name),
185 std::move(identity_cert_name));
186 return &watchers_.back();
187 }
188
CancelWatch(WatcherState * state)189 void CancelWatch(WatcherState* state) {
190 MutexLock lock(&mu_);
191 distributor_->CancelTlsCertificatesWatch(state->watcher);
192 EXPECT_EQ(state->watcher, nullptr);
193 }
194
195 std::string root_cert_;
196 std::string private_key_;
197 std::string cert_chain_;
198 std::string root_cert_2_;
199 std::string private_key_2_;
200 std::string cert_chain_2_;
201 std::string malformed_cert_;
202 std::string malformed_key_;
203 RefCountedPtr<grpc_tls_certificate_distributor> distributor_;
204 // Use a std::list<> here to avoid the address invalidation caused by internal
205 // reallocation of std::vector<>.
206 std::list<WatcherState> watchers_;
207 // This is to make watchers_ thread-safe.
208 Mutex mu_;
209 };
210
TEST_F(GrpcTlsCertificateProviderTest,StaticDataCertificateProviderCreation)211 TEST_F(GrpcTlsCertificateProviderTest, StaticDataCertificateProviderCreation) {
212 StaticDataCertificateProvider provider(
213 root_cert_, MakeCertKeyPairs(private_key_.c_str(), cert_chain_.c_str()));
214 // Watcher watching both root and identity certs.
215 WatcherState* watcher_state_1 =
216 MakeWatcher(provider.distributor(), kCertName, kCertName);
217 EXPECT_THAT(watcher_state_1->GetCredentialQueue(),
218 ::testing::ElementsAre(CredentialInfo(
219 root_cert_, MakeCertKeyPairs(private_key_.c_str(),
220 cert_chain_.c_str()))));
221 CancelWatch(watcher_state_1);
222 // Watcher watching only root certs.
223 WatcherState* watcher_state_2 =
224 MakeWatcher(provider.distributor(), kCertName, absl::nullopt);
225 EXPECT_THAT(watcher_state_2->GetCredentialQueue(),
226 ::testing::ElementsAre(CredentialInfo(root_cert_, {})));
227 CancelWatch(watcher_state_2);
228 // Watcher watching only identity certs.
229 WatcherState* watcher_state_3 =
230 MakeWatcher(provider.distributor(), absl::nullopt, kCertName);
231 EXPECT_THAT(
232 watcher_state_3->GetCredentialQueue(),
233 ::testing::ElementsAre(CredentialInfo(
234 "", MakeCertKeyPairs(private_key_.c_str(), cert_chain_.c_str()))));
235 CancelWatch(watcher_state_3);
236 }
237
TEST_F(GrpcTlsCertificateProviderTest,StaticDataCertificateProviderWithGoodPathsAndCredentialValidation)238 TEST_F(GrpcTlsCertificateProviderTest,
239 StaticDataCertificateProviderWithGoodPathsAndCredentialValidation) {
240 StaticDataCertificateProvider provider(
241 root_cert_, MakeCertKeyPairs(private_key_.c_str(), cert_chain_.c_str()));
242 EXPECT_EQ(provider.ValidateCredentials(), absl::OkStatus());
243 }
244
TEST_F(GrpcTlsCertificateProviderTest,StaticDataCertificateProviderWithMalformedRootCertificate)245 TEST_F(GrpcTlsCertificateProviderTest,
246 StaticDataCertificateProviderWithMalformedRootCertificate) {
247 StaticDataCertificateProvider provider(
248 malformed_cert_,
249 MakeCertKeyPairs(private_key_.c_str(), cert_chain_.c_str()));
250 EXPECT_EQ(provider.ValidateCredentials(),
251 absl::FailedPreconditionError("Invalid PEM."));
252 }
253
TEST_F(GrpcTlsCertificateProviderTest,StaticDataCertificateProviderWithMalformedIdentityCertificate)254 TEST_F(GrpcTlsCertificateProviderTest,
255 StaticDataCertificateProviderWithMalformedIdentityCertificate) {
256 StaticDataCertificateProvider provider(
257 root_cert_,
258 MakeCertKeyPairs(private_key_.c_str(), malformed_cert_.c_str()));
259 EXPECT_EQ(provider.ValidateCredentials(),
260 absl::FailedPreconditionError("Invalid PEM."));
261 }
262
TEST_F(GrpcTlsCertificateProviderTest,StaticDataCertificateProviderWithMalformedIdentityKey)263 TEST_F(GrpcTlsCertificateProviderTest,
264 StaticDataCertificateProviderWithMalformedIdentityKey) {
265 StaticDataCertificateProvider provider(
266 root_cert_,
267 MakeCertKeyPairs(malformed_key_.c_str(), cert_chain_.c_str()));
268 EXPECT_EQ(provider.ValidateCredentials(),
269 absl::NotFoundError("No private key found."));
270 }
271
TEST_F(GrpcTlsCertificateProviderTest,FileWatcherCertificateProviderWithGoodPaths)272 TEST_F(GrpcTlsCertificateProviderTest,
273 FileWatcherCertificateProviderWithGoodPaths) {
274 FileWatcherCertificateProvider provider(SERVER_KEY_PATH, SERVER_CERT_PATH,
275 CA_CERT_PATH, 1);
276 // Watcher watching both root and identity certs.
277 WatcherState* watcher_state_1 =
278 MakeWatcher(provider.distributor(), kCertName, kCertName);
279 EXPECT_THAT(watcher_state_1->GetCredentialQueue(),
280 ::testing::ElementsAre(CredentialInfo(
281 root_cert_, MakeCertKeyPairs(private_key_.c_str(),
282 cert_chain_.c_str()))));
283 CancelWatch(watcher_state_1);
284 // Watcher watching only root certs.
285 WatcherState* watcher_state_2 =
286 MakeWatcher(provider.distributor(), kCertName, absl::nullopt);
287 EXPECT_THAT(watcher_state_2->GetCredentialQueue(),
288 ::testing::ElementsAre(CredentialInfo(root_cert_, {})));
289 CancelWatch(watcher_state_2);
290 // Watcher watching only identity certs.
291 WatcherState* watcher_state_3 =
292 MakeWatcher(provider.distributor(), absl::nullopt, kCertName);
293 EXPECT_THAT(
294 watcher_state_3->GetCredentialQueue(),
295 ::testing::ElementsAre(CredentialInfo(
296 "", MakeCertKeyPairs(private_key_.c_str(), cert_chain_.c_str()))));
297 CancelWatch(watcher_state_3);
298 }
299
TEST_F(GrpcTlsCertificateProviderTest,FileWatcherCertificateProviderWithGoodPathsAndCredentialValidation)300 TEST_F(GrpcTlsCertificateProviderTest,
301 FileWatcherCertificateProviderWithGoodPathsAndCredentialValidation) {
302 FileWatcherCertificateProvider provider(SERVER_KEY_PATH, SERVER_CERT_PATH,
303 CA_CERT_PATH, 1);
304 EXPECT_EQ(provider.ValidateCredentials(), absl::OkStatus());
305 }
306
TEST_F(GrpcTlsCertificateProviderTest,FileWatcherCertificateProviderWithMalformedRootCertificate)307 TEST_F(GrpcTlsCertificateProviderTest,
308 FileWatcherCertificateProviderWithMalformedRootCertificate) {
309 FileWatcherCertificateProvider provider(SERVER_KEY_PATH_2, SERVER_CERT_PATH_2,
310 MALFORMED_CERT_PATH, 1);
311 EXPECT_EQ(provider.ValidateCredentials(),
312 absl::FailedPreconditionError("Invalid PEM."));
313 }
314
TEST_F(GrpcTlsCertificateProviderTest,FileWatcherCertificateProviderWithMalformedIdentityCertificate)315 TEST_F(GrpcTlsCertificateProviderTest,
316 FileWatcherCertificateProviderWithMalformedIdentityCertificate) {
317 FileWatcherCertificateProvider provider(
318 SERVER_KEY_PATH_2, MALFORMED_CERT_PATH, CA_CERT_PATH_2, 1);
319 EXPECT_EQ(provider.ValidateCredentials(),
320 absl::FailedPreconditionError("Invalid PEM."));
321 }
322
TEST_F(GrpcTlsCertificateProviderTest,FileWatcherCertificateProviderWithMalformedIdentityKey)323 TEST_F(GrpcTlsCertificateProviderTest,
324 FileWatcherCertificateProviderWithMalformedIdentityKey) {
325 FileWatcherCertificateProvider provider(
326 MALFORMED_KEY_PATH, SERVER_CERT_PATH_2, CA_CERT_PATH_2, 1);
327 EXPECT_EQ(provider.ValidateCredentials(),
328 absl::NotFoundError("No private key found."));
329 }
330
TEST_F(GrpcTlsCertificateProviderTest,FileWatcherCertificateProviderWithBadPaths)331 TEST_F(GrpcTlsCertificateProviderTest,
332 FileWatcherCertificateProviderWithBadPaths) {
333 FileWatcherCertificateProvider provider(INVALID_PATH, INVALID_PATH,
334 INVALID_PATH, 1);
335 // Watcher watching both root and identity certs.
336 WatcherState* watcher_state_1 =
337 MakeWatcher(provider.distributor(), kCertName, kCertName);
338 EXPECT_THAT(watcher_state_1->GetErrorQueue(),
339 ::testing::ElementsAre(ErrorInfo(kRootError, kIdentityError)));
340 EXPECT_THAT(watcher_state_1->GetCredentialQueue(), ::testing::ElementsAre());
341 CancelWatch(watcher_state_1);
342 // Watcher watching only root certs.
343 WatcherState* watcher_state_2 =
344 MakeWatcher(provider.distributor(), kCertName, absl::nullopt);
345 EXPECT_THAT(watcher_state_2->GetErrorQueue(),
346 ::testing::ElementsAre(ErrorInfo(kRootError, "")));
347 EXPECT_THAT(watcher_state_2->GetCredentialQueue(), ::testing::ElementsAre());
348 CancelWatch(watcher_state_2);
349 // Watcher watching only identity certs.
350 WatcherState* watcher_state_3 =
351 MakeWatcher(provider.distributor(), absl::nullopt, kCertName);
352 EXPECT_THAT(watcher_state_3->GetErrorQueue(),
353 ::testing::ElementsAre(ErrorInfo("", kIdentityError)));
354 EXPECT_THAT(watcher_state_3->GetCredentialQueue(), ::testing::ElementsAre());
355 CancelWatch(watcher_state_3);
356 }
357
358 // The following tests write credential data to temporary files to test the
359 // transition behavior of the provider.
TEST_F(GrpcTlsCertificateProviderTest,FileWatcherCertificateProviderOnBothCertsRefreshed)360 TEST_F(GrpcTlsCertificateProviderTest,
361 FileWatcherCertificateProviderOnBothCertsRefreshed) {
362 // Create temporary files and copy cert data into them.
363 TmpFile tmp_root_cert(root_cert_);
364 TmpFile tmp_identity_key(private_key_);
365 TmpFile tmp_identity_cert(cert_chain_);
366 // Create FileWatcherCertificateProvider.
367 FileWatcherCertificateProvider provider(tmp_identity_key.name(),
368 tmp_identity_cert.name(),
369 tmp_root_cert.name(), 1);
370 WatcherState* watcher_state_1 =
371 MakeWatcher(provider.distributor(), kCertName, kCertName);
372 // Expect to see the credential data.
373 EXPECT_THAT(watcher_state_1->GetCredentialQueue(),
374 ::testing::ElementsAre(CredentialInfo(
375 root_cert_, MakeCertKeyPairs(private_key_.c_str(),
376 cert_chain_.c_str()))));
377 // Copy new data to files.
378 // TODO(ZhenLian): right now it is not completely atomic. Use the real atomic
379 // update when the directory renaming is added in gpr.
380 tmp_root_cert.RewriteFile(root_cert_2_);
381 tmp_identity_key.RewriteFile(private_key_2_);
382 tmp_identity_cert.RewriteFile(cert_chain_2_);
383 // Wait 2 seconds for the provider's refresh thread to read the updated files.
384 gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
385 gpr_time_from_seconds(2, GPR_TIMESPAN)));
386 // Expect to see the new credential data.
387 EXPECT_THAT(watcher_state_1->GetCredentialQueue(),
388 ::testing::ElementsAre(CredentialInfo(
389 root_cert_2_, MakeCertKeyPairs(private_key_2_.c_str(),
390 cert_chain_2_.c_str()))));
391 // Clean up.
392 CancelWatch(watcher_state_1);
393 }
394
TEST_F(GrpcTlsCertificateProviderTest,FileWatcherCertificateProviderOnRootCertsRefreshed)395 TEST_F(GrpcTlsCertificateProviderTest,
396 FileWatcherCertificateProviderOnRootCertsRefreshed) {
397 // Create temporary files and copy cert data into them.
398 TmpFile tmp_root_cert(root_cert_);
399 TmpFile tmp_identity_key(private_key_);
400 TmpFile tmp_identity_cert(cert_chain_);
401 // Create FileWatcherCertificateProvider.
402 FileWatcherCertificateProvider provider(tmp_identity_key.name(),
403 tmp_identity_cert.name(),
404 tmp_root_cert.name(), 1);
405 WatcherState* watcher_state_1 =
406 MakeWatcher(provider.distributor(), kCertName, kCertName);
407 // Expect to see the credential data.
408 EXPECT_THAT(watcher_state_1->GetCredentialQueue(),
409 ::testing::ElementsAre(CredentialInfo(
410 root_cert_, MakeCertKeyPairs(private_key_.c_str(),
411 cert_chain_.c_str()))));
412 // Copy new data to files.
413 // TODO(ZhenLian): right now it is not completely atomic. Use the real atomic
414 // update when the directory renaming is added in gpr.
415 tmp_root_cert.RewriteFile(root_cert_2_);
416 // Wait 2 seconds for the provider's refresh thread to read the updated files.
417 gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
418 gpr_time_from_seconds(2, GPR_TIMESPAN)));
419 // Expect to see the new credential data.
420 EXPECT_THAT(watcher_state_1->GetCredentialQueue(),
421 ::testing::ElementsAre(CredentialInfo(
422 root_cert_2_, MakeCertKeyPairs(private_key_.c_str(),
423 cert_chain_.c_str()))));
424 // Clean up.
425 CancelWatch(watcher_state_1);
426 }
427
TEST_F(GrpcTlsCertificateProviderTest,FileWatcherCertificateProviderOnIdentityCertsRefreshed)428 TEST_F(GrpcTlsCertificateProviderTest,
429 FileWatcherCertificateProviderOnIdentityCertsRefreshed) {
430 // Create temporary files and copy cert data into them.
431 TmpFile tmp_root_cert(root_cert_);
432 TmpFile tmp_identity_key(private_key_);
433 TmpFile tmp_identity_cert(cert_chain_);
434 // Create FileWatcherCertificateProvider.
435 FileWatcherCertificateProvider provider(tmp_identity_key.name(),
436 tmp_identity_cert.name(),
437 tmp_root_cert.name(), 1);
438 WatcherState* watcher_state_1 =
439 MakeWatcher(provider.distributor(), kCertName, kCertName);
440 // Expect to see the credential data.
441 EXPECT_THAT(watcher_state_1->GetCredentialQueue(),
442 ::testing::ElementsAre(CredentialInfo(
443 root_cert_, MakeCertKeyPairs(private_key_.c_str(),
444 cert_chain_.c_str()))));
445 // Copy new data to files.
446 // TODO(ZhenLian): right now it is not completely atomic. Use the real atomic
447 // update when the directory renaming is added in gpr.
448 tmp_identity_key.RewriteFile(private_key_2_);
449 tmp_identity_cert.RewriteFile(cert_chain_2_);
450 // Wait 2 seconds for the provider's refresh thread to read the updated files.
451 gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
452 gpr_time_from_seconds(2, GPR_TIMESPAN)));
453 // Expect to see the new credential data.
454 EXPECT_THAT(watcher_state_1->GetCredentialQueue(),
455 ::testing::ElementsAre(CredentialInfo(
456 root_cert_, MakeCertKeyPairs(private_key_2_.c_str(),
457 cert_chain_2_.c_str()))));
458 // Clean up.
459 CancelWatch(watcher_state_1);
460 }
461
TEST_F(GrpcTlsCertificateProviderTest,FileWatcherCertificateProviderWithGoodAtFirstThenDeletedBothCerts)462 TEST_F(GrpcTlsCertificateProviderTest,
463 FileWatcherCertificateProviderWithGoodAtFirstThenDeletedBothCerts) {
464 // Create temporary files and copy cert data into it.
465 auto tmp_root_cert = std::make_unique<TmpFile>(root_cert_);
466 auto tmp_identity_key = std::make_unique<TmpFile>(private_key_);
467 auto tmp_identity_cert = std::make_unique<TmpFile>(cert_chain_);
468 // Create FileWatcherCertificateProvider.
469 FileWatcherCertificateProvider provider(tmp_identity_key->name(),
470 tmp_identity_cert->name(),
471 tmp_root_cert->name(), 1);
472 WatcherState* watcher_state_1 =
473 MakeWatcher(provider.distributor(), kCertName, kCertName);
474 // The initial data is all good, so we expect to have successful credential
475 // updates.
476 EXPECT_THAT(watcher_state_1->GetCredentialQueue(),
477 ::testing::ElementsAre(CredentialInfo(
478 root_cert_, MakeCertKeyPairs(private_key_.c_str(),
479 cert_chain_.c_str()))));
480 // Delete TmpFile objects, which will remove the corresponding files.
481 tmp_root_cert.reset();
482 tmp_identity_key.reset();
483 tmp_identity_cert.reset();
484 // Wait 2 seconds for the provider's refresh thread to read the deleted files.
485 gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
486 gpr_time_from_seconds(2, GPR_TIMESPAN)));
487 // Expect to see errors sent to watchers, and no credential updates.
488 // We have no ideas on how many errors we will receive, so we only check once.
489 EXPECT_THAT(watcher_state_1->GetErrorQueue(),
490 ::testing::Contains(ErrorInfo(kRootError, kIdentityError)));
491 EXPECT_THAT(watcher_state_1->GetCredentialQueue(), ::testing::ElementsAre());
492 // Clean up.
493 CancelWatch(watcher_state_1);
494 }
495
TEST_F(GrpcTlsCertificateProviderTest,FileWatcherCertificateProviderWithGoodAtFirstThenDeletedRootCerts)496 TEST_F(GrpcTlsCertificateProviderTest,
497 FileWatcherCertificateProviderWithGoodAtFirstThenDeletedRootCerts) {
498 // Create temporary files and copy cert data into it.
499 auto tmp_root_cert = std::make_unique<TmpFile>(root_cert_);
500 TmpFile tmp_identity_key(private_key_);
501 TmpFile tmp_identity_cert(cert_chain_);
502 // Create FileWatcherCertificateProvider.
503 FileWatcherCertificateProvider provider(tmp_identity_key.name(),
504 tmp_identity_cert.name(),
505 tmp_root_cert->name(), 1);
506 WatcherState* watcher_state_1 =
507 MakeWatcher(provider.distributor(), kCertName, kCertName);
508 // The initial data is all good, so we expect to have successful credential
509 // updates.
510 EXPECT_THAT(watcher_state_1->GetCredentialQueue(),
511 ::testing::ElementsAre(CredentialInfo(
512 root_cert_, MakeCertKeyPairs(private_key_.c_str(),
513 cert_chain_.c_str()))));
514 // Delete root TmpFile object, which will remove the corresponding file.
515 tmp_root_cert.reset();
516 // Wait 2 seconds for the provider's refresh thread to read the deleted files.
517 gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
518 gpr_time_from_seconds(2, GPR_TIMESPAN)));
519 // Expect to see errors sent to watchers, and no credential updates.
520 // We have no ideas on how many errors we will receive, so we only check once.
521 EXPECT_THAT(watcher_state_1->GetErrorQueue(),
522 ::testing::Contains(ErrorInfo(kRootError, "")));
523 EXPECT_THAT(watcher_state_1->GetCredentialQueue(), ::testing::ElementsAre());
524 // Clean up.
525 CancelWatch(watcher_state_1);
526 }
527
TEST_F(GrpcTlsCertificateProviderTest,FileWatcherCertificateProviderWithGoodAtFirstThenDeletedIdentityCerts)528 TEST_F(GrpcTlsCertificateProviderTest,
529 FileWatcherCertificateProviderWithGoodAtFirstThenDeletedIdentityCerts) {
530 // Create temporary files and copy cert data into it.
531 TmpFile tmp_root_cert(root_cert_);
532 auto tmp_identity_key = std::make_unique<TmpFile>(private_key_);
533 auto tmp_identity_cert = std::make_unique<TmpFile>(cert_chain_);
534 // Create FileWatcherCertificateProvider.
535 FileWatcherCertificateProvider provider(tmp_identity_key->name(),
536 tmp_identity_cert->name(),
537 tmp_root_cert.name(), 1);
538 WatcherState* watcher_state_1 =
539 MakeWatcher(provider.distributor(), kCertName, kCertName);
540 // The initial data is all good, so we expect to have successful credential
541 // updates.
542 EXPECT_THAT(watcher_state_1->GetCredentialQueue(),
543 ::testing::ElementsAre(CredentialInfo(
544 root_cert_, MakeCertKeyPairs(private_key_.c_str(),
545 cert_chain_.c_str()))));
546 // Delete identity TmpFile objects, which will remove the corresponding files.
547 tmp_identity_key.reset();
548 tmp_identity_cert.reset();
549 // Wait 2 seconds for the provider's refresh thread to read the deleted files.
550 gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
551 gpr_time_from_seconds(2, GPR_TIMESPAN)));
552 // Expect to see errors sent to watchers, and no credential updates.
553 // We have no ideas on how many errors we will receive, so we only check once.
554 EXPECT_THAT(watcher_state_1->GetErrorQueue(),
555 ::testing::Contains(ErrorInfo("", kIdentityError)));
556 EXPECT_THAT(watcher_state_1->GetCredentialQueue(), ::testing::ElementsAre());
557 // Clean up.
558 CancelWatch(watcher_state_1);
559 }
560
TEST_F(GrpcTlsCertificateProviderTest,FileWatcherCertificateProviderTooShortRefreshIntervalIsOverwritten)561 TEST_F(GrpcTlsCertificateProviderTest,
562 FileWatcherCertificateProviderTooShortRefreshIntervalIsOverwritten) {
563 FileWatcherCertificateProvider provider(SERVER_KEY_PATH, SERVER_CERT_PATH,
564 CA_CERT_PATH, 0);
565 ASSERT_THAT(provider.TestOnlyGetRefreshIntervalSecond(), 1);
566 }
567
TEST_F(GrpcTlsCertificateProviderTest,FailedKeyCertMatchOnEmptyPrivateKey)568 TEST_F(GrpcTlsCertificateProviderTest, FailedKeyCertMatchOnEmptyPrivateKey) {
569 absl::StatusOr<bool> status =
570 PrivateKeyAndCertificateMatch(/*private_key=*/"", cert_chain_);
571 EXPECT_FALSE(status.ok());
572 EXPECT_EQ(status.status().code(), absl::StatusCode::kInvalidArgument);
573 EXPECT_EQ(status.status().message(), "Private key string is empty.");
574 }
575
TEST_F(GrpcTlsCertificateProviderTest,FailedKeyCertMatchOnEmptyCertificate)576 TEST_F(GrpcTlsCertificateProviderTest, FailedKeyCertMatchOnEmptyCertificate) {
577 absl::StatusOr<bool> status =
578 PrivateKeyAndCertificateMatch(private_key_2_, /*cert_chain=*/"");
579 EXPECT_FALSE(status.ok());
580 EXPECT_EQ(status.status().code(), absl::StatusCode::kInvalidArgument);
581 EXPECT_EQ(status.status().message(), "Certificate string is empty.");
582 }
583
TEST_F(GrpcTlsCertificateProviderTest,FailedKeyCertMatchOnInvalidCertFormat)584 TEST_F(GrpcTlsCertificateProviderTest, FailedKeyCertMatchOnInvalidCertFormat) {
585 absl::StatusOr<bool> status =
586 PrivateKeyAndCertificateMatch(private_key_2_, "invalid_certificate");
587 EXPECT_FALSE(status.ok());
588 EXPECT_EQ(status.status().code(), absl::StatusCode::kInvalidArgument);
589 EXPECT_EQ(status.status().message(),
590 "Conversion from PEM string to X509 failed.");
591 }
592
TEST_F(GrpcTlsCertificateProviderTest,FailedKeyCertMatchOnInvalidPrivateKeyFormat)593 TEST_F(GrpcTlsCertificateProviderTest,
594 FailedKeyCertMatchOnInvalidPrivateKeyFormat) {
595 absl::StatusOr<bool> status =
596 PrivateKeyAndCertificateMatch("invalid_private_key", cert_chain_2_);
597 EXPECT_EQ(status.status().code(), absl::StatusCode::kInvalidArgument);
598 EXPECT_EQ(status.status().message(),
599 "Conversion from PEM string to EVP_PKEY failed.");
600 }
601
TEST_F(GrpcTlsCertificateProviderTest,SuccessfulKeyCertMatch)602 TEST_F(GrpcTlsCertificateProviderTest, SuccessfulKeyCertMatch) {
603 absl::StatusOr<bool> status =
604 PrivateKeyAndCertificateMatch(private_key_2_, cert_chain_2_);
605 EXPECT_TRUE(status.ok());
606 EXPECT_TRUE(*status);
607 }
608
TEST_F(GrpcTlsCertificateProviderTest,FailedKeyCertMatchOnInvalidPair)609 TEST_F(GrpcTlsCertificateProviderTest, FailedKeyCertMatchOnInvalidPair) {
610 absl::StatusOr<bool> status =
611 PrivateKeyAndCertificateMatch(private_key_2_, cert_chain_);
612 EXPECT_TRUE(status.ok());
613 EXPECT_FALSE(*status);
614 }
615
616 } // namespace testing
617 } // namespace grpc_core
618
main(int argc,char ** argv)619 int main(int argc, char** argv) {
620 grpc::testing::TestEnvironment env(&argc, argv);
621 ::testing::InitGoogleTest(&argc, argv);
622 grpc_init();
623 int ret = RUN_ALL_TESTS();
624 grpc_shutdown();
625 return ret;
626 }
627