• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2021 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 
17 #include "src/core/ext/filters/rbac/rbac_service_config_parser.h"
18 
19 #include <grpc/grpc_audit_logging.h>
20 #include <grpc/support/port_platform.h>
21 
22 #include <cstdint>
23 #include <map>
24 #include <memory>
25 #include <string>
26 
27 #include "absl/status/status.h"
28 #include "absl/status/statusor.h"
29 #include "absl/strings/str_cat.h"
30 #include "absl/types/optional.h"
31 #include "src/core/lib/channel/channel_args.h"
32 #include "src/core/lib/security/authorization/audit_logging.h"
33 #include "src/core/util/json/json_args.h"
34 #include "src/core/util/json/json_object_loader.h"
35 #include "src/core/util/matchers.h"
36 
37 namespace grpc_core {
38 
39 namespace {
40 
41 using experimental::AuditLoggerFactory;
42 using experimental::AuditLoggerRegistry;
43 
44 // RbacConfig: one or more RbacPolicy structs
45 struct RbacConfig {
46   // RbacPolicy: optional Rules
47   struct RbacPolicy {
48     // Rules: an action, plus a map of policy names to Policy structs
49     struct Rules {
50       // Policy: a list of Permissions and a list of Principals
51       struct Policy {
52         // CidrRange: represents an IP range
53         struct CidrRange {
54           Rbac::CidrRange cidr_range;
55 
56           static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
57           void JsonPostLoad(const Json& json, const JsonArgs& args,
58                             ValidationErrors* errors);
59         };
60 
61         // SafeRegexMatch: a regex matcher
62         struct SafeRegexMatch {
63           std::string regex;
64 
65           static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
66         };
67 
68         // HeaderMatch: a matcher for HTTP headers
69         struct HeaderMatch {
70           // RangeMatch: matches a range of numerical values
71           struct RangeMatch {
72             int64_t start;
73             int64_t end;
74 
75             static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
76           };
77 
78           HeaderMatcher matcher;
79 
80           static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
81           void JsonPostLoad(const Json& json, const JsonArgs& args,
82                             ValidationErrors* errors);
83         };
84 
85         // StringMatch: a matcher for strings
86         struct StringMatch {
87           StringMatcher matcher;
88 
89           static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
90           void JsonPostLoad(const Json& json, const JsonArgs& args,
91                             ValidationErrors* errors);
92         };
93 
94         // PathMatch: a matcher for paths
95         struct PathMatch {
96           StringMatch path;
97 
98           static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
99         };
100 
101         // Metadata: a matcher for Envoy metadata (not really applicable
102         // to gRPC; we use only the invert field for proper match semantics)
103         struct Metadata {
104           bool invert = false;
105 
106           static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
107         };
108 
109         // Permission: a matcher for request attributes
110         struct Permission {
111           // PermissionList: a list used for "and" and "or" matchers
112           struct PermissionList {
113             std::vector<Permission> rules;
114 
115             PermissionList() = default;
116             PermissionList(const PermissionList&) = delete;
117             PermissionList& operator=(const PermissionList&) = delete;
118             PermissionList(PermissionList&&) = default;
119             PermissionList& operator=(PermissionList&&) = default;
120 
121             static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
122           };
123 
124           std::unique_ptr<Rbac::Permission> permission;
125 
126           Permission() = default;
127           Permission(const Permission&) = delete;
128           Permission& operator=(const Permission&) = delete;
129           Permission(Permission&&) = default;
130           Permission& operator=(Permission&&) = default;
131 
132           static std::vector<std::unique_ptr<Rbac::Permission>>
133           MakeRbacPermissionList(std::vector<Permission> permission_list);
134           static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
135           void JsonPostLoad(const Json& json, const JsonArgs& args,
136                             ValidationErrors* errors);
137         };
138 
139         // Principal: a matcher for client identity
140         struct Principal {
141           // PrincipalList: a list used for "and" and "or" matchers
142           struct PrincipalList {
143             std::vector<Principal> ids;
144 
145             PrincipalList() = default;
146             PrincipalList(const PrincipalList&) = delete;
147             PrincipalList& operator=(const PrincipalList&) = delete;
148             PrincipalList(PrincipalList&&) = default;
149             PrincipalList& operator=(PrincipalList&&) = default;
150 
151             static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
152           };
153 
154           struct Authenticated {
155             absl::optional<StringMatch> principal_name;
156 
157             static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
158           };
159 
160           std::unique_ptr<Rbac::Principal> principal;
161 
162           Principal() = default;
163           Principal(const Principal&) = delete;
164           Principal& operator=(const Principal&) = delete;
165           Principal(Principal&&) = default;
166           Principal& operator=(Principal&&) = default;
167 
168           static std::vector<std::unique_ptr<Rbac::Principal>>
169           MakeRbacPrincipalList(std::vector<Principal> principal_list);
170           static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
171           void JsonPostLoad(const Json& json, const JsonArgs& args,
172                             ValidationErrors* errors);
173         };
174 
175         std::vector<Permission> permissions;
176         std::vector<Principal> principals;
177 
178         Policy() = default;
179         Policy(const Policy&) = delete;
180         Policy& operator=(const Policy&) = delete;
181         Policy(Policy&&) = default;
182         Policy& operator=(Policy&&) = default;
183 
184         Rbac::Policy TakeAsRbacPolicy();
185         static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
186       };
187 
188       // AuditLogger: the name of logger and its config in json
189       struct AuditLogger {
190         std::string name;
191         Json::Object config;
192 
193         AuditLogger() = default;
194         AuditLogger(const AuditLogger&) = delete;
195         AuditLogger& operator=(const AuditLogger&) = delete;
196         AuditLogger(AuditLogger&&) = default;
197         AuditLogger& operator=(AuditLogger&&) = default;
198 
199         static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
200         void JsonPostLoad(const Json&, const JsonArgs&,
201                           ValidationErrors* errors);
202       };
203 
204       int action = static_cast<int>(Rbac::Action::kDeny);
205       std::map<std::string, Policy> policies;
206       // Defaults to kNone since its json field is optional.
207       Rbac::AuditCondition audit_condition = Rbac::AuditCondition::kNone;
208       std::vector<std::unique_ptr<AuditLoggerFactory::Config>> logger_configs;
209 
Rulesgrpc_core::__anon3119f2da0111::RbacConfig::RbacPolicy::Rules210       Rules() {}
211       Rules(const Rules&) = delete;
212       Rules& operator=(const Rules&) = delete;
213       Rules(Rules&&) = default;
214       Rules& operator=(Rules&&) = default;
215 
216       Rbac TakeAsRbac();
217       static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
218       void JsonPostLoad(const Json&, const JsonArgs&, ValidationErrors* errors);
219     };
220 
221     absl::optional<Rules> rules;
222 
223     Rbac TakeAsRbac();
224     static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
225   };
226 
227   std::vector<RbacPolicy> rbac_policies;
228 
229   std::vector<Rbac> TakeAsRbacList();
230   static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
231 };
232 
233 //
234 // RbacConfig::RbacPolicy::Rules::Policy::CidrRange
235 //
236 
237 const JsonLoaderInterface*
JsonLoader(const JsonArgs &)238 RbacConfig::RbacPolicy::Rules::Policy::CidrRange::JsonLoader(const JsonArgs&) {
239   // All fields handled in JsonPostLoad().
240   static const auto* loader = JsonObjectLoader<CidrRange>().Finish();
241   return loader;
242 }
243 
JsonPostLoad(const Json & json,const JsonArgs & args,ValidationErrors * errors)244 void RbacConfig::RbacPolicy::Rules::Policy::CidrRange::JsonPostLoad(
245     const Json& json, const JsonArgs& args, ValidationErrors* errors) {
246   auto address_prefix = LoadJsonObjectField<std::string>(
247       json.object(), args, "addressPrefix", errors);
248   auto prefix_len =
249       LoadJsonObjectField<uint32_t>(json.object(), args, "prefixLen", errors,
250                                     /*required=*/false);
251   cidr_range =
252       Rbac::CidrRange(address_prefix.value_or(""), prefix_len.value_or(0));
253 }
254 
255 //
256 // RbacConfig::RbacPolicy::Rules::Policy::SafeRegexMatch
257 //
258 
259 const JsonLoaderInterface*
JsonLoader(const JsonArgs &)260 RbacConfig::RbacPolicy::Rules::Policy::SafeRegexMatch::JsonLoader(
261     const JsonArgs&) {
262   static const auto* loader = JsonObjectLoader<SafeRegexMatch>()
263                                   .Field("regex", &SafeRegexMatch::regex)
264                                   .Finish();
265   return loader;
266 }
267 
268 //
269 // RbacConfig::RbacPolicy::Rules::Policy::HeaderMatch::RangeMatch
270 //
271 
272 const JsonLoaderInterface*
JsonLoader(const JsonArgs &)273 RbacConfig::RbacPolicy::Rules::Policy::HeaderMatch::RangeMatch::JsonLoader(
274     const JsonArgs&) {
275   static const auto* loader = JsonObjectLoader<RangeMatch>()
276                                   .Field("start", &RangeMatch::start)
277                                   .Field("end", &RangeMatch::end)
278                                   .Finish();
279   return loader;
280 }
281 
282 //
283 // RbacConfig::RbacPolicy::Rules::Policy::HeaderMatch
284 //
285 
286 const JsonLoaderInterface*
JsonLoader(const JsonArgs &)287 RbacConfig::RbacPolicy::Rules::Policy::HeaderMatch::JsonLoader(
288     const JsonArgs&) {
289   // All fields handled in JsonPostLoad().
290   static const auto* loader = JsonObjectLoader<HeaderMatch>().Finish();
291   return loader;
292 }
293 
JsonPostLoad(const Json & json,const JsonArgs & args,ValidationErrors * errors)294 void RbacConfig::RbacPolicy::Rules::Policy::HeaderMatch::JsonPostLoad(
295     const Json& json, const JsonArgs& args, ValidationErrors* errors) {
296   const size_t original_error_size = errors->size();
297   std::string name =
298       LoadJsonObjectField<std::string>(json.object(), args, "name", errors)
299           .value_or("");
300   bool invert_match =
301       LoadJsonObjectField<bool>(json.object(), args, "invertMatch", errors,
302                                 /*required=*/false)
303           .value_or(false);
304   auto set_header_matcher = [&](absl::StatusOr<HeaderMatcher> header_matcher) {
305     if (header_matcher.ok()) {
306       matcher = *header_matcher;
307     } else {
308       errors->AddError(header_matcher.status().message());
309     }
310   };
311   auto check_match = [&](absl::string_view field_name,
312                          HeaderMatcher::Type type) {
313     auto match = LoadJsonObjectField<std::string>(json.object(), args,
314                                                   field_name, errors,
315                                                   /*required=*/false);
316     if (match.has_value()) {
317       set_header_matcher(
318           HeaderMatcher::Create(name, type, *match, 0, 0, false, invert_match));
319       return true;
320     }
321     return false;
322   };
323   if (check_match("exactMatch", HeaderMatcher::Type::kExact) ||
324       check_match("prefixMatch", HeaderMatcher::Type::kPrefix) ||
325       check_match("suffixMatch", HeaderMatcher::Type::kSuffix) ||
326       check_match("containsMatch", HeaderMatcher::Type::kContains)) {
327     return;
328   }
329   auto present_match =
330       LoadJsonObjectField<bool>(json.object(), args, "presentMatch", errors,
331                                 /*required=*/false);
332   if (present_match.has_value()) {
333     set_header_matcher(
334         HeaderMatcher::Create(name, HeaderMatcher::Type::kPresent, "", 0, 0,
335                               *present_match, invert_match));
336     return;
337   }
338   auto regex_match = LoadJsonObjectField<SafeRegexMatch>(
339       json.object(), args, "safeRegexMatch", errors,
340       /*required=*/false);
341   if (regex_match.has_value()) {
342     set_header_matcher(
343         HeaderMatcher::Create(name, HeaderMatcher::Type::kSafeRegex,
344                               regex_match->regex, 0, 0, false, invert_match));
345     return;
346   }
347   auto range_match =
348       LoadJsonObjectField<RangeMatch>(json.object(), args, "rangeMatch", errors,
349                                       /*required=*/false);
350   if (range_match.has_value()) {
351     set_header_matcher(HeaderMatcher::Create(name, HeaderMatcher::Type::kRange,
352                                              "", range_match->start,
353                                              range_match->end, invert_match));
354     return;
355   }
356   auto string_match = LoadJsonObjectField<StringMatch>(
357       json.object(), args, "stringMatch", errors, /*required=*/false);
358   if (string_match.has_value()) {
359     matcher = HeaderMatcher::CreateFromStringMatcher(
360         name, std::move(string_match->matcher), invert_match);
361     return;
362   }
363   if (errors->size() == original_error_size) {
364     errors->AddError("no valid matcher found");
365   }
366 }
367 
368 //
369 // RbacConfig::RbacPolicy::Rules::Policy::StringMatch
370 //
371 
372 const JsonLoaderInterface*
JsonLoader(const JsonArgs &)373 RbacConfig::RbacPolicy::Rules::Policy::StringMatch::JsonLoader(
374     const JsonArgs&) {
375   // All fields handled in JsonPostLoad().
376   static const auto* loader = JsonObjectLoader<StringMatch>().Finish();
377   return loader;
378 }
379 
JsonPostLoad(const Json & json,const JsonArgs & args,ValidationErrors * errors)380 void RbacConfig::RbacPolicy::Rules::Policy::StringMatch::JsonPostLoad(
381     const Json& json, const JsonArgs& args, ValidationErrors* errors) {
382   const size_t original_error_size = errors->size();
383   bool ignore_case =
384       LoadJsonObjectField<bool>(json.object(), args, "ignoreCase", errors,
385                                 /*required=*/false)
386           .value_or(false);
387   auto set_string_matcher = [&](absl::StatusOr<StringMatcher> string_matcher) {
388     if (string_matcher.ok()) {
389       matcher = *string_matcher;
390     } else {
391       errors->AddError(string_matcher.status().message());
392     }
393   };
394   auto check_match = [&](absl::string_view field_name,
395                          StringMatcher::Type type) {
396     auto match = LoadJsonObjectField<std::string>(json.object(), args,
397                                                   field_name, errors,
398                                                   /*required=*/false);
399     if (match.has_value()) {
400       set_string_matcher(
401           StringMatcher::Create(type, *match, /*case_sensitive=*/!ignore_case));
402       return true;
403     }
404     return false;
405   };
406   if (check_match("exact", StringMatcher::Type::kExact) ||
407       check_match("prefix", StringMatcher::Type::kPrefix) ||
408       check_match("suffix", StringMatcher::Type::kSuffix) ||
409       check_match("contains", StringMatcher::Type::kContains)) {
410     return;
411   }
412   auto regex_match = LoadJsonObjectField<SafeRegexMatch>(json.object(), args,
413                                                          "safeRegex", errors,
414                                                          /*required=*/false);
415   if (regex_match.has_value()) {
416     set_string_matcher(StringMatcher::Create(StringMatcher::Type::kSafeRegex,
417                                              regex_match->regex));
418     return;
419   }
420   if (errors->size() == original_error_size) {
421     errors->AddError("no valid matcher found");
422   }
423 }
424 
425 //
426 // RbacConfig::RbacPolicy::Rules::Policy::PathMatch
427 //
428 
429 const JsonLoaderInterface*
JsonLoader(const JsonArgs &)430 RbacConfig::RbacPolicy::Rules::Policy::PathMatch::JsonLoader(const JsonArgs&) {
431   static const auto* loader =
432       JsonObjectLoader<PathMatch>().Field("path", &PathMatch::path).Finish();
433   return loader;
434 }
435 
436 //
437 // RbacConfig::RbacPolicy::Rules::Policy::Metadata
438 //
439 
440 const JsonLoaderInterface*
JsonLoader(const JsonArgs &)441 RbacConfig::RbacPolicy::Rules::Policy::Metadata::JsonLoader(const JsonArgs&) {
442   static const auto* loader = JsonObjectLoader<Metadata>()
443                                   .OptionalField("invert", &Metadata::invert)
444                                   .Finish();
445   return loader;
446 }
447 
448 //
449 // RbacConfig::RbacPolicy::Rules::Policy::Permission::PermissionList
450 //
451 
452 const JsonLoaderInterface*
JsonLoader(const JsonArgs &)453 RbacConfig::RbacPolicy::Rules::Policy::Permission::PermissionList::JsonLoader(
454     const JsonArgs&) {
455   static const auto* loader = JsonObjectLoader<PermissionList>()
456                                   .Field("rules", &PermissionList::rules)
457                                   .Finish();
458   return loader;
459 }
460 
461 //
462 // RbacConfig::RbacPolicy::Rules::Policy::Permission
463 //
464 
465 std::vector<std::unique_ptr<Rbac::Permission>>
MakeRbacPermissionList(std::vector<Permission> permission_list)466 RbacConfig::RbacPolicy::Rules::Policy::Permission::MakeRbacPermissionList(
467     std::vector<Permission> permission_list) {
468   std::vector<std::unique_ptr<Rbac::Permission>> permissions;
469   permissions.reserve(permission_list.size());
470   for (auto& rule : permission_list) {
471     permissions.emplace_back(std::move(rule.permission));
472   }
473   return permissions;
474 }
475 
476 const JsonLoaderInterface*
JsonLoader(const JsonArgs &)477 RbacConfig::RbacPolicy::Rules::Policy::Permission::JsonLoader(const JsonArgs&) {
478   // All fields handled in JsonPostLoad().
479   static const auto* loader = JsonObjectLoader<Permission>().Finish();
480   return loader;
481 }
482 
JsonPostLoad(const Json & json,const JsonArgs & args,ValidationErrors * errors)483 void RbacConfig::RbacPolicy::Rules::Policy::Permission::JsonPostLoad(
484     const Json& json, const JsonArgs& args, ValidationErrors* errors) {
485   const size_t original_error_size = errors->size();
486   auto any = LoadJsonObjectField<bool>(json.object(), args, "any", errors,
487                                        /*required=*/false);
488   if (any.has_value()) {
489     permission = std::make_unique<Rbac::Permission>(
490         Rbac::Permission::MakeAnyPermission());
491     return;
492   }
493   auto header =
494       LoadJsonObjectField<HeaderMatch>(json.object(), args, "header", errors,
495                                        /*required=*/false);
496   if (header.has_value()) {
497     permission = std::make_unique<Rbac::Permission>(
498         Rbac::Permission::MakeHeaderPermission(std::move(header->matcher)));
499     return;
500   }
501   auto url_path =
502       LoadJsonObjectField<PathMatch>(json.object(), args, "urlPath", errors,
503                                      /*required=*/false);
504   if (url_path.has_value()) {
505     permission = std::make_unique<Rbac::Permission>(
506         Rbac::Permission::MakePathPermission(url_path->path.matcher));
507     return;
508   }
509   auto destination_ip = LoadJsonObjectField<CidrRange>(json.object(), args,
510                                                        "destinationIp", errors,
511                                                        /*required=*/false);
512   if (destination_ip.has_value()) {
513     permission = std::make_unique<Rbac::Permission>(
514         Rbac::Permission::MakeDestIpPermission(
515             std::move(destination_ip->cidr_range)));
516     return;
517   }
518   auto destination_port = LoadJsonObjectField<uint32_t>(
519       json.object(), args, "destinationPort", errors,
520       /*required=*/false);
521   if (destination_port.has_value()) {
522     permission = std::make_unique<Rbac::Permission>(
523         Rbac::Permission::MakeDestPortPermission(*destination_port));
524     return;
525   }
526   auto metadata =
527       LoadJsonObjectField<Metadata>(json.object(), args, "metadata", errors,
528                                     /*required=*/false);
529   if (metadata.has_value()) {
530     permission = std::make_unique<Rbac::Permission>(
531         Rbac::Permission::MakeMetadataPermission(metadata->invert));
532     return;
533   }
534   auto requested_server_name = LoadJsonObjectField<StringMatch>(
535       json.object(), args, "requestedServerName", errors,
536       /*required=*/false);
537   if (requested_server_name.has_value()) {
538     permission = std::make_unique<Rbac::Permission>(
539         Rbac::Permission::MakeReqServerNamePermission(
540             std::move(requested_server_name->matcher)));
541     return;
542   }
543   auto rules = LoadJsonObjectField<PermissionList>(json.object(), args,
544                                                    "andRules", errors,
545                                                    /*required=*/false);
546   if (rules.has_value()) {
547     permission =
548         std::make_unique<Rbac::Permission>(Rbac::Permission::MakeAndPermission(
549             MakeRbacPermissionList(std::move(rules->rules))));
550     return;
551   }
552   rules = LoadJsonObjectField<PermissionList>(json.object(), args, "orRules",
553                                               errors,
554                                               /*required=*/false);
555   if (rules.has_value()) {
556     permission =
557         std::make_unique<Rbac::Permission>(Rbac::Permission::MakeOrPermission(
558             MakeRbacPermissionList(std::move(rules->rules))));
559     return;
560   }
561   auto not_rule =
562       LoadJsonObjectField<Permission>(json.object(), args, "notRule", errors,
563                                       /*required=*/false);
564   if (not_rule.has_value()) {
565     permission = std::make_unique<Rbac::Permission>(
566         Rbac::Permission::MakeNotPermission(std::move(*not_rule->permission)));
567     return;
568   }
569   if (errors->size() == original_error_size) {
570     errors->AddError("no valid rule found");
571   }
572 }
573 
574 //
575 // RbacConfig::RbacPolicy::Rules::Policy::Principal::PrincipalList
576 //
577 
578 const JsonLoaderInterface*
JsonLoader(const JsonArgs &)579 RbacConfig::RbacPolicy::Rules::Policy::Principal::PrincipalList::JsonLoader(
580     const JsonArgs&) {
581   static const auto* loader = JsonObjectLoader<PrincipalList>()
582                                   .Field("ids", &PrincipalList::ids)
583                                   .Finish();
584   return loader;
585 }
586 
587 //
588 // RbacConfig::RbacPolicy::Rules::Policy::Principal::Authenticated
589 //
590 
591 const JsonLoaderInterface*
JsonLoader(const JsonArgs &)592 RbacConfig::RbacPolicy::Rules::Policy::Principal::Authenticated::JsonLoader(
593     const JsonArgs&) {
594   static const auto* loader =
595       JsonObjectLoader<Authenticated>()
596           .OptionalField("principalName", &Authenticated::principal_name)
597           .Finish();
598   return loader;
599 }
600 
601 //
602 // RbacConfig::RbacPolicy::Rules::Policy::Principal
603 //
604 
605 std::vector<std::unique_ptr<Rbac::Principal>>
MakeRbacPrincipalList(std::vector<Principal> principal_list)606 RbacConfig::RbacPolicy::Rules::Policy::Principal::MakeRbacPrincipalList(
607     std::vector<Principal> principal_list) {
608   std::vector<std::unique_ptr<Rbac::Principal>> principals;
609   principals.reserve(principal_list.size());
610   for (auto& id : principal_list) {
611     principals.emplace_back(std::move(id.principal));
612   }
613   return principals;
614 }
615 
616 const JsonLoaderInterface*
JsonLoader(const JsonArgs &)617 RbacConfig::RbacPolicy::Rules::Policy::Principal::JsonLoader(const JsonArgs&) {
618   // All fields handled in JsonPostLoad().
619   static const auto* loader = JsonObjectLoader<Principal>().Finish();
620   return loader;
621 }
622 
JsonPostLoad(const Json & json,const JsonArgs & args,ValidationErrors * errors)623 void RbacConfig::RbacPolicy::Rules::Policy::Principal::JsonPostLoad(
624     const Json& json, const JsonArgs& args, ValidationErrors* errors) {
625   const size_t original_error_size = errors->size();
626   auto any = LoadJsonObjectField<bool>(json.object(), args, "any", errors,
627                                        /*required=*/false);
628   if (any.has_value()) {
629     principal =
630         std::make_unique<Rbac::Principal>(Rbac::Principal::MakeAnyPrincipal());
631     return;
632   }
633   auto authenticated = LoadJsonObjectField<Authenticated>(
634       json.object(), args, "authenticated", errors,
635       /*required=*/false);
636   if (authenticated.has_value()) {
637     if (authenticated->principal_name.has_value()) {
638       principal = std::make_unique<Rbac::Principal>(
639           Rbac::Principal::MakeAuthenticatedPrincipal(
640               std::move(authenticated->principal_name->matcher)));
641     } else {
642       // No principalName found. Match for all users.
643       principal = std::make_unique<Rbac::Principal>(
644           Rbac::Principal::MakeAnyPrincipal());
645     }
646     return;
647   }
648   auto cidr_range =
649       LoadJsonObjectField<CidrRange>(json.object(), args, "sourceIp", errors,
650                                      /*required=*/false);
651   if (cidr_range.has_value()) {
652     principal = std::make_unique<Rbac::Principal>(
653         Rbac::Principal::MakeSourceIpPrincipal(
654             std::move(cidr_range->cidr_range)));
655     return;
656   }
657   cidr_range = LoadJsonObjectField<CidrRange>(json.object(), args,
658                                               "directRemoteIp", errors,
659                                               /*required=*/false);
660   if (cidr_range.has_value()) {
661     principal = std::make_unique<Rbac::Principal>(
662         Rbac::Principal::MakeDirectRemoteIpPrincipal(
663             std::move(cidr_range->cidr_range)));
664     return;
665   }
666   cidr_range =
667       LoadJsonObjectField<CidrRange>(json.object(), args, "remoteIp", errors,
668                                      /*required=*/false);
669   if (cidr_range.has_value()) {
670     principal = std::make_unique<Rbac::Principal>(
671         Rbac::Principal::MakeRemoteIpPrincipal(
672             std::move(cidr_range->cidr_range)));
673     return;
674   }
675   auto header =
676       LoadJsonObjectField<HeaderMatch>(json.object(), args, "header", errors,
677                                        /*required=*/false);
678   if (header.has_value()) {
679     principal = std::make_unique<Rbac::Principal>(
680         Rbac::Principal::MakeHeaderPrincipal(std::move(header->matcher)));
681     return;
682   }
683   auto url_path =
684       LoadJsonObjectField<PathMatch>(json.object(), args, "urlPath", errors,
685                                      /*required=*/false);
686   if (url_path.has_value()) {
687     principal = std::make_unique<Rbac::Principal>(
688         Rbac::Principal::MakePathPrincipal(std::move(url_path->path.matcher)));
689     return;
690   }
691   auto metadata =
692       LoadJsonObjectField<Metadata>(json.object(), args, "metadata", errors,
693                                     /*required=*/false);
694   if (metadata.has_value()) {
695     principal = std::make_unique<Rbac::Principal>(
696         Rbac::Principal::MakeMetadataPrincipal(metadata->invert));
697     return;
698   }
699   auto ids =
700       LoadJsonObjectField<PrincipalList>(json.object(), args, "andIds", errors,
701                                          /*required=*/false);
702   if (ids.has_value()) {
703     principal =
704         std::make_unique<Rbac::Principal>(Rbac::Principal::MakeAndPrincipal(
705             MakeRbacPrincipalList(std::move(ids->ids))));
706     return;
707   }
708   ids = LoadJsonObjectField<PrincipalList>(json.object(), args, "orIds", errors,
709                                            /*required=*/false);
710   if (ids.has_value()) {
711     principal =
712         std::make_unique<Rbac::Principal>(Rbac::Principal::MakeOrPrincipal(
713             MakeRbacPrincipalList(std::move(ids->ids))));
714     return;
715   }
716   auto not_rule =
717       LoadJsonObjectField<Principal>(json.object(), args, "notId", errors,
718                                      /*required=*/false);
719   if (not_rule.has_value()) {
720     principal = std::make_unique<Rbac::Principal>(
721         Rbac::Principal::MakeNotPrincipal(std::move(*not_rule->principal)));
722     return;
723   }
724   if (errors->size() == original_error_size) {
725     errors->AddError("no valid id found");
726   }
727 }
728 
729 //
730 // RbacConfig::RbacPolicy::Rules::Policy
731 //
732 
TakeAsRbacPolicy()733 Rbac::Policy RbacConfig::RbacPolicy::Rules::Policy::TakeAsRbacPolicy() {
734   Rbac::Policy policy;
735   policy.permissions = Rbac::Permission::MakeOrPermission(
736       Permission::MakeRbacPermissionList(std::move(permissions)));
737   policy.principals = Rbac::Principal::MakeOrPrincipal(
738       Principal::MakeRbacPrincipalList(std::move(principals)));
739   return policy;
740 }
741 
JsonLoader(const JsonArgs &)742 const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::Policy::JsonLoader(
743     const JsonArgs&) {
744   static const auto* loader = JsonObjectLoader<Policy>()
745                                   .Field("permissions", &Policy::permissions)
746                                   .Field("principals", &Policy::principals)
747                                   .Finish();
748   return loader;
749 }
750 
751 //
752 // RbacConfig::RbacPolicy::Rules::AuditLogger
753 //
754 
755 const JsonLoaderInterface*
JsonLoader(const JsonArgs &)756 RbacConfig::RbacPolicy::Rules::AuditLogger::JsonLoader(const JsonArgs&) {
757   // All fields handled in JsonPostLoad().
758   static const auto* loader = JsonObjectLoader<AuditLogger>().Finish();
759   return loader;
760 }
761 
JsonPostLoad(const Json & json,const JsonArgs & args,ValidationErrors * errors)762 void RbacConfig::RbacPolicy::Rules::AuditLogger::JsonPostLoad(
763     const Json& json, const JsonArgs& args, ValidationErrors* errors) {
764   // Should have exactly one field as the logger name.
765   if (json.object().size() != 1) {
766     errors->AddError("audit logger should have exactly one field");
767     return;
768   }
769   name = json.object().begin()->first;
770   auto config_or =
771       LoadJsonObjectField<Json::Object>(json.object(), args, name, errors);
772   if (config_or.has_value()) {
773     config = std::move(*config_or);
774   }
775 }
776 
777 //
778 // RbacConfig::RbacPolicy::Rules
779 //
780 
TakeAsRbac()781 Rbac RbacConfig::RbacPolicy::Rules::TakeAsRbac() {
782   Rbac rbac;
783   rbac.action = static_cast<Rbac::Action>(action);
784   rbac.audit_condition = audit_condition;
785   for (auto& p : policies) {
786     rbac.policies.emplace(p.first, p.second.TakeAsRbacPolicy());
787   }
788   rbac.logger_configs = std::move(logger_configs);
789   return rbac;
790 }
791 
JsonLoader(const JsonArgs &)792 const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::JsonLoader(
793     const JsonArgs&) {
794   // Audit logger configs handled in post load.
795   static const auto* loader = JsonObjectLoader<Rules>()
796                                   .Field("action", &Rules::action)
797                                   .OptionalField("policies", &Rules::policies)
798                                   .Finish();
799   return loader;
800 }
801 
JsonPostLoad(const Json & json,const JsonArgs & args,ValidationErrors * errors)802 void RbacConfig::RbacPolicy::Rules::JsonPostLoad(const Json& json,
803                                                  const JsonArgs& args,
804                                                  ValidationErrors* errors) {
805   // Validate action field.
806   auto rbac_action = static_cast<Rbac::Action>(action);
807   if (rbac_action != Rbac::Action::kAllow &&
808       rbac_action != Rbac::Action::kDeny) {
809     ValidationErrors::ScopedField field(errors, ".action");
810     errors->AddError(absl::StrCat("unknown action ", rbac_action));
811   }
812   // Parse and validate audit_condition field.
813   auto condition = LoadJsonObjectField<int>(json.object(), args,
814                                             "audit_condition", errors, false);
815   if (condition.has_value()) {
816     switch (*condition) {
817       case static_cast<int>(Rbac::AuditCondition::kNone):
818       case static_cast<int>(Rbac::AuditCondition::kOnAllow):
819       case static_cast<int>(Rbac::AuditCondition::kOnDeny):
820       case static_cast<int>(Rbac::AuditCondition::kOnDenyAndAllow):
821         audit_condition = static_cast<Rbac::AuditCondition>(*condition);
822         break;
823       default: {
824         ValidationErrors::ScopedField field(errors, ".audit_condition");
825         errors->AddError("unknown audit condition");
826       }
827     }
828   }
829   // Parse and validate audit logger configs.
830   auto configs = LoadJsonObjectField<std::vector<AuditLogger>>(
831       json.object(), args, "audit_loggers", errors, false);
832   if (configs.has_value()) {
833     for (size_t i = 0; i < configs->size(); ++i) {
834       auto& logger = (*configs)[i];
835       auto config = AuditLoggerRegistry::ParseConfig(
836           logger.name, Json::FromObject(std::move(logger.config)));
837       if (!config.ok()) {
838         ValidationErrors::ScopedField field(
839             errors, absl::StrCat(".audit_loggers[", i, "]"));
840         errors->AddError(config.status().message());
841         continue;
842       }
843       logger_configs.push_back(std::move(*config));
844     }
845   }
846 }
847 
848 //
849 // RbacConfig::RbacPolicy
850 //
851 
TakeAsRbac()852 Rbac RbacConfig::RbacPolicy::TakeAsRbac() {
853   if (!rules.has_value()) {
854     // No enforcing to be applied. An empty deny policy with an empty map
855     // is equivalent to no enforcing.
856     return Rbac("", Rbac::Action::kDeny, {});
857   }
858   return rules->TakeAsRbac();
859 }
860 
JsonLoader(const JsonArgs &)861 const JsonLoaderInterface* RbacConfig::RbacPolicy::JsonLoader(const JsonArgs&) {
862   static const auto* loader = JsonObjectLoader<RbacPolicy>()
863                                   .OptionalField("rules", &RbacPolicy::rules)
864                                   .Finish();
865   return loader;
866 }
867 
868 //
869 // RbacConfig
870 //
871 
TakeAsRbacList()872 std::vector<Rbac> RbacConfig::TakeAsRbacList() {
873   std::vector<Rbac> rbac_list;
874   rbac_list.reserve(rbac_policies.size());
875   for (auto& rbac_policy : rbac_policies) {
876     rbac_list.emplace_back(rbac_policy.TakeAsRbac());
877   }
878   return rbac_list;
879 }
880 
JsonLoader(const JsonArgs &)881 const JsonLoaderInterface* RbacConfig::JsonLoader(const JsonArgs&) {
882   static const auto* loader =
883       JsonObjectLoader<RbacConfig>()
884           .Field("rbacPolicy", &RbacConfig::rbac_policies)
885           .Finish();
886   return loader;
887 }
888 
889 }  // namespace
890 
891 std::unique_ptr<ServiceConfigParser::ParsedConfig>
ParsePerMethodParams(const ChannelArgs & args,const Json & json,ValidationErrors * errors)892 RbacServiceConfigParser::ParsePerMethodParams(const ChannelArgs& args,
893                                               const Json& json,
894                                               ValidationErrors* errors) {
895   // Only parse rbac policy if the channel arg is present
896   if (!args.GetBool(GRPC_ARG_PARSE_RBAC_METHOD_CONFIG).value_or(false)) {
897     return nullptr;
898   }
899   auto rbac_config = LoadFromJson<RbacConfig>(json, JsonArgs(), errors);
900   std::vector<Rbac> rbac_policies = rbac_config.TakeAsRbacList();
901   if (rbac_policies.empty()) return nullptr;
902   return std::make_unique<RbacMethodParsedConfig>(std::move(rbac_policies));
903 }
904 
Register(CoreConfiguration::Builder * builder)905 void RbacServiceConfigParser::Register(CoreConfiguration::Builder* builder) {
906   builder->service_config_parser()->RegisterParser(
907       std::make_unique<RbacServiceConfigParser>());
908 }
909 
ParserIndex()910 size_t RbacServiceConfigParser::ParserIndex() {
911   return CoreConfiguration::Get().service_config_parser().GetParserIndex(
912       parser_name());
913 }
914 
915 }  // namespace grpc_core
916