// // Copyright 2021 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "src/core/ext/filters/rbac/rbac_service_config_parser.h" #include #include #include #include #include #include #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/str_cat.h" #include "absl/types/optional.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/security/authorization/audit_logging.h" #include "src/core/util/json/json_args.h" #include "src/core/util/json/json_object_loader.h" #include "src/core/util/matchers.h" namespace grpc_core { namespace { using experimental::AuditLoggerFactory; using experimental::AuditLoggerRegistry; // RbacConfig: one or more RbacPolicy structs struct RbacConfig { // RbacPolicy: optional Rules struct RbacPolicy { // Rules: an action, plus a map of policy names to Policy structs struct Rules { // Policy: a list of Permissions and a list of Principals struct Policy { // CidrRange: represents an IP range struct CidrRange { Rbac::CidrRange cidr_range; static const JsonLoaderInterface* JsonLoader(const JsonArgs&); void JsonPostLoad(const Json& json, const JsonArgs& args, ValidationErrors* errors); }; // SafeRegexMatch: a regex matcher struct SafeRegexMatch { std::string regex; static const JsonLoaderInterface* JsonLoader(const JsonArgs&); }; // HeaderMatch: a matcher for HTTP headers struct HeaderMatch { // RangeMatch: matches a range of numerical values struct RangeMatch { int64_t start; int64_t end; static const JsonLoaderInterface* JsonLoader(const JsonArgs&); }; HeaderMatcher matcher; static const JsonLoaderInterface* JsonLoader(const JsonArgs&); void JsonPostLoad(const Json& json, const JsonArgs& args, ValidationErrors* errors); }; // StringMatch: a matcher for strings struct StringMatch { StringMatcher matcher; static const JsonLoaderInterface* JsonLoader(const JsonArgs&); void JsonPostLoad(const Json& json, const JsonArgs& args, ValidationErrors* errors); }; // PathMatch: a matcher for paths struct PathMatch { StringMatch path; static const JsonLoaderInterface* JsonLoader(const JsonArgs&); }; // Metadata: a matcher for Envoy metadata (not really applicable // to gRPC; we use only the invert field for proper match semantics) struct Metadata { bool invert = false; static const JsonLoaderInterface* JsonLoader(const JsonArgs&); }; // Permission: a matcher for request attributes struct Permission { // PermissionList: a list used for "and" and "or" matchers struct PermissionList { std::vector rules; PermissionList() = default; PermissionList(const PermissionList&) = delete; PermissionList& operator=(const PermissionList&) = delete; PermissionList(PermissionList&&) = default; PermissionList& operator=(PermissionList&&) = default; static const JsonLoaderInterface* JsonLoader(const JsonArgs&); }; std::unique_ptr permission; Permission() = default; Permission(const Permission&) = delete; Permission& operator=(const Permission&) = delete; Permission(Permission&&) = default; Permission& operator=(Permission&&) = default; static std::vector> MakeRbacPermissionList(std::vector permission_list); static const JsonLoaderInterface* JsonLoader(const JsonArgs&); void JsonPostLoad(const Json& json, const JsonArgs& args, ValidationErrors* errors); }; // Principal: a matcher for client identity struct Principal { // PrincipalList: a list used for "and" and "or" matchers struct PrincipalList { std::vector ids; PrincipalList() = default; PrincipalList(const PrincipalList&) = delete; PrincipalList& operator=(const PrincipalList&) = delete; PrincipalList(PrincipalList&&) = default; PrincipalList& operator=(PrincipalList&&) = default; static const JsonLoaderInterface* JsonLoader(const JsonArgs&); }; struct Authenticated { absl::optional principal_name; static const JsonLoaderInterface* JsonLoader(const JsonArgs&); }; std::unique_ptr principal; Principal() = default; Principal(const Principal&) = delete; Principal& operator=(const Principal&) = delete; Principal(Principal&&) = default; Principal& operator=(Principal&&) = default; static std::vector> MakeRbacPrincipalList(std::vector principal_list); static const JsonLoaderInterface* JsonLoader(const JsonArgs&); void JsonPostLoad(const Json& json, const JsonArgs& args, ValidationErrors* errors); }; std::vector permissions; std::vector principals; Policy() = default; Policy(const Policy&) = delete; Policy& operator=(const Policy&) = delete; Policy(Policy&&) = default; Policy& operator=(Policy&&) = default; Rbac::Policy TakeAsRbacPolicy(); static const JsonLoaderInterface* JsonLoader(const JsonArgs&); }; // AuditLogger: the name of logger and its config in json struct AuditLogger { std::string name; Json::Object config; AuditLogger() = default; AuditLogger(const AuditLogger&) = delete; AuditLogger& operator=(const AuditLogger&) = delete; AuditLogger(AuditLogger&&) = default; AuditLogger& operator=(AuditLogger&&) = default; static const JsonLoaderInterface* JsonLoader(const JsonArgs&); void JsonPostLoad(const Json&, const JsonArgs&, ValidationErrors* errors); }; int action = static_cast(Rbac::Action::kDeny); std::map policies; // Defaults to kNone since its json field is optional. Rbac::AuditCondition audit_condition = Rbac::AuditCondition::kNone; std::vector> logger_configs; Rules() {} Rules(const Rules&) = delete; Rules& operator=(const Rules&) = delete; Rules(Rules&&) = default; Rules& operator=(Rules&&) = default; Rbac TakeAsRbac(); static const JsonLoaderInterface* JsonLoader(const JsonArgs&); void JsonPostLoad(const Json&, const JsonArgs&, ValidationErrors* errors); }; absl::optional rules; Rbac TakeAsRbac(); static const JsonLoaderInterface* JsonLoader(const JsonArgs&); }; std::vector rbac_policies; std::vector TakeAsRbacList(); static const JsonLoaderInterface* JsonLoader(const JsonArgs&); }; // // RbacConfig::RbacPolicy::Rules::Policy::CidrRange // const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::Policy::CidrRange::JsonLoader(const JsonArgs&) { // All fields handled in JsonPostLoad(). static const auto* loader = JsonObjectLoader().Finish(); return loader; } void RbacConfig::RbacPolicy::Rules::Policy::CidrRange::JsonPostLoad( const Json& json, const JsonArgs& args, ValidationErrors* errors) { auto address_prefix = LoadJsonObjectField( json.object(), args, "addressPrefix", errors); auto prefix_len = LoadJsonObjectField(json.object(), args, "prefixLen", errors, /*required=*/false); cidr_range = Rbac::CidrRange(address_prefix.value_or(""), prefix_len.value_or(0)); } // // RbacConfig::RbacPolicy::Rules::Policy::SafeRegexMatch // const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::Policy::SafeRegexMatch::JsonLoader( const JsonArgs&) { static const auto* loader = JsonObjectLoader() .Field("regex", &SafeRegexMatch::regex) .Finish(); return loader; } // // RbacConfig::RbacPolicy::Rules::Policy::HeaderMatch::RangeMatch // const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::Policy::HeaderMatch::RangeMatch::JsonLoader( const JsonArgs&) { static const auto* loader = JsonObjectLoader() .Field("start", &RangeMatch::start) .Field("end", &RangeMatch::end) .Finish(); return loader; } // // RbacConfig::RbacPolicy::Rules::Policy::HeaderMatch // const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::Policy::HeaderMatch::JsonLoader( const JsonArgs&) { // All fields handled in JsonPostLoad(). static const auto* loader = JsonObjectLoader().Finish(); return loader; } void RbacConfig::RbacPolicy::Rules::Policy::HeaderMatch::JsonPostLoad( const Json& json, const JsonArgs& args, ValidationErrors* errors) { const size_t original_error_size = errors->size(); std::string name = LoadJsonObjectField(json.object(), args, "name", errors) .value_or(""); bool invert_match = LoadJsonObjectField(json.object(), args, "invertMatch", errors, /*required=*/false) .value_or(false); auto set_header_matcher = [&](absl::StatusOr header_matcher) { if (header_matcher.ok()) { matcher = *header_matcher; } else { errors->AddError(header_matcher.status().message()); } }; auto check_match = [&](absl::string_view field_name, HeaderMatcher::Type type) { auto match = LoadJsonObjectField(json.object(), args, field_name, errors, /*required=*/false); if (match.has_value()) { set_header_matcher( HeaderMatcher::Create(name, type, *match, 0, 0, false, invert_match)); return true; } return false; }; if (check_match("exactMatch", HeaderMatcher::Type::kExact) || check_match("prefixMatch", HeaderMatcher::Type::kPrefix) || check_match("suffixMatch", HeaderMatcher::Type::kSuffix) || check_match("containsMatch", HeaderMatcher::Type::kContains)) { return; } auto present_match = LoadJsonObjectField(json.object(), args, "presentMatch", errors, /*required=*/false); if (present_match.has_value()) { set_header_matcher( HeaderMatcher::Create(name, HeaderMatcher::Type::kPresent, "", 0, 0, *present_match, invert_match)); return; } auto regex_match = LoadJsonObjectField( json.object(), args, "safeRegexMatch", errors, /*required=*/false); if (regex_match.has_value()) { set_header_matcher( HeaderMatcher::Create(name, HeaderMatcher::Type::kSafeRegex, regex_match->regex, 0, 0, false, invert_match)); return; } auto range_match = LoadJsonObjectField(json.object(), args, "rangeMatch", errors, /*required=*/false); if (range_match.has_value()) { set_header_matcher(HeaderMatcher::Create(name, HeaderMatcher::Type::kRange, "", range_match->start, range_match->end, invert_match)); return; } auto string_match = LoadJsonObjectField( json.object(), args, "stringMatch", errors, /*required=*/false); if (string_match.has_value()) { matcher = HeaderMatcher::CreateFromStringMatcher( name, std::move(string_match->matcher), invert_match); return; } if (errors->size() == original_error_size) { errors->AddError("no valid matcher found"); } } // // RbacConfig::RbacPolicy::Rules::Policy::StringMatch // const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::Policy::StringMatch::JsonLoader( const JsonArgs&) { // All fields handled in JsonPostLoad(). static const auto* loader = JsonObjectLoader().Finish(); return loader; } void RbacConfig::RbacPolicy::Rules::Policy::StringMatch::JsonPostLoad( const Json& json, const JsonArgs& args, ValidationErrors* errors) { const size_t original_error_size = errors->size(); bool ignore_case = LoadJsonObjectField(json.object(), args, "ignoreCase", errors, /*required=*/false) .value_or(false); auto set_string_matcher = [&](absl::StatusOr string_matcher) { if (string_matcher.ok()) { matcher = *string_matcher; } else { errors->AddError(string_matcher.status().message()); } }; auto check_match = [&](absl::string_view field_name, StringMatcher::Type type) { auto match = LoadJsonObjectField(json.object(), args, field_name, errors, /*required=*/false); if (match.has_value()) { set_string_matcher( StringMatcher::Create(type, *match, /*case_sensitive=*/!ignore_case)); return true; } return false; }; if (check_match("exact", StringMatcher::Type::kExact) || check_match("prefix", StringMatcher::Type::kPrefix) || check_match("suffix", StringMatcher::Type::kSuffix) || check_match("contains", StringMatcher::Type::kContains)) { return; } auto regex_match = LoadJsonObjectField(json.object(), args, "safeRegex", errors, /*required=*/false); if (regex_match.has_value()) { set_string_matcher(StringMatcher::Create(StringMatcher::Type::kSafeRegex, regex_match->regex)); return; } if (errors->size() == original_error_size) { errors->AddError("no valid matcher found"); } } // // RbacConfig::RbacPolicy::Rules::Policy::PathMatch // const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::Policy::PathMatch::JsonLoader(const JsonArgs&) { static const auto* loader = JsonObjectLoader().Field("path", &PathMatch::path).Finish(); return loader; } // // RbacConfig::RbacPolicy::Rules::Policy::Metadata // const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::Policy::Metadata::JsonLoader(const JsonArgs&) { static const auto* loader = JsonObjectLoader() .OptionalField("invert", &Metadata::invert) .Finish(); return loader; } // // RbacConfig::RbacPolicy::Rules::Policy::Permission::PermissionList // const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::Policy::Permission::PermissionList::JsonLoader( const JsonArgs&) { static const auto* loader = JsonObjectLoader() .Field("rules", &PermissionList::rules) .Finish(); return loader; } // // RbacConfig::RbacPolicy::Rules::Policy::Permission // std::vector> RbacConfig::RbacPolicy::Rules::Policy::Permission::MakeRbacPermissionList( std::vector permission_list) { std::vector> permissions; permissions.reserve(permission_list.size()); for (auto& rule : permission_list) { permissions.emplace_back(std::move(rule.permission)); } return permissions; } const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::Policy::Permission::JsonLoader(const JsonArgs&) { // All fields handled in JsonPostLoad(). static const auto* loader = JsonObjectLoader().Finish(); return loader; } void RbacConfig::RbacPolicy::Rules::Policy::Permission::JsonPostLoad( const Json& json, const JsonArgs& args, ValidationErrors* errors) { const size_t original_error_size = errors->size(); auto any = LoadJsonObjectField(json.object(), args, "any", errors, /*required=*/false); if (any.has_value()) { permission = std::make_unique( Rbac::Permission::MakeAnyPermission()); return; } auto header = LoadJsonObjectField(json.object(), args, "header", errors, /*required=*/false); if (header.has_value()) { permission = std::make_unique( Rbac::Permission::MakeHeaderPermission(std::move(header->matcher))); return; } auto url_path = LoadJsonObjectField(json.object(), args, "urlPath", errors, /*required=*/false); if (url_path.has_value()) { permission = std::make_unique( Rbac::Permission::MakePathPermission(url_path->path.matcher)); return; } auto destination_ip = LoadJsonObjectField(json.object(), args, "destinationIp", errors, /*required=*/false); if (destination_ip.has_value()) { permission = std::make_unique( Rbac::Permission::MakeDestIpPermission( std::move(destination_ip->cidr_range))); return; } auto destination_port = LoadJsonObjectField( json.object(), args, "destinationPort", errors, /*required=*/false); if (destination_port.has_value()) { permission = std::make_unique( Rbac::Permission::MakeDestPortPermission(*destination_port)); return; } auto metadata = LoadJsonObjectField(json.object(), args, "metadata", errors, /*required=*/false); if (metadata.has_value()) { permission = std::make_unique( Rbac::Permission::MakeMetadataPermission(metadata->invert)); return; } auto requested_server_name = LoadJsonObjectField( json.object(), args, "requestedServerName", errors, /*required=*/false); if (requested_server_name.has_value()) { permission = std::make_unique( Rbac::Permission::MakeReqServerNamePermission( std::move(requested_server_name->matcher))); return; } auto rules = LoadJsonObjectField(json.object(), args, "andRules", errors, /*required=*/false); if (rules.has_value()) { permission = std::make_unique(Rbac::Permission::MakeAndPermission( MakeRbacPermissionList(std::move(rules->rules)))); return; } rules = LoadJsonObjectField(json.object(), args, "orRules", errors, /*required=*/false); if (rules.has_value()) { permission = std::make_unique(Rbac::Permission::MakeOrPermission( MakeRbacPermissionList(std::move(rules->rules)))); return; } auto not_rule = LoadJsonObjectField(json.object(), args, "notRule", errors, /*required=*/false); if (not_rule.has_value()) { permission = std::make_unique( Rbac::Permission::MakeNotPermission(std::move(*not_rule->permission))); return; } if (errors->size() == original_error_size) { errors->AddError("no valid rule found"); } } // // RbacConfig::RbacPolicy::Rules::Policy::Principal::PrincipalList // const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::Policy::Principal::PrincipalList::JsonLoader( const JsonArgs&) { static const auto* loader = JsonObjectLoader() .Field("ids", &PrincipalList::ids) .Finish(); return loader; } // // RbacConfig::RbacPolicy::Rules::Policy::Principal::Authenticated // const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::Policy::Principal::Authenticated::JsonLoader( const JsonArgs&) { static const auto* loader = JsonObjectLoader() .OptionalField("principalName", &Authenticated::principal_name) .Finish(); return loader; } // // RbacConfig::RbacPolicy::Rules::Policy::Principal // std::vector> RbacConfig::RbacPolicy::Rules::Policy::Principal::MakeRbacPrincipalList( std::vector principal_list) { std::vector> principals; principals.reserve(principal_list.size()); for (auto& id : principal_list) { principals.emplace_back(std::move(id.principal)); } return principals; } const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::Policy::Principal::JsonLoader(const JsonArgs&) { // All fields handled in JsonPostLoad(). static const auto* loader = JsonObjectLoader().Finish(); return loader; } void RbacConfig::RbacPolicy::Rules::Policy::Principal::JsonPostLoad( const Json& json, const JsonArgs& args, ValidationErrors* errors) { const size_t original_error_size = errors->size(); auto any = LoadJsonObjectField(json.object(), args, "any", errors, /*required=*/false); if (any.has_value()) { principal = std::make_unique(Rbac::Principal::MakeAnyPrincipal()); return; } auto authenticated = LoadJsonObjectField( json.object(), args, "authenticated", errors, /*required=*/false); if (authenticated.has_value()) { if (authenticated->principal_name.has_value()) { principal = std::make_unique( Rbac::Principal::MakeAuthenticatedPrincipal( std::move(authenticated->principal_name->matcher))); } else { // No principalName found. Match for all users. principal = std::make_unique( Rbac::Principal::MakeAnyPrincipal()); } return; } auto cidr_range = LoadJsonObjectField(json.object(), args, "sourceIp", errors, /*required=*/false); if (cidr_range.has_value()) { principal = std::make_unique( Rbac::Principal::MakeSourceIpPrincipal( std::move(cidr_range->cidr_range))); return; } cidr_range = LoadJsonObjectField(json.object(), args, "directRemoteIp", errors, /*required=*/false); if (cidr_range.has_value()) { principal = std::make_unique( Rbac::Principal::MakeDirectRemoteIpPrincipal( std::move(cidr_range->cidr_range))); return; } cidr_range = LoadJsonObjectField(json.object(), args, "remoteIp", errors, /*required=*/false); if (cidr_range.has_value()) { principal = std::make_unique( Rbac::Principal::MakeRemoteIpPrincipal( std::move(cidr_range->cidr_range))); return; } auto header = LoadJsonObjectField(json.object(), args, "header", errors, /*required=*/false); if (header.has_value()) { principal = std::make_unique( Rbac::Principal::MakeHeaderPrincipal(std::move(header->matcher))); return; } auto url_path = LoadJsonObjectField(json.object(), args, "urlPath", errors, /*required=*/false); if (url_path.has_value()) { principal = std::make_unique( Rbac::Principal::MakePathPrincipal(std::move(url_path->path.matcher))); return; } auto metadata = LoadJsonObjectField(json.object(), args, "metadata", errors, /*required=*/false); if (metadata.has_value()) { principal = std::make_unique( Rbac::Principal::MakeMetadataPrincipal(metadata->invert)); return; } auto ids = LoadJsonObjectField(json.object(), args, "andIds", errors, /*required=*/false); if (ids.has_value()) { principal = std::make_unique(Rbac::Principal::MakeAndPrincipal( MakeRbacPrincipalList(std::move(ids->ids)))); return; } ids = LoadJsonObjectField(json.object(), args, "orIds", errors, /*required=*/false); if (ids.has_value()) { principal = std::make_unique(Rbac::Principal::MakeOrPrincipal( MakeRbacPrincipalList(std::move(ids->ids)))); return; } auto not_rule = LoadJsonObjectField(json.object(), args, "notId", errors, /*required=*/false); if (not_rule.has_value()) { principal = std::make_unique( Rbac::Principal::MakeNotPrincipal(std::move(*not_rule->principal))); return; } if (errors->size() == original_error_size) { errors->AddError("no valid id found"); } } // // RbacConfig::RbacPolicy::Rules::Policy // Rbac::Policy RbacConfig::RbacPolicy::Rules::Policy::TakeAsRbacPolicy() { Rbac::Policy policy; policy.permissions = Rbac::Permission::MakeOrPermission( Permission::MakeRbacPermissionList(std::move(permissions))); policy.principals = Rbac::Principal::MakeOrPrincipal( Principal::MakeRbacPrincipalList(std::move(principals))); return policy; } const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::Policy::JsonLoader( const JsonArgs&) { static const auto* loader = JsonObjectLoader() .Field("permissions", &Policy::permissions) .Field("principals", &Policy::principals) .Finish(); return loader; } // // RbacConfig::RbacPolicy::Rules::AuditLogger // const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::AuditLogger::JsonLoader(const JsonArgs&) { // All fields handled in JsonPostLoad(). static const auto* loader = JsonObjectLoader().Finish(); return loader; } void RbacConfig::RbacPolicy::Rules::AuditLogger::JsonPostLoad( const Json& json, const JsonArgs& args, ValidationErrors* errors) { // Should have exactly one field as the logger name. if (json.object().size() != 1) { errors->AddError("audit logger should have exactly one field"); return; } name = json.object().begin()->first; auto config_or = LoadJsonObjectField(json.object(), args, name, errors); if (config_or.has_value()) { config = std::move(*config_or); } } // // RbacConfig::RbacPolicy::Rules // Rbac RbacConfig::RbacPolicy::Rules::TakeAsRbac() { Rbac rbac; rbac.action = static_cast(action); rbac.audit_condition = audit_condition; for (auto& p : policies) { rbac.policies.emplace(p.first, p.second.TakeAsRbacPolicy()); } rbac.logger_configs = std::move(logger_configs); return rbac; } const JsonLoaderInterface* RbacConfig::RbacPolicy::Rules::JsonLoader( const JsonArgs&) { // Audit logger configs handled in post load. static const auto* loader = JsonObjectLoader() .Field("action", &Rules::action) .OptionalField("policies", &Rules::policies) .Finish(); return loader; } void RbacConfig::RbacPolicy::Rules::JsonPostLoad(const Json& json, const JsonArgs& args, ValidationErrors* errors) { // Validate action field. auto rbac_action = static_cast(action); if (rbac_action != Rbac::Action::kAllow && rbac_action != Rbac::Action::kDeny) { ValidationErrors::ScopedField field(errors, ".action"); errors->AddError(absl::StrCat("unknown action ", rbac_action)); } // Parse and validate audit_condition field. auto condition = LoadJsonObjectField(json.object(), args, "audit_condition", errors, false); if (condition.has_value()) { switch (*condition) { case static_cast(Rbac::AuditCondition::kNone): case static_cast(Rbac::AuditCondition::kOnAllow): case static_cast(Rbac::AuditCondition::kOnDeny): case static_cast(Rbac::AuditCondition::kOnDenyAndAllow): audit_condition = static_cast(*condition); break; default: { ValidationErrors::ScopedField field(errors, ".audit_condition"); errors->AddError("unknown audit condition"); } } } // Parse and validate audit logger configs. auto configs = LoadJsonObjectField>( json.object(), args, "audit_loggers", errors, false); if (configs.has_value()) { for (size_t i = 0; i < configs->size(); ++i) { auto& logger = (*configs)[i]; auto config = AuditLoggerRegistry::ParseConfig( logger.name, Json::FromObject(std::move(logger.config))); if (!config.ok()) { ValidationErrors::ScopedField field( errors, absl::StrCat(".audit_loggers[", i, "]")); errors->AddError(config.status().message()); continue; } logger_configs.push_back(std::move(*config)); } } } // // RbacConfig::RbacPolicy // Rbac RbacConfig::RbacPolicy::TakeAsRbac() { if (!rules.has_value()) { // No enforcing to be applied. An empty deny policy with an empty map // is equivalent to no enforcing. return Rbac("", Rbac::Action::kDeny, {}); } return rules->TakeAsRbac(); } const JsonLoaderInterface* RbacConfig::RbacPolicy::JsonLoader(const JsonArgs&) { static const auto* loader = JsonObjectLoader() .OptionalField("rules", &RbacPolicy::rules) .Finish(); return loader; } // // RbacConfig // std::vector RbacConfig::TakeAsRbacList() { std::vector rbac_list; rbac_list.reserve(rbac_policies.size()); for (auto& rbac_policy : rbac_policies) { rbac_list.emplace_back(rbac_policy.TakeAsRbac()); } return rbac_list; } const JsonLoaderInterface* RbacConfig::JsonLoader(const JsonArgs&) { static const auto* loader = JsonObjectLoader() .Field("rbacPolicy", &RbacConfig::rbac_policies) .Finish(); return loader; } } // namespace std::unique_ptr RbacServiceConfigParser::ParsePerMethodParams(const ChannelArgs& args, const Json& json, ValidationErrors* errors) { // Only parse rbac policy if the channel arg is present if (!args.GetBool(GRPC_ARG_PARSE_RBAC_METHOD_CONFIG).value_or(false)) { return nullptr; } auto rbac_config = LoadFromJson(json, JsonArgs(), errors); std::vector rbac_policies = rbac_config.TakeAsRbacList(); if (rbac_policies.empty()) return nullptr; return std::make_unique(std::move(rbac_policies)); } void RbacServiceConfigParser::Register(CoreConfiguration::Builder* builder) { builder->service_config_parser()->RegisterParser( std::make_unique()); } size_t RbacServiceConfigParser::ParserIndex() { return CoreConfiguration::Get().service_config_parser().GetParserIndex( parser_name()); } } // namespace grpc_core