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