• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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