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