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/rbac_policy.h"
18
19 #include "absl/strings/str_format.h"
20 #include "absl/strings/str_join.h"
21
22 namespace grpc_core {
23
24 //
25 // Rbac
26 //
27
Rbac(Rbac::Action action,std::map<std::string,Policy> policies)28 Rbac::Rbac(Rbac::Action action, std::map<std::string, Policy> policies)
29 : action(action), policies(std::move(policies)) {}
30
Rbac(Rbac && other)31 Rbac::Rbac(Rbac&& other) noexcept
32 : action(other.action), policies(std::move(other.policies)) {}
33
operator =(Rbac && other)34 Rbac& Rbac::operator=(Rbac&& other) noexcept {
35 action = other.action;
36 policies = std::move(other.policies);
37 return *this;
38 }
39
ToString() const40 std::string Rbac::ToString() const {
41 std::vector<std::string> contents;
42 contents.push_back(absl::StrFormat(
43 "Rbac action=%s{", action == Rbac::Action::kAllow ? "Allow" : "Deny"));
44 for (const auto& p : policies) {
45 contents.push_back(absl::StrFormat("{\n policy_name=%s\n%s\n}", p.first,
46 p.second.ToString()));
47 }
48 contents.push_back("}");
49 return absl::StrJoin(contents, "\n");
50 }
51
52 //
53 // CidrRange
54 //
55
CidrRange(std::string address_prefix,uint32_t prefix_len)56 Rbac::CidrRange::CidrRange(std::string address_prefix, uint32_t prefix_len)
57 : address_prefix(std::move(address_prefix)), prefix_len(prefix_len) {}
58
CidrRange(Rbac::CidrRange && other)59 Rbac::CidrRange::CidrRange(Rbac::CidrRange&& other) noexcept
60 : address_prefix(std::move(other.address_prefix)),
61 prefix_len(other.prefix_len) {}
62
operator =(Rbac::CidrRange && other)63 Rbac::CidrRange& Rbac::CidrRange::operator=(Rbac::CidrRange&& other) noexcept {
64 address_prefix = std::move(other.address_prefix);
65 prefix_len = other.prefix_len;
66 return *this;
67 }
68
ToString() const69 std::string Rbac::CidrRange::ToString() const {
70 return absl::StrFormat("CidrRange{address_prefix=%s,prefix_len=%d}",
71 address_prefix, prefix_len);
72 }
73
74 //
75 // Permission
76 //
77
Permission(Permission::RuleType type,std::vector<std::unique_ptr<Permission>> permissions,bool not_rule)78 Rbac::Permission::Permission(
79 Permission::RuleType type,
80 std::vector<std::unique_ptr<Permission>> permissions, bool not_rule)
81 : type(type), permissions(std::move(permissions)), not_rule(not_rule) {}
Permission(Permission::RuleType type,bool not_rule)82 Rbac::Permission::Permission(Permission::RuleType type, bool not_rule)
83 : type(type), not_rule(not_rule) {}
Permission(Permission::RuleType type,HeaderMatcher header_matcher,bool not_rule)84 Rbac::Permission::Permission(Permission::RuleType type,
85 HeaderMatcher header_matcher, bool not_rule)
86 : type(type),
87 header_matcher(std::move(header_matcher)),
88 not_rule(not_rule) {}
Permission(Permission::RuleType type,StringMatcher string_matcher,bool not_rule)89 Rbac::Permission::Permission(Permission::RuleType type,
90 StringMatcher string_matcher, bool not_rule)
91 : type(type),
92 string_matcher(std::move(string_matcher)),
93 not_rule(not_rule) {}
Permission(Permission::RuleType type,CidrRange ip,bool not_rule)94 Rbac::Permission::Permission(Permission::RuleType type, CidrRange ip,
95 bool not_rule)
96 : type(type), ip(std::move(ip)), not_rule(not_rule) {}
Permission(Permission::RuleType type,int port,bool not_rule)97 Rbac::Permission::Permission(Permission::RuleType type, int port, bool not_rule)
98 : type(type), port(port), not_rule(not_rule) {}
99
Permission(Rbac::Permission && other)100 Rbac::Permission::Permission(Rbac::Permission&& other) noexcept
101 : type(other.type), not_rule(other.not_rule) {
102 switch (type) {
103 case RuleType::kAnd:
104 case RuleType::kOr:
105 permissions = std::move(other.permissions);
106 break;
107 case RuleType::kAny:
108 break;
109 case RuleType::kHeader:
110 header_matcher = std::move(other.header_matcher);
111 break;
112 case RuleType::kPath:
113 case RuleType::kReqServerName:
114 string_matcher = std::move(other.string_matcher);
115 break;
116 case RuleType::kDestIp:
117 ip = std::move(other.ip);
118 break;
119 default:
120 port = other.port;
121 }
122 }
123
operator =(Rbac::Permission && other)124 Rbac::Permission& Rbac::Permission::operator=(
125 Rbac::Permission&& other) noexcept {
126 type = other.type;
127 not_rule = other.not_rule;
128 switch (type) {
129 case RuleType::kAnd:
130 case RuleType::kOr:
131 permissions = std::move(other.permissions);
132 break;
133 case RuleType::kAny:
134 break;
135 case RuleType::kHeader:
136 header_matcher = std::move(other.header_matcher);
137 break;
138 case RuleType::kPath:
139 case RuleType::kReqServerName:
140 string_matcher = std::move(other.string_matcher);
141 break;
142 case RuleType::kDestIp:
143 ip = std::move(other.ip);
144 break;
145 default:
146 port = other.port;
147 }
148 return *this;
149 }
150
ToString() const151 std::string Rbac::Permission::ToString() const {
152 switch (type) {
153 case RuleType::kAnd: {
154 std::vector<std::string> contents;
155 contents.reserve(permissions.size());
156 for (const auto& permission : permissions) {
157 contents.push_back(permission->ToString());
158 }
159 return absl::StrFormat("%sand=[%s]", not_rule ? "not " : "",
160 absl::StrJoin(contents, ","));
161 }
162 case RuleType::kOr: {
163 std::vector<std::string> contents;
164 contents.reserve(permissions.size());
165 for (const auto& permission : permissions) {
166 contents.push_back(permission->ToString());
167 }
168 return absl::StrFormat("%sor=[%s]", not_rule ? "not " : "",
169 absl::StrJoin(contents, ","));
170 }
171 case RuleType::kAny:
172 return absl::StrFormat("%sany", not_rule ? "not " : "");
173 case RuleType::kHeader:
174 return absl::StrFormat("%sheader=%s", not_rule ? "not " : "",
175 header_matcher.ToString());
176 case RuleType::kPath:
177 return absl::StrFormat("%spath=%s", not_rule ? "not " : "",
178 string_matcher.ToString());
179 case RuleType::kDestIp:
180 return absl::StrFormat("%sdest_ip=%s", not_rule ? "not " : "",
181 ip.ToString());
182 case RuleType::kDestPort:
183 return absl::StrFormat("%sdest_port=%d", not_rule ? "not " : "", port);
184 case RuleType::kReqServerName:
185 return absl::StrFormat("%srequested_server_name=%s",
186 not_rule ? "not " : "", string_matcher.ToString());
187 default:
188 return "";
189 }
190 }
191
192 //
193 // Principal
194 //
195
Principal(Principal::RuleType type,std::vector<std::unique_ptr<Principal>> principals,bool not_rule)196 Rbac::Principal::Principal(Principal::RuleType type,
197 std::vector<std::unique_ptr<Principal>> principals,
198 bool not_rule)
199 : type(type), principals(std::move(principals)), not_rule(not_rule) {}
Principal(Principal::RuleType type,bool not_rule)200 Rbac::Principal::Principal(Principal::RuleType type, bool not_rule)
201 : type(type), not_rule(not_rule) {}
Principal(Principal::RuleType type,StringMatcher string_matcher,bool not_rule)202 Rbac::Principal::Principal(Principal::RuleType type,
203 StringMatcher string_matcher, bool not_rule)
204 : type(type),
205 string_matcher(std::move(string_matcher)),
206 not_rule(not_rule) {}
Principal(Principal::RuleType type,CidrRange ip,bool not_rule)207 Rbac::Principal::Principal(Principal::RuleType type, CidrRange ip,
208 bool not_rule)
209 : type(type), ip(std::move(ip)), not_rule(not_rule) {}
Principal(Principal::RuleType type,HeaderMatcher header_matcher,bool not_rule)210 Rbac::Principal::Principal(Principal::RuleType type,
211 HeaderMatcher header_matcher, bool not_rule)
212 : type(type),
213 header_matcher(std::move(header_matcher)),
214 not_rule(not_rule) {}
215
Principal(Rbac::Principal && other)216 Rbac::Principal::Principal(Rbac::Principal&& other) noexcept
217 : type(other.type), not_rule(other.not_rule) {
218 switch (type) {
219 case RuleType::kAnd:
220 case RuleType::kOr:
221 principals = std::move(other.principals);
222 break;
223 case RuleType::kAny:
224 break;
225 case RuleType::kHeader:
226 header_matcher = std::move(other.header_matcher);
227 break;
228 case RuleType::kPrincipalName:
229 case RuleType::kPath:
230 string_matcher = std::move(other.string_matcher);
231 break;
232 default:
233 ip = std::move(other.ip);
234 }
235 }
236
operator =(Rbac::Principal && other)237 Rbac::Principal& Rbac::Principal::operator=(Rbac::Principal&& other) noexcept {
238 type = other.type;
239 not_rule = other.not_rule;
240 switch (type) {
241 case RuleType::kAnd:
242 case RuleType::kOr:
243 principals = std::move(other.principals);
244 break;
245 case RuleType::kAny:
246 break;
247 case RuleType::kHeader:
248 header_matcher = std::move(other.header_matcher);
249 break;
250 case RuleType::kPrincipalName:
251 case RuleType::kPath:
252 string_matcher = std::move(other.string_matcher);
253 break;
254 default:
255 ip = std::move(other.ip);
256 }
257 return *this;
258 }
259
ToString() const260 std::string Rbac::Principal::ToString() const {
261 switch (type) {
262 case RuleType::kAnd: {
263 std::vector<std::string> contents;
264 contents.reserve(principals.size());
265 for (const auto& principal : principals) {
266 contents.push_back(principal->ToString());
267 }
268 return absl::StrFormat("%sand=[%s]", not_rule ? "not " : "",
269 absl::StrJoin(contents, ","));
270 }
271 case RuleType::kOr: {
272 std::vector<std::string> contents;
273 contents.reserve(principals.size());
274 for (const auto& principal : principals) {
275 contents.push_back(principal->ToString());
276 }
277 return absl::StrFormat("%sor=[%s]", not_rule ? "not " : "",
278 absl::StrJoin(contents, ","));
279 }
280 case RuleType::kAny:
281 return absl::StrFormat("%sany", not_rule ? "not " : "");
282 case RuleType::kPrincipalName:
283 return absl::StrFormat("%sprincipal_name=%s", not_rule ? "not " : "",
284 string_matcher.ToString());
285 case RuleType::kSourceIp:
286 return absl::StrFormat("%ssource_ip=%s", not_rule ? "not " : "",
287 ip.ToString());
288 case RuleType::kDirectRemoteIp:
289 return absl::StrFormat("%sdirect_remote_ip=%s", not_rule ? "not " : "",
290 ip.ToString());
291 case RuleType::kRemoteIp:
292 return absl::StrFormat("%sremote_ip=%s", not_rule ? "not " : "",
293 ip.ToString());
294 case RuleType::kHeader:
295 return absl::StrFormat("%sheader=%s", not_rule ? "not " : "",
296 header_matcher.ToString());
297 case RuleType::kPath:
298 return absl::StrFormat("%spath=%s", not_rule ? "not " : "",
299 string_matcher.ToString());
300 default:
301 return "";
302 }
303 }
304
305 //
306 // Policy
307 //
308
Policy(Permission permissions,Principal principals)309 Rbac::Policy::Policy(Permission permissions, Principal principals)
310 : permissions(std::move(permissions)), principals(std::move(principals)) {}
311
Policy(Rbac::Policy && other)312 Rbac::Policy::Policy(Rbac::Policy&& other) noexcept
313 : permissions(std::move(other.permissions)),
314 principals(std::move(other.principals)) {}
315
operator =(Rbac::Policy && other)316 Rbac::Policy& Rbac::Policy::operator=(Rbac::Policy&& other) noexcept {
317 permissions = std::move(other.permissions);
318 principals = std::move(other.principals);
319 return *this;
320 }
321
ToString() const322 std::string Rbac::Policy::ToString() const {
323 return absl::StrFormat(
324 " Policy {\n Permissions{%s}\n Principals{%s}\n }",
325 permissions.ToString(), principals.ToString());
326 }
327
328 } // namespace grpc_core
329