• 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 <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