summaryrefslogtreecommitdiff
path: root/grpc/src/core/ext/xds/xds_certificate_provider.cc
diff options
context:
space:
mode:
Diffstat (limited to 'grpc/src/core/ext/xds/xds_certificate_provider.cc')
-rw-r--r--grpc/src/core/ext/xds/xds_certificate_provider.cc262
1 files changed, 184 insertions, 78 deletions
diff --git a/grpc/src/core/ext/xds/xds_certificate_provider.cc b/grpc/src/core/ext/xds/xds_certificate_provider.cc
index f285b6db..ce1ba673 100644
--- a/grpc/src/core/ext/xds/xds_certificate_provider.cc
+++ b/grpc/src/core/ext/xds/xds_certificate_provider.cc
@@ -37,23 +37,24 @@ class RootCertificatesWatcher
// 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)) {}
+ RootCertificatesWatcher(
+ RefCountedPtr<grpc_tls_certificate_distributor> parent,
+ std::string cert_name)
+ : parent_(std::move(parent)), cert_name_(std::move(cert_name)) {}
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()),
+ parent_->SetKeyMaterials(cert_name_, std::string(root_certs.value()),
absl::nullopt);
}
}
- void OnError(grpc_error* root_cert_error,
- grpc_error* identity_cert_error) override {
+ void OnError(grpc_error_handle root_cert_error,
+ grpc_error_handle identity_cert_error) override {
if (root_cert_error != GRPC_ERROR_NONE) {
- parent_->SetErrorForCert("", root_cert_error /* pass the ref */,
+ parent_->SetErrorForCert(cert_name_, root_cert_error /* pass the ref */,
absl::nullopt);
}
GRPC_ERROR_UNREF(identity_cert_error);
@@ -61,6 +62,7 @@ class RootCertificatesWatcher
private:
RefCountedPtr<grpc_tls_certificate_distributor> parent_;
+ std::string cert_name_;
};
class IdentityCertificatesWatcher
@@ -71,22 +73,23 @@ class IdentityCertificatesWatcher
// 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)) {}
+ IdentityCertificatesWatcher(
+ RefCountedPtr<grpc_tls_certificate_distributor> parent,
+ std::string cert_name)
+ : parent_(std::move(parent)), cert_name_(std::move(cert_name)) {}
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);
+ parent_->SetKeyMaterials(cert_name_, absl::nullopt, key_cert_pairs);
}
}
- void OnError(grpc_error* root_cert_error,
- grpc_error* identity_cert_error) override {
+ void OnError(grpc_error_handle root_cert_error,
+ grpc_error_handle identity_cert_error) override {
if (identity_cert_error != GRPC_ERROR_NONE) {
- parent_->SetErrorForCert("", absl::nullopt,
+ parent_->SetErrorForCert(cert_name_, absl::nullopt,
identity_cert_error /* pass the ref */);
}
GRPC_ERROR_UNREF(root_cert_error);
@@ -94,34 +97,35 @@ class IdentityCertificatesWatcher
private:
RefCountedPtr<grpc_tls_certificate_distributor> parent_;
+ std::string cert_name_;
};
} // 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,
- std::vector<XdsApi::StringMatcher> san_matchers)
- : 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)),
- san_matchers_(std::move(san_matchers)),
- distributor_(MakeRefCounted<grpc_tls_certificate_distributor>()) {
- distributor_->SetWatchStatusCallback(
- absl::bind_front(&XdsCertificateProvider::WatchStatusCallback, this));
+//
+// XdsCertificateProvider::ClusterCertificateState
+//
+
+XdsCertificateProvider::ClusterCertificateState::~ClusterCertificateState() {
+ if (root_cert_watcher_ != nullptr) {
+ root_cert_distributor_->CancelTlsCertificatesWatch(root_cert_watcher_);
+ }
+ if (identity_cert_watcher_ != nullptr) {
+ identity_cert_distributor_->CancelTlsCertificatesWatch(
+ identity_cert_watcher_);
+ }
}
-XdsCertificateProvider::~XdsCertificateProvider() {
- distributor_->SetWatchStatusCallback(nullptr);
+bool XdsCertificateProvider::ClusterCertificateState::IsSafeToRemove() const {
+ return !watching_root_certs_ && !watching_identity_certs_ &&
+ root_cert_distributor_ == nullptr &&
+ identity_cert_distributor_ == nullptr;
}
-void XdsCertificateProvider::UpdateRootCertNameAndDistributor(
- absl::string_view root_cert_name,
- RefCountedPtr<grpc_tls_certificate_distributor> root_cert_distributor) {
- MutexLock lock(&mu_);
+void XdsCertificateProvider::ClusterCertificateState::
+ UpdateRootCertNameAndDistributor(
+ const std::string& cert_name, absl::string_view root_cert_name,
+ RefCountedPtr<grpc_tls_certificate_distributor> root_cert_distributor) {
if (root_cert_name_ == root_cert_name &&
root_cert_distributor_ == root_cert_distributor) {
return;
@@ -133,10 +137,10 @@ void XdsCertificateProvider::UpdateRootCertNameAndDistributor(
root_cert_distributor_->CancelTlsCertificatesWatch(root_cert_watcher_);
}
if (root_cert_distributor != nullptr) {
- UpdateRootCertWatcher(root_cert_distributor.get());
+ UpdateRootCertWatcher(cert_name, root_cert_distributor.get());
} else {
root_cert_watcher_ = nullptr;
- distributor_->SetErrorForCert(
+ xds_certificate_provider_->distributor_->SetErrorForCert(
"",
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"No certificate provider available for root certificates"),
@@ -147,10 +151,11 @@ void XdsCertificateProvider::UpdateRootCertNameAndDistributor(
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_);
+void XdsCertificateProvider::ClusterCertificateState::
+ UpdateIdentityCertNameAndDistributor(
+ const std::string& cert_name, absl::string_view identity_cert_name,
+ RefCountedPtr<grpc_tls_certificate_distributor>
+ identity_cert_distributor) {
if (identity_cert_name_ == identity_cert_name &&
identity_cert_distributor_ == identity_cert_distributor) {
return;
@@ -163,10 +168,10 @@ void XdsCertificateProvider::UpdateIdentityCertNameAndDistributor(
identity_cert_watcher_);
}
if (identity_cert_distributor != nullptr) {
- UpdateIdentityCertWatcher(identity_cert_distributor.get());
+ UpdateIdentityCertWatcher(cert_name, identity_cert_distributor.get());
} else {
identity_cert_watcher_ = nullptr;
- distributor_->SetErrorForCert(
+ xds_certificate_provider_->distributor_->SetErrorForCert(
"", absl::nullopt,
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"No certificate provider available for identity certificates"));
@@ -176,42 +181,45 @@ void XdsCertificateProvider::UpdateIdentityCertNameAndDistributor(
identity_cert_distributor_ = std::move(identity_cert_distributor);
}
-void XdsCertificateProvider::UpdateSubjectAlternativeNameMatchers(
- std::vector<XdsApi::StringMatcher> matchers) {
- MutexLock lock(&san_matchers_mu_);
- san_matchers_ = std::move(matchers);
+void XdsCertificateProvider::ClusterCertificateState::UpdateRootCertWatcher(
+ const std::string& cert_name,
+ grpc_tls_certificate_distributor* root_cert_distributor) {
+ auto watcher = absl::make_unique<RootCertificatesWatcher>(
+ xds_certificate_provider_->distributor_, cert_name);
+ root_cert_watcher_ = watcher.get();
+ root_cert_distributor->WatchTlsCertificates(std::move(watcher),
+ root_cert_name_, absl::nullopt);
}
-void XdsCertificateProvider::WatchStatusCallback(std::string cert_name,
- bool root_being_watched,
- bool identity_being_watched) {
+void XdsCertificateProvider::ClusterCertificateState::UpdateIdentityCertWatcher(
+ const std::string& cert_name,
+ grpc_tls_certificate_distributor* identity_cert_distributor) {
+ auto watcher = absl::make_unique<IdentityCertificatesWatcher>(
+ xds_certificate_provider_->distributor_, cert_name);
+ identity_cert_watcher_ = watcher.get();
+ identity_cert_distributor->WatchTlsCertificates(
+ std::move(watcher), absl::nullopt, identity_cert_name_);
+}
+
+void XdsCertificateProvider::ClusterCertificateState::WatchStatusCallback(
+ const 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(
- "",
+ xds_certificate_provider_->distributor_->SetErrorForCert(
+ cert_name,
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"No certificate provider available for root certificates"),
absl::nullopt);
} else {
- UpdateRootCertWatcher(root_cert_distributor_.get());
+ UpdateRootCertWatcher(cert_name, root_cert_distributor_.get());
}
} else if (!root_being_watched && watching_root_certs_) {
// We need to cancel root certs watch.
@@ -225,12 +233,12 @@ void XdsCertificateProvider::WatchStatusCallback(std::string cert_name,
if (identity_being_watched && !watching_identity_certs_) {
watching_identity_certs_ = true;
if (identity_cert_distributor_ == nullptr) {
- distributor_->SetErrorForCert(
- "", absl::nullopt,
+ xds_certificate_provider_->distributor_->SetErrorForCert(
+ cert_name, absl::nullopt,
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"No certificate provider available for identity certificates"));
} else {
- UpdateIdentityCertWatcher(identity_cert_distributor_.get());
+ UpdateIdentityCertWatcher(cert_name, identity_cert_distributor_.get());
}
} else if (!identity_being_watched && watching_identity_certs_) {
watching_identity_certs_ = false;
@@ -243,20 +251,118 @@ void XdsCertificateProvider::WatchStatusCallback(std::string cert_name,
}
}
-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);
+//
+// XdsCertificateProvider
+//
+
+XdsCertificateProvider::XdsCertificateProvider()
+ : distributor_(MakeRefCounted<grpc_tls_certificate_distributor>()) {
+ distributor_->SetWatchStatusCallback(
+ absl::bind_front(&XdsCertificateProvider::WatchStatusCallback, this));
}
-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_);
+XdsCertificateProvider::~XdsCertificateProvider() {
+ distributor_->SetWatchStatusCallback(nullptr);
+}
+
+bool XdsCertificateProvider::ProvidesRootCerts(const std::string& cert_name) {
+ MutexLock lock(&mu_);
+ auto it = certificate_state_map_.find(cert_name);
+ if (it == certificate_state_map_.end()) return false;
+ return it->second->ProvidesRootCerts();
+}
+
+void XdsCertificateProvider::UpdateRootCertNameAndDistributor(
+ const std::string& cert_name, absl::string_view root_cert_name,
+ RefCountedPtr<grpc_tls_certificate_distributor> root_cert_distributor) {
+ MutexLock lock(&mu_);
+ auto it = certificate_state_map_.find(cert_name);
+ if (it == certificate_state_map_.end()) {
+ it = certificate_state_map_
+ .emplace(cert_name,
+ absl::make_unique<ClusterCertificateState>(this))
+ .first;
+ }
+ it->second->UpdateRootCertNameAndDistributor(cert_name, root_cert_name,
+ root_cert_distributor);
+ // Delete unused entries.
+ if (it->second->IsSafeToRemove()) certificate_state_map_.erase(it);
+}
+
+bool XdsCertificateProvider::ProvidesIdentityCerts(
+ const std::string& cert_name) {
+ MutexLock lock(&mu_);
+ auto it = certificate_state_map_.find(cert_name);
+ if (it == certificate_state_map_.end()) return false;
+ return it->second->ProvidesIdentityCerts();
+}
+
+void XdsCertificateProvider::UpdateIdentityCertNameAndDistributor(
+ const std::string& cert_name, absl::string_view identity_cert_name,
+ RefCountedPtr<grpc_tls_certificate_distributor> identity_cert_distributor) {
+ MutexLock lock(&mu_);
+ auto it = certificate_state_map_.find(cert_name);
+ if (it == certificate_state_map_.end()) {
+ it = certificate_state_map_
+ .emplace(cert_name,
+ absl::make_unique<ClusterCertificateState>(this))
+ .first;
+ }
+ it->second->UpdateIdentityCertNameAndDistributor(
+ cert_name, identity_cert_name, identity_cert_distributor);
+ // Delete unused entries.
+ if (it->second->IsSafeToRemove()) certificate_state_map_.erase(it);
+}
+
+bool XdsCertificateProvider::GetRequireClientCertificate(
+ const std::string& cert_name) {
+ MutexLock lock(&mu_);
+ auto it = certificate_state_map_.find(cert_name);
+ if (it == certificate_state_map_.end()) return false;
+ return it->second->require_client_certificate();
+}
+
+void XdsCertificateProvider::UpdateRequireClientCertificate(
+ const std::string& cert_name, bool require_client_certificate) {
+ MutexLock lock(&mu_);
+ auto it = certificate_state_map_.find(cert_name);
+ if (it == certificate_state_map_.end()) return;
+ it->second->set_require_client_certificate(require_client_certificate);
+}
+
+std::vector<StringMatcher> XdsCertificateProvider::GetSanMatchers(
+ const std::string& cluster) {
+ MutexLock lock(&san_matchers_mu_);
+ auto it = san_matcher_map_.find(cluster);
+ if (it == san_matcher_map_.end()) return {};
+ return it->second;
+}
+
+void XdsCertificateProvider::UpdateSubjectAlternativeNameMatchers(
+ const std::string& cluster, std::vector<StringMatcher> matchers) {
+ MutexLock lock(&san_matchers_mu_);
+ if (matchers.empty()) {
+ san_matcher_map_.erase(cluster);
+ } else {
+ san_matcher_map_[cluster] = std::move(matchers);
+ }
+}
+
+void XdsCertificateProvider::WatchStatusCallback(std::string cert_name,
+ bool root_being_watched,
+ bool identity_being_watched) {
+ MutexLock lock(&mu_);
+ auto it = certificate_state_map_.find(cert_name);
+ if (it == certificate_state_map_.end()) {
+ it = certificate_state_map_
+ .emplace(cert_name,
+ absl::make_unique<ClusterCertificateState>(this))
+ .first;
+ }
+ it->second->WatchStatusCallback(cert_name, root_being_watched,
+ identity_being_watched);
+ // Delete unused entries.
+ if (it->second->IsSafeToRemove()) certificate_state_map_.erase(it);
}
namespace {