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