xref: /aosp_15_r20/external/grpc-grpc/test/core/security/grpc_authorization_engine_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/grpc_authorization_engine.h"
16 
17 #include <memory>
18 
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 
22 #include <grpc/grpc_audit_logging.h>
23 #include <grpc/grpc_security_constants.h>
24 #include <grpc/support/port_platform.h>
25 
26 #include "src/core/lib/json/json.h"
27 #include "src/core/lib/security/authorization/audit_logging.h"
28 #include "test/core/util/audit_logging_utils.h"
29 #include "test/core/util/evaluate_args_test_util.h"
30 
31 namespace grpc_core {
32 
33 namespace {
34 
35 constexpr absl::string_view kPolicyName = "authz";
36 constexpr absl::string_view kSpiffeId = "spiffe://foo";
37 constexpr absl::string_view kRpcMethod = "/foo.Bar/Echo";
38 
39 using experimental::AuditLoggerRegistry;
40 using experimental::RegisterAuditLoggerFactory;
41 using testing::TestAuditLoggerFactory;
42 
43 class GrpcAuthorizationEngineTest : public ::testing::Test {
44  protected:
SetUp()45   void SetUp() override {
46     RegisterAuditLoggerFactory(
47         std::make_unique<TestAuditLoggerFactory>(&audit_logs_));
48     evaluate_args_util_.AddPairToMetadata(":path", kRpcMethod.data());
49     evaluate_args_util_.AddPropertyToAuthContext(
50         GRPC_PEER_SPIFFE_ID_PROPERTY_NAME, kSpiffeId.data());
51   }
52 
TearDown()53   void TearDown() override { AuditLoggerRegistry::TestOnlyResetRegistry(); }
54 
55   std::vector<std::string> audit_logs_;
56   EvaluateArgsTestUtil evaluate_args_util_;
57 };
58 
59 }  // namespace
60 
TEST_F(GrpcAuthorizationEngineTest,AllowEngineWithMatchingPolicy)61 TEST_F(GrpcAuthorizationEngineTest, AllowEngineWithMatchingPolicy) {
62   Rbac::Policy policy1(
63       Rbac::Permission::MakeNotPermission(
64           Rbac::Permission::MakeAnyPermission()),
65       Rbac::Principal::MakeNotPrincipal(Rbac::Principal::MakeAnyPrincipal()));
66   Rbac::Policy policy2(Rbac::Permission::MakeAnyPermission(),
67                        Rbac::Principal::MakeAnyPrincipal());
68   std::map<std::string, Rbac::Policy> policies;
69   policies["policy1"] = std::move(policy1);
70   policies["policy2"] = std::move(policy2);
71   Rbac rbac("authz", Rbac::Action::kAllow, std::move(policies));
72   GrpcAuthorizationEngine engine(std::move(rbac));
73   AuthorizationEngine::Decision decision =
74       engine.Evaluate(EvaluateArgs(nullptr, nullptr));
75   EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kAllow);
76   EXPECT_EQ(decision.matching_policy_name, "policy2");
77 }
78 
TEST_F(GrpcAuthorizationEngineTest,AllowEngineWithNoMatchingPolicy)79 TEST_F(GrpcAuthorizationEngineTest, AllowEngineWithNoMatchingPolicy) {
80   Rbac::Policy policy1(
81       Rbac::Permission::MakeNotPermission(
82           Rbac::Permission::MakeAnyPermission()),
83       Rbac::Principal::MakeNotPrincipal(Rbac::Principal::MakeAnyPrincipal()));
84   std::map<std::string, Rbac::Policy> policies;
85   policies["policy1"] = std::move(policy1);
86   Rbac rbac("authz", Rbac::Action::kAllow, std::move(policies));
87   GrpcAuthorizationEngine engine(std::move(rbac));
88   AuthorizationEngine::Decision decision =
89       engine.Evaluate(EvaluateArgs(nullptr, nullptr));
90   EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kDeny);
91   EXPECT_TRUE(decision.matching_policy_name.empty());
92 }
93 
TEST_F(GrpcAuthorizationEngineTest,AllowEngineWithEmptyPolicies)94 TEST_F(GrpcAuthorizationEngineTest, AllowEngineWithEmptyPolicies) {
95   GrpcAuthorizationEngine engine(Rbac::Action::kAllow);
96   AuthorizationEngine::Decision decision =
97       engine.Evaluate(EvaluateArgs(nullptr, nullptr));
98   EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kDeny);
99   EXPECT_TRUE(decision.matching_policy_name.empty());
100 }
101 
TEST_F(GrpcAuthorizationEngineTest,DenyEngineWithMatchingPolicy)102 TEST_F(GrpcAuthorizationEngineTest, DenyEngineWithMatchingPolicy) {
103   Rbac::Policy policy1(
104       Rbac::Permission::MakeNotPermission(
105           Rbac::Permission::MakeAnyPermission()),
106       Rbac::Principal::MakeNotPrincipal(Rbac::Principal::MakeAnyPrincipal()));
107   Rbac::Policy policy2(Rbac::Permission::MakeAnyPermission(),
108                        Rbac::Principal::MakeAnyPrincipal());
109   std::map<std::string, Rbac::Policy> policies;
110   policies["policy1"] = std::move(policy1);
111   policies["policy2"] = std::move(policy2);
112   Rbac rbac("authz", Rbac::Action::kDeny, std::move(policies));
113   GrpcAuthorizationEngine engine(std::move(rbac));
114   AuthorizationEngine::Decision decision =
115       engine.Evaluate(EvaluateArgs(nullptr, nullptr));
116   EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kDeny);
117   EXPECT_EQ(decision.matching_policy_name, "policy2");
118 }
119 
TEST_F(GrpcAuthorizationEngineTest,DenyEngineWithNoMatchingPolicy)120 TEST_F(GrpcAuthorizationEngineTest, DenyEngineWithNoMatchingPolicy) {
121   Rbac::Policy policy1(
122       Rbac::Permission::MakeNotPermission(
123           Rbac::Permission::MakeAnyPermission()),
124       Rbac::Principal::MakeNotPrincipal(Rbac::Principal::MakeAnyPrincipal()));
125   std::map<std::string, Rbac::Policy> policies;
126   policies["policy1"] = std::move(policy1);
127   Rbac rbac("authz", Rbac::Action::kDeny, std::move(policies));
128   GrpcAuthorizationEngine engine(std::move(rbac));
129   AuthorizationEngine::Decision decision =
130       engine.Evaluate(EvaluateArgs(nullptr, nullptr));
131   EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kAllow);
132   EXPECT_TRUE(decision.matching_policy_name.empty());
133 }
134 
TEST_F(GrpcAuthorizationEngineTest,DenyEngineWithEmptyPolicies)135 TEST_F(GrpcAuthorizationEngineTest, DenyEngineWithEmptyPolicies) {
136   GrpcAuthorizationEngine engine(Rbac::Action::kDeny);
137   AuthorizationEngine::Decision decision =
138       engine.Evaluate(EvaluateArgs(nullptr, nullptr));
139   EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kAllow);
140   EXPECT_TRUE(decision.matching_policy_name.empty());
141 }
142 
TEST_F(GrpcAuthorizationEngineTest,AuditLoggerNoneNotInvokedOnAllowedRequest)143 TEST_F(GrpcAuthorizationEngineTest, AuditLoggerNoneNotInvokedOnAllowedRequest) {
144   Rbac::Policy policy1(Rbac::Permission::MakeAnyPermission(),
145                        Rbac::Principal::MakeAnyPrincipal());
146   std::map<std::string, Rbac::Policy> policies;
147   policies["policy1"] = std::move(policy1);
148   Rbac rbac(std::string(kPolicyName), Rbac::Action::kAllow,
149             std::move(policies));
150   rbac.audit_condition = Rbac::AuditCondition::kNone;
151   rbac.logger_configs.push_back(
152       std::make_unique<TestAuditLoggerFactory::Config>());
153   GrpcAuthorizationEngine engine(std::move(rbac));
154   AuthorizationEngine::Decision decision =
155       engine.Evaluate(evaluate_args_util_.MakeEvaluateArgs());
156   EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kAllow);
157   EXPECT_EQ(decision.matching_policy_name, "policy1");
158   EXPECT_EQ(audit_logs_.size(), 0);
159 }
160 
TEST_F(GrpcAuthorizationEngineTest,AuditLoggerNoneNotInvokedOnDeniedRequest)161 TEST_F(GrpcAuthorizationEngineTest, AuditLoggerNoneNotInvokedOnDeniedRequest) {
162   Rbac::Policy policy1(
163       Rbac::Permission::MakeNotPermission(
164           Rbac::Permission::MakeAnyPermission()),
165       Rbac::Principal::MakeNotPrincipal(Rbac::Principal::MakeAnyPrincipal()));
166   std::map<std::string, Rbac::Policy> policies;
167   policies["policy1"] = std::move(policy1);
168   Rbac rbac(std::string(kPolicyName), Rbac::Action::kAllow,
169             std::move(policies));
170   rbac.audit_condition = Rbac::AuditCondition::kNone;
171   rbac.logger_configs.push_back(
172       std::make_unique<TestAuditLoggerFactory::Config>());
173   GrpcAuthorizationEngine engine(std::move(rbac));
174   AuthorizationEngine::Decision decision =
175       engine.Evaluate(evaluate_args_util_.MakeEvaluateArgs());
176   EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kDeny);
177   EXPECT_EQ(decision.matching_policy_name, "");
178   EXPECT_EQ(audit_logs_.size(), 0);
179 }
180 
TEST_F(GrpcAuthorizationEngineTest,AuditLoggerOnDenyNotInvoked)181 TEST_F(GrpcAuthorizationEngineTest, AuditLoggerOnDenyNotInvoked) {
182   Rbac::Policy policy1(Rbac::Permission::MakeAnyPermission(),
183                        Rbac::Principal::MakeAnyPrincipal());
184   std::map<std::string, Rbac::Policy> policies;
185   policies["policy1"] = std::move(policy1);
186   Rbac rbac(std::string(kPolicyName), Rbac::Action::kAllow,
187             std::move(policies));
188   rbac.audit_condition = Rbac::AuditCondition::kOnDeny;
189   rbac.logger_configs.push_back(
190       std::make_unique<TestAuditLoggerFactory::Config>());
191   GrpcAuthorizationEngine engine(std::move(rbac));
192   AuthorizationEngine::Decision decision =
193       engine.Evaluate(evaluate_args_util_.MakeEvaluateArgs());
194   EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kAllow);
195   EXPECT_EQ(decision.matching_policy_name, "policy1");
196   EXPECT_EQ(audit_logs_.size(), 0);
197 }
198 
TEST_F(GrpcAuthorizationEngineTest,AuditLoggerOnAllowNotInvoked)199 TEST_F(GrpcAuthorizationEngineTest, AuditLoggerOnAllowNotInvoked) {
200   Rbac::Policy policy1(
201       Rbac::Permission::MakeNotPermission(
202           Rbac::Permission::MakeAnyPermission()),
203       Rbac::Principal::MakeNotPrincipal(Rbac::Principal::MakeAnyPrincipal()));
204   std::map<std::string, Rbac::Policy> policies;
205   policies["policy1"] = std::move(policy1);
206   Rbac rbac(std::string(kPolicyName), Rbac::Action::kAllow,
207             std::move(policies));
208   rbac.audit_condition = Rbac::AuditCondition::kOnAllow;
209   rbac.logger_configs.push_back(
210       std::make_unique<TestAuditLoggerFactory::Config>());
211   GrpcAuthorizationEngine engine(std::move(rbac));
212   AuthorizationEngine::Decision decision =
213       engine.Evaluate(evaluate_args_util_.MakeEvaluateArgs());
214   EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kDeny);
215   EXPECT_EQ(decision.matching_policy_name, "");
216   EXPECT_EQ(audit_logs_.size(), 0);
217 }
218 
TEST_F(GrpcAuthorizationEngineTest,AuditLoggerOnAllowInvoked)219 TEST_F(GrpcAuthorizationEngineTest, AuditLoggerOnAllowInvoked) {
220   Rbac::Policy policy1(Rbac::Permission::MakeAnyPermission(),
221                        Rbac::Principal::MakeAnyPrincipal());
222   std::map<std::string, Rbac::Policy> policies;
223   policies["policy1"] = std::move(policy1);
224   Rbac rbac(std::string(kPolicyName), Rbac::Action::kAllow,
225             std::move(policies));
226   rbac.audit_condition = Rbac::AuditCondition::kOnAllow;
227   rbac.logger_configs.push_back(
228       std::make_unique<TestAuditLoggerFactory::Config>());
229   GrpcAuthorizationEngine engine(std::move(rbac));
230   AuthorizationEngine::Decision decision =
231       engine.Evaluate(evaluate_args_util_.MakeEvaluateArgs());
232   EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kAllow);
233   EXPECT_EQ(decision.matching_policy_name, "policy1");
234   EXPECT_THAT(audit_logs_,
235               ::testing::ElementsAre(absl::StrFormat(
236                   "{\"authorized\":true,\"matched_rule\":\"policy1\",\"policy_"
237                   "name\":\"%s\",\"principal\":\"%s\",\"rpc_method\":\"%s\"}",
238                   kPolicyName, kSpiffeId, kRpcMethod)));
239 }
240 
TEST_F(GrpcAuthorizationEngineTest,AuditLoggerOnDenyAndAllowInvokedWithAllowedRequest)241 TEST_F(GrpcAuthorizationEngineTest,
242        AuditLoggerOnDenyAndAllowInvokedWithAllowedRequest) {
243   Rbac::Policy policy1(Rbac::Permission::MakeAnyPermission(),
244                        Rbac::Principal::MakeAnyPrincipal());
245   std::map<std::string, Rbac::Policy> policies;
246   policies["policy1"] = std::move(policy1);
247   Rbac rbac(std::string(kPolicyName), Rbac::Action::kAllow,
248             std::move(policies));
249   rbac.audit_condition = Rbac::AuditCondition::kOnDenyAndAllow;
250   rbac.logger_configs.push_back(
251       std::make_unique<TestAuditLoggerFactory::Config>());
252   GrpcAuthorizationEngine engine(std::move(rbac));
253   AuthorizationEngine::Decision decision =
254       engine.Evaluate(evaluate_args_util_.MakeEvaluateArgs());
255   EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kAllow);
256   EXPECT_EQ(decision.matching_policy_name, "policy1");
257   EXPECT_THAT(audit_logs_,
258               ::testing::ElementsAre(absl::StrFormat(
259                   "{\"authorized\":true,\"matched_rule\":\"policy1\",\"policy_"
260                   "name\":\"%s\",\"principal\":\"%s\",\"rpc_method\":\"%s\"}",
261                   kPolicyName, kSpiffeId, kRpcMethod)));
262 }
263 
TEST_F(GrpcAuthorizationEngineTest,AuditLoggerOnDenyInvoked)264 TEST_F(GrpcAuthorizationEngineTest, AuditLoggerOnDenyInvoked) {
265   Rbac::Policy policy1(
266       Rbac::Permission::MakeNotPermission(
267           Rbac::Permission::MakeAnyPermission()),
268       Rbac::Principal::MakeNotPrincipal(Rbac::Principal::MakeAnyPrincipal()));
269   std::map<std::string, Rbac::Policy> policies;
270   policies["policy1"] = std::move(policy1);
271   Rbac rbac(std::string(kPolicyName), Rbac::Action::kAllow,
272             std::move(policies));
273   rbac.audit_condition = Rbac::AuditCondition::kOnDeny;
274   rbac.logger_configs.push_back(
275       std::make_unique<TestAuditLoggerFactory::Config>());
276   GrpcAuthorizationEngine engine(std::move(rbac));
277   AuthorizationEngine::Decision decision =
278       engine.Evaluate(evaluate_args_util_.MakeEvaluateArgs());
279   EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kDeny);
280   EXPECT_EQ(decision.matching_policy_name, "");
281   EXPECT_THAT(audit_logs_,
282               ::testing::ElementsAre(absl::StrFormat(
283                   "{\"authorized\":false,\"matched_rule\":\"\",\"policy_"
284                   "name\":\"%s\",\"principal\":\"%s\",\"rpc_method\":\"%s\"}",
285                   kPolicyName, kSpiffeId, kRpcMethod)));
286 }
287 
TEST_F(GrpcAuthorizationEngineTest,AuditLoggerOnDenyAndAllowInvokedWithDeniedRequest)288 TEST_F(GrpcAuthorizationEngineTest,
289        AuditLoggerOnDenyAndAllowInvokedWithDeniedRequest) {
290   Rbac::Policy policy1(
291       Rbac::Permission::MakeNotPermission(
292           Rbac::Permission::MakeAnyPermission()),
293       Rbac::Principal::MakeNotPrincipal(Rbac::Principal::MakeAnyPrincipal()));
294   std::map<std::string, Rbac::Policy> policies;
295   policies["policy1"] = std::move(policy1);
296   Rbac rbac(std::string(kPolicyName), Rbac::Action::kAllow,
297             std::move(policies));
298   rbac.audit_condition = Rbac::AuditCondition::kOnDenyAndAllow;
299   rbac.logger_configs.push_back(
300       std::make_unique<TestAuditLoggerFactory::Config>());
301   GrpcAuthorizationEngine engine(std::move(rbac));
302   AuthorizationEngine::Decision decision =
303       engine.Evaluate(evaluate_args_util_.MakeEvaluateArgs());
304   EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kDeny);
305   EXPECT_EQ(decision.matching_policy_name, "");
306   EXPECT_THAT(audit_logs_,
307               ::testing::ElementsAre(absl::StrFormat(
308                   "{\"authorized\":false,\"matched_rule\":\"\",\"policy_"
309                   "name\":\"%s\",\"principal\":\"%s\",\"rpc_method\":\"%s\"}",
310                   kPolicyName, kSpiffeId, kRpcMethod)));
311 }
312 
TEST_F(GrpcAuthorizationEngineTest,MultipleAuditLoggerInvoked)313 TEST_F(GrpcAuthorizationEngineTest, MultipleAuditLoggerInvoked) {
314   Rbac::Policy policy1(
315       Rbac::Permission::MakeNotPermission(
316           Rbac::Permission::MakeAnyPermission()),
317       Rbac::Principal::MakeNotPrincipal(Rbac::Principal::MakeAnyPrincipal()));
318   std::map<std::string, Rbac::Policy> policies;
319   policies["policy1"] = std::move(policy1);
320   Rbac rbac(std::string(kPolicyName), Rbac::Action::kAllow,
321             std::move(policies));
322   rbac.audit_condition = Rbac::AuditCondition::kOnDenyAndAllow;
323   rbac.logger_configs.push_back(
324       std::make_unique<TestAuditLoggerFactory::Config>());
325   rbac.logger_configs.push_back(
326       std::make_unique<TestAuditLoggerFactory::Config>());
327   GrpcAuthorizationEngine engine(std::move(rbac));
328   AuthorizationEngine::Decision decision =
329       engine.Evaluate(evaluate_args_util_.MakeEvaluateArgs());
330   EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kDeny);
331   EXPECT_EQ(decision.matching_policy_name, "");
332   EXPECT_THAT(
333       audit_logs_,
334       ::testing::ElementsAre(
335           absl::StrFormat(
336               "{\"authorized\":false,\"matched_rule\":\"\",\"policy_"
337               "name\":\"%s\",\"principal\":\"%s\",\"rpc_method\":\"%s\"}",
338               kPolicyName, kSpiffeId, kRpcMethod),
339           absl::StrFormat(
340               "{\"authorized\":false,\"matched_rule\":\"\",\"policy_"
341               "name\":\"%s\",\"principal\":\"%s\",\"rpc_method\":\"%s\"}",
342               kPolicyName, kSpiffeId, kRpcMethod)));
343 }
344 
345 }  // namespace grpc_core
346 
main(int argc,char ** argv)347 int main(int argc, char** argv) {
348   ::testing::InitGoogleTest(&argc, argv);
349   return RUN_ALL_TESTS();
350 }
351