• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "src/core/xds/grpc/xds_certificate_provider.h"
20 
21 #include <grpc/support/port_platform.h>
22 
23 #include <utility>
24 
25 #include "absl/functional/bind_front.h"
26 #include "absl/log/check.h"
27 #include "absl/types/optional.h"
28 #include "src/core/lib/channel/channel_args.h"
29 #include "src/core/lib/iomgr/error.h"
30 #include "src/core/lib/security/security_connector/ssl_utils.h"
31 
32 namespace grpc_core {
33 
34 namespace {
35 
36 class RootCertificatesWatcher final
37     : public grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface {
38  public:
39   // Takes a ref to \a parent instead of a raw pointer since the watcher is
40   // owned by the root certificate distributor and not by \a parent. Note that
41   // presently, the watcher is immediately deleted when
42   // CancelTlsCertificatesWatch() is called, but that can potentially change in
43   // the future.
RootCertificatesWatcher(RefCountedPtr<grpc_tls_certificate_distributor> parent)44   explicit RootCertificatesWatcher(
45       RefCountedPtr<grpc_tls_certificate_distributor> parent)
46       : parent_(std::move(parent)) {}
47 
OnCertificatesChanged(absl::optional<absl::string_view> root_certs,absl::optional<PemKeyCertPairList>)48   void OnCertificatesChanged(absl::optional<absl::string_view> root_certs,
49                              absl::optional<PemKeyCertPairList>
50                              /* key_cert_pairs */) override {
51     if (root_certs.has_value()) {
52       parent_->SetKeyMaterials("", std::string(root_certs.value()),
53                                absl::nullopt);
54     }
55   }
56 
OnError(grpc_error_handle root_cert_error,grpc_error_handle)57   void OnError(grpc_error_handle root_cert_error,
58                grpc_error_handle /*identity_cert_error*/) override {
59     if (!root_cert_error.ok()) {
60       parent_->SetErrorForCert("", root_cert_error /* pass the ref */,
61                                absl::nullopt);
62     }
63   }
64 
65  private:
66   RefCountedPtr<grpc_tls_certificate_distributor> parent_;
67 };
68 
69 class IdentityCertificatesWatcher final
70     : public grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface {
71  public:
72   // Takes a ref to \a parent instead of a raw pointer since the watcher is
73   // owned by the root certificate distributor and not by \a parent. Note that
74   // presently, the watcher is immediately deleted when
75   // CancelTlsCertificatesWatch() is called, but that can potentially change in
76   // the future.
IdentityCertificatesWatcher(RefCountedPtr<grpc_tls_certificate_distributor> parent)77   explicit IdentityCertificatesWatcher(
78       RefCountedPtr<grpc_tls_certificate_distributor> parent)
79       : parent_(std::move(parent)) {}
80 
OnCertificatesChanged(absl::optional<absl::string_view>,absl::optional<PemKeyCertPairList> key_cert_pairs)81   void OnCertificatesChanged(
82       absl::optional<absl::string_view> /* root_certs */,
83       absl::optional<PemKeyCertPairList> key_cert_pairs) override {
84     if (key_cert_pairs.has_value()) {
85       parent_->SetKeyMaterials("", absl::nullopt, key_cert_pairs);
86     }
87   }
88 
OnError(grpc_error_handle,grpc_error_handle identity_cert_error)89   void OnError(grpc_error_handle /*root_cert_error*/,
90                grpc_error_handle identity_cert_error) override {
91     if (!identity_cert_error.ok()) {
92       parent_->SetErrorForCert("", absl::nullopt,
93                                identity_cert_error /* pass the ref */);
94     }
95   }
96 
97  private:
98   RefCountedPtr<grpc_tls_certificate_distributor> parent_;
99 };
100 
101 }  // namespace
102 
103 //
104 // XdsCertificateProvider
105 //
106 
XdsCertificateProvider(RefCountedPtr<grpc_tls_certificate_provider> root_cert_provider,absl::string_view root_cert_name,bool use_system_root_certs,RefCountedPtr<grpc_tls_certificate_provider> identity_cert_provider,absl::string_view identity_cert_name,std::vector<StringMatcher> san_matchers)107 XdsCertificateProvider::XdsCertificateProvider(
108     RefCountedPtr<grpc_tls_certificate_provider> root_cert_provider,
109     absl::string_view root_cert_name, bool use_system_root_certs,
110     RefCountedPtr<grpc_tls_certificate_provider> identity_cert_provider,
111     absl::string_view identity_cert_name,
112     std::vector<StringMatcher> san_matchers)
113     : distributor_(MakeRefCounted<grpc_tls_certificate_distributor>()),
114       root_cert_provider_(std::move(root_cert_provider)),
115       root_cert_name_(root_cert_name),
116       use_system_root_certs_(use_system_root_certs),
117       identity_cert_provider_(std::move(identity_cert_provider)),
118       identity_cert_name_(identity_cert_name),
119       san_matchers_(std::move(san_matchers)),
120       require_client_certificate_(false) {
121   distributor_->SetWatchStatusCallback(
122       absl::bind_front(&XdsCertificateProvider::WatchStatusCallback, this));
123 }
124 
XdsCertificateProvider(RefCountedPtr<grpc_tls_certificate_provider> root_cert_provider,absl::string_view root_cert_name,RefCountedPtr<grpc_tls_certificate_provider> identity_cert_provider,absl::string_view identity_cert_name,bool require_client_certificate)125 XdsCertificateProvider::XdsCertificateProvider(
126     RefCountedPtr<grpc_tls_certificate_provider> root_cert_provider,
127     absl::string_view root_cert_name,
128     RefCountedPtr<grpc_tls_certificate_provider> identity_cert_provider,
129     absl::string_view identity_cert_name, bool require_client_certificate)
130     : distributor_(MakeRefCounted<grpc_tls_certificate_distributor>()),
131       root_cert_provider_(std::move(root_cert_provider)),
132       root_cert_name_(root_cert_name),
133       identity_cert_provider_(std::move(identity_cert_provider)),
134       identity_cert_name_(identity_cert_name),
135       require_client_certificate_(require_client_certificate) {
136   distributor_->SetWatchStatusCallback(
137       absl::bind_front(&XdsCertificateProvider::WatchStatusCallback, this));
138 }
139 
~XdsCertificateProvider()140 XdsCertificateProvider::~XdsCertificateProvider() {
141   distributor_->SetWatchStatusCallback(nullptr);
142 }
143 
type() const144 UniqueTypeName XdsCertificateProvider::type() const {
145   static UniqueTypeName::Factory kFactory("Xds");
146   return kFactory.Create();
147 }
148 
WatchStatusCallback(std::string cert_name,bool root_being_watched,bool identity_being_watched)149 void XdsCertificateProvider::WatchStatusCallback(std::string cert_name,
150                                                  bool root_being_watched,
151                                                  bool identity_being_watched) {
152   if (!cert_name.empty()) {
153     if (root_being_watched) {
154       distributor_->SetErrorForCert(
155           cert_name,
156           GRPC_ERROR_CREATE(
157               "No certificate provider available for root certificates"),
158           absl::nullopt);
159     }
160     if (identity_being_watched) {
161       distributor_->SetErrorForCert(
162           cert_name, absl::nullopt,
163           GRPC_ERROR_CREATE(
164               "No certificate provider available for identity certificates"));
165     }
166     return;
167   }
168   // We aren't specially handling the case where root_cert_distributor is same
169   // as identity_cert_distributor. Always using two separate watchers
170   // irrespective of the fact results in a straightforward design, and using a
171   // single watcher does not seem to provide any benefit other than cutting down
172   // on the number of callbacks.
173   if (root_being_watched && root_cert_watcher_ == nullptr) {
174     // Start watching root cert.
175     if (root_cert_provider_ == nullptr) {
176       distributor_->SetErrorForCert(
177           cert_name,
178           GRPC_ERROR_CREATE(
179               "No certificate provider available for root certificates"),
180           absl::nullopt);
181     } else {
182       auto watcher = std::make_unique<RootCertificatesWatcher>(distributor_);
183       root_cert_watcher_ = watcher.get();
184       root_cert_provider_->distributor()->WatchTlsCertificates(
185           std::move(watcher), root_cert_name_, absl::nullopt);
186     }
187   } else if (!root_being_watched && root_cert_watcher_ != nullptr) {
188     // Cancel root cert watch.
189     CHECK(root_cert_provider_ != nullptr);
190     root_cert_provider_->distributor()->CancelTlsCertificatesWatch(
191         root_cert_watcher_);
192     root_cert_watcher_ = nullptr;
193   }
194   if (identity_being_watched && identity_cert_watcher_ == nullptr) {
195     // Start watching identity cert.
196     if (identity_cert_provider_ == nullptr) {
197       distributor_->SetErrorForCert(
198           cert_name, absl::nullopt,
199           GRPC_ERROR_CREATE(
200               "No certificate provider available for identity certificates"));
201     } else {
202       auto watcher =
203           std::make_unique<IdentityCertificatesWatcher>(distributor_);
204       identity_cert_watcher_ = watcher.get();
205       identity_cert_provider_->distributor()->WatchTlsCertificates(
206           std::move(watcher), absl::nullopt, identity_cert_name_);
207     }
208   } else if (!identity_being_watched && identity_cert_watcher_ != nullptr) {
209     CHECK(identity_cert_provider_ != nullptr);
210     identity_cert_provider_->distributor()->CancelTlsCertificatesWatch(
211         identity_cert_watcher_);
212     identity_cert_watcher_ = nullptr;
213   }
214 }
215 
216 }  // namespace grpc_core
217