• 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 <grpc/support/port_platform.h>
20 
21 #include "src/core/lib/security/credentials/xds/xds_credentials.h"
22 
23 #include "src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_args.h"
24 #include "src/core/ext/xds/xds_certificate_provider.h"
25 #include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h"
26 #include "src/core/lib/security/credentials/tls/tls_credentials.h"
27 #include "src/core/lib/security/credentials/tls/tls_utils.h"
28 #include "src/core/lib/uri/uri_parser.h"
29 
30 namespace grpc_core {
31 
32 const char kCredentialsTypeXds[] = "Xds";
33 
34 namespace {
35 
XdsVerifySubjectAlternativeNames(const char * const * subject_alternative_names,size_t subject_alternative_names_size,const std::vector<StringMatcher> & matchers)36 bool XdsVerifySubjectAlternativeNames(
37     const char* const* subject_alternative_names,
38     size_t subject_alternative_names_size,
39     const std::vector<StringMatcher>& matchers) {
40   if (matchers.empty()) return true;
41   for (size_t i = 0; i < subject_alternative_names_size; ++i) {
42     for (const auto& matcher : matchers) {
43       if (matcher.type() == StringMatcher::Type::EXACT) {
44         // For EXACT match, use DNS rules for verifying SANs
45         // TODO(zhenlian): Right now, the SSL layer does not save the type of
46         // the SAN, so we are doing a DNS style verification for all SANs when
47         // the type is EXACT. When we expose the SAN type, change this to only
48         // do this verification when the SAN type is DNS and match type is
49         // EXACT. For all other cases, we should use matcher.Match().
50         if (VerifySubjectAlternativeName(subject_alternative_names[i],
51                                          matcher.string_matcher())) {
52           return true;
53         }
54       } else {
55         if (matcher.Match(subject_alternative_names[i])) {
56           return true;
57         }
58       }
59     }
60   }
61   return false;
62 }
63 
64 class ServerAuthCheck {
65  public:
ServerAuthCheck(RefCountedPtr<XdsCertificateProvider> xds_certificate_provider,std::string cluster_name)66   ServerAuthCheck(
67       RefCountedPtr<XdsCertificateProvider> xds_certificate_provider,
68       std::string cluster_name)
69       : xds_certificate_provider_(std::move(xds_certificate_provider)),
70         cluster_name_(std::move(cluster_name)) {}
71 
Schedule(void * config_user_data,grpc_tls_server_authorization_check_arg * arg)72   static int Schedule(void* config_user_data,
73                       grpc_tls_server_authorization_check_arg* arg) {
74     return static_cast<ServerAuthCheck*>(config_user_data)->ScheduleImpl(arg);
75   }
76 
Destroy(void * config_user_data)77   static void Destroy(void* config_user_data) {
78     delete static_cast<ServerAuthCheck*>(config_user_data);
79   }
80 
81  private:
ScheduleImpl(grpc_tls_server_authorization_check_arg * arg)82   int ScheduleImpl(grpc_tls_server_authorization_check_arg* arg) {
83     if (XdsVerifySubjectAlternativeNames(
84             arg->subject_alternative_names, arg->subject_alternative_names_size,
85             xds_certificate_provider_->GetSanMatchers(cluster_name_))) {
86       arg->success = 1;
87       arg->status = GRPC_STATUS_OK;
88     } else {
89       arg->success = 0;
90       arg->status = GRPC_STATUS_UNAUTHENTICATED;
91       if (arg->error_details) {
92         arg->error_details->set_error_details(
93             "SANs from certificate did not match SANs from xDS control plane");
94       }
95     }
96     return 0; /* synchronous check */
97   }
98 
99   RefCountedPtr<XdsCertificateProvider> xds_certificate_provider_;
100   std::string cluster_name_;
101 };
102 
103 }  // namespace
104 
TestOnlyXdsVerifySubjectAlternativeNames(const char * const * subject_alternative_names,size_t subject_alternative_names_size,const std::vector<StringMatcher> & matchers)105 bool TestOnlyXdsVerifySubjectAlternativeNames(
106     const char* const* subject_alternative_names,
107     size_t subject_alternative_names_size,
108     const std::vector<StringMatcher>& matchers) {
109   return XdsVerifySubjectAlternativeNames(
110       subject_alternative_names, subject_alternative_names_size, matchers);
111 }
112 
113 //
114 // XdsCredentials
115 //
116 
117 RefCountedPtr<grpc_channel_security_connector>
create_security_connector(RefCountedPtr<grpc_call_credentials> call_creds,const char * target_name,const grpc_channel_args * args,grpc_channel_args ** new_args)118 XdsCredentials::create_security_connector(
119     RefCountedPtr<grpc_call_credentials> call_creds, const char* target_name,
120     const grpc_channel_args* args, grpc_channel_args** new_args) {
121   struct ChannelArgsDeleter {
122     const grpc_channel_args* args;
123     bool owned;
124     ~ChannelArgsDeleter() {
125       if (owned) grpc_channel_args_destroy(args);
126     }
127   };
128   ChannelArgsDeleter temp_args{args, false};
129   // TODO(yashykt): This arg will no longer need to be added after b/173119596
130   // is fixed.
131   grpc_arg override_arg = grpc_channel_arg_string_create(
132       const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
133       const_cast<char*>(target_name));
134   const char* override_arg_name = GRPC_SSL_TARGET_NAME_OVERRIDE_ARG;
135   if (grpc_channel_args_find(args, override_arg_name) == nullptr) {
136     temp_args.args = grpc_channel_args_copy_and_add_and_remove(
137         args, &override_arg_name, 1, &override_arg, 1);
138     temp_args.owned = true;
139   }
140   RefCountedPtr<grpc_channel_security_connector> security_connector;
141   auto xds_certificate_provider =
142       XdsCertificateProvider::GetFromChannelArgs(args);
143   if (xds_certificate_provider != nullptr) {
144     std::string cluster_name =
145         grpc_channel_args_find_string(args, GRPC_ARG_XDS_CLUSTER_NAME);
146     GPR_ASSERT(cluster_name.data() != nullptr);
147     const bool watch_root =
148         xds_certificate_provider->ProvidesRootCerts(cluster_name);
149     const bool watch_identity =
150         xds_certificate_provider->ProvidesIdentityCerts(cluster_name);
151     if (watch_root || watch_identity) {
152       auto tls_credentials_options =
153           MakeRefCounted<grpc_tls_credentials_options>();
154       tls_credentials_options->set_certificate_provider(
155           xds_certificate_provider);
156       if (watch_root) {
157         tls_credentials_options->set_watch_root_cert(true);
158         tls_credentials_options->set_root_cert_name(cluster_name);
159       }
160       if (watch_identity) {
161         tls_credentials_options->set_watch_identity_pair(true);
162         tls_credentials_options->set_identity_cert_name(cluster_name);
163       }
164       tls_credentials_options->set_server_verification_option(
165           GRPC_TLS_SKIP_HOSTNAME_VERIFICATION);
166       auto* server_auth_check = new ServerAuthCheck(xds_certificate_provider,
167                                                     std::move(cluster_name));
168       tls_credentials_options->set_server_authorization_check_config(
169           MakeRefCounted<grpc_tls_server_authorization_check_config>(
170               server_auth_check, ServerAuthCheck::Schedule, nullptr,
171               ServerAuthCheck::Destroy));
172       // TODO(yashkt): Creating a new TlsCreds object each time we create a
173       // security connector means that the security connector's cmp() method
174       // returns unequal for each instance, which means that every time an LB
175       // policy updates, all the subchannels will be recreated.  This is
176       // going to lead to a lot of connection churn.  Instead, we should
177       // either (a) change the TLS security connector's cmp() method to be
178       // smarter somehow, so that it compares unequal only when the
179       // tls_credentials_options have changed, or (b) cache the TlsCreds
180       // objects in the XdsCredentials object so that we can reuse the
181       // same one when creating new security connectors, swapping out the
182       // TlsCreds object only when the tls_credentials_options change.
183       // Option (a) would probably be better, although it may require some
184       // structural changes to the security connector API.
185       auto tls_credentials =
186           MakeRefCounted<TlsCredentials>(std::move(tls_credentials_options));
187       return tls_credentials->create_security_connector(
188           std::move(call_creds), target_name, temp_args.args, new_args);
189     }
190   }
191   GPR_ASSERT(fallback_credentials_ != nullptr);
192   return fallback_credentials_->create_security_connector(
193       std::move(call_creds), target_name, temp_args.args, new_args);
194 }
195 
196 //
197 // XdsServerCredentials
198 //
199 
200 RefCountedPtr<grpc_server_security_connector>
create_security_connector(const grpc_channel_args * args)201 XdsServerCredentials::create_security_connector(const grpc_channel_args* args) {
202   auto xds_certificate_provider =
203       XdsCertificateProvider::GetFromChannelArgs(args);
204   // Identity certs are a must for TLS.
205   if (xds_certificate_provider != nullptr &&
206       xds_certificate_provider->ProvidesIdentityCerts("")) {
207     auto tls_credentials_options =
208         MakeRefCounted<grpc_tls_credentials_options>();
209     tls_credentials_options->set_watch_identity_pair(true);
210     tls_credentials_options->set_certificate_provider(xds_certificate_provider);
211     if (xds_certificate_provider->ProvidesRootCerts("")) {
212       tls_credentials_options->set_watch_root_cert(true);
213       if (xds_certificate_provider->GetRequireClientCertificate("")) {
214         tls_credentials_options->set_cert_request_type(
215             GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
216       } else {
217         tls_credentials_options->set_cert_request_type(
218             GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY);
219       }
220     } else {
221       // Do not request client certificate if there is no way to verify.
222       tls_credentials_options->set_cert_request_type(
223           GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE);
224     }
225     auto tls_credentials = MakeRefCounted<TlsServerCredentials>(
226         std::move(tls_credentials_options));
227     return tls_credentials->create_security_connector(args);
228   }
229   return fallback_credentials_->create_security_connector(args);
230 }
231 
232 }  // namespace grpc_core
233 
grpc_xds_credentials_create(grpc_channel_credentials * fallback_credentials)234 grpc_channel_credentials* grpc_xds_credentials_create(
235     grpc_channel_credentials* fallback_credentials) {
236   GPR_ASSERT(fallback_credentials != nullptr);
237   return new grpc_core::XdsCredentials(fallback_credentials->Ref());
238 }
239 
grpc_xds_server_credentials_create(grpc_server_credentials * fallback_credentials)240 grpc_server_credentials* grpc_xds_server_credentials_create(
241     grpc_server_credentials* fallback_credentials) {
242   GPR_ASSERT(fallback_credentials != nullptr);
243   return new grpc_core::XdsServerCredentials(fallback_credentials->Ref());
244 }
245