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