grpc_tls_certificate_distributor.cc
Go to the documentation of this file.
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 
18 
20 
21 #include <algorithm>
22 #include <vector>
23 
24 #include <grpc/grpc_security.h>
25 #include <grpc/support/log.h>
26 
30  GPR_ASSERT(pem_root_certs.has_value() || pem_key_cert_pairs.has_value());
32  auto& cert_info = certificate_info_map_[cert_name];
33  if (pem_root_certs.has_value()) {
34  // Successful credential updates will clear any pre-existing error.
35  cert_info.SetRootError(GRPC_ERROR_NONE);
36  for (auto* watcher_ptr : cert_info.root_cert_watchers) {
37  GPR_ASSERT(watcher_ptr != nullptr);
38  const auto watcher_it = watchers_.find(watcher_ptr);
39  GPR_ASSERT(watcher_it != watchers_.end());
40  GPR_ASSERT(watcher_it->second.root_cert_name.has_value());
42  pem_key_cert_pairs_to_report;
43  if (pem_key_cert_pairs.has_value() &&
44  watcher_it->second.identity_cert_name == cert_name) {
45  pem_key_cert_pairs_to_report = pem_key_cert_pairs;
46  } else if (watcher_it->second.identity_cert_name.has_value()) {
47  auto& identity_cert_info =
48  certificate_info_map_[*watcher_it->second.identity_cert_name];
49  if (!identity_cert_info.pem_key_cert_pairs.empty()) {
50  pem_key_cert_pairs_to_report = identity_cert_info.pem_key_cert_pairs;
51  }
52  }
53  watcher_ptr->OnCertificatesChanged(
54  pem_root_certs, std::move(pem_key_cert_pairs_to_report));
55  }
56  cert_info.pem_root_certs = std::move(*pem_root_certs);
57  }
58  if (pem_key_cert_pairs.has_value()) {
59  // Successful credential updates will clear any pre-existing error.
60  cert_info.SetIdentityError(GRPC_ERROR_NONE);
61  for (const auto watcher_ptr : cert_info.identity_cert_watchers) {
62  GPR_ASSERT(watcher_ptr != nullptr);
63  const auto watcher_it = watchers_.find(watcher_ptr);
64  GPR_ASSERT(watcher_it != watchers_.end());
65  GPR_ASSERT(watcher_it->second.identity_cert_name.has_value());
66  absl::optional<absl::string_view> pem_root_certs_to_report;
67  if (pem_root_certs.has_value() &&
68  watcher_it->second.root_cert_name == cert_name) {
69  // In this case, We've already sent the credential updates at the time
70  // when checking pem_root_certs, so we will skip here.
71  continue;
72  } else if (watcher_it->second.root_cert_name.has_value()) {
73  auto& root_cert_info =
74  certificate_info_map_[*watcher_it->second.root_cert_name];
75  if (!root_cert_info.pem_root_certs.empty()) {
76  pem_root_certs_to_report = root_cert_info.pem_root_certs;
77  }
78  }
79  watcher_ptr->OnCertificatesChanged(pem_root_certs_to_report,
80  pem_key_cert_pairs);
81  }
82  cert_info.pem_key_cert_pairs = std::move(*pem_key_cert_pairs);
83  }
84 }
85 
87  const std::string& root_cert_name) {
89  const auto it = certificate_info_map_.find(root_cert_name);
90  return it != certificate_info_map_.end() &&
91  !it->second.pem_root_certs.empty();
92 };
93 
95  const std::string& identity_cert_name) {
97  const auto it = certificate_info_map_.find(identity_cert_name);
98  return it != certificate_info_map_.end() &&
99  !it->second.pem_key_cert_pairs.empty();
100 };
101 
103  const std::string& cert_name,
104  absl::optional<grpc_error_handle> root_cert_error,
105  absl::optional<grpc_error_handle> identity_cert_error) {
106  GPR_ASSERT(root_cert_error.has_value() || identity_cert_error.has_value());
107  grpc_core::MutexLock lock(&mu_);
108  CertificateInfo& cert_info = certificate_info_map_[cert_name];
109  if (root_cert_error.has_value()) {
110  for (auto* watcher_ptr : cert_info.root_cert_watchers) {
111  GPR_ASSERT(watcher_ptr != nullptr);
112  const auto watcher_it = watchers_.find(watcher_ptr);
113  GPR_ASSERT(watcher_it != watchers_.end());
114  // identity_cert_error_to_report is the error of the identity cert this
115  // watcher is watching, if there is any.
116  grpc_error_handle identity_cert_error_to_report = GRPC_ERROR_NONE;
117  if (identity_cert_error.has_value() &&
118  watcher_it->second.identity_cert_name == cert_name) {
119  identity_cert_error_to_report = *identity_cert_error;
120  } else if (watcher_it->second.identity_cert_name.has_value()) {
121  auto& identity_cert_info =
122  certificate_info_map_[*watcher_it->second.identity_cert_name];
123  identity_cert_error_to_report = identity_cert_info.identity_cert_error;
124  }
125  watcher_ptr->OnError(GRPC_ERROR_REF(*root_cert_error),
126  GRPC_ERROR_REF(identity_cert_error_to_report));
127  }
128  cert_info.SetRootError(*root_cert_error);
129  }
130  if (identity_cert_error.has_value()) {
131  for (auto* watcher_ptr : cert_info.identity_cert_watchers) {
132  GPR_ASSERT(watcher_ptr != nullptr);
133  const auto watcher_it = watchers_.find(watcher_ptr);
134  GPR_ASSERT(watcher_it != watchers_.end());
135  // root_cert_error_to_report is the error of the root cert this watcher is
136  // watching, if there is any.
137  grpc_error_handle root_cert_error_to_report = GRPC_ERROR_NONE;
138  if (root_cert_error.has_value() &&
139  watcher_it->second.root_cert_name == cert_name) {
140  // In this case, We've already sent the error updates at the time when
141  // checking root_cert_error, so we will skip here.
142  continue;
143  } else if (watcher_it->second.root_cert_name.has_value()) {
144  auto& root_cert_info =
145  certificate_info_map_[*watcher_it->second.root_cert_name];
146  root_cert_error_to_report = root_cert_info.root_cert_error;
147  }
148  watcher_ptr->OnError(GRPC_ERROR_REF(root_cert_error_to_report),
149  GRPC_ERROR_REF(*identity_cert_error));
150  }
151  cert_info.SetIdentityError(*identity_cert_error);
152  }
153 };
154 
157  grpc_core::MutexLock lock(&mu_);
158  for (const auto& watcher : watchers_) {
159  const auto watcher_ptr = watcher.first;
160  GPR_ASSERT(watcher_ptr != nullptr);
161  const auto& watcher_info = watcher.second;
162  watcher_ptr->OnError(
163  watcher_info.root_cert_name.has_value() ? GRPC_ERROR_REF(error)
164  : GRPC_ERROR_NONE,
165  watcher_info.identity_cert_name.has_value() ? GRPC_ERROR_REF(error)
166  : GRPC_ERROR_NONE);
167  }
168  for (auto& cert_info_entry : certificate_info_map_) {
169  auto& cert_info = cert_info_entry.second;
170  cert_info.SetRootError(GRPC_ERROR_REF(error));
171  cert_info.SetIdentityError(GRPC_ERROR_REF(error));
172  }
174 };
175 
177  std::unique_ptr<TlsCertificatesWatcherInterface> watcher,
178  absl::optional<std::string> root_cert_name,
179  absl::optional<std::string> identity_cert_name) {
180  bool start_watching_root_cert = false;
181  bool already_watching_identity_for_root_cert = false;
182  bool start_watching_identity_cert = false;
183  bool already_watching_root_for_identity_cert = false;
184  GPR_ASSERT(root_cert_name.has_value() || identity_cert_name.has_value());
185  TlsCertificatesWatcherInterface* watcher_ptr = watcher.get();
186  GPR_ASSERT(watcher_ptr != nullptr);
187  // Update watchers_ and certificate_info_map_.
188  {
189  grpc_core::MutexLock lock(&mu_);
190  const auto watcher_it = watchers_.find(watcher_ptr);
191  // The caller needs to cancel the watcher first if it wants to re-register
192  // the watcher.
193  GPR_ASSERT(watcher_it == watchers_.end());
194  watchers_[watcher_ptr] = {std::move(watcher), root_cert_name,
195  identity_cert_name};
196  absl::optional<absl::string_view> updated_root_certs;
197  absl::optional<grpc_core::PemKeyCertPairList> updated_identity_pairs;
198  grpc_error_handle root_error = GRPC_ERROR_NONE;
199  grpc_error_handle identity_error = GRPC_ERROR_NONE;
200  if (root_cert_name.has_value()) {
201  CertificateInfo& cert_info = certificate_info_map_[*root_cert_name];
202  start_watching_root_cert = cert_info.root_cert_watchers.empty();
203  already_watching_identity_for_root_cert =
204  !cert_info.identity_cert_watchers.empty();
205  cert_info.root_cert_watchers.insert(watcher_ptr);
206  root_error = GRPC_ERROR_REF(cert_info.root_cert_error);
207  // Empty credentials will be treated as no updates.
208  if (!cert_info.pem_root_certs.empty()) {
209  updated_root_certs = cert_info.pem_root_certs;
210  }
211  }
212  if (identity_cert_name.has_value()) {
213  CertificateInfo& cert_info = certificate_info_map_[*identity_cert_name];
214  start_watching_identity_cert = cert_info.identity_cert_watchers.empty();
215  already_watching_root_for_identity_cert =
216  !cert_info.root_cert_watchers.empty();
217  cert_info.identity_cert_watchers.insert(watcher_ptr);
218  identity_error = GRPC_ERROR_REF(cert_info.identity_cert_error);
219  // Empty credentials will be treated as no updates.
220  if (!cert_info.pem_key_cert_pairs.empty()) {
221  updated_identity_pairs = cert_info.pem_key_cert_pairs;
222  }
223  }
224  // Notify this watcher if the certs it is watching already had some
225  // contents. Note that an *_cert_error in cert_info only indicates error
226  // occurred while trying to fetch the latest cert, but the updated_*_certs
227  // should always be valid. So we will send the updates regardless of
228  // *_cert_error.
229  if (updated_root_certs.has_value() || updated_identity_pairs.has_value()) {
230  watcher_ptr->OnCertificatesChanged(updated_root_certs,
231  std::move(updated_identity_pairs));
232  }
233  // Notify this watcher if the certs it is watching already had some errors.
234  if (!GRPC_ERROR_IS_NONE(root_error) ||
235  !GRPC_ERROR_IS_NONE(identity_error)) {
236  watcher_ptr->OnError(GRPC_ERROR_REF(root_error),
237  GRPC_ERROR_REF(identity_error));
238  }
239  GRPC_ERROR_UNREF(root_error);
240  GRPC_ERROR_UNREF(identity_error);
241  }
242  // Invoke watch status callback if needed.
243  {
245  if (watch_status_callback_ != nullptr) {
246  if (root_cert_name == identity_cert_name &&
247  (start_watching_root_cert || start_watching_identity_cert)) {
248  watch_status_callback_(*root_cert_name, start_watching_root_cert,
249  start_watching_identity_cert);
250  } else {
251  if (start_watching_root_cert) {
252  watch_status_callback_(*root_cert_name, true,
253  already_watching_identity_for_root_cert);
254  }
255  if (start_watching_identity_cert) {
256  watch_status_callback_(*identity_cert_name,
257  already_watching_root_for_identity_cert, true);
258  }
259  }
260  }
261  }
262 };
263 
266  absl::optional<std::string> root_cert_name;
267  absl::optional<std::string> identity_cert_name;
268  bool stop_watching_root_cert = false;
269  bool already_watching_identity_for_root_cert = false;
270  bool stop_watching_identity_cert = false;
271  bool already_watching_root_for_identity_cert = false;
272  // Update watchers_ and certificate_info_map_.
273  {
274  grpc_core::MutexLock lock(&mu_);
275  auto it = watchers_.find(watcher);
276  if (it == watchers_.end()) return;
277  WatcherInfo& watcher_info = it->second;
278  root_cert_name = std::move(watcher_info.root_cert_name);
279  identity_cert_name = std::move(watcher_info.identity_cert_name);
280  watchers_.erase(it);
281  if (root_cert_name.has_value()) {
282  auto it = certificate_info_map_.find(*root_cert_name);
283  GPR_ASSERT(it != certificate_info_map_.end());
284  CertificateInfo& cert_info = it->second;
285  cert_info.root_cert_watchers.erase(watcher);
286  stop_watching_root_cert = cert_info.root_cert_watchers.empty();
287  already_watching_identity_for_root_cert =
288  !cert_info.identity_cert_watchers.empty();
289  if (stop_watching_root_cert && !already_watching_identity_for_root_cert) {
290  certificate_info_map_.erase(it);
291  }
292  }
293  if (identity_cert_name.has_value()) {
294  auto it = certificate_info_map_.find(*identity_cert_name);
295  GPR_ASSERT(it != certificate_info_map_.end());
296  CertificateInfo& cert_info = it->second;
297  cert_info.identity_cert_watchers.erase(watcher);
298  stop_watching_identity_cert = cert_info.identity_cert_watchers.empty();
299  already_watching_root_for_identity_cert =
300  !cert_info.root_cert_watchers.empty();
301  if (stop_watching_identity_cert &&
302  !already_watching_root_for_identity_cert) {
303  certificate_info_map_.erase(it);
304  }
305  }
306  }
307  // Invoke watch status callback if needed.
308  {
310  if (watch_status_callback_ != nullptr) {
311  if (root_cert_name == identity_cert_name &&
312  (stop_watching_root_cert || stop_watching_identity_cert)) {
313  watch_status_callback_(*root_cert_name, !stop_watching_root_cert,
314  !stop_watching_identity_cert);
315  } else {
316  if (stop_watching_root_cert) {
317  watch_status_callback_(*root_cert_name, false,
318  already_watching_identity_for_root_cert);
319  }
320  if (stop_watching_identity_cert) {
321  watch_status_callback_(*identity_cert_name,
322  already_watching_root_for_identity_cert,
323  false);
324  }
325  }
326  }
327  }
328 };
329 
333  return new grpc_tls_identity_pairs();
334 }
335 
337  const char* private_key,
338  const char* cert_chain) {
339  GPR_ASSERT(pairs != nullptr);
340  GPR_ASSERT(private_key != nullptr);
341  GPR_ASSERT(cert_chain != nullptr);
342  pairs->pem_key_cert_pairs.emplace_back(private_key, cert_chain);
343 }
344 
346  GPR_ASSERT(pairs != nullptr);
347  delete pairs;
348 }
grpc_tls_certificate_distributor::CertificateInfo::pem_key_cert_pairs
grpc_core::PemKeyCertPairList pem_key_cert_pairs
Definition: grpc_tls_certificate_distributor.h:177
grpc_tls_certificate_distributor::WatcherInfo::root_cert_name
absl::optional< std::string > root_cert_name
Definition: grpc_tls_certificate_distributor.h:164
regen-readme.it
it
Definition: regen-readme.py:15
GRPC_ERROR_NONE
#define GRPC_ERROR_NONE
Definition: error.h:234
log.h
grpc_tls_certificate_distributor::CertificateInfo::root_cert_watchers
std::set< TlsCertificatesWatcherInterface * > root_cert_watchers
Definition: grpc_tls_certificate_distributor.h:185
grpc_tls_certificate_distributor.h
grpc_tls_identity_pairs_destroy
void grpc_tls_identity_pairs_destroy(grpc_tls_identity_pairs *pairs)
Definition: grpc_tls_certificate_distributor.cc:345
pem_root_certs
static char * pem_root_certs
Definition: rb_channel_credentials.c:38
grpc_tls_certificate_distributor::CertificateInfo::pem_root_certs
std::string pem_root_certs
Definition: grpc_tls_certificate_distributor.h:175
grpc_tls_certificate_distributor::callback_mu_
grpc_core::Mutex callback_mu_
Definition: grpc_tls_certificate_distributor.h:209
grpc_core::MutexLock
Definition: src/core/lib/gprpp/sync.h:88
grpc_tls_identity_pairs_create
grpc_tls_identity_pairs * grpc_tls_identity_pairs_create()
Definition: grpc_tls_certificate_distributor.cc:332
grpc_tls_identity_pairs
Definition: grpc_tls_certificate_distributor.h:38
grpc_tls_identity_pairs::pem_key_cert_pairs
grpc_core::PemKeyCertPairList pem_key_cert_pairs
Definition: grpc_tls_certificate_distributor.h:39
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
error
grpc_error_handle error
Definition: retry_filter.cc:499
grpc_tls_certificate_distributor::mu_
grpc_core::Mutex mu_
Definition: grpc_tls_certificate_distributor.h:205
grpc_tls_certificate_distributor::HasRootCerts
bool HasRootCerts(const std::string &root_cert_name)
Definition: grpc_tls_certificate_distributor.cc:86
grpc_security.h
grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface
Definition: grpc_tls_certificate_distributor.h:47
grpc_tls_certificate_distributor::CertificateInfo::SetRootError
void SetRootError(grpc_error_handle error)
Definition: grpc_tls_certificate_distributor.h:195
grpc_tls_certificate_distributor::WatchTlsCertificates
void WatchTlsCertificates(std::unique_ptr< TlsCertificatesWatcherInterface > watcher, absl::optional< std::string > root_cert_name, absl::optional< std::string > identity_cert_name)
Definition: grpc_tls_certificate_distributor.cc:176
grpc_tls_certificate_distributor::SetKeyMaterials
void SetKeyMaterials(const std::string &cert_name, absl::optional< std::string > pem_root_certs, absl::optional< grpc_core::PemKeyCertPairList > pem_key_cert_pairs)
Definition: grpc_tls_certificate_distributor.cc:27
grpc_tls_certificate_distributor::CertificateInfo::root_cert_error
grpc_error_handle root_cert_error
Definition: grpc_tls_certificate_distributor.h:179
grpc_tls_certificate_distributor::CertificateInfo::identity_cert_error
grpc_error_handle identity_cert_error
Definition: grpc_tls_certificate_distributor.h:181
grpc_tls_certificate_distributor::WatcherInfo
Definition: grpc_tls_certificate_distributor.h:162
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
absl::optional::has_value
constexpr bool has_value() const noexcept
Definition: abseil-cpp/absl/types/optional.h:461
grpc_tls_certificate_distributor::CertificateInfo::SetIdentityError
void SetIdentityError(grpc_error_handle error)
Definition: grpc_tls_certificate_distributor.h:199
grpc_tls_certificate_distributor::CertificateInfo
Definition: grpc_tls_certificate_distributor.h:173
watchers_
std::map< SubchannelInterface::ConnectivityStateWatcherInterface *, WatcherWrapper * > watchers_
Definition: outlier_detection.cc:226
grpc_tls_certificate_distributor::SetError
void SetError(grpc_error_handle error)
Definition: grpc_tls_certificate_distributor.cc:155
absl::optional< std::string >
grpc_tls_identity_pairs_add_pair
void grpc_tls_identity_pairs_add_pair(grpc_tls_identity_pairs *pairs, const char *private_key, const char *cert_chain)
Definition: grpc_tls_certificate_distributor.cc:336
grpc_tls_certificate_distributor::SetErrorForCert
void SetErrorForCert(const std::string &cert_name, absl::optional< grpc_error_handle > root_cert_error, absl::optional< grpc_error_handle > identity_cert_error)
Definition: grpc_tls_certificate_distributor.cc:102
grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface::OnCertificatesChanged
virtual void OnCertificatesChanged(absl::optional< absl::string_view > root_certs, absl::optional< grpc_core::PemKeyCertPairList > key_cert_pairs)=0
grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface::OnError
virtual void OnError(grpc_error_handle root_cert_error, grpc_error_handle identity_cert_error)=0
grpc_tls_certificate_distributor::CancelTlsCertificatesWatch
void CancelTlsCertificatesWatch(TlsCertificatesWatcherInterface *watcher)
Definition: grpc_tls_certificate_distributor.cc:264
GRPC_ERROR_REF
#define GRPC_ERROR_REF(err)
Definition: error.h:261
grpc_tls_identity_pairs
struct grpc_tls_identity_pairs grpc_tls_identity_pairs
Definition: grpc_security.h:728
private_key
Definition: hrss.c:1885
GRPC_ERROR_UNREF
#define GRPC_ERROR_UNREF(err)
Definition: error.h:262
watcher
ClusterWatcher * watcher
Definition: cds.cc:148
grpc_error
Definition: error_internal.h:42
grpc_tls_certificate_distributor::WatcherInfo::identity_cert_name
absl::optional< std::string > identity_cert_name
Definition: grpc_tls_certificate_distributor.h:165
grpc_tls_certificate_distributor::HasKeyCertPairs
bool HasKeyCertPairs(const std::string &identity_cert_name)
Definition: grpc_tls_certificate_distributor.cc:94
grpc_tls_certificate_distributor::CertificateInfo::identity_cert_watchers
std::set< TlsCertificatesWatcherInterface * > identity_cert_watchers
Definition: grpc_tls_certificate_distributor.h:189
GRPC_ERROR_IS_NONE
#define GRPC_ERROR_IS_NONE(err)
Definition: error.h:241
port_platform.h


grpc
Author(s):
autogenerated on Fri May 16 2025 02:58:45