• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/core/lib/security/authorization/grpc_authorization_engine.h"
16 
17 #include <grpc/support/port_platform.h>
18 
19 #include <algorithm>
20 #include <map>
21 #include <utility>
22 
23 #include "absl/log/check.h"
24 #include "src/core/lib/security/authorization/audit_logging.h"
25 #include "src/core/lib/security/authorization/authorization_engine.h"
26 
27 namespace grpc_core {
28 
29 using experimental::AuditContext;
30 using experimental::AuditLoggerRegistry;
31 
32 namespace {
33 
34 using Decision = AuthorizationEngine::Decision;
35 
ShouldLog(const Decision & decision,const Rbac::AuditCondition & condition)36 bool ShouldLog(const Decision& decision,
37                const Rbac::AuditCondition& condition) {
38   return condition == Rbac::AuditCondition::kOnDenyAndAllow ||
39          (decision.type == Decision::Type::kAllow &&
40           condition == Rbac::AuditCondition::kOnAllow) ||
41          (decision.type == Decision::Type::kDeny &&
42           condition == Rbac::AuditCondition::kOnDeny);
43 }
44 
45 }  // namespace
46 
GrpcAuthorizationEngine(Rbac policy)47 GrpcAuthorizationEngine::GrpcAuthorizationEngine(Rbac policy)
48     : name_(std::move(policy.name)),
49       action_(policy.action),
50       audit_condition_(policy.audit_condition) {
51   for (auto& sub_policy : policy.policies) {
52     Policy policy;
53     policy.name = sub_policy.first;
54     policy.matcher = std::make_unique<PolicyAuthorizationMatcher>(
55         std::move(sub_policy.second));
56     policies_.push_back(std::move(policy));
57   }
58   for (auto& logger_config : policy.logger_configs) {
59     auto logger =
60         AuditLoggerRegistry::CreateAuditLogger(std::move(logger_config));
61     CHECK(logger != nullptr);
62     audit_loggers_.push_back(std::move(logger));
63   }
64 }
65 
GrpcAuthorizationEngine(GrpcAuthorizationEngine && other)66 GrpcAuthorizationEngine::GrpcAuthorizationEngine(
67     GrpcAuthorizationEngine&& other) noexcept
68     : name_(std::move(other.name_)),
69       action_(other.action_),
70       policies_(std::move(other.policies_)),
71       audit_condition_(other.audit_condition_),
72       audit_loggers_(std::move(other.audit_loggers_)) {}
73 
operator =(GrpcAuthorizationEngine && other)74 GrpcAuthorizationEngine& GrpcAuthorizationEngine::operator=(
75     GrpcAuthorizationEngine&& other) noexcept {
76   name_ = std::move(other.name_);
77   action_ = other.action_;
78   policies_ = std::move(other.policies_);
79   audit_condition_ = other.audit_condition_;
80   audit_loggers_ = std::move(other.audit_loggers_);
81   return *this;
82 }
83 
Evaluate(const EvaluateArgs & args) const84 AuthorizationEngine::Decision GrpcAuthorizationEngine::Evaluate(
85     const EvaluateArgs& args) const {
86   Decision decision;
87   bool matches = false;
88   for (const auto& policy : policies_) {
89     if (policy.matcher->Matches(args)) {
90       matches = true;
91       decision.matching_policy_name = policy.name;
92       break;
93     }
94   }
95   decision.type = (matches == (action_ == Rbac::Action::kAllow))
96                       ? Decision::Type::kAllow
97                       : Decision::Type::kDeny;
98   if (ShouldLog(decision, audit_condition_)) {
99     for (auto& logger : audit_loggers_) {
100       logger->Log(AuditContext(args.GetPath(), args.GetSpiffeId(), name_,
101                                decision.matching_policy_name,
102                                decision.type == Decision::Type::kAllow));
103     }
104   }
105   return decision;
106 }
107 
108 }  // namespace grpc_core
109