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