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