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