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