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