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