summaryrefslogtreecommitdiff
path: root/grpc/src/core/lib/security/credentials/tls
diff options
context:
space:
mode:
Diffstat (limited to 'grpc/src/core/lib/security/credentials/tls')
-rw-r--r--grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc321
-rw-r--r--grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h214
-rw-r--r--grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h16
3 files changed, 548 insertions, 3 deletions
diff --git a/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc b/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc
new file mode 100644
index 00000000..2189865b
--- /dev/null
+++ b/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc
@@ -0,0 +1,321 @@
+//
+// 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 "src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <stdlib.h>
+#include <string.h>
+
+void grpc_tls_certificate_distributor::SetKeyMaterials(
+ const std::string& cert_name, absl::optional<std::string> pem_root_certs,
+ absl::optional<PemKeyCertPairList> pem_key_cert_pairs) {
+ GPR_ASSERT(pem_root_certs.has_value() || pem_key_cert_pairs.has_value());
+ grpc_core::MutexLock lock(&mu_);
+ auto& cert_info = certificate_info_map_[cert_name];
+ if (pem_root_certs.has_value()) {
+ // Successful credential updates will clear any pre-existing error.
+ cert_info.SetRootError(GRPC_ERROR_NONE);
+ for (auto* watcher_ptr : cert_info.root_cert_watchers) {
+ GPR_ASSERT(watcher_ptr != nullptr);
+ const auto watcher_it = watchers_.find(watcher_ptr);
+ GPR_ASSERT(watcher_it != watchers_.end());
+ GPR_ASSERT(watcher_it->second.root_cert_name.has_value());
+ absl::optional<PemKeyCertPairList> pem_key_cert_pairs_to_report;
+ if (pem_key_cert_pairs.has_value() &&
+ watcher_it->second.identity_cert_name == cert_name) {
+ pem_key_cert_pairs_to_report = pem_key_cert_pairs;
+ } else if (watcher_it->second.identity_cert_name.has_value()) {
+ auto& identity_cert_info =
+ certificate_info_map_[*watcher_it->second.identity_cert_name];
+ pem_key_cert_pairs_to_report = identity_cert_info.pem_key_cert_pairs;
+ }
+ watcher_ptr->OnCertificatesChanged(
+ pem_root_certs, std::move(pem_key_cert_pairs_to_report));
+ }
+ cert_info.pem_root_certs = std::move(*pem_root_certs);
+ }
+ if (pem_key_cert_pairs.has_value()) {
+ // Successful credential updates will clear any pre-existing error.
+ cert_info.SetIdentityError(GRPC_ERROR_NONE);
+ for (const auto watcher_ptr : cert_info.identity_cert_watchers) {
+ GPR_ASSERT(watcher_ptr != nullptr);
+ const auto watcher_it = watchers_.find(watcher_ptr);
+ GPR_ASSERT(watcher_it != watchers_.end());
+ GPR_ASSERT(watcher_it->second.identity_cert_name.has_value());
+ absl::optional<absl::string_view> pem_root_certs_to_report;
+ if (pem_root_certs.has_value() &&
+ watcher_it->second.root_cert_name == cert_name) {
+ // In this case, We've already sent the credential updates at the time
+ // when checking pem_root_certs, so we will skip here.
+ continue;
+ } else if (watcher_it->second.root_cert_name.has_value()) {
+ auto& root_cert_info =
+ certificate_info_map_[*watcher_it->second.root_cert_name];
+ pem_root_certs_to_report = root_cert_info.pem_root_certs;
+ }
+ watcher_ptr->OnCertificatesChanged(pem_root_certs_to_report,
+ pem_key_cert_pairs);
+ }
+ cert_info.pem_key_cert_pairs = std::move(*pem_key_cert_pairs);
+ }
+}
+
+bool grpc_tls_certificate_distributor::HasRootCerts(
+ const std::string& root_cert_name) {
+ grpc_core::MutexLock lock(&mu_);
+ const auto it = certificate_info_map_.find(root_cert_name);
+ return it != certificate_info_map_.end() &&
+ !it->second.pem_root_certs.empty();
+};
+
+bool grpc_tls_certificate_distributor::HasKeyCertPairs(
+ const std::string& identity_cert_name) {
+ grpc_core::MutexLock lock(&mu_);
+ const auto it = certificate_info_map_.find(identity_cert_name);
+ return it != certificate_info_map_.end() &&
+ !it->second.pem_key_cert_pairs.empty();
+};
+
+void grpc_tls_certificate_distributor::SetErrorForCert(
+ const std::string& cert_name, absl::optional<grpc_error*> root_cert_error,
+ absl::optional<grpc_error*> identity_cert_error) {
+ GPR_ASSERT(root_cert_error.has_value() || identity_cert_error.has_value());
+ grpc_core::MutexLock lock(&mu_);
+ CertificateInfo& cert_info = certificate_info_map_[cert_name];
+ if (root_cert_error.has_value()) {
+ for (auto* watcher_ptr : cert_info.root_cert_watchers) {
+ GPR_ASSERT(watcher_ptr != nullptr);
+ const auto watcher_it = watchers_.find(watcher_ptr);
+ GPR_ASSERT(watcher_it != watchers_.end());
+ // identity_cert_error_to_report is the error of the identity cert this
+ // watcher is watching, if there is any.
+ grpc_error* identity_cert_error_to_report = GRPC_ERROR_NONE;
+ if (identity_cert_error.has_value() &&
+ watcher_it->second.identity_cert_name == cert_name) {
+ identity_cert_error_to_report = *identity_cert_error;
+ } else if (watcher_it->second.identity_cert_name.has_value()) {
+ auto& identity_cert_info =
+ certificate_info_map_[*watcher_it->second.identity_cert_name];
+ identity_cert_error_to_report = identity_cert_info.identity_cert_error;
+ }
+ watcher_ptr->OnError(GRPC_ERROR_REF(*root_cert_error),
+ GRPC_ERROR_REF(identity_cert_error_to_report));
+ }
+ cert_info.SetRootError(*root_cert_error);
+ }
+ if (identity_cert_error.has_value()) {
+ for (auto* watcher_ptr : cert_info.identity_cert_watchers) {
+ GPR_ASSERT(watcher_ptr != nullptr);
+ const auto watcher_it = watchers_.find(watcher_ptr);
+ GPR_ASSERT(watcher_it != watchers_.end());
+ // root_cert_error_to_report is the error of the root cert this watcher is
+ // watching, if there is any.
+ grpc_error* root_cert_error_to_report = GRPC_ERROR_NONE;
+ if (root_cert_error.has_value() &&
+ watcher_it->second.root_cert_name == cert_name) {
+ // In this case, We've already sent the error updates at the time when
+ // checking root_cert_error, so we will skip here.
+ continue;
+ } else if (watcher_it->second.root_cert_name.has_value()) {
+ auto& root_cert_info =
+ certificate_info_map_[*watcher_it->second.root_cert_name];
+ root_cert_error_to_report = root_cert_info.root_cert_error;
+ }
+ watcher_ptr->OnError(GRPC_ERROR_REF(root_cert_error_to_report),
+ GRPC_ERROR_REF(*identity_cert_error));
+ }
+ cert_info.SetIdentityError(*identity_cert_error);
+ }
+};
+
+void grpc_tls_certificate_distributor::SetError(grpc_error* error) {
+ GPR_ASSERT(error != GRPC_ERROR_NONE);
+ grpc_core::MutexLock lock(&mu_);
+ for (const auto& watcher : watchers_) {
+ const auto watcher_ptr = watcher.first;
+ GPR_ASSERT(watcher_ptr != nullptr);
+ const auto& watcher_info = watcher.second;
+ watcher_ptr->OnError(
+ watcher_info.root_cert_name.has_value() ? GRPC_ERROR_REF(error)
+ : GRPC_ERROR_NONE,
+ watcher_info.identity_cert_name.has_value() ? GRPC_ERROR_REF(error)
+ : GRPC_ERROR_NONE);
+ }
+ for (auto& cert_info_entry : certificate_info_map_) {
+ auto& cert_info = cert_info_entry.second;
+ cert_info.SetRootError(GRPC_ERROR_REF(error));
+ cert_info.SetIdentityError(GRPC_ERROR_REF(error));
+ }
+ GRPC_ERROR_UNREF(error);
+};
+
+void grpc_tls_certificate_distributor::WatchTlsCertificates(
+ std::unique_ptr<TlsCertificatesWatcherInterface> watcher,
+ absl::optional<std::string> root_cert_name,
+ absl::optional<std::string> identity_cert_name) {
+ bool start_watching_root_cert = false;
+ bool already_watching_identity_for_root_cert = false;
+ bool start_watching_identity_cert = false;
+ bool already_watching_root_for_identity_cert = false;
+ GPR_ASSERT(root_cert_name.has_value() || identity_cert_name.has_value());
+ TlsCertificatesWatcherInterface* watcher_ptr = watcher.get();
+ GPR_ASSERT(watcher_ptr != nullptr);
+ // Update watchers_ and certificate_info_map_.
+ {
+ grpc_core::MutexLock lock(&mu_);
+ const auto watcher_it = watchers_.find(watcher_ptr);
+ // The caller needs to cancel the watcher first if it wants to re-register
+ // the watcher.
+ GPR_ASSERT(watcher_it == watchers_.end());
+ watchers_[watcher_ptr] = {std::move(watcher), root_cert_name,
+ identity_cert_name};
+ absl::optional<absl::string_view> updated_root_certs;
+ absl::optional<PemKeyCertPairList> updated_identity_pairs;
+ grpc_error* root_error = GRPC_ERROR_NONE;
+ grpc_error* identity_error = GRPC_ERROR_NONE;
+ if (root_cert_name.has_value()) {
+ CertificateInfo& cert_info = certificate_info_map_[*root_cert_name];
+ start_watching_root_cert = cert_info.root_cert_watchers.empty();
+ already_watching_identity_for_root_cert =
+ !cert_info.identity_cert_watchers.empty();
+ cert_info.root_cert_watchers.insert(watcher_ptr);
+ root_error = GRPC_ERROR_REF(cert_info.root_cert_error);
+ // Empty credentials will be treated as no updates.
+ if (!cert_info.pem_root_certs.empty()) {
+ updated_root_certs = cert_info.pem_root_certs;
+ }
+ }
+ if (identity_cert_name.has_value()) {
+ CertificateInfo& cert_info = certificate_info_map_[*identity_cert_name];
+ start_watching_identity_cert = cert_info.identity_cert_watchers.empty();
+ already_watching_root_for_identity_cert =
+ !cert_info.root_cert_watchers.empty();
+ cert_info.identity_cert_watchers.insert(watcher_ptr);
+ identity_error = GRPC_ERROR_REF(cert_info.identity_cert_error);
+ // Empty credentials will be treated as no updates.
+ if (!cert_info.pem_key_cert_pairs.empty()) {
+ updated_identity_pairs = cert_info.pem_key_cert_pairs;
+ }
+ }
+ // Notify this watcher if the certs it is watching already had some
+ // contents. Note that an *_cert_error in cert_info only indicates error
+ // occurred while trying to fetch the latest cert, but the updated_*_certs
+ // should always be valid. So we will send the updates regardless of
+ // *_cert_error.
+ if (updated_root_certs.has_value() || updated_identity_pairs.has_value()) {
+ watcher_ptr->OnCertificatesChanged(updated_root_certs,
+ std::move(updated_identity_pairs));
+ }
+ // Notify this watcher if the certs it is watching already had some errors.
+ if (root_error != GRPC_ERROR_NONE || identity_error != GRPC_ERROR_NONE) {
+ watcher_ptr->OnError(GRPC_ERROR_REF(root_error),
+ GRPC_ERROR_REF(identity_error));
+ }
+ GRPC_ERROR_UNREF(root_error);
+ GRPC_ERROR_UNREF(identity_error);
+ }
+ // Invoke watch status callback if needed.
+ {
+ grpc_core::MutexLock lock(&callback_mu_);
+ if (watch_status_callback_ != nullptr) {
+ if (root_cert_name == identity_cert_name &&
+ (start_watching_root_cert || start_watching_identity_cert)) {
+ watch_status_callback_(*root_cert_name, start_watching_root_cert,
+ start_watching_identity_cert);
+ } else {
+ if (start_watching_root_cert) {
+ watch_status_callback_(*root_cert_name, true,
+ already_watching_identity_for_root_cert);
+ }
+ if (start_watching_identity_cert) {
+ watch_status_callback_(*identity_cert_name,
+ already_watching_root_for_identity_cert, true);
+ }
+ }
+ }
+ }
+};
+
+void grpc_tls_certificate_distributor::CancelTlsCertificatesWatch(
+ TlsCertificatesWatcherInterface* watcher) {
+ absl::optional<std::string> root_cert_name;
+ absl::optional<std::string> identity_cert_name;
+ bool stop_watching_root_cert = false;
+ bool already_watching_identity_for_root_cert = false;
+ bool stop_watching_identity_cert = false;
+ bool already_watching_root_for_identity_cert = false;
+ // Update watchers_ and certificate_info_map_.
+ {
+ grpc_core::MutexLock lock(&mu_);
+ auto it = watchers_.find(watcher);
+ if (it == watchers_.end()) return;
+ WatcherInfo& watcher_info = it->second;
+ root_cert_name = std::move(watcher_info.root_cert_name);
+ identity_cert_name = std::move(watcher_info.identity_cert_name);
+ watchers_.erase(it);
+ if (root_cert_name.has_value()) {
+ auto it = certificate_info_map_.find(*root_cert_name);
+ GPR_ASSERT(it != certificate_info_map_.end());
+ CertificateInfo& cert_info = it->second;
+ cert_info.root_cert_watchers.erase(watcher);
+ stop_watching_root_cert = cert_info.root_cert_watchers.empty();
+ already_watching_identity_for_root_cert =
+ !cert_info.identity_cert_watchers.empty();
+ if (stop_watching_root_cert && !already_watching_identity_for_root_cert) {
+ certificate_info_map_.erase(it);
+ }
+ }
+ if (identity_cert_name.has_value()) {
+ auto it = certificate_info_map_.find(*identity_cert_name);
+ GPR_ASSERT(it != certificate_info_map_.end());
+ CertificateInfo& cert_info = it->second;
+ cert_info.identity_cert_watchers.erase(watcher);
+ stop_watching_identity_cert = cert_info.identity_cert_watchers.empty();
+ already_watching_root_for_identity_cert =
+ !cert_info.root_cert_watchers.empty();
+ if (stop_watching_identity_cert &&
+ !already_watching_root_for_identity_cert) {
+ certificate_info_map_.erase(it);
+ }
+ }
+ }
+ // Invoke watch status callback if needed.
+ {
+ grpc_core::MutexLock lock(&callback_mu_);
+ if (watch_status_callback_ != nullptr) {
+ if (root_cert_name == identity_cert_name &&
+ (stop_watching_root_cert || stop_watching_identity_cert)) {
+ watch_status_callback_(*root_cert_name, !stop_watching_root_cert,
+ !stop_watching_identity_cert);
+ } else {
+ if (stop_watching_root_cert) {
+ watch_status_callback_(*root_cert_name, false,
+ already_watching_identity_for_root_cert);
+ }
+ if (stop_watching_identity_cert) {
+ watch_status_callback_(*identity_cert_name,
+ already_watching_root_for_identity_cert,
+ false);
+ }
+ }
+ }
+ }
+};
diff --git a/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h b/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h
new file mode 100644
index 00000000..efc9e33e
--- /dev/null
+++ b/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h
@@ -0,0 +1,214 @@
+//
+// 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_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CERTIFICATE_DISTRIBUTOR_H
+#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CERTIFICATE_DISTRIBUTOR_H
+
+#include <grpc/support/port_platform.h>
+
+#include <grpc/grpc_security.h>
+
+#include "absl/container/inlined_vector.h"
+#include "absl/types/optional.h"
+#include "src/core/lib/gprpp/ref_counted.h"
+#include "src/core/lib/security/security_connector/ssl_utils.h"
+
+// TLS certificate distributor.
+struct grpc_tls_certificate_distributor
+ : public grpc_core::RefCounted<grpc_tls_certificate_distributor> {
+ public:
+ typedef absl::InlinedVector<grpc_core::PemKeyCertPair, 1> PemKeyCertPairList;
+
+ // Interface for watching TLS certificates update.
+ class TlsCertificatesWatcherInterface {
+ public:
+ virtual ~TlsCertificatesWatcherInterface() = default;
+
+ // Handles the delivery of the updated root and identity certificates.
+ // An absl::nullopt value indicates no corresponding contents for
+ // root_certs or key_cert_pairs. Note that we will send updates of the
+ // latest contents for both root and identity certificates, even when only
+ // one side of it got updated.
+ //
+ // @param root_certs the contents of the reloaded root certs.
+ // @param key_cert_pairs the contents of the reloaded identity key-cert
+ // pairs.
+ virtual void OnCertificatesChanged(
+ absl::optional<absl::string_view> root_certs,
+ absl::optional<PemKeyCertPairList> key_cert_pairs) = 0;
+
+ // Handles an error that occurs while attempting to fetch certificate data.
+ // Note that if a watcher sees an error, it simply means the Provider is
+ // having problems renewing new data. If the watcher has previously received
+ // several OnCertificatesChanged, all the data received from that function
+ // is valid.
+ // In that case, watcher might simply log the error. If the watcher hasn't
+ // received any OnCertificatesChanged before the error occurs, no valid
+ // data is available yet, and the watcher should either fail or "waiting"
+ // for the valid data in a non-blocking way.
+ //
+ // @param root_cert_error the error occurred while reloading root
+ // certificates.
+ // @param identity_cert_error the error occurred while reloading identity
+ // certificates.
+ virtual void OnError(grpc_error* root_cert_error,
+ grpc_error* identity_cert_error) = 0;
+ };
+
+ // Sets the key materials based on their certificate name. Note that we are
+ // not doing any copies for pem_root_certs and pem_key_cert_pairs. For
+ // pem_root_certs, the original string contents need to outlive the
+ // distributor; for pem_key_cert_pairs, internally it is taking two
+ // unique_ptr(s) to the credential string, so the ownership is actually
+ // transferred.
+ //
+ // @param cert_name The name of the certificates being updated.
+ // @param pem_root_certs The content of root certificates.
+ // @param pem_key_cert_pairs The content of identity key-cert pairs.
+ void SetKeyMaterials(const std::string& cert_name,
+ absl::optional<std::string> pem_root_certs,
+ absl::optional<PemKeyCertPairList> pem_key_cert_pairs);
+
+ bool HasRootCerts(const std::string& root_cert_name);
+
+ bool HasKeyCertPairs(const std::string& identity_cert_name);
+
+ // Propagates the error that the caller (e.g. Producer) encounters to all the
+ // watchers watching a particular certificate name.
+ //
+ // @param cert_name The watching cert name of the watchers that the caller
+ // wants to notify when encountering error.
+ // @param root_cert_error The error that the caller encounters when reloading
+ // root certs.
+ // @param identity_cert_error The error that the caller encounters when
+ // reloading identity certs.
+ void SetErrorForCert(const std::string& cert_name,
+ absl::optional<grpc_error*> root_cert_error,
+ absl::optional<grpc_error*> identity_cert_error);
+
+ // Propagates the error that the caller (e.g. Producer) encounters to all
+ // watchers.
+ //
+ // @param error The error that the caller encounters.
+ void SetError(grpc_error* error);
+
+ // Sets the TLS certificate watch status callback function. The
+ // grpc_tls_certificate_distributor will invoke this callback when a new
+ // certificate name is watched by a newly registered watcher, or when a
+ // certificate name is no longer watched by any watchers.
+ // Note that when the callback shows a cert is no longer being watched, the
+ // distributor will delete the corresponding certificate data from its cache,
+ // and clear the corresponding error, if there is any. This means that if the
+ // callback subsequently says the same cert is now being watched again, the
+ // provider must re-provide the credentials or re-invoke the errors to the
+ // distributor, to indicate a successful or failed reloading.
+ // @param callback The callback function being set by the caller, e.g the
+ // Producer. Note that this callback will be invoked for each certificate
+ // name.
+ //
+ // For the parameters in the callback function:
+ // string_value The name of the certificates being watched.
+ // bool_value_1 If the root certificates with the specific name are being
+ // watched. bool_value_2 If the identity certificates with the specific name
+ // are being watched.
+ void SetWatchStatusCallback(
+ std::function<void(std::string, bool, bool)> callback) {
+ grpc_core::MutexLock lock(&mu_);
+ watch_status_callback_ = callback;
+ };
+
+ // Registers a watcher. The caller may keep a raw pointer to the watcher,
+ // which may be used only for cancellation. (Because the caller does not own
+ // the watcher, the pointer must not be used for any other purpose.) At least
+ // one of root_cert_name and identity_cert_name must be specified.
+ //
+ // @param watcher The watcher being registered.
+ // @param root_cert_name The name of the root certificates that will be
+ // watched. If set to absl::nullopt, the root certificates won't be watched.
+ // @param identity_cert_name The name of the identity certificates that will
+ // be watched. If set to absl::nullopt, the identity certificates won't be
+ // watched.
+ void WatchTlsCertificates(
+ std::unique_ptr<TlsCertificatesWatcherInterface> watcher,
+ absl::optional<std::string> root_cert_name,
+ absl::optional<std::string> identity_cert_name);
+
+ // Cancels a watcher.
+ //
+ // @param watcher The watcher being cancelled.
+ void CancelTlsCertificatesWatch(TlsCertificatesWatcherInterface* watcher);
+
+ private:
+ // Contains the information about each watcher.
+ struct WatcherInfo {
+ std::unique_ptr<TlsCertificatesWatcherInterface> watcher;
+ absl::optional<std::string> root_cert_name;
+ absl::optional<std::string> identity_cert_name;
+ };
+ // CertificateInfo contains the credential contents and some additional
+ // watcher information.
+ // Note that having errors doesn't indicate the corresponding credentials are
+ // invalid. For example, if root_cert_error != nullptr but pem_root_certs has
+ // value, it simply means an error occurs while trying to fetch the latest
+ // root certs, while pem_root_certs still contains the valid old data.
+ struct CertificateInfo {
+ // The contents of the root certificates.
+ std::string pem_root_certs;
+ // The contents of the identity key-certificate pairs.
+ PemKeyCertPairList pem_key_cert_pairs;
+ // The root cert reloading error propagated by the caller.
+ grpc_error* root_cert_error = GRPC_ERROR_NONE;
+ // The identity cert reloading error propagated by the caller.
+ grpc_error* identity_cert_error = GRPC_ERROR_NONE;
+ // The set of watchers watching root certificates.
+ // This is mainly used for quickly looking up the affected watchers while
+ // performing a credential reloading.
+ std::set<TlsCertificatesWatcherInterface*> root_cert_watchers;
+ // The set of watchers watching identity certificates. This is mainly used
+ // for quickly looking up the affected watchers while performing a
+ // credential reloading.
+ std::set<TlsCertificatesWatcherInterface*> identity_cert_watchers;
+
+ ~CertificateInfo() {
+ GRPC_ERROR_UNREF(root_cert_error);
+ GRPC_ERROR_UNREF(identity_cert_error);
+ }
+ void SetRootError(grpc_error* error) {
+ GRPC_ERROR_UNREF(root_cert_error);
+ root_cert_error = error;
+ }
+ void SetIdentityError(grpc_error* error) {
+ GRPC_ERROR_UNREF(identity_cert_error);
+ identity_cert_error = error;
+ }
+ };
+
+ grpc_core::Mutex mu_;
+ // We need a dedicated mutex for watch_status_callback_ for allowing
+ // callers(e.g. Producer) to directly set key materials in the callback
+ // functions.
+ grpc_core::Mutex callback_mu_;
+ // Stores information about each watcher.
+ std::map<TlsCertificatesWatcherInterface*, WatcherInfo> watchers_;
+ // The callback to notify the caller, e.g. the Producer, that the watch status
+ // is changed.
+ std::function<void(std::string, bool, bool)> watch_status_callback_;
+ // Stores the names of each certificate, and their corresponding credential
+ // contents as well as some additional watcher information.
+ std::map<std::string, CertificateInfo> certificate_info_map_;
+};
+
+#endif // GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CERTIFICATE_DISTRIBUTOR_H
diff --git a/grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h b/grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h
index c411fb2b..52a1218d 100644
--- a/grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h
+++ b/grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h
@@ -23,7 +23,8 @@
#include <grpc/grpc_security.h>
-#include "src/core/lib/gprpp/inlined_vector.h"
+#include "absl/container/inlined_vector.h"
+
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/security/security_connector/ssl_utils.h"
@@ -44,8 +45,7 @@ struct grpc_tls_error_details
struct grpc_tls_key_materials_config
: public grpc_core::RefCounted<grpc_tls_key_materials_config> {
public:
- typedef grpc_core::InlinedVector<grpc_core::PemKeyCertPair, 1>
- PemKeyCertPairList;
+ typedef absl::InlinedVector<grpc_core::PemKeyCertPair, 1> PemKeyCertPairList;
/** Getters for member fields. **/
const char* pem_root_certs() const { return pem_root_certs_.get(); }
@@ -264,6 +264,8 @@ struct grpc_tls_credentials_options
grpc_tls_server_verification_option server_verification_option() const {
return server_verification_option_;
}
+ grpc_tls_version min_tls_version() const { return min_tls_version_; }
+ grpc_tls_version max_tls_version() const { return max_tls_version_; }
grpc_tls_key_materials_config* key_materials_config() const {
return key_materials_config_.get();
}
@@ -284,6 +286,12 @@ struct grpc_tls_credentials_options
const grpc_tls_server_verification_option server_verification_option) {
server_verification_option_ = server_verification_option;
}
+ void set_min_tls_version(grpc_tls_version min_tls_version) {
+ min_tls_version_ = min_tls_version;
+ }
+ void set_max_tls_version(grpc_tls_version max_tls_version) {
+ max_tls_version_ = max_tls_version;
+ }
void set_key_materials_config(
grpc_core::RefCountedPtr<grpc_tls_key_materials_config> config) {
key_materials_config_ = std::move(config);
@@ -302,6 +310,8 @@ struct grpc_tls_credentials_options
grpc_ssl_client_certificate_request_type cert_request_type_;
grpc_tls_server_verification_option server_verification_option_ =
GRPC_TLS_SERVER_VERIFICATION;
+ grpc_tls_version min_tls_version_ = grpc_tls_version::TLS1_2;
+ grpc_tls_version max_tls_version_ = grpc_tls_version::TLS1_3;
grpc_core::RefCountedPtr<grpc_tls_key_materials_config> key_materials_config_;
grpc_core::RefCountedPtr<grpc_tls_credential_reload_config>
credential_reload_config_;