• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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