diff options
Diffstat (limited to 'grpc/src/core/lib/security/credentials/tls')
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_; |