xref: /aosp_15_r20/external/grpc-grpc/test/core/security/rbac_translator_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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