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