• 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/rbac_policy.h"
16 
17 #include <grpc/support/port_platform.h>
18 
19 #include <utility>
20 
21 #include "absl/strings/str_format.h"
22 #include "absl/strings/str_join.h"
23 #include "absl/strings/string_view.h"
24 
25 namespace grpc_core {
26 
27 //
28 // Rbac
29 //
30 
Rbac(std::string name,Rbac::Action action,std::map<std::string,Policy> policies)31 Rbac::Rbac(std::string name, Rbac::Action action,
32            std::map<std::string, Policy> policies)
33     : name(std::move(name)),
34       action(action),
35       policies(std::move(policies)),
36       audit_condition(Rbac::AuditCondition::kNone) {}
37 
Rbac(Rbac && other)38 Rbac::Rbac(Rbac&& other) noexcept
39     : name(std::move(other.name)),
40       action(other.action),
41       policies(std::move(other.policies)),
42       audit_condition(other.audit_condition),
43       logger_configs(std::move(other.logger_configs)) {}
44 
operator =(Rbac && other)45 Rbac& Rbac::operator=(Rbac&& other) noexcept {
46   name = std::move(other.name);
47   action = other.action;
48   policies = std::move(other.policies);
49   audit_condition = other.audit_condition;
50   logger_configs = std::move(other.logger_configs);
51   return *this;
52 }
53 
ToString() const54 std::string Rbac::ToString() const {
55   std::vector<std::string> contents;
56   absl::string_view condition_str;
57   switch (audit_condition) {
58     case Rbac::AuditCondition::kNone:
59       condition_str = "None";
60       break;
61     case AuditCondition::kOnDeny:
62       condition_str = "OnDeny";
63       break;
64     case AuditCondition::kOnAllow:
65       condition_str = "OnAllow";
66       break;
67     case AuditCondition::kOnDenyAndAllow:
68       condition_str = "OnDenyAndAllow";
69       break;
70   }
71   contents.push_back(absl::StrFormat(
72       "Rbac name=%s action=%s audit_condition=%s{", name,
73       action == Rbac::Action::kAllow ? "Allow" : "Deny", condition_str));
74   for (const auto& p : policies) {
75     contents.push_back(absl::StrFormat("{\n  policy_name=%s\n%s\n}", p.first,
76                                        p.second.ToString()));
77   }
78   for (const auto& config : logger_configs) {
79     contents.push_back(absl::StrFormat("{\n  audit_logger=%s\n%s\n}",
80                                        config->name(), config->ToString()));
81   }
82   contents.push_back("}");
83   return absl::StrJoin(contents, "\n");
84 }
85 
86 //
87 // CidrRange
88 //
89 
CidrRange(std::string address_prefix,uint32_t prefix_len)90 Rbac::CidrRange::CidrRange(std::string address_prefix, uint32_t prefix_len)
91     : address_prefix(std::move(address_prefix)), prefix_len(prefix_len) {}
92 
CidrRange(Rbac::CidrRange && other)93 Rbac::CidrRange::CidrRange(Rbac::CidrRange&& other) noexcept
94     : address_prefix(std::move(other.address_prefix)),
95       prefix_len(other.prefix_len) {}
96 
operator =(Rbac::CidrRange && other)97 Rbac::CidrRange& Rbac::CidrRange::operator=(Rbac::CidrRange&& other) noexcept {
98   address_prefix = std::move(other.address_prefix);
99   prefix_len = other.prefix_len;
100   return *this;
101 }
102 
ToString() const103 std::string Rbac::CidrRange::ToString() const {
104   return absl::StrFormat("CidrRange{address_prefix=%s,prefix_len=%d}",
105                          address_prefix, prefix_len);
106 }
107 
108 //
109 // Permission
110 //
111 
MakeAndPermission(std::vector<std::unique_ptr<Permission>> permissions)112 Rbac::Permission Rbac::Permission::MakeAndPermission(
113     std::vector<std::unique_ptr<Permission>> permissions) {
114   Permission permission;
115   permission.type = Permission::RuleType::kAnd;
116   permission.permissions = std::move(permissions);
117   return permission;
118 }
119 
MakeOrPermission(std::vector<std::unique_ptr<Permission>> permissions)120 Rbac::Permission Rbac::Permission::MakeOrPermission(
121     std::vector<std::unique_ptr<Permission>> permissions) {
122   Permission permission;
123   permission.type = Permission::RuleType::kOr;
124   permission.permissions = std::move(permissions);
125   return permission;
126 }
127 
MakeNotPermission(Permission permission)128 Rbac::Permission Rbac::Permission::MakeNotPermission(Permission permission) {
129   Permission not_permission;
130   not_permission.type = Permission::RuleType::kNot;
131   not_permission.permissions.push_back(
132       std::make_unique<Rbac::Permission>(std::move(permission)));
133   return not_permission;
134 }
135 
MakeAnyPermission()136 Rbac::Permission Rbac::Permission::MakeAnyPermission() {
137   Permission permission;
138   permission.type = Permission::RuleType::kAny;
139   return permission;
140 }
141 
MakeHeaderPermission(HeaderMatcher header_matcher)142 Rbac::Permission Rbac::Permission::MakeHeaderPermission(
143     HeaderMatcher header_matcher) {
144   Permission permission;
145   permission.type = Permission::RuleType::kHeader;
146   permission.header_matcher = std::move(header_matcher);
147   return permission;
148 }
149 
MakePathPermission(StringMatcher string_matcher)150 Rbac::Permission Rbac::Permission::MakePathPermission(
151     StringMatcher string_matcher) {
152   Permission permission;
153   permission.type = Permission::RuleType::kPath;
154   permission.string_matcher = std::move(string_matcher);
155   return permission;
156 }
157 
MakeDestIpPermission(CidrRange ip)158 Rbac::Permission Rbac::Permission::MakeDestIpPermission(CidrRange ip) {
159   Permission permission;
160   permission.type = Permission::RuleType::kDestIp;
161   permission.ip = std::move(ip);
162   return permission;
163 }
164 
MakeDestPortPermission(int port)165 Rbac::Permission Rbac::Permission::MakeDestPortPermission(int port) {
166   Permission permission;
167   permission.type = Permission::RuleType::kDestPort;
168   permission.port = port;
169   return permission;
170 }
171 
MakeMetadataPermission(bool invert)172 Rbac::Permission Rbac::Permission::MakeMetadataPermission(bool invert) {
173   Permission permission;
174   permission.type = Permission::RuleType::kMetadata;
175   permission.invert = invert;
176   return permission;
177 }
178 
MakeReqServerNamePermission(StringMatcher string_matcher)179 Rbac::Permission Rbac::Permission::MakeReqServerNamePermission(
180     StringMatcher string_matcher) {
181   Permission permission;
182   permission.type = Permission::RuleType::kReqServerName;
183   permission.string_matcher = std::move(string_matcher);
184   return permission;
185 }
186 
Permission(Rbac::Permission && other)187 Rbac::Permission::Permission(Rbac::Permission&& other) noexcept
188     : type(other.type), invert(other.invert) {
189   switch (type) {
190     case RuleType::kAnd:
191     case RuleType::kOr:
192     case RuleType::kNot:
193       permissions = std::move(other.permissions);
194       break;
195     case RuleType::kAny:
196       break;
197     case RuleType::kHeader:
198       header_matcher = std::move(other.header_matcher);
199       break;
200     case RuleType::kPath:
201     case RuleType::kReqServerName:
202       string_matcher = std::move(other.string_matcher);
203       break;
204     case RuleType::kDestIp:
205       ip = std::move(other.ip);
206       break;
207     default:
208       port = other.port;
209   }
210 }
211 
operator =(Rbac::Permission && other)212 Rbac::Permission& Rbac::Permission::operator=(
213     Rbac::Permission&& other) noexcept {
214   type = other.type;
215   invert = other.invert;
216   switch (type) {
217     case RuleType::kAnd:
218     case RuleType::kOr:
219     case RuleType::kNot:
220       permissions = std::move(other.permissions);
221       break;
222     case RuleType::kAny:
223       break;
224     case RuleType::kHeader:
225       header_matcher = std::move(other.header_matcher);
226       break;
227     case RuleType::kPath:
228     case RuleType::kReqServerName:
229       string_matcher = std::move(other.string_matcher);
230       break;
231     case RuleType::kDestIp:
232       ip = std::move(other.ip);
233       break;
234     default:
235       port = other.port;
236   }
237   return *this;
238 }
239 
ToString() const240 std::string Rbac::Permission::ToString() const {
241   switch (type) {
242     case RuleType::kAnd: {
243       std::vector<std::string> contents;
244       contents.reserve(permissions.size());
245       for (const auto& permission : permissions) {
246         contents.push_back(permission->ToString());
247       }
248       return absl::StrFormat("and=[%s]", absl::StrJoin(contents, ","));
249     }
250     case RuleType::kOr: {
251       std::vector<std::string> contents;
252       contents.reserve(permissions.size());
253       for (const auto& permission : permissions) {
254         contents.push_back(permission->ToString());
255       }
256       return absl::StrFormat("or=[%s]", absl::StrJoin(contents, ","));
257     }
258     case RuleType::kNot:
259       return absl::StrFormat("not %s", permissions[0]->ToString());
260     case RuleType::kAny:
261       return "any";
262     case RuleType::kHeader:
263       return absl::StrFormat("header=%s", header_matcher.ToString());
264     case RuleType::kPath:
265       return absl::StrFormat("path=%s", string_matcher.ToString());
266     case RuleType::kDestIp:
267       return absl::StrFormat("dest_ip=%s", ip.ToString());
268     case RuleType::kDestPort:
269       return absl::StrFormat("dest_port=%d", port);
270     case RuleType::kMetadata:
271       return absl::StrFormat("%smetadata", invert ? "invert " : "");
272     case RuleType::kReqServerName:
273       return absl::StrFormat("requested_server_name=%s",
274                              string_matcher.ToString());
275     default:
276       return "";
277   }
278 }
279 
280 //
281 // Principal
282 //
283 
MakeAndPrincipal(std::vector<std::unique_ptr<Principal>> principals)284 Rbac::Principal Rbac::Principal::MakeAndPrincipal(
285     std::vector<std::unique_ptr<Principal>> principals) {
286   Principal principal;
287   principal.type = Principal::RuleType::kAnd;
288   principal.principals = std::move(principals);
289   return principal;
290 }
291 
MakeOrPrincipal(std::vector<std::unique_ptr<Principal>> principals)292 Rbac::Principal Rbac::Principal::MakeOrPrincipal(
293     std::vector<std::unique_ptr<Principal>> principals) {
294   Principal principal;
295   principal.type = Principal::RuleType::kOr;
296   principal.principals = std::move(principals);
297   return principal;
298 }
299 
MakeNotPrincipal(Principal principal)300 Rbac::Principal Rbac::Principal::MakeNotPrincipal(Principal principal) {
301   Principal not_principal;
302   not_principal.type = Principal::RuleType::kNot;
303   not_principal.principals.push_back(
304       std::make_unique<Rbac::Principal>(std::move(principal)));
305   return not_principal;
306 }
307 
MakeAnyPrincipal()308 Rbac::Principal Rbac::Principal::MakeAnyPrincipal() {
309   Principal principal;
310   principal.type = Principal::RuleType::kAny;
311   return principal;
312 }
313 
MakeAuthenticatedPrincipal(absl::optional<StringMatcher> string_matcher)314 Rbac::Principal Rbac::Principal::MakeAuthenticatedPrincipal(
315     absl::optional<StringMatcher> string_matcher) {
316   Principal principal;
317   principal.type = Principal::RuleType::kPrincipalName;
318   principal.string_matcher = std::move(string_matcher);
319   return principal;
320 }
321 
MakeSourceIpPrincipal(CidrRange ip)322 Rbac::Principal Rbac::Principal::MakeSourceIpPrincipal(CidrRange ip) {
323   Principal principal;
324   principal.type = Principal::RuleType::kSourceIp;
325   principal.ip = std::move(ip);
326   return principal;
327 }
328 
MakeDirectRemoteIpPrincipal(CidrRange ip)329 Rbac::Principal Rbac::Principal::MakeDirectRemoteIpPrincipal(CidrRange ip) {
330   Principal principal;
331   principal.type = Principal::RuleType::kDirectRemoteIp;
332   principal.ip = std::move(ip);
333   return principal;
334 }
335 
MakeRemoteIpPrincipal(CidrRange ip)336 Rbac::Principal Rbac::Principal::MakeRemoteIpPrincipal(CidrRange ip) {
337   Principal principal;
338   principal.type = Principal::RuleType::kRemoteIp;
339   principal.ip = std::move(ip);
340   return principal;
341 }
342 
MakeHeaderPrincipal(HeaderMatcher header_matcher)343 Rbac::Principal Rbac::Principal::MakeHeaderPrincipal(
344     HeaderMatcher header_matcher) {
345   Principal principal;
346   principal.type = Principal::RuleType::kHeader;
347   principal.header_matcher = std::move(header_matcher);
348   return principal;
349 }
350 
MakePathPrincipal(StringMatcher string_matcher)351 Rbac::Principal Rbac::Principal::MakePathPrincipal(
352     StringMatcher string_matcher) {
353   Principal principal;
354   principal.type = Principal::RuleType::kPath;
355   principal.string_matcher = std::move(string_matcher);
356   return principal;
357 }
358 
MakeMetadataPrincipal(bool invert)359 Rbac::Principal Rbac::Principal::MakeMetadataPrincipal(bool invert) {
360   Principal principal;
361   principal.type = Principal::RuleType::kMetadata;
362   principal.invert = invert;
363   return principal;
364 }
365 
Principal(Rbac::Principal && other)366 Rbac::Principal::Principal(Rbac::Principal&& other) noexcept
367     : type(other.type), invert(other.invert) {
368   switch (type) {
369     case RuleType::kAnd:
370     case RuleType::kOr:
371     case RuleType::kNot:
372       principals = std::move(other.principals);
373       break;
374     case RuleType::kAny:
375       break;
376     case RuleType::kHeader:
377       header_matcher = std::move(other.header_matcher);
378       break;
379     case RuleType::kPrincipalName:
380     case RuleType::kPath:
381       string_matcher = std::move(other.string_matcher);
382       break;
383     default:
384       ip = std::move(other.ip);
385   }
386 }
387 
operator =(Rbac::Principal && other)388 Rbac::Principal& Rbac::Principal::operator=(Rbac::Principal&& other) noexcept {
389   type = other.type;
390   invert = other.invert;
391   switch (type) {
392     case RuleType::kAnd:
393     case RuleType::kOr:
394     case RuleType::kNot:
395       principals = std::move(other.principals);
396       break;
397     case RuleType::kAny:
398       break;
399     case RuleType::kHeader:
400       header_matcher = std::move(other.header_matcher);
401       break;
402     case RuleType::kPrincipalName:
403     case RuleType::kPath:
404       string_matcher = std::move(other.string_matcher);
405       break;
406     default:
407       ip = std::move(other.ip);
408   }
409   return *this;
410 }
411 
ToString() const412 std::string Rbac::Principal::ToString() const {
413   switch (type) {
414     case RuleType::kAnd: {
415       std::vector<std::string> contents;
416       contents.reserve(principals.size());
417       for (const auto& principal : principals) {
418         contents.push_back(principal->ToString());
419       }
420       return absl::StrFormat("and=[%s]", absl::StrJoin(contents, ","));
421     }
422     case RuleType::kOr: {
423       std::vector<std::string> contents;
424       contents.reserve(principals.size());
425       for (const auto& principal : principals) {
426         contents.push_back(principal->ToString());
427       }
428       return absl::StrFormat("or=[%s]", absl::StrJoin(contents, ","));
429     }
430     case RuleType::kNot:
431       return absl::StrFormat("not %s", principals[0]->ToString());
432     case RuleType::kAny:
433       return "any";
434     case RuleType::kPrincipalName:
435       return absl::StrFormat("principal_name=%s", string_matcher->ToString());
436     case RuleType::kSourceIp:
437       return absl::StrFormat("source_ip=%s", ip.ToString());
438     case RuleType::kDirectRemoteIp:
439       return absl::StrFormat("direct_remote_ip=%s", ip.ToString());
440     case RuleType::kRemoteIp:
441       return absl::StrFormat("remote_ip=%s", ip.ToString());
442     case RuleType::kHeader:
443       return absl::StrFormat("header=%s", header_matcher.ToString());
444     case RuleType::kPath:
445       return absl::StrFormat("path=%s", string_matcher->ToString());
446     case RuleType::kMetadata:
447       return absl::StrFormat("%smetadata", invert ? "invert " : "");
448     default:
449       return "";
450   }
451 }
452 
453 //
454 // Policy
455 //
456 
Policy(Permission permissions,Principal principals)457 Rbac::Policy::Policy(Permission permissions, Principal principals)
458     : permissions(std::move(permissions)), principals(std::move(principals)) {}
459 
Policy(Rbac::Policy && other)460 Rbac::Policy::Policy(Rbac::Policy&& other) noexcept
461     : permissions(std::move(other.permissions)),
462       principals(std::move(other.principals)) {}
463 
operator =(Rbac::Policy && other)464 Rbac::Policy& Rbac::Policy::operator=(Rbac::Policy&& other) noexcept {
465   permissions = std::move(other.permissions);
466   principals = std::move(other.principals);
467   return *this;
468 }
469 
ToString() const470 std::string Rbac::Policy::ToString() const {
471   return absl::StrFormat(
472       "  Policy  {\n    Permissions{%s}\n    Principals{%s}\n  }",
473       permissions.ToString(), principals.ToString());
474 }
475 
476 }  // namespace grpc_core
477