Imported Upstream version 1.34.0
[platform/upstream/grpc.git] / src / core / ext / xds / xds_certificate_provider.cc
1 //
2 //
3 // Copyright 2020 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18
19 #include <grpc/support/port_platform.h>
20
21 #include "absl/functional/bind_front.h"
22 #include "absl/strings/str_cat.h"
23
24 #include "src/core/ext/xds/xds_certificate_provider.h"
25
26 namespace grpc_core {
27
28 namespace {
29
30 class RootCertificatesWatcher
31     : public grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface {
32  public:
33   // Takes a ref to \a parent instead of a raw pointer since the watcher is
34   // owned by the root certificate distributor and not by \a parent. Note that
35   // presently, the watcher is immediately deleted when
36   // CancelTlsCertificatesWatch() is called, but that can potentially change in
37   // the future.
38   explicit RootCertificatesWatcher(
39       RefCountedPtr<grpc_tls_certificate_distributor> parent)
40       : parent_(std::move(parent)) {}
41
42   void OnCertificatesChanged(absl::optional<absl::string_view> root_certs,
43                              absl::optional<PemKeyCertPairList>
44                              /* key_cert_pairs */) override {
45     if (root_certs.has_value()) {
46       parent_->SetKeyMaterials("", std::string(root_certs.value()),
47                                absl::nullopt);
48     }
49   }
50
51   void OnError(grpc_error* root_cert_error,
52                grpc_error* identity_cert_error) override {
53     if (root_cert_error != GRPC_ERROR_NONE) {
54       parent_->SetErrorForCert("", root_cert_error /* pass the ref */,
55                                absl::nullopt);
56     }
57     GRPC_ERROR_UNREF(identity_cert_error);
58   }
59
60  private:
61   RefCountedPtr<grpc_tls_certificate_distributor> parent_;
62 };
63
64 class IdentityCertificatesWatcher
65     : public grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface {
66  public:
67   // Takes a ref to \a parent instead of a raw pointer since the watcher is
68   // owned by the root certificate distributor and not by \a parent. Note that
69   // presently, the watcher is immediately deleted when
70   // CancelTlsCertificatesWatch() is called, but that can potentially change in
71   // the future.
72   explicit IdentityCertificatesWatcher(
73       RefCountedPtr<grpc_tls_certificate_distributor> parent)
74       : parent_(std::move(parent)) {}
75
76   void OnCertificatesChanged(
77       absl::optional<absl::string_view> /* root_certs */,
78       absl::optional<PemKeyCertPairList> key_cert_pairs) override {
79     if (key_cert_pairs.has_value()) {
80       parent_->SetKeyMaterials("", absl::nullopt, key_cert_pairs);
81     }
82   }
83
84   void OnError(grpc_error* root_cert_error,
85                grpc_error* identity_cert_error) override {
86     if (identity_cert_error != GRPC_ERROR_NONE) {
87       parent_->SetErrorForCert("", absl::nullopt,
88                                identity_cert_error /* pass the ref */);
89     }
90     GRPC_ERROR_UNREF(root_cert_error);
91   }
92
93  private:
94   RefCountedPtr<grpc_tls_certificate_distributor> parent_;
95 };
96
97 }  // namespace
98
99 XdsCertificateProvider::XdsCertificateProvider(
100     absl::string_view root_cert_name,
101     RefCountedPtr<grpc_tls_certificate_distributor> root_cert_distributor,
102     absl::string_view identity_cert_name,
103     RefCountedPtr<grpc_tls_certificate_distributor> identity_cert_distributor)
104     : root_cert_name_(root_cert_name),
105       identity_cert_name_(identity_cert_name),
106       root_cert_distributor_(std::move(root_cert_distributor)),
107       identity_cert_distributor_(std::move(identity_cert_distributor)),
108       distributor_(MakeRefCounted<grpc_tls_certificate_distributor>()) {
109   distributor_->SetWatchStatusCallback(
110       absl::bind_front(&XdsCertificateProvider::WatchStatusCallback, this));
111 }
112
113 void XdsCertificateProvider::UpdateRootCertNameAndDistributor(
114     absl::string_view root_cert_name,
115     RefCountedPtr<grpc_tls_certificate_distributor> root_cert_distributor) {
116   MutexLock lock(&mu_);
117   root_cert_name_ = std::string(root_cert_name);
118   if (watching_root_certs_) {
119     // The root certificates are being watched. Swap out the watcher.
120     if (root_cert_distributor_ != nullptr) {
121       root_cert_distributor_->CancelTlsCertificatesWatch(root_cert_watcher_);
122     }
123     if (root_cert_distributor != nullptr) {
124       UpdateRootCertWatcher(root_cert_distributor.get());
125     } else {
126       root_cert_watcher_ = nullptr;
127       distributor_->SetErrorForCert(
128           "",
129           GRPC_ERROR_CREATE_FROM_STATIC_STRING(
130               "No certificate provider available for root certificates"),
131           absl::nullopt);
132     }
133   }
134   // Swap out the root certificate distributor
135   root_cert_distributor_ = std::move(root_cert_distributor);
136 }
137
138 void XdsCertificateProvider::UpdateIdentityCertNameAndDistributor(
139     absl::string_view identity_cert_name,
140     RefCountedPtr<grpc_tls_certificate_distributor> identity_cert_distributor) {
141   MutexLock lock(&mu_);
142   identity_cert_name_ = std::string(identity_cert_name);
143   if (watching_identity_certs_) {
144     // The identity certificates are being watched. Swap out the watcher.
145     if (identity_cert_distributor_ != nullptr) {
146       identity_cert_distributor_->CancelTlsCertificatesWatch(
147           identity_cert_watcher_);
148     }
149     if (identity_cert_distributor != nullptr) {
150       UpdateIdentityCertWatcher(identity_cert_distributor.get());
151     } else {
152       identity_cert_watcher_ = nullptr;
153       distributor_->SetErrorForCert(
154           "", absl::nullopt,
155           GRPC_ERROR_CREATE_FROM_STATIC_STRING(
156               "No certificate provider available for identity certificates"));
157     }
158   }
159   // Swap out the identity certificate distributor
160   identity_cert_distributor_ = std::move(identity_cert_distributor);
161 }
162
163 void XdsCertificateProvider::WatchStatusCallback(std::string cert_name,
164                                                  bool root_being_watched,
165                                                  bool identity_being_watched) {
166   // We aren't specially handling the case where root_cert_distributor is same
167   // as identity_cert_distributor. Always using two separate watchers
168   // irrespective of the fact results in a straightforward design, and using a
169   // single watcher does not seem to provide any benefit other than cutting down
170   // on the number of callbacks.
171   MutexLock lock(&mu_);
172   if (!cert_name.empty()) {
173     grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
174         absl::StrCat("Illegal certificate name: \'", cert_name,
175                      "\'. Should be empty.")
176             .c_str());
177     distributor_->SetErrorForCert(cert_name, GRPC_ERROR_REF(error),
178                                   GRPC_ERROR_REF(error));
179     GRPC_ERROR_UNREF(error);
180     return;
181   }
182   if (root_being_watched && !watching_root_certs_) {
183     // We need to start watching root certs.
184     watching_root_certs_ = true;
185     if (root_cert_distributor_ == nullptr) {
186       distributor_->SetErrorForCert(
187           "",
188           GRPC_ERROR_CREATE_FROM_STATIC_STRING(
189               "No certificate provider available for root certificates"),
190           absl::nullopt);
191     } else {
192       UpdateRootCertWatcher(root_cert_distributor_.get());
193     }
194   } else if (!root_being_watched && watching_root_certs_) {
195     // We need to cancel root certs watch.
196     watching_root_certs_ = false;
197     if (root_cert_distributor_ != nullptr) {
198       root_cert_distributor_->CancelTlsCertificatesWatch(root_cert_watcher_);
199       root_cert_watcher_ = nullptr;
200     }
201     GPR_ASSERT(root_cert_watcher_ == nullptr);
202   }
203   if (identity_being_watched && !watching_identity_certs_) {
204     watching_identity_certs_ = true;
205     if (identity_cert_distributor_ == nullptr) {
206       distributor_->SetErrorForCert(
207           "", absl::nullopt,
208           GRPC_ERROR_CREATE_FROM_STATIC_STRING(
209               "No certificate provider available for identity certificates"));
210     } else {
211       UpdateIdentityCertWatcher(identity_cert_distributor_.get());
212     }
213   } else if (!identity_being_watched && watching_identity_certs_) {
214     watching_identity_certs_ = false;
215     if (identity_cert_distributor_ != nullptr) {
216       identity_cert_distributor_->CancelTlsCertificatesWatch(
217           identity_cert_watcher_);
218       identity_cert_watcher_ = nullptr;
219     }
220     GPR_ASSERT(identity_cert_watcher_ == nullptr);
221   }
222 }
223
224 void XdsCertificateProvider::UpdateRootCertWatcher(
225     grpc_tls_certificate_distributor* root_cert_distributor) {
226   auto watcher = absl::make_unique<RootCertificatesWatcher>(distributor());
227   root_cert_watcher_ = watcher.get();
228   root_cert_distributor->WatchTlsCertificates(std::move(watcher),
229                                               root_cert_name_, absl::nullopt);
230 }
231
232 void XdsCertificateProvider::UpdateIdentityCertWatcher(
233     grpc_tls_certificate_distributor* identity_cert_distributor) {
234   auto watcher = absl::make_unique<IdentityCertificatesWatcher>(distributor());
235   identity_cert_watcher_ = watcher.get();
236   identity_cert_distributor->WatchTlsCertificates(
237       std::move(watcher), absl::nullopt, identity_cert_name_);
238 }
239
240 }  // namespace grpc_core