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 <grpc/support/port_platform.h>
16
17 #include "src/core/lib/security/authorization/matchers.h"
18
19 namespace grpc_core {
20
21 namespace {
22
AuthenticatedMatchesHelper(const EvaluateArgs & args,const StringMatcher & matcher)23 bool AuthenticatedMatchesHelper(const EvaluateArgs& args,
24 const StringMatcher& matcher) {
25 if (args.GetTransportSecurityType() != GRPC_SSL_TRANSPORT_SECURITY_TYPE) {
26 // Connection is not authenticated.
27 return false;
28 }
29 if (matcher.string_matcher().empty()) {
30 // Allows any authenticated user.
31 return true;
32 }
33 absl::string_view spiffe_id = args.GetSpiffeId();
34 if (!spiffe_id.empty()) {
35 return matcher.Match(spiffe_id);
36 }
37 // TODO(ashithasantosh): Check principal matches DNS SAN, followed by Subject
38 // field from certificate. This requires updating tsi_peer to expose these
39 // fields.
40 return false;
41 }
42
43 } // namespace
44
Create(Rbac::Permission permission)45 std::unique_ptr<AuthorizationMatcher> AuthorizationMatcher::Create(
46 Rbac::Permission permission) {
47 switch (permission.type) {
48 case Rbac::Permission::RuleType::kAnd:
49 return absl::make_unique<AndAuthorizationMatcher>(
50 std::move(permission.permissions), permission.not_rule);
51 case Rbac::Permission::RuleType::kOr:
52 return absl::make_unique<OrAuthorizationMatcher>(
53 std::move(permission.permissions), permission.not_rule);
54 case Rbac::Permission::RuleType::kAny:
55 return absl::make_unique<AlwaysAuthorizationMatcher>(permission.not_rule);
56 case Rbac::Permission::RuleType::kHeader:
57 return absl::make_unique<HeaderAuthorizationMatcher>(
58 std::move(permission.header_matcher), permission.not_rule);
59 case Rbac::Permission::RuleType::kPath:
60 return absl::make_unique<PathAuthorizationMatcher>(
61 std::move(permission.string_matcher), permission.not_rule);
62 case Rbac::Permission::RuleType::kDestIp:
63 return absl::make_unique<IpAuthorizationMatcher>(std::move(permission.ip),
64 permission.not_rule);
65 case Rbac::Permission::RuleType::kDestPort:
66 return absl::make_unique<PortAuthorizationMatcher>(permission.port,
67 permission.not_rule);
68 case Rbac::Permission::RuleType::kReqServerName:
69 return absl::make_unique<ReqServerNameAuthorizationMatcher>(
70 std::move(permission.string_matcher), permission.not_rule);
71 }
72 return nullptr;
73 }
74
Create(Rbac::Principal principal)75 std::unique_ptr<AuthorizationMatcher> AuthorizationMatcher::Create(
76 Rbac::Principal principal) {
77 switch (principal.type) {
78 case Rbac::Principal::RuleType::kAnd:
79 return absl::make_unique<AndAuthorizationMatcher>(
80 std::move(principal.principals), principal.not_rule);
81 case Rbac::Principal::RuleType::kOr:
82 return absl::make_unique<OrAuthorizationMatcher>(
83 std::move(principal.principals), principal.not_rule);
84 case Rbac::Principal::RuleType::kAny:
85 return absl::make_unique<AlwaysAuthorizationMatcher>(principal.not_rule);
86 case Rbac::Principal::RuleType::kPrincipalName:
87 return absl::make_unique<AuthenticatedAuthorizationMatcher>(
88 std::move(principal.string_matcher), principal.not_rule);
89 case Rbac::Principal::RuleType::kSourceIp:
90 case Rbac::Principal::RuleType::kDirectRemoteIp:
91 case Rbac::Principal::RuleType::kRemoteIp:
92 return absl::make_unique<IpAuthorizationMatcher>(std::move(principal.ip),
93 principal.not_rule);
94 case Rbac::Principal::RuleType::kHeader:
95 return absl::make_unique<HeaderAuthorizationMatcher>(
96 std::move(principal.header_matcher), principal.not_rule);
97 case Rbac::Principal::RuleType::kPath:
98 return absl::make_unique<PathAuthorizationMatcher>(
99 std::move(principal.string_matcher), principal.not_rule);
100 }
101 return nullptr;
102 }
103
AndAuthorizationMatcher(std::vector<std::unique_ptr<Rbac::Permission>> rules,bool not_rule)104 AndAuthorizationMatcher::AndAuthorizationMatcher(
105 std::vector<std::unique_ptr<Rbac::Permission>> rules, bool not_rule)
106 : not_rule_(not_rule) {
107 for (auto& rule : rules) {
108 matchers_.push_back(AuthorizationMatcher::Create(std::move(*rule)));
109 }
110 }
111
AndAuthorizationMatcher(std::vector<std::unique_ptr<Rbac::Principal>> ids,bool not_rule)112 AndAuthorizationMatcher::AndAuthorizationMatcher(
113 std::vector<std::unique_ptr<Rbac::Principal>> ids, bool not_rule)
114 : not_rule_(not_rule) {
115 for (const auto& id : ids) {
116 matchers_.push_back(AuthorizationMatcher::Create(std::move(*id)));
117 }
118 }
119
Matches(const EvaluateArgs & args) const120 bool AndAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
121 bool matches = true;
122 for (const auto& matcher : matchers_) {
123 if (!matcher->Matches(args)) {
124 matches = false;
125 break;
126 }
127 }
128 return matches != not_rule_;
129 }
130
OrAuthorizationMatcher(std::vector<std::unique_ptr<Rbac::Permission>> rules,bool not_rule)131 OrAuthorizationMatcher::OrAuthorizationMatcher(
132 std::vector<std::unique_ptr<Rbac::Permission>> rules, bool not_rule)
133 : not_rule_(not_rule) {
134 for (const auto& rule : rules) {
135 matchers_.push_back(AuthorizationMatcher::Create(std::move(*rule)));
136 }
137 }
138
OrAuthorizationMatcher(std::vector<std::unique_ptr<Rbac::Principal>> ids,bool not_rule)139 OrAuthorizationMatcher::OrAuthorizationMatcher(
140 std::vector<std::unique_ptr<Rbac::Principal>> ids, bool not_rule)
141 : not_rule_(not_rule) {
142 for (const auto& id : ids) {
143 matchers_.push_back(AuthorizationMatcher::Create(std::move(*id)));
144 }
145 }
146
Matches(const EvaluateArgs & args) const147 bool OrAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
148 bool matches = false;
149 for (const auto& matcher : matchers_) {
150 if (matcher->Matches(args)) {
151 matches = true;
152 break;
153 }
154 }
155 return matches != not_rule_;
156 }
157
Matches(const EvaluateArgs & args) const158 bool HeaderAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
159 std::string concatenated_value;
160 bool matches =
161 matcher_.Match(args.GetHeaderValue(matcher_.name(), &concatenated_value));
162 return matches != not_rule_;
163 }
164
165 // TODO(ashithasantosh): Implement IpAuthorizationMatcher::Matches.
Matches(const EvaluateArgs &) const166 bool IpAuthorizationMatcher::Matches(const EvaluateArgs&) const {
167 bool matches = false;
168 return matches != not_rule_;
169 }
170
Matches(const EvaluateArgs & args) const171 bool PortAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
172 bool matches = (port_ == args.GetLocalPort());
173 return matches != not_rule_;
174 }
175
Matches(const EvaluateArgs & args) const176 bool AuthenticatedAuthorizationMatcher::Matches(
177 const EvaluateArgs& args) const {
178 bool matches = AuthenticatedMatchesHelper(args, matcher_);
179 return matches != not_rule_;
180 }
181
Matches(const EvaluateArgs &) const182 bool ReqServerNameAuthorizationMatcher::Matches(const EvaluateArgs&) const {
183 // Currently we do not support matching rules containing
184 // "requested_server_name".
185 bool matches = false;
186 return matches != not_rule_;
187 }
188
Matches(const EvaluateArgs & args) const189 bool PathAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
190 bool matches = false;
191 absl::string_view path = args.GetPath();
192 if (!path.empty()) {
193 matches = matcher_.Match(path);
194 }
195 return matches != not_rule_;
196 }
197
Matches(const EvaluateArgs & args) const198 bool PolicyAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
199 return permissions_->Matches(args) && principals_->Matches(args);
200 }
201
202 } // namespace grpc_core
203