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_translator.h"
16
17 #include <memory>
18
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21
22 #include "absl/strings/match.h"
23 #include "absl/strings/string_view.h"
24
25 #include <grpc/grpc_audit_logging.h>
26
27 #include "src/core/lib/gprpp/crash.h"
28 #include "src/core/lib/json/json.h"
29 #include "src/core/lib/json/json_writer.h"
30 #include "src/core/lib/security/authorization/audit_logging.h"
31 #include "test/core/util/test_config.h"
32
33 namespace grpc_core {
34
35 namespace {
36
37 constexpr absl::string_view kLoggerName = "test_logger";
38
39 using experimental::AuditLogger;
40 using experimental::AuditLoggerFactory;
41 using experimental::AuditLoggerRegistry;
42 using experimental::RegisterAuditLoggerFactory;
43
44 MATCHER_P3(EqualsPrincipalName, expected_matcher_type, expected_matcher_value,
45 is_regex, "") {
46 return arg->type == Rbac::Principal::RuleType::kPrincipalName &&
47 arg->string_matcher.value().type() == expected_matcher_type &&
48 is_regex
49 ? arg->string_matcher.value().regex_matcher()->pattern() ==
50 expected_matcher_value
51 : arg->string_matcher.value().string_matcher() ==
52 expected_matcher_value;
53 }
54
55 MATCHER_P3(EqualsPath, expected_matcher_type, expected_matcher_value, is_regex,
56 "") {
57 return arg->type == Rbac::Permission::RuleType::kPath &&
58 arg->string_matcher.type() == expected_matcher_type && is_regex
59 ? arg->string_matcher.regex_matcher()->pattern() ==
60 expected_matcher_value
61 : arg->string_matcher.string_matcher() == expected_matcher_value;
62 }
63
64 MATCHER_P4(EqualsHeader, expected_name, expected_matcher_type,
65 expected_matcher_value, is_regex, "") {
66 return arg->type == Rbac::Permission::RuleType::kHeader &&
67 arg->header_matcher.name() == expected_name &&
68 arg->header_matcher.type() == expected_matcher_type && is_regex
69 ? arg->header_matcher.regex_matcher()->pattern() ==
70 expected_matcher_value
71 : arg->header_matcher.string_matcher() == expected_matcher_value;
72 }
73
74 class TestAuditLoggerFactory : public AuditLoggerFactory {
75 public:
76 class TestAuditLoggerConfig : public AuditLoggerFactory::Config {
77 public:
TestAuditLoggerConfig(std::string config_dump)78 explicit TestAuditLoggerConfig(std::string config_dump)
79 : config_dump_(std::move(config_dump)) {}
name() const80 absl::string_view name() const override { return kLoggerName; }
ToString() const81 std::string ToString() const override { return config_dump_; }
82
83 private:
84 std::string config_dump_;
85 };
name() const86 absl::string_view name() const override { return kLoggerName; }
87 absl::StatusOr<std::unique_ptr<AuditLoggerFactory::Config>>
ParseAuditLoggerConfig(const Json & json)88 ParseAuditLoggerConfig(const Json& json) override {
89 // Config with a field "bad" will be considered invalid.
90 if (json.object().find("bad") != json.object().end()) {
91 return absl::InvalidArgumentError("bad logger config.");
92 }
93 return std::make_unique<TestAuditLoggerConfig>(JsonDump(json));
94 }
CreateAuditLogger(std::unique_ptr<AuditLoggerFactory::Config>)95 std::unique_ptr<AuditLogger> CreateAuditLogger(
96 std::unique_ptr<AuditLoggerFactory::Config>) override {
97 // This test target should never need to create a logger.
98 Crash("unreachable");
99 return nullptr;
100 }
101 };
102
103 class GenerateRbacPoliciesTest : public ::testing::Test {
104 protected:
SetUp()105 void SetUp() override {
106 RegisterAuditLoggerFactory(std::make_unique<TestAuditLoggerFactory>());
107 }
108
TearDown()109 void TearDown() override { AuditLoggerRegistry::TestOnlyResetRegistry(); }
110 };
111
112 } // namespace
113
TEST_F(GenerateRbacPoliciesTest,InvalidPolicy)114 TEST_F(GenerateRbacPoliciesTest, InvalidPolicy) {
115 const char* authz_policy =
116 "{"
117 " \"name\": \"authz-policy\",,"
118 "}";
119 auto rbac_policies = GenerateRbacPolicies(authz_policy);
120 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
121 EXPECT_THAT(
122 std::string(rbac_policies.status().message()),
123 ::testing::StartsWith("Failed to parse gRPC authorization policy."));
124 }
125
TEST_F(GenerateRbacPoliciesTest,MissingAuthorizationPolicyName)126 TEST_F(GenerateRbacPoliciesTest, MissingAuthorizationPolicyName) {
127 const char* authz_policy = "{}";
128 auto rbac_policies = GenerateRbacPolicies(authz_policy);
129 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
130 EXPECT_EQ(rbac_policies.status().message(), "\"name\" field is not present.");
131 }
132
TEST_F(GenerateRbacPoliciesTest,IncorrectAuthorizationPolicyNameType)133 TEST_F(GenerateRbacPoliciesTest, IncorrectAuthorizationPolicyNameType) {
134 const char* authz_policy =
135 "{"
136 " \"name\": [\"authz_policy\"]"
137 "}";
138 auto rbac_policies = GenerateRbacPolicies(authz_policy);
139 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
140 EXPECT_EQ(rbac_policies.status().message(), "\"name\" is not a string.");
141 }
142
TEST_F(GenerateRbacPoliciesTest,MissingAllowRules)143 TEST_F(GenerateRbacPoliciesTest, MissingAllowRules) {
144 const char* authz_policy =
145 "{"
146 " \"name\": \"authz_policy\""
147 "}";
148 auto rbac_policies = GenerateRbacPolicies(authz_policy);
149 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
150 EXPECT_EQ(rbac_policies.status().message(),
151 "\"allow_rules\" is not present.");
152 }
153
TEST_F(GenerateRbacPoliciesTest,MissingDenyRules)154 TEST_F(GenerateRbacPoliciesTest, MissingDenyRules) {
155 const char* authz_policy =
156 "{"
157 " \"name\": \"authz\","
158 " \"allow_rules\": ["
159 " {"
160 " \"name\": \"allow_policy\""
161 " }"
162 " ]"
163 "}";
164 auto rbac_policies = GenerateRbacPolicies(authz_policy);
165 ASSERT_TRUE(rbac_policies.ok());
166 EXPECT_EQ(rbac_policies->allow_policy.name, "authz");
167 EXPECT_FALSE(rbac_policies->deny_policy.has_value());
168 }
169
TEST_F(GenerateRbacPoliciesTest,IncorrectAllowRulesType)170 TEST_F(GenerateRbacPoliciesTest, IncorrectAllowRulesType) {
171 const char* authz_policy =
172 "{"
173 " \"name\": \"authz\","
174 " \"allow_rules\": {}"
175 "}";
176 auto rbac_policies = GenerateRbacPolicies(authz_policy);
177 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
178 EXPECT_EQ(rbac_policies.status().message(),
179 "\"allow_rules\" is not an array.");
180 }
181
TEST_F(GenerateRbacPoliciesTest,IncorrectDenyRulesType)182 TEST_F(GenerateRbacPoliciesTest, IncorrectDenyRulesType) {
183 const char* authz_policy =
184 "{"
185 " \"name\": \"authz\","
186 " \"deny_rules\": 123"
187 "}";
188 auto rbac_policies = GenerateRbacPolicies(authz_policy);
189 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
190 EXPECT_EQ(rbac_policies.status().message(),
191 "\"deny_rules\" is not an array.");
192 }
193
TEST_F(GenerateRbacPoliciesTest,IncorrectRuleType)194 TEST_F(GenerateRbacPoliciesTest, IncorrectRuleType) {
195 const char* authz_policy =
196 "{"
197 " \"name\": \"authz\","
198 " \"allow_rules\": [\"rule-a\"]"
199 "}";
200 auto rbac_policies = GenerateRbacPolicies(authz_policy);
201 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
202 EXPECT_EQ(rbac_policies.status().message(),
203 "allow_rules 0: is not an object.");
204 }
205
TEST_F(GenerateRbacPoliciesTest,EmptyRuleArray)206 TEST_F(GenerateRbacPoliciesTest, EmptyRuleArray) {
207 const char* authz_policy =
208 "{"
209 " \"name\": \"authz\","
210 " \"allow_rules\": []"
211 "}";
212 auto rbac_policies = GenerateRbacPolicies(authz_policy);
213 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
214 EXPECT_EQ(rbac_policies.status().message(), "allow_rules is empty.");
215 }
216
TEST_F(GenerateRbacPoliciesTest,MissingRuleNameField)217 TEST_F(GenerateRbacPoliciesTest, MissingRuleNameField) {
218 const char* authz_policy =
219 "{"
220 " \"name\": \"authz\","
221 " \"allow_rules\": [{}]"
222 "}";
223 auto rbac_policies = GenerateRbacPolicies(authz_policy);
224 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
225 EXPECT_EQ(rbac_policies.status().message(),
226 "allow_rules 0: \"name\" is not present.");
227 }
228
TEST_F(GenerateRbacPoliciesTest,IncorrectRuleNameType)229 TEST_F(GenerateRbacPoliciesTest, IncorrectRuleNameType) {
230 const char* authz_policy =
231 "{"
232 " \"name\": \"authz\","
233 " \"allow_rules\": ["
234 " {"
235 " \"name\": 123"
236 " }"
237 " ]"
238 "}";
239 auto rbac_policies = GenerateRbacPolicies(authz_policy);
240 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
241 EXPECT_EQ(rbac_policies.status().message(),
242 "allow_rules 0: \"name\" is not a string.");
243 }
244
TEST_F(GenerateRbacPoliciesTest,MissingSourceAndRequest)245 TEST_F(GenerateRbacPoliciesTest, MissingSourceAndRequest) {
246 const char* authz_policy =
247 "{"
248 " \"name\": \"authz\","
249 " \"allow_rules\": ["
250 " {"
251 " \"name\": \"allow_policy\""
252 " }"
253 " ]"
254 "}";
255 auto rbacs = GenerateRbacPolicies(authz_policy);
256 ASSERT_TRUE(rbacs.ok());
257 EXPECT_EQ(rbacs->allow_policy.name, "authz");
258 EXPECT_EQ(rbacs->allow_policy.action, Rbac::Action::kAllow);
259 EXPECT_THAT(
260 rbacs->allow_policy.policies,
261 ::testing::ElementsAre(::testing::Pair(
262 "allow_policy",
263 ::testing::AllOf(
264 ::testing::Field(
265 &Rbac::Policy::permissions,
266 ::testing::Field(&Rbac::Permission::type,
267 Rbac::Permission::RuleType::kAny)),
268 ::testing::Field(
269 &Rbac::Policy::principals,
270 ::testing::Field(&Rbac::Principal::type,
271 Rbac::Principal::RuleType::kAny))))));
272 }
273
TEST_F(GenerateRbacPoliciesTest,EmptySourceAndRequest)274 TEST_F(GenerateRbacPoliciesTest, EmptySourceAndRequest) {
275 const char* authz_policy =
276 "{"
277 " \"name\": \"authz\","
278 " \"allow_rules\": ["
279 " {"
280 " \"name\": \"allow_policy\","
281 " \"source\": {},"
282 " \"request\": {}"
283 " }"
284 " ]"
285 "}";
286 auto rbacs = GenerateRbacPolicies(authz_policy);
287 ASSERT_TRUE(rbacs.ok());
288 EXPECT_EQ(rbacs->allow_policy.name, "authz");
289 EXPECT_EQ(rbacs->allow_policy.action, Rbac::Action::kAllow);
290 EXPECT_THAT(
291 rbacs->allow_policy.policies,
292 ::testing::ElementsAre(::testing::Pair(
293 "allow_policy",
294 ::testing::AllOf(
295 ::testing::Field(
296 &Rbac::Policy::permissions,
297 ::testing::Field(&Rbac::Permission::type,
298 Rbac::Permission::RuleType::kAny)),
299 ::testing::Field(
300 &Rbac::Policy::principals,
301 ::testing::Field(&Rbac::Principal::type,
302 Rbac::Principal::RuleType::kAny))))));
303 }
304
TEST_F(GenerateRbacPoliciesTest,IncorrectSourceType)305 TEST_F(GenerateRbacPoliciesTest, IncorrectSourceType) {
306 const char* authz_policy =
307 "{"
308 " \"name\": \"authz\","
309 " \"allow_rules\": ["
310 " {"
311 " \"name\": \"allow_policy\","
312 " \"source\": 111"
313 " }"
314 " ]"
315 "}";
316 auto rbac_policies = GenerateRbacPolicies(authz_policy);
317 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
318 EXPECT_EQ(rbac_policies.status().message(),
319 "allow_rules 0: \"source\" is not an object.");
320 }
321
TEST_F(GenerateRbacPoliciesTest,IncorrectPrincipalsType)322 TEST_F(GenerateRbacPoliciesTest, IncorrectPrincipalsType) {
323 const char* authz_policy =
324 "{"
325 " \"name\": \"authz\","
326 " \"allow_rules\": ["
327 " {"
328 " \"name\": \"allow_policy\","
329 " \"source\": {"
330 " \"principals\": ["
331 " \"*\","
332 " 123"
333 " ]"
334 " }"
335 " }"
336 " ]"
337 "}";
338 auto rbac_policies = GenerateRbacPolicies(authz_policy);
339 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
340 EXPECT_EQ(rbac_policies.status().message(),
341 "allow_rules 0: \"principals\" 1: is not a string.");
342 }
343
TEST_F(GenerateRbacPoliciesTest,ParseSourceSuccess)344 TEST_F(GenerateRbacPoliciesTest, ParseSourceSuccess) {
345 const char* authz_policy =
346 "{"
347 " \"name\": \"authz\","
348 " \"allow_rules\": ["
349 " {"
350 " \"name\": \"allow_policy\","
351 " \"source\": {"
352 " \"principals\": ["
353 " \"spiffe://foo.abc\","
354 " \"spiffe://bar*\","
355 " \"*baz\","
356 " \"spiffe://abc.*.com\""
357 " ]"
358 " }"
359 " }"
360 " ],"
361 " \"deny_rules\": ["
362 " {"
363 " \"name\": \"deny_policy\","
364 " \"source\": {"
365 " \"principals\": ["
366 " \"*\""
367 " ]"
368 " }"
369 " }"
370 " ]"
371 "}";
372 auto rbacs = GenerateRbacPolicies(authz_policy);
373 ASSERT_TRUE(rbacs.ok());
374 EXPECT_EQ(rbacs->allow_policy.name, "authz");
375 EXPECT_EQ(rbacs->deny_policy->name, "authz");
376 EXPECT_EQ(rbacs->allow_policy.action, Rbac::Action::kAllow);
377 EXPECT_THAT(rbacs->allow_policy.policies,
378 ::testing::ElementsAre(::testing::Pair(
379 "allow_policy",
380 ::testing::AllOf(
381 ::testing::Field(
382 &Rbac::Policy::permissions,
383 ::testing::Field(&Rbac::Permission::type,
384 Rbac::Permission::RuleType::kAny)),
385 ::testing::Field(
386 &Rbac::Policy::principals,
387 ::testing::AllOf(
388 ::testing::Field(&Rbac::Principal::type,
389 Rbac::Principal::RuleType::kAnd),
390 ::testing::Field(
391 &Rbac::Principal::principals,
392 ::testing::ElementsAre(::testing::AllOf(
393 ::testing::Pointee(::testing::Field(
394 &Rbac::Principal::type,
395 Rbac::Principal::RuleType::kOr)),
396 ::testing::Pointee(::testing::Field(
397 &Rbac::Principal::principals,
398 ::testing::ElementsAre(
399 EqualsPrincipalName(
400 StringMatcher::Type::kExact,
401 "spiffe://foo.abc", false),
402 EqualsPrincipalName(
403 StringMatcher::Type::kPrefix,
404 "spiffe://bar", false),
405 EqualsPrincipalName(
406 StringMatcher::Type::kSuffix,
407 "baz", false),
408 EqualsPrincipalName(
409 StringMatcher::Type::kExact,
410 "spiffe://abc.*.com",
411 false)))))))))))));
412 ASSERT_TRUE(rbacs->deny_policy.has_value());
413 EXPECT_EQ(rbacs->deny_policy->action, Rbac::Action::kDeny);
414 EXPECT_THAT(
415 rbacs->deny_policy->policies,
416 ::testing::ElementsAre(::testing::Pair(
417 "deny_policy",
418 ::testing::AllOf(
419 ::testing::Field(
420 &Rbac::Policy::permissions,
421 ::testing::Field(&Rbac::Permission::type,
422 Rbac::Permission::RuleType::kAny)),
423 ::testing::Field(
424 &Rbac::Policy::principals,
425 ::testing::AllOf(
426 ::testing::Field(&Rbac::Principal::type,
427 Rbac::Principal::RuleType::kAnd),
428 ::testing::Field(
429 &Rbac::Principal::principals,
430 ::testing::ElementsAre(::testing::AllOf(
431 ::testing::Pointee(::testing::Field(
432 &Rbac::Principal::type,
433 Rbac::Principal::RuleType::kOr)),
434 ::testing::Pointee(::testing::Field(
435 &Rbac::Principal::principals,
436 ::testing::ElementsAre(EqualsPrincipalName(
437 StringMatcher::Type::kSafeRegex, ".+",
438 true)))))))))))));
439 }
440
TEST_F(GenerateRbacPoliciesTest,IncorrectRequestType)441 TEST_F(GenerateRbacPoliciesTest, IncorrectRequestType) {
442 const char* authz_policy =
443 "{"
444 " \"name\": \"authz\","
445 " \"deny_rules\": ["
446 " {"
447 " \"name\": \"deny_policy\","
448 " \"request\": 111"
449 " }"
450 " ]"
451 "}";
452 auto rbac_policies = GenerateRbacPolicies(authz_policy);
453 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
454 EXPECT_EQ(rbac_policies.status().message(),
455 "deny_rules 0: \"request\" is not an object.");
456 }
457
TEST_F(GenerateRbacPoliciesTest,IncorrectPathType)458 TEST_F(GenerateRbacPoliciesTest, IncorrectPathType) {
459 const char* authz_policy =
460 "{"
461 " \"name\": \"authz\","
462 " \"deny_rules\": ["
463 " {"
464 " \"name\": \"allow_policy\","
465 " \"request\": {"
466 " \"paths\": ["
467 " \"path-a\","
468 " 123"
469 " ]"
470 " }"
471 " }"
472 " ]"
473 "}";
474 auto rbac_policies = GenerateRbacPolicies(authz_policy);
475 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
476 EXPECT_EQ(rbac_policies.status().message(),
477 "deny_rules 0: \"paths\" 1: is not a string.");
478 }
479
TEST_F(GenerateRbacPoliciesTest,ParseRequestPathsSuccess)480 TEST_F(GenerateRbacPoliciesTest, ParseRequestPathsSuccess) {
481 const char* authz_policy =
482 "{"
483 " \"name\": \"authz\","
484 " \"allow_rules\": ["
485 " {"
486 " \"name\": \"allow_policy\","
487 " \"request\": {"
488 " \"paths\": ["
489 " \"*\""
490 " ]"
491 " }"
492 " }"
493 " ],"
494 " \"deny_rules\": ["
495 " {"
496 " \"name\": \"deny_policy\","
497 " \"request\": {"
498 " \"paths\": ["
499 " \"path-foo\","
500 " \"path-bar*\","
501 " \"*baz\""
502 " ]"
503 " }"
504 " }"
505 " ]"
506 "}";
507 auto rbacs = GenerateRbacPolicies(authz_policy);
508 ASSERT_TRUE(rbacs.ok());
509 EXPECT_EQ(rbacs->allow_policy.name, "authz");
510 EXPECT_EQ(rbacs->deny_policy->name, "authz");
511 ASSERT_TRUE(rbacs->deny_policy.has_value());
512 EXPECT_EQ(rbacs->deny_policy->action, Rbac::Action::kDeny);
513 EXPECT_THAT(
514 rbacs->deny_policy->policies,
515 ::testing::ElementsAre(::testing::Pair(
516 "deny_policy",
517 ::testing::AllOf(
518 ::testing::Field(
519 &Rbac::Policy::principals,
520 ::testing::Field(&Rbac::Principal::type,
521 Rbac::Principal::RuleType::kAny)),
522 ::testing::Field(
523 &Rbac::Policy::permissions,
524 ::testing::AllOf(
525 ::testing::Field(&Rbac::Permission::type,
526 Rbac::Permission::RuleType::kAnd),
527 ::testing::Field(
528 &Rbac::Permission::permissions,
529 ::testing::ElementsAre(::testing::AllOf(
530 ::testing::Pointee(::testing::Field(
531 &Rbac::Permission::type,
532 Rbac::Permission::RuleType::kOr)),
533 ::testing::Pointee(::testing::Field(
534 &Rbac::Permission::permissions,
535 ::testing::ElementsAre(
536 EqualsPath(StringMatcher::Type::kExact,
537 "path-foo", false),
538 EqualsPath(StringMatcher::Type::kPrefix,
539 "path-bar", false),
540 EqualsPath(StringMatcher::Type::kSuffix,
541 "baz", false)))))))))))));
542 EXPECT_EQ(rbacs->allow_policy.action, Rbac::Action::kAllow);
543 EXPECT_THAT(
544 rbacs->allow_policy.policies,
545 ::testing::ElementsAre(::testing::Pair(
546 "allow_policy",
547 ::testing::AllOf(
548 ::testing::Field(
549 &Rbac::Policy::principals,
550 ::testing::Field(&Rbac::Principal::type,
551 Rbac::Principal::RuleType::kAny)),
552 ::testing::Field(
553 &Rbac::Policy::permissions,
554 ::testing::AllOf(
555 ::testing::Field(&Rbac::Permission::type,
556 Rbac::Permission::RuleType::kAnd),
557 ::testing::Field(
558 &Rbac::Permission::permissions,
559 ::testing::ElementsAre(::testing::AllOf(
560 ::testing::Pointee(::testing::Field(
561 &Rbac::Permission::type,
562 Rbac::Permission::RuleType::kOr)),
563 ::testing::Pointee(::testing::Field(
564 &Rbac::Permission::permissions,
565 ::testing::ElementsAre(EqualsPath(
566 StringMatcher::Type::kSafeRegex, ".+",
567 true)))))))))))));
568 }
569
TEST_F(GenerateRbacPoliciesTest,IncorrectHeaderType)570 TEST_F(GenerateRbacPoliciesTest, IncorrectHeaderType) {
571 const char* authz_policy =
572 "{"
573 " \"name\": \"authz\","
574 " \"deny_rules\": ["
575 " {"
576 " \"name\": \"allow_policy\","
577 " \"request\": {"
578 " \"headers\": ["
579 " \"header-a\""
580 " ]"
581 " }"
582 " }"
583 " ]"
584 "}";
585 auto rbac_policies = GenerateRbacPolicies(authz_policy);
586 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
587 EXPECT_EQ(rbac_policies.status().message(),
588 "deny_rules 0: \"headers\" 0: is not an object.");
589 }
590
TEST_F(GenerateRbacPoliciesTest,MissingHeaderKey)591 TEST_F(GenerateRbacPoliciesTest, MissingHeaderKey) {
592 const char* authz_policy =
593 "{"
594 " \"name\": \"authz\","
595 " \"allow_rules\": ["
596 " {"
597 " \"name\": \"policy\","
598 " \"request\": {"
599 " \"headers\": ["
600 " {}"
601 " ]"
602 " }"
603 " }"
604 " ]"
605 "}";
606 auto rbac_policies = GenerateRbacPolicies(authz_policy);
607 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
608 EXPECT_EQ(rbac_policies.status().message(),
609 "allow_rules 0: \"headers\" 0: \"key\" is not present.");
610 }
611
TEST_F(GenerateRbacPoliciesTest,MissingHeaderValues)612 TEST_F(GenerateRbacPoliciesTest, MissingHeaderValues) {
613 const char* authz_policy =
614 "{"
615 " \"name\": \"authz\","
616 " \"allow_rules\": ["
617 " {"
618 " \"name\": \"policy\","
619 " \"request\": {"
620 " \"headers\": ["
621 " {"
622 " \"key\": \"key-abc\""
623 " }"
624 " ]"
625 " }"
626 " }"
627 " ]"
628 "}";
629 auto rbac_policies = GenerateRbacPolicies(authz_policy);
630 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
631 EXPECT_EQ(rbac_policies.status().message(),
632 "allow_rules 0: \"headers\" 0: \"values\" is not present.");
633 }
634
TEST_F(GenerateRbacPoliciesTest,IncorrectHeaderKeyType)635 TEST_F(GenerateRbacPoliciesTest, IncorrectHeaderKeyType) {
636 const char* authz_policy =
637 "{"
638 " \"name\": \"authz\","
639 " \"allow_rules\": ["
640 " {"
641 " \"name\": \"policy\","
642 " \"request\": {"
643 " \"headers\": ["
644 " {"
645 " \"key\": 123,"
646 " \"values\": [\"value-a\"]"
647 " }"
648 " ]"
649 " }"
650 " }"
651 " ]"
652 "}";
653 auto rbac_policies = GenerateRbacPolicies(authz_policy);
654 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
655 EXPECT_EQ(rbac_policies.status().message(),
656 "allow_rules 0: \"headers\" 0: \"key\" is not a string.");
657 }
658
TEST_F(GenerateRbacPoliciesTest,IncorrectHeaderValuesType)659 TEST_F(GenerateRbacPoliciesTest, IncorrectHeaderValuesType) {
660 const char* authz_policy =
661 "{"
662 " \"name\": \"authz\","
663 " \"allow_rules\": ["
664 " {"
665 " \"name\": \"policy\","
666 " \"request\": {"
667 " \"headers\": ["
668 " {"
669 " \"key\": \"key-abc\","
670 " \"values\": {}"
671 " }"
672 " ]"
673 " }"
674 " }"
675 " ]"
676 "}";
677 auto rbac_policies = GenerateRbacPolicies(authz_policy);
678 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
679 EXPECT_EQ(rbac_policies.status().message(),
680 "allow_rules 0: \"headers\" 0: \"values\" is not an array.");
681 }
682
TEST_F(GenerateRbacPoliciesTest,UnsupportedGrpcHeaders)683 TEST_F(GenerateRbacPoliciesTest, UnsupportedGrpcHeaders) {
684 const char* authz_policy =
685 "{"
686 " \"name\": \"authz\","
687 " \"deny_rules\": ["
688 " {"
689 " \"name\": \"policy\","
690 " \"request\": {"
691 " \"headers\": ["
692 " {"
693 " \"key\": \"grpc-xxx\","
694 " \"values\": ["
695 " \"*\""
696 " ]"
697 " }"
698 " ]"
699 " }"
700 " }"
701 " ]"
702 "}";
703 auto rbac_policies = GenerateRbacPolicies(authz_policy);
704 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
705 EXPECT_EQ(rbac_policies.status().message(),
706 "deny_rules 0: \"headers\" 0: Unsupported \"key\" grpc-xxx.");
707 }
708
TEST_F(GenerateRbacPoliciesTest,UnsupportedPseudoHeaders)709 TEST_F(GenerateRbacPoliciesTest, UnsupportedPseudoHeaders) {
710 const char* authz_policy =
711 "{"
712 " \"name\": \"authz\","
713 " \"allow_rules\": ["
714 " {"
715 " \"name\": \"policy\","
716 " \"request\": {"
717 " \"headers\": ["
718 " {"
719 " \"key\": \":method\","
720 " \"values\": ["
721 " \"*\""
722 " ]"
723 " }"
724 " ]"
725 " }"
726 " }"
727 " ]"
728 "}";
729 auto rbac_policies = GenerateRbacPolicies(authz_policy);
730 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
731 EXPECT_EQ(rbac_policies.status().message(),
732 "allow_rules 0: \"headers\" 0: Unsupported \"key\" :method.");
733 }
734
TEST_F(GenerateRbacPoliciesTest,UnsupportedHostHeader)735 TEST_F(GenerateRbacPoliciesTest, UnsupportedHostHeader) {
736 const char* authz_policy =
737 "{"
738 " \"name\": \"authz\","
739 " \"allow_rules\": ["
740 " {"
741 " \"name\": \"policy\","
742 " \"request\": {"
743 " \"headers\": ["
744 " {"
745 " \"key\": \"Host\","
746 " \"values\": ["
747 " \"*\""
748 " ]"
749 " }"
750 " ]"
751 " }"
752 " }"
753 " ]"
754 "}";
755 auto rbac_policies = GenerateRbacPolicies(authz_policy);
756 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
757 EXPECT_EQ(rbac_policies.status().message(),
758 "allow_rules 0: \"headers\" 0: Unsupported \"key\" Host.");
759 }
760
TEST_F(GenerateRbacPoliciesTest,EmptyHeaderValuesList)761 TEST_F(GenerateRbacPoliciesTest, EmptyHeaderValuesList) {
762 const char* authz_policy =
763 "{"
764 " \"name\": \"authz\","
765 " \"allow_rules\": ["
766 " {"
767 " \"name\": \"allow_policy_1\","
768 " \"request\": {"
769 " \"headers\": ["
770 " {"
771 " \"key\": \"key-a\","
772 " \"values\": ["
773 " ]"
774 " }"
775 " ]"
776 " }"
777 " }"
778 " ]"
779 "}";
780 auto rbac_policies = GenerateRbacPolicies(authz_policy);
781 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
782 EXPECT_EQ(rbac_policies.status().message(),
783 "allow_rules 0: \"headers\" 0: \"values\" list is empty.");
784 }
785
TEST_F(GenerateRbacPoliciesTest,ParseRequestHeadersSuccess)786 TEST_F(GenerateRbacPoliciesTest, ParseRequestHeadersSuccess) {
787 const char* authz_policy =
788 "{"
789 " \"name\": \"authz\","
790 " \"allow_rules\": ["
791 " {"
792 " \"name\": \"allow_policy\","
793 " \"request\": {"
794 " \"headers\": ["
795 " {"
796 " \"key\": \"key-1\","
797 " \"values\": ["
798 " \"*\""
799 " ]"
800 " },"
801 " {"
802 " \"key\": \"key-2\","
803 " \"values\": ["
804 " \"foo\","
805 " \"bar*\","
806 " \"*baz\""
807 " ]"
808 " }"
809 " ]"
810 " }"
811 " }"
812 " ]"
813 "}";
814 auto rbacs = GenerateRbacPolicies(authz_policy);
815 ASSERT_TRUE(rbacs.ok());
816 EXPECT_EQ(rbacs->allow_policy.name, "authz");
817 EXPECT_EQ(rbacs->allow_policy.action, Rbac::Action::kAllow);
818 EXPECT_THAT(
819 rbacs->allow_policy.policies,
820 ::testing::ElementsAre(::testing::Pair(
821 "allow_policy",
822 ::testing::AllOf(
823 ::testing::Field(
824 &Rbac::Policy::principals,
825 ::testing::Field(&Rbac::Principal::type,
826 Rbac::Principal::RuleType::kAny)),
827 ::testing::Field(
828 &Rbac::Policy::permissions,
829 ::testing::AllOf(
830 ::testing::Field(&Rbac::Permission::type,
831 Rbac::Permission::RuleType::kAnd),
832 ::testing::Field(
833 &Rbac::Permission::permissions,
834 ::testing::ElementsAre(::testing::AllOf(
835 ::testing::Pointee(::testing::Field(
836 &Rbac::Permission::type,
837 Rbac::Permission::RuleType::kAnd)),
838 ::testing::Pointee(::testing::Field(
839 &Rbac::Permission::permissions,
840 ::testing::ElementsAre(
841 ::testing::AllOf(
842 ::testing::Pointee(::testing::Field(
843 &Rbac::Permission::type,
844 Rbac::Permission::RuleType::kOr)),
845 ::testing::Pointee(::testing::Field(
846 &Rbac::Permission::permissions,
847 ::testing::ElementsAre(
848 EqualsHeader(
849 "key-1",
850 HeaderMatcher::Type::
851 kSafeRegex,
852 ".+", true))))),
853 ::testing::AllOf(
854 ::testing::Pointee(::testing::Field(
855 &Rbac::Permission::type,
856 Rbac::Permission::RuleType::kOr)),
857 ::testing::Pointee(::testing::Field(
858 &Rbac::Permission::permissions,
859 ::testing::ElementsAre(
860 EqualsHeader("key-2",
861 HeaderMatcher::
862 Type::kExact,
863 "foo", false),
864 EqualsHeader(
865 "key-2",
866 HeaderMatcher::Type::
867 kPrefix,
868 "bar", false),
869 EqualsHeader(
870 "key-2",
871 HeaderMatcher::Type::
872 kSuffix,
873 "baz",
874 false)))))))))))))))));
875 }
876
TEST_F(GenerateRbacPoliciesTest,ParseRulesArraySuccess)877 TEST_F(GenerateRbacPoliciesTest, ParseRulesArraySuccess) {
878 const char* authz_policy =
879 "{"
880 " \"name\": \"authz\","
881 " \"allow_rules\": ["
882 " {"
883 " \"name\": \"allow_policy_1\","
884 " \"source\": {"
885 " \"principals\": ["
886 " \"spiffe://foo.abc\""
887 " ]"
888 " },"
889 " \"request\": {"
890 " \"paths\": ["
891 " \"foo\""
892 " ]"
893 " }"
894 " },"
895 " {"
896 " \"name\": \"allow_policy_2\""
897 " }"
898 " ]"
899 "}";
900 auto rbacs = GenerateRbacPolicies(authz_policy);
901 ASSERT_TRUE(rbacs.ok());
902 EXPECT_EQ(rbacs->allow_policy.name, "authz");
903 EXPECT_EQ(rbacs->allow_policy.action, Rbac::Action::kAllow);
904 EXPECT_THAT(
905 rbacs->allow_policy.policies,
906 ::testing::ElementsAre(
907 ::testing::Pair(
908 "allow_policy_1",
909 ::testing::AllOf(
910 ::testing::Field(
911 &Rbac::Policy::permissions,
912 ::testing::AllOf(
913 ::testing::Field(&Rbac::Permission::type,
914 Rbac::Permission::RuleType::kAnd),
915 ::testing::Field(
916 &Rbac::Permission::permissions,
917 ::testing::ElementsAre(::testing::AllOf(
918 ::testing::Pointee(::testing::Field(
919 &Rbac::Permission::type,
920 Rbac::Permission::RuleType::kOr)),
921 ::testing::Pointee(::testing::Field(
922 &Rbac::Permission::permissions,
923 ::testing::ElementsAre(EqualsPath(
924 StringMatcher::Type::kExact, "foo",
925 false))))))))),
926 ::testing::Field(
927 &Rbac::Policy::principals,
928 ::testing::AllOf(
929 ::testing::Field(&Rbac::Principal::type,
930 Rbac::Principal::RuleType::kAnd),
931 ::testing::Field(
932 &Rbac::Principal::principals,
933 ::testing::ElementsAre(::testing::AllOf(
934 ::testing::Pointee(::testing::Field(
935 &Rbac::Principal::type,
936 Rbac::Principal::RuleType::kOr)),
937 ::testing::Pointee(::testing::Field(
938 &Rbac::Principal::principals,
939 ::testing::ElementsAre(
940 EqualsPrincipalName(
941 StringMatcher::Type::kExact,
942 "spiffe://foo.abc",
943 false))))))))))),
944 ::testing::Pair(
945 "allow_policy_2",
946 ::testing::AllOf(
947 ::testing::Field(
948 &Rbac::Policy::permissions,
949 ::testing::Field(&Rbac::Permission::type,
950 Rbac::Permission::RuleType::kAny)),
951 ::testing::Field(
952 &Rbac::Policy::principals,
953 ::testing::Field(&Rbac::Principal::type,
954 Rbac::Principal::RuleType::kAny))))));
955 }
956
TEST_F(GenerateRbacPoliciesTest,UnknownFieldInTopLayer)957 TEST_F(GenerateRbacPoliciesTest, UnknownFieldInTopLayer) {
958 const char* authz_policy =
959 "{"
960 " \"name\": \"authz\","
961 " \"allow_rules\": ["
962 " {"
963 " \"name\": \"allow_policy\""
964 " }"
965 " ],"
966 " \"foo\": \"123\""
967 "}";
968 auto rbac_policies = GenerateRbacPolicies(authz_policy);
969 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
970 EXPECT_THAT(rbac_policies.status().message(),
971 "policy contains unknown field \"foo\".");
972 }
973
TEST_F(GenerateRbacPoliciesTest,UnknownFieldInRule)974 TEST_F(GenerateRbacPoliciesTest, UnknownFieldInRule) {
975 const char* authz_policy =
976 "{"
977 " \"name\": \"authz\","
978 " \"allow_rules\": ["
979 " {"
980 " \"name\": \"allow_policy\","
981 " \"foo\": {}"
982 " }"
983 " ]"
984 "}";
985 auto rbac_policies = GenerateRbacPolicies(authz_policy);
986 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
987 EXPECT_THAT(
988 rbac_policies.status().message(),
989 "allow_rules 0: policy contains unknown field \"foo\" in \"rule\".");
990 }
991
TEST_F(GenerateRbacPoliciesTest,UnknownFieldInSource)992 TEST_F(GenerateRbacPoliciesTest, UnknownFieldInSource) {
993 const char* authz_policy =
994 "{"
995 " \"name\": \"authz\","
996 " \"allow_rules\": ["
997 " {"
998 " \"name\": \"allow_policy\","
999 " \"source\": "
1000 " {"
1001 " \"principals\": [\"spiffe://foo.abc\"],"
1002 " \"foo\": {} "
1003 " }"
1004 " }"
1005 " ]"
1006 "}";
1007 auto rbac_policies = GenerateRbacPolicies(authz_policy);
1008 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
1009 EXPECT_THAT(
1010 rbac_policies.status().message(),
1011 "allow_rules 0: policy contains unknown field \"foo\" in \"source\".");
1012 }
1013
TEST_F(GenerateRbacPoliciesTest,UnknownFieldInRequest)1014 TEST_F(GenerateRbacPoliciesTest, UnknownFieldInRequest) {
1015 const char* authz_policy =
1016 "{"
1017 " \"name\": \"authz\","
1018 " \"allow_rules\": ["
1019 " {"
1020 " \"name\": \"allow_policy\","
1021 " \"request\": { \"foo\": {}}"
1022 " }"
1023 " ]"
1024 "}";
1025 auto rbac_policies = GenerateRbacPolicies(authz_policy);
1026 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
1027 EXPECT_THAT(
1028 rbac_policies.status().message(),
1029 "allow_rules 0: policy contains unknown field \"foo\" in \"request\".");
1030 }
1031
TEST_F(GenerateRbacPoliciesTest,UnknownFieldInHeaders)1032 TEST_F(GenerateRbacPoliciesTest, UnknownFieldInHeaders) {
1033 const char* authz_policy =
1034 "{"
1035 " \"name\": \"authz\","
1036 " \"allow_rules\": ["
1037 " {"
1038 " \"name\": \"allow_policy\","
1039 " \"request\": {"
1040 " \"headers\": [{ \"foo\": {}}]"
1041 " }"
1042 " }"
1043 " ]"
1044 "}";
1045 auto rbac_policies = GenerateRbacPolicies(authz_policy);
1046 EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument);
1047 EXPECT_THAT(rbac_policies.status().message(),
1048 "allow_rules 0: \"headers\" 0: policy contains unknown field "
1049 "\"foo\".");
1050 }
1051
TEST_F(GenerateRbacPoliciesTest,EmptyAuditLoggingOptions)1052 TEST_F(GenerateRbacPoliciesTest, EmptyAuditLoggingOptions) {
1053 const char* authz_policy =
1054 "{"
1055 " \"name\": \"authz\","
1056 " \"allow_rules\": ["
1057 " {"
1058 " \"name\": \"allow_policy\""
1059 " }"
1060 " ],"
1061 " \"audit_logging_options\": {}"
1062 "}";
1063 auto rbacs = GenerateRbacPolicies(authz_policy);
1064 ASSERT_TRUE(rbacs.ok());
1065 EXPECT_EQ(rbacs->allow_policy.name, "authz");
1066 }
1067
TEST_F(GenerateRbacPoliciesTest,AuditConditionNone)1068 TEST_F(GenerateRbacPoliciesTest, AuditConditionNone) {
1069 const char* authz_policy =
1070 "{"
1071 " \"name\": \"authz\","
1072 " \"allow_rules\": ["
1073 " {"
1074 " \"name\": \"allow_policy\""
1075 " }"
1076 " ],"
1077 " \"audit_logging_options\": {"
1078 " \"audit_condition\": \"NONE\""
1079 " }"
1080 "}";
1081 auto rbacs = GenerateRbacPolicies(authz_policy);
1082 ASSERT_TRUE(rbacs.ok());
1083 EXPECT_EQ(rbacs->allow_policy.name, "authz");
1084 EXPECT_EQ(rbacs->allow_policy.audit_condition, Rbac::AuditCondition::kNone);
1085 EXPECT_TRUE(
1086 absl::StartsWith(rbacs->allow_policy.ToString(),
1087 "Rbac name=authz action=Allow audit_condition=None"));
1088 }
1089
TEST_F(GenerateRbacPoliciesTest,AuditConditionOnDeny)1090 TEST_F(GenerateRbacPoliciesTest, AuditConditionOnDeny) {
1091 const char* authz_policy =
1092 "{"
1093 " \"name\": \"authz\","
1094 " \"allow_rules\": ["
1095 " {"
1096 " \"name\": \"allow_policy\""
1097 " }"
1098 " ],"
1099 " \"deny_rules\": ["
1100 " {"
1101 " \"name\": \"deny_policy\""
1102 " }"
1103 " ],"
1104 " \"audit_logging_options\": {"
1105 " \"audit_condition\": \"ON_DENY\""
1106 " }"
1107 "}";
1108 auto rbacs = GenerateRbacPolicies(authz_policy);
1109 ASSERT_TRUE(rbacs.ok());
1110 EXPECT_EQ(rbacs->allow_policy.name, "authz");
1111 EXPECT_EQ(rbacs->deny_policy->name, "authz");
1112 EXPECT_EQ(rbacs->allow_policy.audit_condition, Rbac::AuditCondition::kOnDeny);
1113 EXPECT_EQ(rbacs->deny_policy->audit_condition, Rbac::AuditCondition::kOnDeny);
1114 }
1115
TEST_F(GenerateRbacPoliciesTest,AuditConditionOnAllowWithAuditLoggers)1116 TEST_F(GenerateRbacPoliciesTest, AuditConditionOnAllowWithAuditLoggers) {
1117 const char* authz_policy =
1118 "{"
1119 " \"name\": \"authz\","
1120 " \"allow_rules\": ["
1121 " {"
1122 " \"name\": \"allow_policy\""
1123 " }"
1124 " ],"
1125 " \"deny_rules\": ["
1126 " {"
1127 " \"name\": \"deny_policy\""
1128 " }"
1129 " ],"
1130 " \"audit_logging_options\": {"
1131 " \"audit_condition\": \"ON_ALLOW\","
1132 " \"audit_loggers\": ["
1133 " {"
1134 " \"name\": \"test_logger\","
1135 " \"config\": {"
1136 " \"foo\": true"
1137 " }"
1138 " },"
1139 " {"
1140 " \"name\": \"test_logger\","
1141 " \"config\": {"
1142 " \"bar\": true"
1143 " }"
1144 " }"
1145 " ]"
1146 " }"
1147 "}";
1148 auto rbacs = GenerateRbacPolicies(authz_policy);
1149 ASSERT_TRUE(rbacs.ok());
1150 EXPECT_EQ(rbacs->allow_policy.name, "authz");
1151 EXPECT_EQ(rbacs->deny_policy->name, "authz");
1152 EXPECT_EQ(rbacs->allow_policy.audit_condition,
1153 Rbac::AuditCondition::kOnAllow);
1154 EXPECT_EQ(rbacs->deny_policy->audit_condition, Rbac::AuditCondition::kNone);
1155 ASSERT_EQ(rbacs->allow_policy.logger_configs.size(), 2);
1156 EXPECT_EQ(rbacs->deny_policy->logger_configs.size(), 0);
1157 EXPECT_EQ(rbacs->allow_policy.logger_configs.at(0)->name(), kLoggerName);
1158 EXPECT_EQ(rbacs->allow_policy.logger_configs.at(1)->name(), kLoggerName);
1159 EXPECT_EQ(rbacs->allow_policy.logger_configs.at(0)->ToString(),
1160 "{\"foo\":true}");
1161 EXPECT_EQ(rbacs->allow_policy.logger_configs.at(1)->ToString(),
1162 "{\"bar\":true}");
1163 EXPECT_EQ(rbacs->allow_policy.ToString(),
1164 "Rbac name=authz action=Allow audit_condition=OnAllow{\n{\n "
1165 "policy_name=allow_policy\n Policy {\n Permissions{any}\n "
1166 "Principals{any}\n }\n}\n{\n "
1167 "audit_logger=test_logger\n{\"foo\":true}\n}\n{\n "
1168 "audit_logger=test_logger\n{\"bar\":true}\n}\n}");
1169 }
1170
TEST_F(GenerateRbacPoliciesTest,AuditConditionOnDenyAndAllowWithUnsupportedButOptionalLogger)1171 TEST_F(GenerateRbacPoliciesTest,
1172 AuditConditionOnDenyAndAllowWithUnsupportedButOptionalLogger) {
1173 const char* authz_policy =
1174 "{"
1175 " \"name\": \"authz\","
1176 " \"allow_rules\": ["
1177 " {"
1178 " \"name\": \"allow_policy\""
1179 " }"
1180 " ],"
1181 " \"deny_rules\": ["
1182 " {"
1183 " \"name\": \"deny_policy\""
1184 " }"
1185 " ],"
1186 " \"audit_logging_options\": {"
1187 " \"audit_condition\": \"ON_DENY_AND_ALLOW\","
1188 " \"audit_loggers\": ["
1189 " {"
1190 " \"name\": \"unknown_logger\","
1191 " \"is_optional\": true,"
1192 " \"config\": {}"
1193 " }"
1194 " ]"
1195 " }"
1196 "}";
1197 auto rbacs = GenerateRbacPolicies(authz_policy);
1198 ASSERT_TRUE(rbacs.ok());
1199 EXPECT_EQ(rbacs->allow_policy.name, "authz");
1200 EXPECT_EQ(rbacs->deny_policy->name, "authz");
1201 EXPECT_EQ(rbacs->allow_policy.audit_condition,
1202 Rbac::AuditCondition::kOnDenyAndAllow);
1203 EXPECT_EQ(rbacs->deny_policy->audit_condition, Rbac::AuditCondition::kOnDeny);
1204 EXPECT_EQ(rbacs->allow_policy.logger_configs.size(), 0);
1205 EXPECT_EQ(rbacs->deny_policy->logger_configs.size(), 0);
1206 }
1207
TEST_F(GenerateRbacPoliciesTest,UnknownFieldInAuditLoggingOptions)1208 TEST_F(GenerateRbacPoliciesTest, UnknownFieldInAuditLoggingOptions) {
1209 const char* authz_policy =
1210 "{"
1211 " \"name\": \"authz\","
1212 " \"allow_rules\": ["
1213 " {"
1214 " \"name\": \"allow_policy\""
1215 " }"
1216 " ],"
1217 " \"audit_logging_options\": {"
1218 " \"foo\": 123"
1219 " }"
1220 "}";
1221 auto rbacs = GenerateRbacPolicies(authz_policy);
1222 EXPECT_EQ(rbacs.status().code(), absl::StatusCode::kInvalidArgument);
1223 EXPECT_THAT(
1224 rbacs.status().message(),
1225 "policy contains unknown field \"foo\" in \"audit_logging_options\".");
1226 }
1227
TEST_F(GenerateRbacPoliciesTest,AuditConditionIsNotString)1228 TEST_F(GenerateRbacPoliciesTest, AuditConditionIsNotString) {
1229 const char* authz_policy =
1230 "{"
1231 " \"name\": \"authz\","
1232 " \"allow_rules\": ["
1233 " {"
1234 " \"name\": \"allow_policy\""
1235 " }"
1236 " ],"
1237 " \"audit_logging_options\": {"
1238 " \"audit_condition\": 123"
1239 " }"
1240 "}";
1241 auto rbacs = GenerateRbacPolicies(authz_policy);
1242 EXPECT_EQ(rbacs.status().code(), absl::StatusCode::kInvalidArgument);
1243 EXPECT_THAT(rbacs.status().message(), "\"audit_condition\" is not a string.");
1244 }
1245
TEST_F(GenerateRbacPoliciesTest,IncorrectAuditConditionValue)1246 TEST_F(GenerateRbacPoliciesTest, IncorrectAuditConditionValue) {
1247 const char* authz_policy =
1248 "{"
1249 " \"name\": \"authz\","
1250 " \"allow_rules\": ["
1251 " {"
1252 " \"name\": \"allow_policy\""
1253 " }"
1254 " ],"
1255 " \"audit_logging_options\": {"
1256 " \"audit_condition\": \"UNKNOWN\""
1257 " }"
1258 "}";
1259 auto rbacs = GenerateRbacPolicies(authz_policy);
1260 EXPECT_EQ(rbacs.status().code(), absl::StatusCode::kInvalidArgument);
1261 EXPECT_THAT(rbacs.status().message(),
1262 "Unsupported \"audit_condition\" value UNKNOWN.");
1263 }
1264
TEST_F(GenerateRbacPoliciesTest,IncorrectAuditLoggersType)1265 TEST_F(GenerateRbacPoliciesTest, IncorrectAuditLoggersType) {
1266 const char* authz_policy =
1267 "{"
1268 " \"name\": \"authz\","
1269 " \"allow_rules\": ["
1270 " {"
1271 " \"name\": \"allow_policy\""
1272 " }"
1273 " ],"
1274 " \"audit_logging_options\": {"
1275 " \"audit_loggers\": 123"
1276 " }"
1277 "}";
1278 auto rbacs = GenerateRbacPolicies(authz_policy);
1279 EXPECT_EQ(rbacs.status().code(), absl::StatusCode::kInvalidArgument);
1280 EXPECT_THAT(rbacs.status().message(), "\"audit_loggers\" is not an array.");
1281 }
1282
TEST_F(GenerateRbacPoliciesTest,IncorrectAuditLoggerType)1283 TEST_F(GenerateRbacPoliciesTest, IncorrectAuditLoggerType) {
1284 const char* authz_policy =
1285 "{"
1286 " \"name\": \"authz\","
1287 " \"allow_rules\": ["
1288 " {"
1289 " \"name\": \"allow_policy\""
1290 " }"
1291 " ],"
1292 " \"audit_logging_options\": {"
1293 " \"audit_loggers\": [123]"
1294 " }"
1295 "}";
1296 auto rbacs = GenerateRbacPolicies(authz_policy);
1297 EXPECT_EQ(rbacs.status().code(), absl::StatusCode::kInvalidArgument);
1298 EXPECT_THAT(rbacs.status().message(),
1299 "\"audit_loggers[0]\" is not an object.");
1300 }
1301
TEST_F(GenerateRbacPoliciesTest,UnknownFieldInAuditLoggers)1302 TEST_F(GenerateRbacPoliciesTest, UnknownFieldInAuditLoggers) {
1303 const char* authz_policy =
1304 "{"
1305 " \"name\": \"authz\","
1306 " \"allow_rules\": ["
1307 " {"
1308 " \"name\": \"allow_policy\""
1309 " }"
1310 " ],"
1311 " \"audit_logging_options\": {"
1312 " \"audit_loggers\": ["
1313 " {"
1314 " \"foo\": 123"
1315 " }"
1316 " ]"
1317 " }"
1318 "}";
1319 auto rbacs = GenerateRbacPolicies(authz_policy);
1320 EXPECT_EQ(rbacs.status().code(), absl::StatusCode::kInvalidArgument);
1321 EXPECT_THAT(rbacs.status().message(),
1322 "policy contains unknown field \"foo\" in "
1323 "\"audit_logging_options.audit_loggers[0]\".");
1324 }
1325
TEST_F(GenerateRbacPoliciesTest,IncorrectAuditLoggerConfigType)1326 TEST_F(GenerateRbacPoliciesTest, IncorrectAuditLoggerConfigType) {
1327 const char* authz_policy =
1328 "{"
1329 " \"name\": \"authz\","
1330 " \"allow_rules\": ["
1331 " {"
1332 " \"name\": \"allow_policy\""
1333 " }"
1334 " ],"
1335 " \"audit_logging_options\": {"
1336 " \"audit_loggers\": ["
1337 " {"
1338 " \"name\": \"unknown_logger\","
1339 " \"config\": 123"
1340 " }"
1341 " ]"
1342 " }"
1343 "}";
1344 auto rbacs = GenerateRbacPolicies(authz_policy);
1345 EXPECT_EQ(rbacs.status().code(), absl::StatusCode::kInvalidArgument);
1346 EXPECT_THAT(rbacs.status().message(),
1347 "\"audit_loggers[0].config\" is not an object.");
1348 }
1349
TEST_F(GenerateRbacPoliciesTest,BadAuditLoggerConfig)1350 TEST_F(GenerateRbacPoliciesTest, BadAuditLoggerConfig) {
1351 const char* authz_policy =
1352 "{"
1353 " \"name\": \"authz\","
1354 " \"allow_rules\": ["
1355 " {"
1356 " \"name\": \"allow_policy\""
1357 " }"
1358 " ],"
1359 " \"audit_logging_options\": {"
1360 " \"audit_loggers\": ["
1361 " {"
1362 " \"name\": \"test_logger\","
1363 " \"config\": {\"bad\": true}"
1364 " }"
1365 " ]"
1366 " }"
1367 "}";
1368 auto rbacs = GenerateRbacPolicies(authz_policy);
1369 EXPECT_EQ(rbacs.status().code(), absl::StatusCode::kInvalidArgument);
1370 EXPECT_THAT(rbacs.status().message(),
1371 "\"audit_loggers[0]\" bad logger config.");
1372 }
1373
TEST_F(GenerateRbacPoliciesTest,IncorrectAuditLoggerNameType)1374 TEST_F(GenerateRbacPoliciesTest, IncorrectAuditLoggerNameType) {
1375 const char* authz_policy =
1376 "{"
1377 " \"name\": \"authz\","
1378 " \"allow_rules\": ["
1379 " {"
1380 " \"name\": \"allow_policy\""
1381 " }"
1382 " ],"
1383 " \"audit_logging_options\": {"
1384 " \"audit_loggers\": ["
1385 " {"
1386 " \"name\": 123,"
1387 " \"config\": {}"
1388 " }"
1389 " ]"
1390 " }"
1391 "}";
1392 auto rbacs = GenerateRbacPolicies(authz_policy);
1393 EXPECT_EQ(rbacs.status().code(), absl::StatusCode::kInvalidArgument);
1394 EXPECT_THAT(rbacs.status().message(),
1395 "\"audit_loggers[0].name\" is not a string.");
1396 }
1397
TEST_F(GenerateRbacPoliciesTest,IncorrectAuditLoggerIsOptionalType)1398 TEST_F(GenerateRbacPoliciesTest, IncorrectAuditLoggerIsOptionalType) {
1399 const char* authz_policy =
1400 "{"
1401 " \"name\": \"authz\","
1402 " \"allow_rules\": ["
1403 " {"
1404 " \"name\": \"allow_policy\""
1405 " }"
1406 " ],"
1407 " \"audit_logging_options\": {"
1408 " \"audit_loggers\": ["
1409 " {"
1410 " \"name\": \"test_logger\","
1411 " \"is_optional\": 123,"
1412 " \"config\": {}"
1413 " }"
1414 " ]"
1415 " }"
1416 "}";
1417 auto rbacs = GenerateRbacPolicies(authz_policy);
1418 EXPECT_EQ(rbacs.status().code(), absl::StatusCode::kInvalidArgument);
1419 EXPECT_THAT(rbacs.status().message(),
1420 "\"audit_loggers[0].is_optional\" is not a boolean.");
1421 }
1422
TEST_F(GenerateRbacPoliciesTest,MissingAuditLoggerName)1423 TEST_F(GenerateRbacPoliciesTest, MissingAuditLoggerName) {
1424 const char* authz_policy =
1425 "{"
1426 " \"name\": \"authz\","
1427 " \"allow_rules\": ["
1428 " {"
1429 " \"name\": \"allow_policy\""
1430 " }"
1431 " ],"
1432 " \"audit_logging_options\": {"
1433 " \"audit_loggers\": ["
1434 " {"
1435 " \"config\": {}"
1436 " }"
1437 " ]"
1438 " }"
1439 "}";
1440 auto rbacs = GenerateRbacPolicies(authz_policy);
1441 EXPECT_EQ(rbacs.status().code(), absl::StatusCode::kInvalidArgument);
1442 EXPECT_THAT(rbacs.status().message(),
1443 "\"audit_loggers[0].name\" is required.");
1444 }
1445
TEST_F(GenerateRbacPoliciesTest,MissingAuditLoggerConfig)1446 TEST_F(GenerateRbacPoliciesTest, MissingAuditLoggerConfig) {
1447 const char* authz_policy =
1448 "{"
1449 " \"name\": \"authz\","
1450 " \"allow_rules\": ["
1451 " {"
1452 " \"name\": \"allow_policy\""
1453 " }"
1454 " ],"
1455 " \"audit_logging_options\": {"
1456 " \"audit_condition\": \"ON_DENY\","
1457 " \"audit_loggers\": ["
1458 " {"
1459 " \"name\": \"test_logger\""
1460 " }"
1461 " ]"
1462 " }"
1463 "}";
1464 auto rbacs = GenerateRbacPolicies(authz_policy);
1465 ASSERT_TRUE(rbacs.ok());
1466 EXPECT_EQ(rbacs->allow_policy.name, "authz");
1467 EXPECT_EQ(rbacs->allow_policy.audit_condition, Rbac::AuditCondition::kOnDeny);
1468 EXPECT_EQ(rbacs->allow_policy.logger_configs.size(), 1);
1469 EXPECT_EQ(rbacs->allow_policy.logger_configs.at(0)->name(), kLoggerName);
1470 EXPECT_EQ(rbacs->allow_policy.logger_configs.at(0)->ToString(), "{}");
1471 }
1472
TEST_F(GenerateRbacPoliciesTest,UnsupportedAuditLogger)1473 TEST_F(GenerateRbacPoliciesTest, UnsupportedAuditLogger) {
1474 const char* authz_policy =
1475 "{"
1476 " \"name\": \"authz\","
1477 " \"allow_rules\": ["
1478 " {"
1479 " \"name\": \"allow_policy\""
1480 " }"
1481 " ],"
1482 " \"audit_logging_options\": {"
1483 " \"audit_loggers\": ["
1484 " {"
1485 " \"name\": \"unknown_logger\","
1486 " \"config\": {}"
1487 " }"
1488 " ]"
1489 " }"
1490 "}";
1491 auto rbacs = GenerateRbacPolicies(authz_policy);
1492 EXPECT_EQ(rbacs.status().code(), absl::StatusCode::kInvalidArgument);
1493 EXPECT_THAT(rbacs.status().message(),
1494 "\"audit_loggers[0].name\" unknown_logger is not supported "
1495 "natively or registered.");
1496 }
1497
1498 } // namespace grpc_core
1499
main(int argc,char ** argv)1500 int main(int argc, char** argv) {
1501 ::testing::InitGoogleTest(&argc, argv);
1502 return RUN_ALL_TESTS();
1503 }
1504