xref: /aosp_15_r20/external/grpc-grpc/test/core/security/grpc_authorization_policy_provider_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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