blob: 819c46a9fca569c94a959a39ba741925fb3a0e25 [file]
//
//
// 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 "src/core/ext/xds/xds_certificate_provider.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "test/core/util/test_config.h"
#include "test/core/util/tls_utils.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 MakeKeyCertPairsType1() {
return MakeCertKeyPairs(kIdentityCert1PrivateKey, kIdentityCert1);
}
PemKeyCertPairList MakeKeyCertPairsType2() {
return MakeCertKeyPairs(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_handle root_cert_error,
grpc_error_handle 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_handle root_cert_error() const { return root_cert_error_; }
grpc_error_handle identity_cert_error() const { return identity_cert_error_; }
private:
absl::optional<std::string> root_certs_;
absl::optional<PemKeyCertPairList> key_cert_pairs_;
grpc_error_handle root_cert_error_ = GRPC_ERROR_NONE;
grpc_error_handle 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;
provider.UpdateRootCertNameAndDistributor("", "root", root_cert_distributor);
provider.UpdateIdentityCertNameAndDistributor("", "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_std_string(watcher->root_cert_error()),
::testing::HasSubstr(kRootErrorMessage));
EXPECT_THAT(grpc_error_std_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_std_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;
provider.UpdateRootCertNameAndDistributor("", "test", root_cert_distributor);
provider.UpdateIdentityCertNameAndDistributor("", "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_std_string(watcher->root_cert_error()),
::testing::HasSubstr(kRootErrorMessage));
EXPECT_THAT(grpc_error_std_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_std_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;
provider.UpdateRootCertNameAndDistributor("", "root", distributor);
provider.UpdateIdentityCertNameAndDistributor("", "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_std_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_std_string(watcher->root_cert_error()),
::testing::HasSubstr(kRootErrorMessage));
EXPECT_THAT(grpc_error_std_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_std_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;
provider.UpdateRootCertNameAndDistributor("", "", distributor);
provider.UpdateIdentityCertNameAndDistributor("", "", 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_std_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_std_string(watcher->root_cert_error()),
::testing::HasSubstr(kRootErrorMessage));
EXPECT_THAT(grpc_error_std_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_std_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;
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_std_string(watcher->root_cert_error()),
::testing::HasSubstr(
"No certificate provider available for root certificates"));
EXPECT_THAT(
grpc_error_std_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_std_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_std_string(watcher->root_cert_error()),
::testing::HasSubstr(kRootErrorMessage));
EXPECT_THAT(grpc_error_std_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_std_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_std_string(watcher->root_cert_error()),
::testing::HasSubstr(
"No certificate provider available for root certificates"));
EXPECT_THAT(
grpc_error_std_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_std_string(watcher->root_cert_error()),
::testing::HasSubstr(
"No certificate provider available for root certificates"));
EXPECT_THAT(
grpc_error_std_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, MultipleCertNames) {
XdsCertificateProvider provider;
// Start watch for "test1". There are no underlying distributors for
// that cert name, so it will return an error.
auto* watcher1 = new TestCertificatesWatcher;
provider.distributor()->WatchTlsCertificates(
std::unique_ptr<TestCertificatesWatcher>(watcher1), "test1", "test1");
EXPECT_EQ(watcher1->root_certs(), absl::nullopt);
EXPECT_EQ(watcher1->key_cert_pairs(), absl::nullopt);
EXPECT_THAT(grpc_error_std_string(watcher1->root_cert_error()),
::testing::HasSubstr(
"No certificate provider available for root certificates"));
EXPECT_THAT(
grpc_error_std_string(watcher1->identity_cert_error()),
::testing::HasSubstr(
"No certificate provider available for identity certificates"));
// Add distributor for "test1". This will return data to the watcher.
auto cert_distributor1 = MakeRefCounted<grpc_tls_certificate_distributor>();
cert_distributor1->SetKeyMaterials("root", kRootCert1, absl::nullopt);
cert_distributor1->SetKeyMaterials("identity", absl::nullopt,
MakeKeyCertPairsType1());
provider.UpdateRootCertNameAndDistributor("test1", "root", cert_distributor1);
provider.UpdateIdentityCertNameAndDistributor("test1", "identity",
cert_distributor1);
EXPECT_EQ(watcher1->root_certs(), kRootCert1);
EXPECT_EQ(watcher1->key_cert_pairs(), MakeKeyCertPairsType1());
EXPECT_EQ(watcher1->root_cert_error(), GRPC_ERROR_NONE);
EXPECT_EQ(watcher1->identity_cert_error(), GRPC_ERROR_NONE);
// Add distributor for "test2".
auto cert_distributor2 = MakeRefCounted<grpc_tls_certificate_distributor>();
cert_distributor2->SetKeyMaterials("root2", kRootCert2, absl::nullopt);
cert_distributor2->SetKeyMaterials("identity2", absl::nullopt,
MakeKeyCertPairsType2());
provider.UpdateRootCertNameAndDistributor("test2", "root2",
cert_distributor2);
provider.UpdateIdentityCertNameAndDistributor("test2", "identity2",
cert_distributor2);
// Add watcher for "test2". This one should return data immediately.
auto* watcher2 = new TestCertificatesWatcher;
provider.distributor()->WatchTlsCertificates(
std::unique_ptr<TestCertificatesWatcher>(watcher2), "test2", "test2");
EXPECT_EQ(watcher2->root_certs(), kRootCert2);
EXPECT_EQ(watcher2->key_cert_pairs(), MakeKeyCertPairsType2());
EXPECT_EQ(watcher2->root_cert_error(), GRPC_ERROR_NONE);
EXPECT_EQ(watcher2->identity_cert_error(), GRPC_ERROR_NONE);
// The presence of "test2" should not affect "test1".
EXPECT_EQ(watcher1->root_certs(), kRootCert1);
EXPECT_EQ(watcher1->key_cert_pairs(), MakeKeyCertPairsType1());
EXPECT_EQ(watcher1->root_cert_error(), GRPC_ERROR_NONE);
EXPECT_EQ(watcher1->identity_cert_error(), GRPC_ERROR_NONE);
}
TEST(XdsCertificateProviderTest, UnknownCertName) {
XdsCertificateProvider provider;
auto* watcher = new TestCertificatesWatcher;
provider.distributor()->WatchTlsCertificates(
std::unique_ptr<TestCertificatesWatcher>(watcher), "test", "test");
EXPECT_THAT(grpc_error_std_string(watcher->root_cert_error()),
::testing::HasSubstr(
"No certificate provider available for root certificates"));
EXPECT_THAT(
grpc_error_std_string(watcher->identity_cert_error()),
::testing::HasSubstr(
"No certificate provider available for identity certificates"));
}
} // 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;
}