mirror of https://github.com/grpc/grpc.git
parent
93fc14a17f
commit
e11a670736
21 changed files with 979 additions and 2 deletions
@ -0,0 +1,240 @@ |
|||||||
|
//
|
||||||
|
//
|
||||||
|
// Copyright 2020 gRPC authors.
|
||||||
|
//
|
||||||
|
// Licensed 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 <grpc/support/port_platform.h> |
||||||
|
|
||||||
|
#include "absl/functional/bind_front.h" |
||||||
|
#include "absl/strings/str_cat.h" |
||||||
|
|
||||||
|
#include "src/core/ext/xds/xds_certificate_provider.h" |
||||||
|
|
||||||
|
namespace grpc_core { |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
class RootCertificatesWatcher |
||||||
|
: public grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface { |
||||||
|
public: |
||||||
|
// Takes a ref to \a parent instead of a raw pointer since the watcher is
|
||||||
|
// owned by the root certificate distributor and not by \a parent. Note that
|
||||||
|
// presently, the watcher is immediately deleted when
|
||||||
|
// CancelTlsCertificatesWatch() is called, but that can potentially change in
|
||||||
|
// the future.
|
||||||
|
explicit RootCertificatesWatcher( |
||||||
|
RefCountedPtr<grpc_tls_certificate_distributor> parent) |
||||||
|
: parent_(std::move(parent)) {} |
||||||
|
|
||||||
|
void OnCertificatesChanged(absl::optional<absl::string_view> root_certs, |
||||||
|
absl::optional<PemKeyCertPairList> |
||||||
|
/* key_cert_pairs */) override { |
||||||
|
if (root_certs.has_value()) { |
||||||
|
parent_->SetKeyMaterials("", std::string(root_certs.value()), |
||||||
|
absl::nullopt); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void OnError(grpc_error* root_cert_error, |
||||||
|
grpc_error* identity_cert_error) override { |
||||||
|
if (root_cert_error != GRPC_ERROR_NONE) { |
||||||
|
parent_->SetErrorForCert("", root_cert_error /* pass the ref */, |
||||||
|
absl::nullopt); |
||||||
|
} |
||||||
|
GRPC_ERROR_UNREF(identity_cert_error); |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
RefCountedPtr<grpc_tls_certificate_distributor> parent_; |
||||||
|
}; |
||||||
|
|
||||||
|
class IdentityCertificatesWatcher |
||||||
|
: public grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface { |
||||||
|
public: |
||||||
|
// Takes a ref to \a parent instead of a raw pointer since the watcher is
|
||||||
|
// owned by the root certificate distributor and not by \a parent. Note that
|
||||||
|
// presently, the watcher is immediately deleted when
|
||||||
|
// CancelTlsCertificatesWatch() is called, but that can potentially change in
|
||||||
|
// the future.
|
||||||
|
explicit IdentityCertificatesWatcher( |
||||||
|
RefCountedPtr<grpc_tls_certificate_distributor> parent) |
||||||
|
: parent_(std::move(parent)) {} |
||||||
|
|
||||||
|
void OnCertificatesChanged( |
||||||
|
absl::optional<absl::string_view> /* root_certs */, |
||||||
|
absl::optional<PemKeyCertPairList> key_cert_pairs) override { |
||||||
|
if (key_cert_pairs.has_value()) { |
||||||
|
parent_->SetKeyMaterials("", absl::nullopt, key_cert_pairs); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void OnError(grpc_error* root_cert_error, |
||||||
|
grpc_error* identity_cert_error) override { |
||||||
|
if (identity_cert_error != GRPC_ERROR_NONE) { |
||||||
|
parent_->SetErrorForCert("", absl::nullopt, |
||||||
|
identity_cert_error /* pass the ref */); |
||||||
|
} |
||||||
|
GRPC_ERROR_UNREF(root_cert_error); |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
RefCountedPtr<grpc_tls_certificate_distributor> parent_; |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
XdsCertificateProvider::XdsCertificateProvider( |
||||||
|
absl::string_view root_cert_name, |
||||||
|
RefCountedPtr<grpc_tls_certificate_distributor> root_cert_distributor, |
||||||
|
absl::string_view identity_cert_name, |
||||||
|
RefCountedPtr<grpc_tls_certificate_distributor> identity_cert_distributor) |
||||||
|
: root_cert_name_(root_cert_name), |
||||||
|
identity_cert_name_(identity_cert_name), |
||||||
|
root_cert_distributor_(std::move(root_cert_distributor)), |
||||||
|
identity_cert_distributor_(std::move(identity_cert_distributor)), |
||||||
|
distributor_(MakeRefCounted<grpc_tls_certificate_distributor>()) { |
||||||
|
distributor_->SetWatchStatusCallback( |
||||||
|
absl::bind_front(&XdsCertificateProvider::WatchStatusCallback, this)); |
||||||
|
} |
||||||
|
|
||||||
|
void XdsCertificateProvider::UpdateRootCertNameAndDistributor( |
||||||
|
absl::string_view root_cert_name, |
||||||
|
RefCountedPtr<grpc_tls_certificate_distributor> root_cert_distributor) { |
||||||
|
MutexLock lock(&mu_); |
||||||
|
root_cert_name_ = std::string(root_cert_name); |
||||||
|
if (watching_root_certs_) { |
||||||
|
// The root certificates are being watched. Swap out the watcher.
|
||||||
|
if (root_cert_distributor_ != nullptr) { |
||||||
|
root_cert_distributor_->CancelTlsCertificatesWatch(root_cert_watcher_); |
||||||
|
} |
||||||
|
if (root_cert_distributor != nullptr) { |
||||||
|
UpdateRootCertWatcher(root_cert_distributor.get()); |
||||||
|
} else { |
||||||
|
root_cert_watcher_ = nullptr; |
||||||
|
distributor_->SetErrorForCert( |
||||||
|
"", |
||||||
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||||
|
"No certificate provider available for root certificates"), |
||||||
|
absl::nullopt); |
||||||
|
} |
||||||
|
} |
||||||
|
// Swap out the root certificate distributor
|
||||||
|
root_cert_distributor_ = std::move(root_cert_distributor); |
||||||
|
} |
||||||
|
|
||||||
|
void XdsCertificateProvider::UpdateIdentityCertNameAndDistributor( |
||||||
|
absl::string_view identity_cert_name, |
||||||
|
RefCountedPtr<grpc_tls_certificate_distributor> identity_cert_distributor) { |
||||||
|
MutexLock lock(&mu_); |
||||||
|
identity_cert_name_ = std::string(identity_cert_name); |
||||||
|
if (watching_identity_certs_) { |
||||||
|
// The identity certificates are being watched. Swap out the watcher.
|
||||||
|
if (identity_cert_distributor_ != nullptr) { |
||||||
|
identity_cert_distributor_->CancelTlsCertificatesWatch( |
||||||
|
identity_cert_watcher_); |
||||||
|
} |
||||||
|
if (identity_cert_distributor != nullptr) { |
||||||
|
UpdateIdentityCertWatcher(identity_cert_distributor.get()); |
||||||
|
} else { |
||||||
|
identity_cert_watcher_ = nullptr; |
||||||
|
distributor_->SetErrorForCert( |
||||||
|
"", absl::nullopt, |
||||||
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||||
|
"No certificate provider available for identity certificates")); |
||||||
|
} |
||||||
|
} |
||||||
|
// Swap out the identity certificate distributor
|
||||||
|
identity_cert_distributor_ = std::move(identity_cert_distributor); |
||||||
|
} |
||||||
|
|
||||||
|
void XdsCertificateProvider::WatchStatusCallback(std::string cert_name, |
||||||
|
bool root_being_watched, |
||||||
|
bool identity_being_watched) { |
||||||
|
// We aren't specially handling the case where root_cert_distributor is same
|
||||||
|
// as identity_cert_distributor. Always using two separate watchers
|
||||||
|
// irrespective of the fact results in a straightforward design, and using a
|
||||||
|
// single watcher does not seem to provide any benefit other than cutting down
|
||||||
|
// on the number of callbacks.
|
||||||
|
MutexLock lock(&mu_); |
||||||
|
if (!cert_name.empty()) { |
||||||
|
grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
||||||
|
absl::StrCat("Illegal certificate name: \'", cert_name, |
||||||
|
"\'. Should be empty.") |
||||||
|
.c_str()); |
||||||
|
distributor_->SetErrorForCert(cert_name, GRPC_ERROR_REF(error), |
||||||
|
GRPC_ERROR_REF(error)); |
||||||
|
GRPC_ERROR_UNREF(error); |
||||||
|
return; |
||||||
|
} |
||||||
|
if (root_being_watched && !watching_root_certs_) { |
||||||
|
// We need to start watching root certs.
|
||||||
|
watching_root_certs_ = true; |
||||||
|
if (root_cert_distributor_ == nullptr) { |
||||||
|
distributor_->SetErrorForCert( |
||||||
|
"", |
||||||
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||||
|
"No certificate provider available for root certificates"), |
||||||
|
absl::nullopt); |
||||||
|
} else { |
||||||
|
UpdateRootCertWatcher(root_cert_distributor_.get()); |
||||||
|
} |
||||||
|
} else if (!root_being_watched && watching_root_certs_) { |
||||||
|
// We need to cancel root certs watch.
|
||||||
|
watching_root_certs_ = false; |
||||||
|
if (root_cert_distributor_ != nullptr) { |
||||||
|
root_cert_distributor_->CancelTlsCertificatesWatch(root_cert_watcher_); |
||||||
|
root_cert_watcher_ = nullptr; |
||||||
|
} |
||||||
|
GPR_ASSERT(root_cert_watcher_ == nullptr); |
||||||
|
} |
||||||
|
if (identity_being_watched && !watching_identity_certs_) { |
||||||
|
watching_identity_certs_ = true; |
||||||
|
if (identity_cert_distributor_ == nullptr) { |
||||||
|
distributor_->SetErrorForCert( |
||||||
|
"", absl::nullopt, |
||||||
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
||||||
|
"No certificate provider available for identity certificates")); |
||||||
|
} else { |
||||||
|
UpdateIdentityCertWatcher(identity_cert_distributor_.get()); |
||||||
|
} |
||||||
|
} else if (!identity_being_watched && watching_identity_certs_) { |
||||||
|
watching_identity_certs_ = false; |
||||||
|
if (identity_cert_distributor_ != nullptr) { |
||||||
|
identity_cert_distributor_->CancelTlsCertificatesWatch( |
||||||
|
identity_cert_watcher_); |
||||||
|
identity_cert_watcher_ = nullptr; |
||||||
|
} |
||||||
|
GPR_ASSERT(identity_cert_watcher_ == nullptr); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void XdsCertificateProvider::UpdateRootCertWatcher( |
||||||
|
grpc_tls_certificate_distributor* root_cert_distributor) { |
||||||
|
auto watcher = absl::make_unique<RootCertificatesWatcher>(distributor()); |
||||||
|
root_cert_watcher_ = watcher.get(); |
||||||
|
root_cert_distributor->WatchTlsCertificates(std::move(watcher), |
||||||
|
root_cert_name_, absl::nullopt); |
||||||
|
} |
||||||
|
|
||||||
|
void XdsCertificateProvider::UpdateIdentityCertWatcher( |
||||||
|
grpc_tls_certificate_distributor* identity_cert_distributor) { |
||||||
|
auto watcher = absl::make_unique<IdentityCertificatesWatcher>(distributor()); |
||||||
|
identity_cert_watcher_ = watcher.get(); |
||||||
|
identity_cert_distributor->WatchTlsCertificates( |
||||||
|
std::move(watcher), absl::nullopt, identity_cert_name_); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace grpc_core
|
@ -0,0 +1,74 @@ |
|||||||
|
//
|
||||||
|
//
|
||||||
|
// Copyright 2020 gRPC authors.
|
||||||
|
//
|
||||||
|
// Licensed 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.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GRPC_CORE_EXT_XDS_XDS_CERTIFICATE_PROVIDER_H |
||||||
|
#define GRPC_CORE_EXT_XDS_XDS_CERTIFICATE_PROVIDER_H |
||||||
|
|
||||||
|
#include <grpc/support/port_platform.h> |
||||||
|
|
||||||
|
#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h" |
||||||
|
|
||||||
|
namespace grpc_core { |
||||||
|
|
||||||
|
class XdsCertificateProvider : public grpc_tls_certificate_provider { |
||||||
|
public: |
||||||
|
XdsCertificateProvider( |
||||||
|
absl::string_view root_cert_name, |
||||||
|
RefCountedPtr<grpc_tls_certificate_distributor> root_cert_distributor, |
||||||
|
absl::string_view identity_cert_name, |
||||||
|
RefCountedPtr<grpc_tls_certificate_distributor> |
||||||
|
identity_cert_distributor); |
||||||
|
|
||||||
|
void UpdateRootCertNameAndDistributor( |
||||||
|
absl::string_view root_cert_name, |
||||||
|
RefCountedPtr<grpc_tls_certificate_distributor> root_cert_distributor); |
||||||
|
void UpdateIdentityCertNameAndDistributor( |
||||||
|
absl::string_view identity_cert_name, |
||||||
|
RefCountedPtr<grpc_tls_certificate_distributor> |
||||||
|
identity_cert_distributor); |
||||||
|
|
||||||
|
grpc_core::RefCountedPtr<grpc_tls_certificate_distributor> distributor() |
||||||
|
const override { |
||||||
|
return distributor_; |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
void WatchStatusCallback(std::string cert_name, bool root_being_watched, |
||||||
|
bool identity_being_watched); |
||||||
|
void UpdateRootCertWatcher( |
||||||
|
grpc_tls_certificate_distributor* root_cert_distributor); |
||||||
|
void UpdateIdentityCertWatcher( |
||||||
|
grpc_tls_certificate_distributor* identity_cert_distributor); |
||||||
|
|
||||||
|
Mutex mu_; |
||||||
|
bool watching_root_certs_ = false; |
||||||
|
bool watching_identity_certs_ = false; |
||||||
|
std::string root_cert_name_; |
||||||
|
std::string identity_cert_name_; |
||||||
|
RefCountedPtr<grpc_tls_certificate_distributor> root_cert_distributor_; |
||||||
|
RefCountedPtr<grpc_tls_certificate_distributor> identity_cert_distributor_; |
||||||
|
RefCountedPtr<grpc_tls_certificate_distributor> distributor_; |
||||||
|
grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface* |
||||||
|
root_cert_watcher_ = nullptr; |
||||||
|
grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface* |
||||||
|
identity_cert_watcher_ = nullptr; |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace grpc_core
|
||||||
|
|
||||||
|
#endif // GRPC_CORE_EXT_XDS_XDS_CERTIFICATE_PROVIDER_H
|
@ -0,0 +1,529 @@ |
|||||||
|
//
|
||||||
|
//
|
||||||
|
// Copyright 2020 gRPC authors.
|
||||||
|
//
|
||||||
|
// Licensed 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 <gmock/gmock.h> |
||||||
|
#include <gtest/gtest.h> |
||||||
|
|
||||||
|
#include "src/core/ext/xds/xds_certificate_provider.h" |
||||||
|
#include "test/core/util/test_config.h" |
||||||
|
|
||||||
|
namespace grpc_core { |
||||||
|
namespace testing { |
||||||
|
namespace { |
||||||
|
|
||||||
|
constexpr const char* kRootCert1 = "root_cert_1_contents"; |
||||||
|
constexpr const char* kRootCert2 = "root_cert_2_contents"; |
||||||
|
constexpr const char* kIdentityCert1PrivateKey = "identity_private_key_1"; |
||||||
|
constexpr const char* kIdentityCert1 = "identity_cert_1_contents"; |
||||||
|
constexpr const char* kIdentityCert2PrivateKey = "identity_private_key_2"; |
||||||
|
constexpr const char* kIdentityCert2 = "identity_cert_2_contents"; |
||||||
|
constexpr const char* kRootErrorMessage = "root_error_message"; |
||||||
|
constexpr const char* kIdentityErrorMessage = "identity_error_message"; |
||||||
|
|
||||||
|
PemKeyCertPairList MakeKeyCertPairs(const char* private_key, |
||||||
|
const char* certs) { |
||||||
|
if (strcmp(private_key, "") == 0 && strcmp(certs, "") == 0) { |
||||||
|
return {}; |
||||||
|
} |
||||||
|
grpc_ssl_pem_key_cert_pair* ssl_pair = |
||||||
|
static_cast<grpc_ssl_pem_key_cert_pair*>( |
||||||
|
gpr_malloc(sizeof(grpc_ssl_pem_key_cert_pair))); |
||||||
|
ssl_pair->private_key = gpr_strdup(private_key); |
||||||
|
ssl_pair->cert_chain = gpr_strdup(certs); |
||||||
|
return PemKeyCertPairList{PemKeyCertPair(ssl_pair)}; |
||||||
|
} |
||||||
|
|
||||||
|
PemKeyCertPairList MakeKeyCertPairsType1() { |
||||||
|
return MakeKeyCertPairs(kIdentityCert1PrivateKey, kIdentityCert1); |
||||||
|
} |
||||||
|
|
||||||
|
PemKeyCertPairList MakeKeyCertPairsType2() { |
||||||
|
return MakeKeyCertPairs(kIdentityCert2PrivateKey, kIdentityCert2); |
||||||
|
} |
||||||
|
|
||||||
|
class TestCertificatesWatcher |
||||||
|
: public grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface { |
||||||
|
public: |
||||||
|
~TestCertificatesWatcher() override { |
||||||
|
GRPC_ERROR_UNREF(root_cert_error_); |
||||||
|
GRPC_ERROR_UNREF(identity_cert_error_); |
||||||
|
} |
||||||
|
|
||||||
|
void OnCertificatesChanged( |
||||||
|
absl::optional<absl::string_view> root_certs, |
||||||
|
absl::optional<PemKeyCertPairList> key_cert_pairs) override { |
||||||
|
if (root_certs.has_value()) { |
||||||
|
if (!root_certs_.has_value() || |
||||||
|
(root_certs_.has_value() && |
||||||
|
std::string(root_certs.value()) != root_certs_.value())) { |
||||||
|
GRPC_ERROR_UNREF(root_cert_error_); |
||||||
|
root_cert_error_ = GRPC_ERROR_NONE; |
||||||
|
} |
||||||
|
root_certs_.emplace(std::string(root_certs.value())); |
||||||
|
} |
||||||
|
if (key_cert_pairs.has_value()) { |
||||||
|
if (key_cert_pairs != key_cert_pairs_) { |
||||||
|
GRPC_ERROR_UNREF(identity_cert_error_); |
||||||
|
identity_cert_error_ = GRPC_ERROR_NONE; |
||||||
|
key_cert_pairs_ = key_cert_pairs; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void OnError(grpc_error* root_cert_error, |
||||||
|
grpc_error* identity_cert_error) override { |
||||||
|
GRPC_ERROR_UNREF(root_cert_error_); |
||||||
|
root_cert_error_ = root_cert_error; |
||||||
|
GRPC_ERROR_UNREF(identity_cert_error_); |
||||||
|
identity_cert_error_ = identity_cert_error; |
||||||
|
} |
||||||
|
|
||||||
|
const absl::optional<std::string>& root_certs() const { return root_certs_; } |
||||||
|
|
||||||
|
const absl::optional<PemKeyCertPairList>& key_cert_pairs() const { |
||||||
|
return key_cert_pairs_; |
||||||
|
} |
||||||
|
|
||||||
|
grpc_error* root_cert_error() const { return root_cert_error_; } |
||||||
|
|
||||||
|
grpc_error* identity_cert_error() const { return identity_cert_error_; } |
||||||
|
|
||||||
|
private: |
||||||
|
absl::optional<std::string> root_certs_; |
||||||
|
absl::optional<PemKeyCertPairList> key_cert_pairs_; |
||||||
|
grpc_error* root_cert_error_ = GRPC_ERROR_NONE; |
||||||
|
grpc_error* identity_cert_error_ = GRPC_ERROR_NONE; |
||||||
|
}; |
||||||
|
|
||||||
|
TEST( |
||||||
|
XdsCertificateProviderTest, |
||||||
|
RootCertDistributorDifferentFromIdentityCertDistributorDifferentCertNames) { |
||||||
|
auto root_cert_distributor = |
||||||
|
MakeRefCounted<grpc_tls_certificate_distributor>(); |
||||||
|
auto identity_cert_distributor = |
||||||
|
MakeRefCounted<grpc_tls_certificate_distributor>(); |
||||||
|
XdsCertificateProvider provider("root", root_cert_distributor, "identity", |
||||||
|
identity_cert_distributor); |
||||||
|
auto* watcher = new TestCertificatesWatcher; |
||||||
|
provider.distributor()->WatchTlsCertificates( |
||||||
|
std::unique_ptr<TestCertificatesWatcher>(watcher), "", ""); |
||||||
|
EXPECT_EQ(watcher->root_certs(), absl::nullopt); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), absl::nullopt); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Update both root certs and identity certs
|
||||||
|
root_cert_distributor->SetKeyMaterials("root", kRootCert1, absl::nullopt); |
||||||
|
identity_cert_distributor->SetKeyMaterials("identity", absl::nullopt, |
||||||
|
MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Second update for just root certs
|
||||||
|
root_cert_distributor->SetKeyMaterials( |
||||||
|
"root", kRootCert2, |
||||||
|
MakeKeyCertPairsType2() /* does not have an effect */); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Second update for identity certs
|
||||||
|
identity_cert_distributor->SetKeyMaterials( |
||||||
|
"identity", kRootCert1 /* does not have an effect */, |
||||||
|
MakeKeyCertPairsType2()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Set error for both root and identity
|
||||||
|
root_cert_distributor->SetErrorForCert( |
||||||
|
"root", GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage), |
||||||
|
absl::nullopt); |
||||||
|
identity_cert_distributor->SetErrorForCert( |
||||||
|
"identity", absl::nullopt, |
||||||
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage)); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), |
||||||
|
::testing::HasSubstr(kRootErrorMessage)); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), |
||||||
|
::testing::HasSubstr(kIdentityErrorMessage)); |
||||||
|
// Send an update for root certs. Test that the root cert error is reset.
|
||||||
|
root_cert_distributor->SetKeyMaterials("root", kRootCert1, absl::nullopt); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), |
||||||
|
::testing::HasSubstr(kIdentityErrorMessage)); |
||||||
|
// Send an update for identity certs. Test that the identity cert error is
|
||||||
|
// reset.
|
||||||
|
identity_cert_distributor->SetKeyMaterials("identity", absl::nullopt, |
||||||
|
MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(XdsCertificateProviderTest, |
||||||
|
RootCertDistributorDifferentFromIdentityCertDistributorSameCertNames) { |
||||||
|
auto root_cert_distributor = |
||||||
|
MakeRefCounted<grpc_tls_certificate_distributor>(); |
||||||
|
auto identity_cert_distributor = |
||||||
|
MakeRefCounted<grpc_tls_certificate_distributor>(); |
||||||
|
XdsCertificateProvider provider("test", root_cert_distributor, "test", |
||||||
|
identity_cert_distributor); |
||||||
|
auto* watcher = new TestCertificatesWatcher; |
||||||
|
provider.distributor()->WatchTlsCertificates( |
||||||
|
std::unique_ptr<TestCertificatesWatcher>(watcher), "", ""); |
||||||
|
EXPECT_EQ(watcher->root_certs(), absl::nullopt); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), absl::nullopt); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Update both root certs and identity certs
|
||||||
|
root_cert_distributor->SetKeyMaterials("test", kRootCert1, absl::nullopt); |
||||||
|
identity_cert_distributor->SetKeyMaterials("test", absl::nullopt, |
||||||
|
MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Second update for just root certs
|
||||||
|
root_cert_distributor->SetKeyMaterials("test", kRootCert2, absl::nullopt); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Second update for identity certs
|
||||||
|
identity_cert_distributor->SetKeyMaterials("test", absl::nullopt, |
||||||
|
MakeKeyCertPairsType2()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Set error for both root and identity
|
||||||
|
root_cert_distributor->SetErrorForCert( |
||||||
|
"test", GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage), |
||||||
|
absl::nullopt); |
||||||
|
identity_cert_distributor->SetErrorForCert( |
||||||
|
"test", absl::nullopt, |
||||||
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage)); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), |
||||||
|
::testing::HasSubstr(kRootErrorMessage)); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), |
||||||
|
::testing::HasSubstr(kIdentityErrorMessage)); |
||||||
|
// Send an update for root certs. Test that the root cert error is reset.
|
||||||
|
root_cert_distributor->SetKeyMaterials("test", kRootCert1, absl::nullopt); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), |
||||||
|
::testing::HasSubstr(kIdentityErrorMessage)); |
||||||
|
// Send an update for identity certs. Test that the identity cert error is
|
||||||
|
// reset.
|
||||||
|
identity_cert_distributor->SetKeyMaterials("test", absl::nullopt, |
||||||
|
MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Test update on unwatched cert name
|
||||||
|
identity_cert_distributor->SetKeyMaterials("identity", kRootCert2, |
||||||
|
MakeKeyCertPairsType2()); |
||||||
|
root_cert_distributor->SetKeyMaterials("root", kRootCert1, |
||||||
|
MakeKeyCertPairsType1()); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(XdsCertificateProviderTest, |
||||||
|
RootCertDistributorSameAsIdentityCertDistributorDifferentCertNames) { |
||||||
|
auto distributor = MakeRefCounted<grpc_tls_certificate_distributor>(); |
||||||
|
XdsCertificateProvider provider("root", distributor, "identity", distributor); |
||||||
|
auto* watcher = new TestCertificatesWatcher; |
||||||
|
provider.distributor()->WatchTlsCertificates( |
||||||
|
std::unique_ptr<TestCertificatesWatcher>(watcher), "", ""); |
||||||
|
EXPECT_EQ(watcher->root_certs(), absl::nullopt); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), absl::nullopt); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Update both root certs and identity certs
|
||||||
|
distributor->SetKeyMaterials("root", kRootCert1, MakeKeyCertPairsType2()); |
||||||
|
distributor->SetKeyMaterials("identity", kRootCert2, MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Second update for just root certs
|
||||||
|
distributor->SetKeyMaterials("root", kRootCert2, MakeKeyCertPairsType2()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Second update for identity certs
|
||||||
|
distributor->SetKeyMaterials("identity", kRootCert1, MakeKeyCertPairsType2()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Set error for root
|
||||||
|
distributor->SetErrorForCert( |
||||||
|
"root", GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage), |
||||||
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage)); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), |
||||||
|
::testing::HasSubstr(kRootErrorMessage)); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
distributor->SetErrorForCert( |
||||||
|
"identity", GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage), |
||||||
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage)); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), |
||||||
|
::testing::HasSubstr(kRootErrorMessage)); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), |
||||||
|
::testing::HasSubstr(kIdentityErrorMessage)); |
||||||
|
// Send an update for root
|
||||||
|
distributor->SetKeyMaterials("root", kRootCert1, MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), |
||||||
|
::testing::HasSubstr(kIdentityErrorMessage)); |
||||||
|
// Send an update for identity
|
||||||
|
distributor->SetKeyMaterials("identity", kRootCert2, MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(XdsCertificateProviderTest, |
||||||
|
RootCertDistributorSameAsIdentityCertDistributorSameCertNames) { |
||||||
|
auto distributor = MakeRefCounted<grpc_tls_certificate_distributor>(); |
||||||
|
XdsCertificateProvider provider("", distributor, "", distributor); |
||||||
|
auto* watcher = new TestCertificatesWatcher; |
||||||
|
provider.distributor()->WatchTlsCertificates( |
||||||
|
std::unique_ptr<TestCertificatesWatcher>(watcher), "", ""); |
||||||
|
EXPECT_EQ(watcher->root_certs(), absl::nullopt); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), absl::nullopt); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Update both root certs and identity certs
|
||||||
|
distributor->SetKeyMaterials("", kRootCert1, MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Second update for just root certs
|
||||||
|
distributor->SetKeyMaterials("", kRootCert2, absl::nullopt); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Second update for identity certs
|
||||||
|
distributor->SetKeyMaterials("", absl::nullopt, MakeKeyCertPairsType2()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Set error for root
|
||||||
|
distributor->SetErrorForCert( |
||||||
|
"", GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage), |
||||||
|
absl::nullopt); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), |
||||||
|
::testing::HasSubstr(kRootErrorMessage)); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Set error for identity
|
||||||
|
distributor->SetErrorForCert( |
||||||
|
"", absl::nullopt, |
||||||
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage)); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), |
||||||
|
::testing::HasSubstr(kRootErrorMessage)); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), |
||||||
|
::testing::HasSubstr(kIdentityErrorMessage)); |
||||||
|
// Send an update for root
|
||||||
|
distributor->SetKeyMaterials("", kRootCert1, absl::nullopt); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), |
||||||
|
::testing::HasSubstr(kIdentityErrorMessage)); |
||||||
|
// Send an update for identity
|
||||||
|
distributor->SetKeyMaterials("", absl::nullopt, MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(XdsCertificateProviderTest, SwapOutDistributorsMultipleTimes) { |
||||||
|
auto distributor = MakeRefCounted<grpc_tls_certificate_distributor>(); |
||||||
|
distributor->SetKeyMaterials("", kRootCert1, MakeKeyCertPairsType1()); |
||||||
|
XdsCertificateProvider provider("", nullptr, "", nullptr); |
||||||
|
auto* watcher = new TestCertificatesWatcher; |
||||||
|
provider.distributor()->WatchTlsCertificates( |
||||||
|
std::unique_ptr<TestCertificatesWatcher>(watcher), "", ""); |
||||||
|
// Initially there are no certificate providers.
|
||||||
|
EXPECT_EQ(watcher->root_certs(), absl::nullopt); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), absl::nullopt); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), |
||||||
|
::testing::HasSubstr( |
||||||
|
"No certificate provider available for root certificates")); |
||||||
|
EXPECT_THAT( |
||||||
|
grpc_error_string(watcher->identity_cert_error()), |
||||||
|
::testing::HasSubstr( |
||||||
|
"No certificate provider available for identity certificates")); |
||||||
|
// Update root cert distributor.
|
||||||
|
provider.UpdateRootCertNameAndDistributor("", distributor); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), absl::nullopt); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_THAT( |
||||||
|
grpc_error_string(watcher->identity_cert_error()), |
||||||
|
::testing::HasSubstr( |
||||||
|
"No certificate provider available for identity certificates")); |
||||||
|
// Update identity cert distributor
|
||||||
|
provider.UpdateIdentityCertNameAndDistributor("", distributor); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Update both root and identity certs
|
||||||
|
distributor->SetKeyMaterials("", kRootCert2, MakeKeyCertPairsType2()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Set error for both root and identity
|
||||||
|
distributor->SetErrorForCert( |
||||||
|
"", GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage), |
||||||
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage)); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), |
||||||
|
::testing::HasSubstr(kRootErrorMessage)); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), |
||||||
|
::testing::HasSubstr(kIdentityErrorMessage)); |
||||||
|
// Send an update again
|
||||||
|
distributor->SetKeyMaterials("", kRootCert1, MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Remove root cert provider
|
||||||
|
provider.UpdateRootCertNameAndDistributor("", nullptr); |
||||||
|
distributor->SetKeyMaterials("", kRootCert2, MakeKeyCertPairsType2()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); // not updated
|
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), |
||||||
|
::testing::HasSubstr( |
||||||
|
"No certificate provider available for root certificates")); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Remove identity cert provider too
|
||||||
|
provider.UpdateIdentityCertNameAndDistributor("", nullptr); |
||||||
|
distributor->SetKeyMaterials("", kRootCert1, MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); // not updated
|
||||||
|
EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), |
||||||
|
::testing::HasSubstr( |
||||||
|
"No certificate provider available for root certificates")); |
||||||
|
EXPECT_THAT( |
||||||
|
grpc_error_string(watcher->identity_cert_error()), |
||||||
|
::testing::HasSubstr( |
||||||
|
"No certificate provider available for identity certificates")); |
||||||
|
// Change certificate names being watched, without any certificate updates.
|
||||||
|
provider.UpdateRootCertNameAndDistributor("root", distributor); |
||||||
|
provider.UpdateIdentityCertNameAndDistributor("identity", distributor); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), |
||||||
|
::testing::HasSubstr( |
||||||
|
"No certificate provider available for root certificates")); |
||||||
|
EXPECT_THAT( |
||||||
|
grpc_error_string(watcher->identity_cert_error()), |
||||||
|
::testing::HasSubstr( |
||||||
|
"No certificate provider available for identity certificates")); |
||||||
|
// Send out certificate updates.
|
||||||
|
distributor->SetKeyMaterials("root", kRootCert2, absl::nullopt); |
||||||
|
distributor->SetKeyMaterials("identity", absl::nullopt, |
||||||
|
MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Swap in new certificate distributors with different certificate names and
|
||||||
|
// existing updates.
|
||||||
|
auto root_cert_distributor = |
||||||
|
MakeRefCounted<grpc_tls_certificate_distributor>(); |
||||||
|
auto identity_cert_distributor = |
||||||
|
MakeRefCounted<grpc_tls_certificate_distributor>(); |
||||||
|
provider.UpdateRootCertNameAndDistributor("root", root_cert_distributor); |
||||||
|
provider.UpdateIdentityCertNameAndDistributor("identity", |
||||||
|
identity_cert_distributor); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Change certificate names without any certificate updates.
|
||||||
|
provider.UpdateRootCertNameAndDistributor("test", root_cert_distributor); |
||||||
|
provider.UpdateIdentityCertNameAndDistributor("test", |
||||||
|
identity_cert_distributor); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert2); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType1()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
// Send out certificate updates.
|
||||||
|
root_cert_distributor->SetKeyMaterials("test", kRootCert1, |
||||||
|
MakeKeyCertPairsType1()); |
||||||
|
identity_cert_distributor->SetKeyMaterials("test", kRootCert2, |
||||||
|
MakeKeyCertPairsType2()); |
||||||
|
EXPECT_EQ(watcher->root_certs(), kRootCert1); |
||||||
|
EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); |
||||||
|
EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); |
||||||
|
EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(XdsCertificateProviderTest, CertificateNameNotEmpty) { |
||||||
|
XdsCertificateProvider provider("", nullptr, "", nullptr); |
||||||
|
auto* watcher = new TestCertificatesWatcher; |
||||||
|
provider.distributor()->WatchTlsCertificates( |
||||||
|
std::unique_ptr<TestCertificatesWatcher>(watcher), "test", "test"); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), |
||||||
|
::testing::HasSubstr("Illegal certificate name: \'test\'")); |
||||||
|
EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), |
||||||
|
::testing::HasSubstr("Illegal certificate name: \'test\'")); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace testing
|
||||||
|
} // namespace grpc_core
|
||||||
|
|
||||||
|
int main(int argc, char** argv) { |
||||||
|
::testing::InitGoogleTest(&argc, argv); |
||||||
|
grpc::testing::TestEnvironment env(argc, argv); |
||||||
|
grpc_init(); |
||||||
|
auto result = RUN_ALL_TESTS(); |
||||||
|
grpc_shutdown(); |
||||||
|
return result; |
||||||
|
} |
Loading…
Reference in new issue