blob: 36c46beff9ba8aacba582ed1b4c98547ee2ecb46 [file] [log] [blame]
//
// 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 <utility>
#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"
struct grpc_tls_identity_pairs {
grpc_core::PemKeyCertPairList pem_key_cert_pairs;
};
// TLS certificate distributor.
struct grpc_tls_certificate_distributor
: public grpc_core::RefCounted<grpc_tls_certificate_distributor> {
public:
// 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<grpc_core::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_handle root_cert_error,
grpc_error_handle identity_cert_error) = 0;
};
// Sets the key materials based on their certificate name.
//
// @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<grpc_core::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_handle> root_cert_error,
absl::optional<grpc_error_handle> 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_handle 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_ = std::move(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.
grpc_core::PemKeyCertPairList pem_key_cert_pairs;
// The root cert reloading error propagated by the caller.
grpc_error_handle root_cert_error = GRPC_ERROR_NONE;
// The identity cert reloading error propagated by the caller.
grpc_error_handle 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_handle error) {
GRPC_ERROR_UNREF(root_cert_error);
root_cert_error = error;
}
void SetIdentityError(grpc_error_handle 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