|
|
|
@ -37,15 +37,16 @@ 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); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -53,7 +54,7 @@ class RootCertificatesWatcher |
|
|
|
|
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 */, |
|
|
|
|
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 { |
|
|
|
|
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,102 @@ 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>(Ref())) |
|
|
|
|
.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>(Ref())) |
|
|
|
|
.first; |
|
|
|
|
} |
|
|
|
|
it->second->UpdateIdentityCertNameAndDistributor( |
|
|
|
|
cert_name, identity_cert_name, identity_cert_distributor); |
|
|
|
|
// Delete unused entries.
|
|
|
|
|
if (it->second->IsSafeToRemove()) certificate_state_map_.erase(it); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::vector<XdsApi::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<XdsApi::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>(Ref())) |
|
|
|
|
.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 { |
|
|
|
|