1 // 2 // Copyright 2020 gRPC authors. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #ifndef GRPC_SRC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CERTIFICATE_PROVIDER_H 18 #define GRPC_SRC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CERTIFICATE_PROVIDER_H 19 20 #include <grpc/support/port_platform.h> 21 22 #include <stdint.h> 23 24 #include <map> 25 #include <string> 26 27 #include "absl/base/thread_annotations.h" 28 #include "absl/status/statusor.h" 29 #include "absl/strings/string_view.h" 30 #include "absl/types/optional.h" 31 32 #include <grpc/grpc_security.h> 33 #include <grpc/support/log.h> 34 #include <grpc/support/sync.h> 35 36 #include "src/core/lib/gpr/useful.h" 37 #include "src/core/lib/gprpp/ref_counted.h" 38 #include "src/core/lib/gprpp/ref_counted_ptr.h" 39 #include "src/core/lib/gprpp/sync.h" 40 #include "src/core/lib/gprpp/thd.h" 41 #include "src/core/lib/gprpp/unique_type_name.h" 42 #include "src/core/lib/iomgr/iomgr_fwd.h" 43 #include "src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h" 44 #include "src/core/lib/security/security_connector/ssl_utils.h" 45 46 // Interface for a grpc_tls_certificate_provider that handles the process to 47 // fetch credentials and validation contexts. Implementations are free to rely 48 // on local or remote sources to fetch the latest secrets, and free to share any 49 // state among different instances as they deem fit. 50 // 51 // On creation, grpc_tls_certificate_provider creates a 52 // grpc_tls_certificate_distributor object. When the credentials and validation 53 // contexts become valid or changed, a grpc_tls_certificate_provider should 54 // notify its distributor so as to propagate the update to the watchers. 55 struct grpc_tls_certificate_provider 56 : public grpc_core::RefCounted<grpc_tls_certificate_provider> { 57 public: interested_partiesgrpc_tls_certificate_provider58 virtual grpc_pollset_set* interested_parties() const { return nullptr; } 59 60 virtual grpc_core::RefCountedPtr<grpc_tls_certificate_distributor> 61 distributor() const = 0; 62 63 // Compares this grpc_tls_certificate_provider object with \a other. 64 // If this method returns 0, it means that gRPC can treat the two certificate 65 // providers as effectively the same. This method is used to compare 66 // `grpc_tls_certificate_provider` objects when they are present in 67 // channel_args. One important usage of this is when channel args are used in 68 // SubchannelKey, which leads to a useful property that allows subchannels to 69 // be reused when two different `grpc_tls_certificate_provider` objects are 70 // used but they compare as equal (assuming other channel args match). Comparegrpc_tls_certificate_provider71 int Compare(const grpc_tls_certificate_provider* other) const { 72 GPR_ASSERT(other != nullptr); 73 int r = type().Compare(other->type()); 74 if (r != 0) return r; 75 return CompareImpl(other); 76 } 77 78 // The pointer value \a type is used to uniquely identify a creds 79 // implementation for down-casting purposes. Every provider implementation 80 // should use a unique string instance, which should be returned by all 81 // instances of that provider implementation. 82 virtual grpc_core::UniqueTypeName type() const = 0; 83 84 static absl::string_view ChannelArgName(); ChannelArgsComparegrpc_tls_certificate_provider85 static int ChannelArgsCompare(const grpc_tls_certificate_provider* a, 86 const grpc_tls_certificate_provider* b) { 87 return a->Compare(b); 88 } 89 90 private: 91 // Implementation for `Compare` method intended to be overridden by 92 // subclasses. Only invoked if `type()` and `other->type()` point to the same 93 // string. 94 virtual int CompareImpl(const grpc_tls_certificate_provider* other) const = 0; 95 }; 96 97 namespace grpc_core { 98 99 // A basic provider class that will get credentials from string during 100 // initialization. 101 class StaticDataCertificateProvider final 102 : public grpc_tls_certificate_provider { 103 public: 104 StaticDataCertificateProvider(std::string root_certificate, 105 PemKeyCertPairList pem_key_cert_pairs); 106 107 ~StaticDataCertificateProvider() override; 108 distributor()109 RefCountedPtr<grpc_tls_certificate_distributor> distributor() const override { 110 return distributor_; 111 } 112 113 UniqueTypeName type() const override; 114 115 private: 116 struct WatcherInfo { 117 bool root_being_watched = false; 118 bool identity_being_watched = false; 119 }; 120 CompareImpl(const grpc_tls_certificate_provider * other)121 int CompareImpl(const grpc_tls_certificate_provider* other) const override { 122 // TODO(yashykt): Maybe do something better here. 123 return QsortCompare(static_cast<const grpc_tls_certificate_provider*>(this), 124 other); 125 } 126 127 RefCountedPtr<grpc_tls_certificate_distributor> distributor_; 128 std::string root_certificate_; 129 PemKeyCertPairList pem_key_cert_pairs_; 130 // Guards members below. 131 Mutex mu_; 132 // Stores each cert_name we get from the distributor callback and its watcher 133 // information. 134 std::map<std::string, WatcherInfo> watcher_info_; 135 }; 136 137 // A provider class that will watch the credential changes on the file system. 138 class FileWatcherCertificateProvider final 139 : public grpc_tls_certificate_provider { 140 public: 141 FileWatcherCertificateProvider(std::string private_key_path, 142 std::string identity_certificate_path, 143 std::string root_cert_path, 144 int64_t refresh_interval_sec); 145 146 ~FileWatcherCertificateProvider() override; 147 distributor()148 RefCountedPtr<grpc_tls_certificate_distributor> distributor() const override { 149 return distributor_; 150 } 151 152 UniqueTypeName type() const override; 153 154 int64_t TestOnlyGetRefreshIntervalSecond() const; 155 156 private: 157 struct WatcherInfo { 158 bool root_being_watched = false; 159 bool identity_being_watched = false; 160 }; 161 CompareImpl(const grpc_tls_certificate_provider * other)162 int CompareImpl(const grpc_tls_certificate_provider* other) const override { 163 // TODO(yashykt): Maybe do something better here. 164 return QsortCompare(static_cast<const grpc_tls_certificate_provider*>(this), 165 other); 166 } 167 168 // Force an update from the file system regardless of the interval. 169 void ForceUpdate(); 170 // Read the root certificates from files and update the distributor. 171 absl::optional<std::string> ReadRootCertificatesFromFile( 172 const std::string& root_cert_full_path); 173 // Read the private key and the certificate chain from files and update the 174 // distributor. 175 absl::optional<PemKeyCertPairList> ReadIdentityKeyCertPairFromFiles( 176 const std::string& private_key_path, 177 const std::string& identity_certificate_path); 178 179 // Information that is used by the refreshing thread. 180 std::string private_key_path_; 181 std::string identity_certificate_path_; 182 std::string root_cert_path_; 183 int64_t refresh_interval_sec_ = 0; 184 185 RefCountedPtr<grpc_tls_certificate_distributor> distributor_; 186 Thread refresh_thread_; 187 gpr_event shutdown_event_; 188 189 // Guards members below. 190 Mutex mu_; 191 // The most-recent credential data. It will be empty if the most recent read 192 // attempt failed. 193 std::string root_certificate_ ABSL_GUARDED_BY(mu_); 194 PemKeyCertPairList pem_key_cert_pairs_ ABSL_GUARDED_BY(mu_); 195 // Stores each cert_name we get from the distributor callback and its watcher 196 // information. 197 std::map<std::string, WatcherInfo> watcher_info_ ABSL_GUARDED_BY(mu_); 198 }; 199 200 // Checks if the private key matches the certificate's public key. 201 // Returns a not-OK status on failure, or a bool indicating 202 // whether the key/cert pair matches. 203 absl::StatusOr<bool> PrivateKeyAndCertificateMatch( 204 absl::string_view private_key, absl::string_view cert_chain); 205 206 } // namespace grpc_core 207 208 #endif // GRPC_SRC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CERTIFICATE_PROVIDER_H 209