blob: af235590f2ed1680bb924865c5fba0b25e5caff1 [file] [log] [blame]
Ivan Lozano86747a92023-06-21 14:25:47 +00001// 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 <grpc/support/port_platform.h>
16
17#include "src/core/lib/security/authorization/grpc_authorization_policy_provider.h"
18
19#include <gmock/gmock.h>
20#include <gtest/gtest.h>
21
22#include <grpc/grpc_security.h>
23
24#include "src/core/lib/security/authorization/grpc_authorization_engine.h"
25#include "test/core/util/test_config.h"
26#include "test/core/util/tls_utils.h"
27
28#define VALID_POLICY_PATH_1 \
29 "test/core/security/authorization/test_policies/valid_policy_1.json"
30#define VALID_POLICY_PATH_2 \
31 "test/core/security/authorization/test_policies/valid_policy_2.json"
32#define INVALID_POLICY_PATH \
33 "test/core/security/authorization/test_policies/invalid_policy.json"
34
35namespace grpc_core {
36
37TEST(AuthorizationPolicyProviderTest, StaticDataInitializationSuccessful) {
38 auto provider = StaticDataAuthorizationPolicyProvider::Create(
39 testing::GetFileContents(VALID_POLICY_PATH_1));
40 ASSERT_TRUE(provider.ok());
41 auto engines = (*provider)->engines();
42 auto* allow_engine =
43 dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get());
44 ASSERT_NE(allow_engine, nullptr);
45 EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow);
46 EXPECT_EQ(allow_engine->num_policies(), 1);
47 auto* deny_engine =
48 dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get());
49 ASSERT_NE(deny_engine, nullptr);
50 EXPECT_EQ(deny_engine->action(), Rbac::Action::kDeny);
51 EXPECT_EQ(deny_engine->num_policies(), 1);
52}
53
54TEST(AuthorizationPolicyProviderTest,
55 StaticDataInitializationFailedInvalidPolicy) {
56 auto provider = StaticDataAuthorizationPolicyProvider::Create(
57 testing::GetFileContents(INVALID_POLICY_PATH));
58 EXPECT_EQ(provider.status().code(), absl::StatusCode::kInvalidArgument);
59 EXPECT_EQ(provider.status().message(), "\"name\" field is not present.");
60}
61
62TEST(AuthorizationPolicyProviderTest,
63 FileWatcherInitializationSuccessValidPolicy) {
Shuo Wang Hsu67249fc2024-01-02 16:54:20 -080064 auto tmp_authz_policy = std::make_unique<testing::TmpFile>(
Ivan Lozano86747a92023-06-21 14:25:47 +000065 testing::GetFileContents(VALID_POLICY_PATH_1));
66 auto provider = FileWatcherAuthorizationPolicyProvider::Create(
67 tmp_authz_policy->name(), /*refresh_interval_sec=*/1);
68 ASSERT_TRUE(provider.ok());
69 auto engines = (*provider)->engines();
70 auto* allow_engine =
71 dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get());
72 ASSERT_NE(allow_engine, nullptr);
73 EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow);
74 EXPECT_EQ(allow_engine->num_policies(), 1);
75 auto* deny_engine =
76 dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get());
77 ASSERT_NE(deny_engine, nullptr);
78 EXPECT_EQ(deny_engine->action(), Rbac::Action::kDeny);
79 EXPECT_EQ(deny_engine->num_policies(), 1);
80}
81
82TEST(AuthorizationPolicyProviderTest,
83 FileWatcherInitializationFailedInvalidPolicy) {
Shuo Wang Hsu67249fc2024-01-02 16:54:20 -080084 auto tmp_authz_policy = std::make_unique<testing::TmpFile>(
Ivan Lozano86747a92023-06-21 14:25:47 +000085 testing::GetFileContents(INVALID_POLICY_PATH));
86 auto provider = FileWatcherAuthorizationPolicyProvider::Create(
87 tmp_authz_policy->name(), /*refresh_interval_sec=*/1);
88 EXPECT_EQ(provider.status().code(), absl::StatusCode::kInvalidArgument);
89 EXPECT_EQ(provider.status().message(), "\"name\" field is not present.");
90}
91
92TEST(AuthorizationPolicyProviderTest, FileWatcherSuccessValidPolicyRefresh) {
Shuo Wang Hsu67249fc2024-01-02 16:54:20 -080093 auto tmp_authz_policy = std::make_unique<testing::TmpFile>(
Ivan Lozano86747a92023-06-21 14:25:47 +000094 testing::GetFileContents(VALID_POLICY_PATH_1));
95 auto provider = FileWatcherAuthorizationPolicyProvider::Create(
96 tmp_authz_policy->name(), /*refresh_interval_sec=*/1);
97 ASSERT_TRUE(provider.ok());
98 auto engines = (*provider)->engines();
99 auto* allow_engine =
100 dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get());
101 ASSERT_NE(allow_engine, nullptr);
102 EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow);
103 EXPECT_EQ(allow_engine->num_policies(), 1);
104 auto* deny_engine =
105 dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get());
106 ASSERT_NE(deny_engine, nullptr);
107 EXPECT_EQ(deny_engine->action(), Rbac::Action::kDeny);
108 EXPECT_EQ(deny_engine->num_policies(), 1);
Shuo Wang Hsu67249fc2024-01-02 16:54:20 -0800109 gpr_event on_reload_done;
110 gpr_event_init(&on_reload_done);
111 std::function<void(bool contents_changed, absl::Status status)> callback =
112 [&on_reload_done](bool contents_changed, absl::Status status) {
113 if (contents_changed) {
114 EXPECT_TRUE(status.ok());
115 gpr_event_set(&on_reload_done, reinterpret_cast<void*>(1));
116 }
117 };
118 dynamic_cast<FileWatcherAuthorizationPolicyProvider*>(provider->get())
119 ->SetCallbackForTesting(std::move(callback));
Ivan Lozano86747a92023-06-21 14:25:47 +0000120 // Rewrite the file with a different valid authorization policy.
121 tmp_authz_policy->RewriteFile(testing::GetFileContents(VALID_POLICY_PATH_2));
Shuo Wang Hsu67249fc2024-01-02 16:54:20 -0800122 // Wait for the provider's refresh thread to read the updated files.
123 ASSERT_EQ(
124 gpr_event_wait(&on_reload_done, gpr_inf_future(GPR_CLOCK_MONOTONIC)),
125 reinterpret_cast<void*>(1));
Ivan Lozano86747a92023-06-21 14:25:47 +0000126 engines = (*provider)->engines();
127 allow_engine =
128 dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get());
129 ASSERT_NE(allow_engine, nullptr);
130 EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow);
131 EXPECT_EQ(allow_engine->num_policies(), 2);
132 deny_engine =
133 dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get());
Shuo Wang Hsu67249fc2024-01-02 16:54:20 -0800134 EXPECT_EQ(deny_engine, nullptr);
Ivan Lozano86747a92023-06-21 14:25:47 +0000135}
136
137TEST(AuthorizationPolicyProviderTest,
138 FileWatcherInvalidPolicyRefreshSkipReload) {
Shuo Wang Hsu67249fc2024-01-02 16:54:20 -0800139 auto tmp_authz_policy = std::make_unique<testing::TmpFile>(
Ivan Lozano86747a92023-06-21 14:25:47 +0000140 testing::GetFileContents(VALID_POLICY_PATH_1));
141 auto provider = FileWatcherAuthorizationPolicyProvider::Create(
142 tmp_authz_policy->name(), /*refresh_interval_sec=*/1);
143 ASSERT_TRUE(provider.ok());
144 auto engines = (*provider)->engines();
145 auto* allow_engine =
146 dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get());
147 ASSERT_NE(allow_engine, nullptr);
148 EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow);
149 EXPECT_EQ(allow_engine->num_policies(), 1);
150 auto* deny_engine =
151 dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get());
152 ASSERT_NE(deny_engine, nullptr);
153 EXPECT_EQ(deny_engine->action(), Rbac::Action::kDeny);
154 EXPECT_EQ(deny_engine->num_policies(), 1);
Shuo Wang Hsu67249fc2024-01-02 16:54:20 -0800155 gpr_event on_reload_done;
156 gpr_event_init(&on_reload_done);
157 std::function<void(bool contents_changed, absl::Status status)> callback =
158 [&on_reload_done](bool contents_changed, absl::Status status) {
159 if (contents_changed) {
160 EXPECT_EQ(status.code(), absl::StatusCode::kInvalidArgument);
161 EXPECT_EQ(status.message(), "\"name\" field is not present.");
162 gpr_event_set(&on_reload_done, reinterpret_cast<void*>(1));
163 }
164 };
165 dynamic_cast<FileWatcherAuthorizationPolicyProvider*>(provider->get())
166 ->SetCallbackForTesting(std::move(callback));
Ivan Lozano86747a92023-06-21 14:25:47 +0000167 // Skips the following policy update, and continues to use the valid policy.
168 tmp_authz_policy->RewriteFile(testing::GetFileContents(INVALID_POLICY_PATH));
Shuo Wang Hsu67249fc2024-01-02 16:54:20 -0800169 // Wait for the provider's refresh thread to read the updated files.
170 ASSERT_EQ(
171 gpr_event_wait(&on_reload_done, gpr_inf_future(GPR_CLOCK_MONOTONIC)),
172 reinterpret_cast<void*>(1));
Ivan Lozano86747a92023-06-21 14:25:47 +0000173 engines = (*provider)->engines();
174 allow_engine =
175 dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get());
176 ASSERT_NE(allow_engine, nullptr);
177 EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow);
178 EXPECT_EQ(allow_engine->num_policies(), 1);
179 deny_engine =
180 dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get());
181 ASSERT_NE(deny_engine, nullptr);
182 EXPECT_EQ(deny_engine->action(), Rbac::Action::kDeny);
183 EXPECT_EQ(deny_engine->num_policies(), 1);
Shuo Wang Hsu67249fc2024-01-02 16:54:20 -0800184 dynamic_cast<FileWatcherAuthorizationPolicyProvider*>(provider->get())
185 ->SetCallbackForTesting(nullptr);
Ivan Lozano86747a92023-06-21 14:25:47 +0000186}
187
188TEST(AuthorizationPolicyProviderTest, FileWatcherRecoversFromFailure) {
Shuo Wang Hsu67249fc2024-01-02 16:54:20 -0800189 auto tmp_authz_policy = std::make_unique<testing::TmpFile>(
Ivan Lozano86747a92023-06-21 14:25:47 +0000190 testing::GetFileContents(VALID_POLICY_PATH_1));
191 auto provider = FileWatcherAuthorizationPolicyProvider::Create(
192 tmp_authz_policy->name(), /*refresh_interval_sec=*/1);
193 ASSERT_TRUE(provider.ok());
194 auto engines = (*provider)->engines();
195 auto* allow_engine =
196 dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get());
197 ASSERT_NE(allow_engine, nullptr);
198 EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow);
199 EXPECT_EQ(allow_engine->num_policies(), 1);
200 auto* deny_engine =
201 dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get());
202 ASSERT_NE(deny_engine, nullptr);
203 EXPECT_EQ(deny_engine->action(), Rbac::Action::kDeny);
204 EXPECT_EQ(deny_engine->num_policies(), 1);
Shuo Wang Hsu67249fc2024-01-02 16:54:20 -0800205 gpr_event on_first_reload_done;
206 gpr_event_init(&on_first_reload_done);
207 std::function<void(bool contents_changed, absl::Status status)> callback1 =
208 [&on_first_reload_done](bool contents_changed, absl::Status status) {
209 if (contents_changed) {
210 EXPECT_EQ(status.code(), absl::StatusCode::kInvalidArgument);
211 EXPECT_EQ(status.message(), "\"name\" field is not present.");
212 gpr_event_set(&on_first_reload_done, reinterpret_cast<void*>(1));
213 }
214 };
215 dynamic_cast<FileWatcherAuthorizationPolicyProvider*>(provider->get())
216 ->SetCallbackForTesting(std::move(callback1));
Ivan Lozano86747a92023-06-21 14:25:47 +0000217 // Skips the following policy update, and continues to use the valid policy.
218 tmp_authz_policy->RewriteFile(testing::GetFileContents(INVALID_POLICY_PATH));
Shuo Wang Hsu67249fc2024-01-02 16:54:20 -0800219 // Wait for the provider's refresh thread to read the updated files.
220 ASSERT_EQ(gpr_event_wait(&on_first_reload_done,
221 gpr_inf_future(GPR_CLOCK_MONOTONIC)),
222 reinterpret_cast<void*>(1));
Ivan Lozano86747a92023-06-21 14:25:47 +0000223 engines = (*provider)->engines();
224 allow_engine =
225 dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get());
226 ASSERT_NE(allow_engine, nullptr);
227 EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow);
228 EXPECT_EQ(allow_engine->num_policies(), 1);
229 deny_engine =
230 dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get());
231 ASSERT_NE(deny_engine, nullptr);
232 EXPECT_EQ(deny_engine->action(), Rbac::Action::kDeny);
233 EXPECT_EQ(deny_engine->num_policies(), 1);
Shuo Wang Hsu67249fc2024-01-02 16:54:20 -0800234 gpr_event on_second_reload_done;
235 gpr_event_init(&on_second_reload_done);
236 std::function<void(bool contents_changed, absl::Status status)> callback2 =
237 [&on_second_reload_done](bool contents_changed, absl::Status status) {
238 if (contents_changed) {
239 EXPECT_TRUE(status.ok());
240 gpr_event_set(&on_second_reload_done, reinterpret_cast<void*>(1));
241 }
242 };
243 dynamic_cast<FileWatcherAuthorizationPolicyProvider*>(provider->get())
244 ->SetCallbackForTesting(std::move(callback2));
Ivan Lozano86747a92023-06-21 14:25:47 +0000245 // Rewrite the file with a valid authorization policy.
246 tmp_authz_policy->RewriteFile(testing::GetFileContents(VALID_POLICY_PATH_2));
Shuo Wang Hsu67249fc2024-01-02 16:54:20 -0800247 // Wait for the provider's refresh thread to read the updated files.
248 ASSERT_EQ(gpr_event_wait(&on_second_reload_done,
249 gpr_inf_future(GPR_CLOCK_MONOTONIC)),
250 reinterpret_cast<void*>(1));
Ivan Lozano86747a92023-06-21 14:25:47 +0000251 engines = (*provider)->engines();
252 allow_engine =
253 dynamic_cast<GrpcAuthorizationEngine*>(engines.allow_engine.get());
254 ASSERT_NE(allow_engine, nullptr);
255 EXPECT_EQ(allow_engine->action(), Rbac::Action::kAllow);
256 EXPECT_EQ(allow_engine->num_policies(), 2);
257 deny_engine =
258 dynamic_cast<GrpcAuthorizationEngine*>(engines.deny_engine.get());
Shuo Wang Hsu67249fc2024-01-02 16:54:20 -0800259 EXPECT_EQ(deny_engine, nullptr);
Ivan Lozano86747a92023-06-21 14:25:47 +0000260}
261
262} // namespace grpc_core
263
264int main(int argc, char** argv) {
265 grpc::testing::TestEnvironment env(&argc, argv);
266 ::testing::InitGoogleTest(&argc, argv);
267 grpc_init();
268 int ret = RUN_ALL_TESTS();
269 grpc_shutdown();
270 return ret;
271}