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