]>
Commit | Line | Data |
---|---|---|
31f18b77 FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2015 Red Hat | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | ||
15 | #include <string> | |
16 | ||
17 | #include <boost/intrusive_ptr.hpp> | |
18 | #include <boost/optional.hpp> | |
19 | ||
20 | #include <gtest/gtest.h> | |
21 | ||
b32b8144 | 22 | #include "include/stringify.h" |
31f18b77 FG |
23 | #include "common/code_environment.h" |
24 | #include "common/ceph_context.h" | |
25 | #include "global/global_init.h" | |
26 | #include "rgw/rgw_auth.h" | |
27 | #include "rgw/rgw_iam_policy.h" | |
b32b8144 | 28 | #include "rgw/rgw_op.h" |
f67539c2 | 29 | #include "rgw_sal_rados.h" |
31f18b77 FG |
30 | |
31 | ||
32 | using std::string; | |
33 | using std::vector; | |
34 | ||
35 | using boost::container::flat_set; | |
36 | using boost::intrusive_ptr; | |
37 | using boost::make_optional; | |
38 | using boost::none; | |
31f18b77 FG |
39 | |
40 | using rgw::auth::Identity; | |
41 | using rgw::auth::Principal; | |
42 | ||
eafe8130 | 43 | using rgw::ARN; |
31f18b77 FG |
44 | using rgw::IAM::Effect; |
45 | using rgw::IAM::Environment; | |
eafe8130 | 46 | using rgw::Partition; |
31f18b77 FG |
47 | using rgw::IAM::Policy; |
48 | using rgw::IAM::s3All; | |
49 | using rgw::IAM::s3Count; | |
50 | using rgw::IAM::s3GetAccelerateConfiguration; | |
51 | using rgw::IAM::s3GetBucketAcl; | |
52 | using rgw::IAM::s3GetBucketCORS; | |
53 | using rgw::IAM::s3GetBucketLocation; | |
54 | using rgw::IAM::s3GetBucketLogging; | |
55 | using rgw::IAM::s3GetBucketNotification; | |
56 | using rgw::IAM::s3GetBucketPolicy; | |
9f95a23c TL |
57 | using rgw::IAM::s3GetBucketPolicyStatus; |
58 | using rgw::IAM::s3GetBucketPublicAccessBlock; | |
20effc67 | 59 | using rgw::IAM::s3GetBucketEncryption; |
31f18b77 FG |
60 | using rgw::IAM::s3GetBucketRequestPayment; |
61 | using rgw::IAM::s3GetBucketTagging; | |
62 | using rgw::IAM::s3GetBucketVersioning; | |
63 | using rgw::IAM::s3GetBucketWebsite; | |
64 | using rgw::IAM::s3GetLifecycleConfiguration; | |
65 | using rgw::IAM::s3GetObject; | |
66 | using rgw::IAM::s3GetObjectAcl; | |
67 | using rgw::IAM::s3GetObjectVersionAcl; | |
68 | using rgw::IAM::s3GetObjectTorrent; | |
d2e6a577 | 69 | using rgw::IAM::s3GetObjectTagging; |
31f18b77 | 70 | using rgw::IAM::s3GetObjectVersion; |
d2e6a577 | 71 | using rgw::IAM::s3GetObjectVersionTagging; |
31f18b77 | 72 | using rgw::IAM::s3GetObjectVersionTorrent; |
9f95a23c | 73 | using rgw::IAM::s3GetPublicAccessBlock; |
31f18b77 FG |
74 | using rgw::IAM::s3GetReplicationConfiguration; |
75 | using rgw::IAM::s3ListAllMyBuckets; | |
76 | using rgw::IAM::s3ListBucket; | |
77 | using rgw::IAM::s3ListBucket; | |
28e407b8 | 78 | using rgw::IAM::s3ListBucketMultipartUploads; |
31f18b77 FG |
79 | using rgw::IAM::s3ListBucketVersions; |
80 | using rgw::IAM::s3ListMultipartUploadParts; | |
11fdf7f2 | 81 | using rgw::IAM::None; |
31f18b77 FG |
82 | using rgw::IAM::s3PutBucketAcl; |
83 | using rgw::IAM::s3PutBucketPolicy; | |
eafe8130 TL |
84 | using rgw::IAM::s3GetBucketObjectLockConfiguration; |
85 | using rgw::IAM::s3GetObjectRetention; | |
86 | using rgw::IAM::s3GetObjectLegalHold; | |
9f95a23c | 87 | using rgw::Service; |
31f18b77 FG |
88 | using rgw::IAM::TokenID; |
89 | using rgw::IAM::Version; | |
11fdf7f2 TL |
90 | using rgw::IAM::Action_t; |
91 | using rgw::IAM::NotAction_t; | |
92 | using rgw::IAM::iamCreateRole; | |
93 | using rgw::IAM::iamDeleteRole; | |
94 | using rgw::IAM::iamAll; | |
95 | using rgw::IAM::stsAll; | |
9f95a23c | 96 | using rgw::IAM::allCount; |
31f18b77 FG |
97 | |
98 | class FakeIdentity : public Identity { | |
99 | const Principal id; | |
100 | public: | |
101 | ||
11fdf7f2 TL |
102 | explicit FakeIdentity(Principal&& id) : id(std::move(id)) {} |
103 | uint32_t get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const override { | |
104 | ceph_abort(); | |
31f18b77 FG |
105 | return 0; |
106 | }; | |
107 | ||
108 | bool is_admin_of(const rgw_user& uid) const override { | |
11fdf7f2 | 109 | ceph_abort(); |
31f18b77 FG |
110 | return false; |
111 | } | |
112 | ||
113 | bool is_owner_of(const rgw_user& uid) const override { | |
11fdf7f2 | 114 | ceph_abort(); |
31f18b77 FG |
115 | return false; |
116 | } | |
117 | ||
118 | virtual uint32_t get_perm_mask() const override { | |
11fdf7f2 TL |
119 | ceph_abort(); |
120 | return 0; | |
121 | } | |
122 | ||
11fdf7f2 | 123 | string get_acct_name() const override { |
31f18b77 FG |
124 | abort(); |
125 | return 0; | |
126 | } | |
127 | ||
f6b5b4d7 TL |
128 | string get_subuser() const override { |
129 | abort(); | |
130 | return 0; | |
131 | } | |
132 | ||
31f18b77 | 133 | void to_str(std::ostream& out) const override { |
b32b8144 | 134 | out << id; |
31f18b77 FG |
135 | } |
136 | ||
137 | bool is_identity(const flat_set<Principal>& ids) const override { | |
b32b8144 FG |
138 | if (id.is_wildcard() && (!ids.empty())) { |
139 | return true; | |
140 | } | |
141 | return ids.find(id) != ids.end() || ids.find(Principal::wildcard()) != ids.end(); | |
31f18b77 | 142 | } |
522d829b TL |
143 | |
144 | uint32_t get_identity_type() const override { | |
145 | return TYPE_RGW; | |
146 | } | |
31f18b77 FG |
147 | }; |
148 | ||
149 | class PolicyTest : public ::testing::Test { | |
150 | protected: | |
151 | intrusive_ptr<CephContext> cct; | |
152 | static const string arbitrary_tenant; | |
153 | static string example1; | |
154 | static string example2; | |
155 | static string example3; | |
11fdf7f2 TL |
156 | static string example4; |
157 | static string example5; | |
158 | static string example6; | |
9f95a23c | 159 | static string example7; |
31f18b77 FG |
160 | public: |
161 | PolicyTest() { | |
162 | cct = new CephContext(CEPH_ENTITY_TYPE_CLIENT); | |
163 | } | |
164 | }; | |
165 | ||
166 | TEST_F(PolicyTest, Parse1) { | |
11fdf7f2 | 167 | boost::optional<Policy> p; |
31f18b77 FG |
168 | |
169 | ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, | |
170 | bufferlist::static_from_string(example1))); | |
171 | ASSERT_TRUE(p); | |
172 | ||
173 | EXPECT_EQ(p->text, example1); | |
174 | EXPECT_EQ(p->version, Version::v2012_10_17); | |
175 | EXPECT_FALSE(p->id); | |
176 | EXPECT_FALSE(p->statements[0].sid); | |
177 | EXPECT_FALSE(p->statements.empty()); | |
178 | EXPECT_EQ(p->statements.size(), 1U); | |
179 | EXPECT_TRUE(p->statements[0].princ.empty()); | |
180 | EXPECT_TRUE(p->statements[0].noprinc.empty()); | |
181 | EXPECT_EQ(p->statements[0].effect, Effect::Allow); | |
11fdf7f2 TL |
182 | Action_t act; |
183 | act[s3ListBucket] = 1; | |
184 | EXPECT_EQ(p->statements[0].action, act); | |
185 | EXPECT_EQ(p->statements[0].notaction, None); | |
31f18b77 FG |
186 | ASSERT_FALSE(p->statements[0].resource.empty()); |
187 | ASSERT_EQ(p->statements[0].resource.size(), 1U); | |
188 | EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws); | |
189 | EXPECT_EQ(p->statements[0].resource.begin()->service, Service::s3); | |
190 | EXPECT_TRUE(p->statements[0].resource.begin()->region.empty()); | |
191 | EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant); | |
192 | EXPECT_EQ(p->statements[0].resource.begin()->resource, "example_bucket"); | |
193 | EXPECT_TRUE(p->statements[0].notresource.empty()); | |
194 | EXPECT_TRUE(p->statements[0].conditions.empty()); | |
195 | } | |
196 | ||
197 | TEST_F(PolicyTest, Eval1) { | |
198 | auto p = Policy(cct.get(), arbitrary_tenant, | |
199 | bufferlist::static_from_string(example1)); | |
200 | Environment e; | |
201 | ||
20effc67 TL |
202 | ARN arn1(Partition::aws, Service::s3, |
203 | "", arbitrary_tenant, "example_bucket"); | |
204 | EXPECT_EQ(p.eval(e, none, s3ListBucket, arn1), | |
31f18b77 FG |
205 | Effect::Allow); |
206 | ||
20effc67 TL |
207 | ARN arn2(Partition::aws, Service::s3, |
208 | "", arbitrary_tenant, "example_bucket"); | |
209 | EXPECT_EQ(p.eval(e, none, s3PutBucketAcl, arn2), | |
31f18b77 FG |
210 | Effect::Pass); |
211 | ||
20effc67 TL |
212 | ARN arn3(Partition::aws, Service::s3, |
213 | "", arbitrary_tenant, "erroneous_bucket"); | |
214 | EXPECT_EQ(p.eval(e, none, s3ListBucket, arn3), | |
31f18b77 FG |
215 | Effect::Pass); |
216 | ||
217 | } | |
218 | ||
219 | TEST_F(PolicyTest, Parse2) { | |
11fdf7f2 | 220 | boost::optional<Policy> p; |
31f18b77 FG |
221 | |
222 | ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, | |
223 | bufferlist::static_from_string(example2))); | |
224 | ASSERT_TRUE(p); | |
225 | ||
226 | EXPECT_EQ(p->text, example2); | |
227 | EXPECT_EQ(p->version, Version::v2012_10_17); | |
228 | EXPECT_EQ(*p->id, "S3-Account-Permissions"); | |
229 | ASSERT_FALSE(p->statements.empty()); | |
230 | EXPECT_EQ(p->statements.size(), 1U); | |
231 | EXPECT_EQ(*p->statements[0].sid, "1"); | |
232 | EXPECT_FALSE(p->statements[0].princ.empty()); | |
233 | EXPECT_EQ(p->statements[0].princ.size(), 1U); | |
234 | EXPECT_EQ(*p->statements[0].princ.begin(), | |
235 | Principal::tenant("ACCOUNT-ID-WITHOUT-HYPHENS")); | |
236 | EXPECT_TRUE(p->statements[0].noprinc.empty()); | |
237 | EXPECT_EQ(p->statements[0].effect, Effect::Allow); | |
11fdf7f2 TL |
238 | Action_t act; |
239 | for (auto i = 0ULL; i < s3Count; i++) | |
240 | act[i] = 1; | |
241 | act[s3All] = 1; | |
242 | EXPECT_EQ(p->statements[0].action, act); | |
243 | EXPECT_EQ(p->statements[0].notaction, None); | |
31f18b77 FG |
244 | ASSERT_FALSE(p->statements[0].resource.empty()); |
245 | ASSERT_EQ(p->statements[0].resource.size(), 2U); | |
246 | EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws); | |
247 | EXPECT_EQ(p->statements[0].resource.begin()->service, Service::s3); | |
248 | EXPECT_TRUE(p->statements[0].resource.begin()->region.empty()); | |
249 | EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant); | |
250 | EXPECT_EQ(p->statements[0].resource.begin()->resource, "mybucket"); | |
251 | EXPECT_EQ((p->statements[0].resource.begin() + 1)->partition, | |
252 | Partition::aws); | |
253 | EXPECT_EQ((p->statements[0].resource.begin() + 1)->service, | |
254 | Service::s3); | |
255 | EXPECT_TRUE((p->statements[0].resource.begin() + 1)->region.empty()); | |
256 | EXPECT_EQ((p->statements[0].resource.begin() + 1)->account, | |
257 | arbitrary_tenant); | |
258 | EXPECT_EQ((p->statements[0].resource.begin() + 1)->resource, "mybucket/*"); | |
259 | EXPECT_TRUE(p->statements[0].notresource.empty()); | |
260 | EXPECT_TRUE(p->statements[0].conditions.empty()); | |
261 | } | |
262 | ||
263 | TEST_F(PolicyTest, Eval2) { | |
264 | auto p = Policy(cct.get(), arbitrary_tenant, | |
265 | bufferlist::static_from_string(example2)); | |
266 | Environment e; | |
267 | ||
268 | auto trueacct = FakeIdentity( | |
269 | Principal::tenant("ACCOUNT-ID-WITHOUT-HYPHENS")); | |
270 | ||
271 | auto notacct = FakeIdentity( | |
272 | Principal::tenant("some-other-account")); | |
273 | for (auto i = 0ULL; i < s3Count; ++i) { | |
20effc67 TL |
274 | ARN arn1(Partition::aws, Service::s3, |
275 | "", arbitrary_tenant, "mybucket"); | |
276 | EXPECT_EQ(p.eval(e, trueacct, i, arn1), | |
31f18b77 | 277 | Effect::Allow); |
20effc67 TL |
278 | ARN arn2(Partition::aws, Service::s3, |
279 | "", arbitrary_tenant, "mybucket/myobject"); | |
280 | EXPECT_EQ(p.eval(e, trueacct, i, arn2), | |
31f18b77 | 281 | Effect::Allow); |
20effc67 TL |
282 | ARN arn3(Partition::aws, Service::s3, |
283 | "", arbitrary_tenant, "mybucket"); | |
284 | EXPECT_EQ(p.eval(e, notacct, i, arn3), | |
31f18b77 | 285 | Effect::Pass); |
20effc67 TL |
286 | ARN arn4(Partition::aws, Service::s3, |
287 | "", arbitrary_tenant, "mybucket/myobject"); | |
288 | EXPECT_EQ(p.eval(e, notacct, i, arn4), | |
31f18b77 | 289 | Effect::Pass); |
20effc67 TL |
290 | ARN arn5(Partition::aws, Service::s3, |
291 | "", arbitrary_tenant, "notyourbucket"); | |
292 | EXPECT_EQ(p.eval(e, trueacct, i, arn5), | |
31f18b77 | 293 | Effect::Pass); |
20effc67 TL |
294 | ARN arn6(Partition::aws, Service::s3, |
295 | "", arbitrary_tenant, "notyourbucket/notyourobject"); | |
296 | EXPECT_EQ(p.eval(e, trueacct, i, arn6), | |
31f18b77 FG |
297 | Effect::Pass); |
298 | ||
299 | } | |
300 | } | |
301 | ||
302 | TEST_F(PolicyTest, Parse3) { | |
11fdf7f2 | 303 | boost::optional<Policy> p; |
31f18b77 FG |
304 | |
305 | ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, | |
306 | bufferlist::static_from_string(example3))); | |
307 | ASSERT_TRUE(p); | |
308 | ||
309 | EXPECT_EQ(p->text, example3); | |
310 | EXPECT_EQ(p->version, Version::v2012_10_17); | |
311 | EXPECT_FALSE(p->id); | |
312 | ASSERT_FALSE(p->statements.empty()); | |
313 | EXPECT_EQ(p->statements.size(), 3U); | |
314 | ||
315 | EXPECT_EQ(*p->statements[0].sid, "FirstStatement"); | |
316 | EXPECT_TRUE(p->statements[0].princ.empty()); | |
317 | EXPECT_TRUE(p->statements[0].noprinc.empty()); | |
318 | EXPECT_EQ(p->statements[0].effect, Effect::Allow); | |
11fdf7f2 TL |
319 | Action_t act; |
320 | act[s3PutBucketPolicy] = 1; | |
321 | EXPECT_EQ(p->statements[0].action, act); | |
322 | EXPECT_EQ(p->statements[0].notaction, None); | |
31f18b77 FG |
323 | ASSERT_FALSE(p->statements[0].resource.empty()); |
324 | ASSERT_EQ(p->statements[0].resource.size(), 1U); | |
325 | EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::wildcard); | |
326 | EXPECT_EQ(p->statements[0].resource.begin()->service, Service::wildcard); | |
327 | EXPECT_EQ(p->statements[0].resource.begin()->region, "*"); | |
328 | EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant); | |
329 | EXPECT_EQ(p->statements[0].resource.begin()->resource, "*"); | |
330 | EXPECT_TRUE(p->statements[0].notresource.empty()); | |
331 | EXPECT_TRUE(p->statements[0].conditions.empty()); | |
332 | ||
333 | EXPECT_EQ(*p->statements[1].sid, "SecondStatement"); | |
334 | EXPECT_TRUE(p->statements[1].princ.empty()); | |
335 | EXPECT_TRUE(p->statements[1].noprinc.empty()); | |
336 | EXPECT_EQ(p->statements[1].effect, Effect::Allow); | |
11fdf7f2 TL |
337 | Action_t act1; |
338 | act1[s3ListAllMyBuckets] = 1; | |
339 | EXPECT_EQ(p->statements[1].action, act1); | |
340 | EXPECT_EQ(p->statements[1].notaction, None); | |
31f18b77 FG |
341 | ASSERT_FALSE(p->statements[1].resource.empty()); |
342 | ASSERT_EQ(p->statements[1].resource.size(), 1U); | |
343 | EXPECT_EQ(p->statements[1].resource.begin()->partition, Partition::wildcard); | |
344 | EXPECT_EQ(p->statements[1].resource.begin()->service, Service::wildcard); | |
345 | EXPECT_EQ(p->statements[1].resource.begin()->region, "*"); | |
346 | EXPECT_EQ(p->statements[1].resource.begin()->account, arbitrary_tenant); | |
347 | EXPECT_EQ(p->statements[1].resource.begin()->resource, "*"); | |
348 | EXPECT_TRUE(p->statements[1].notresource.empty()); | |
349 | EXPECT_TRUE(p->statements[1].conditions.empty()); | |
350 | ||
351 | EXPECT_EQ(*p->statements[2].sid, "ThirdStatement"); | |
352 | EXPECT_TRUE(p->statements[2].princ.empty()); | |
353 | EXPECT_TRUE(p->statements[2].noprinc.empty()); | |
354 | EXPECT_EQ(p->statements[2].effect, Effect::Allow); | |
11fdf7f2 TL |
355 | Action_t act2; |
356 | act2[s3ListMultipartUploadParts] = 1; | |
357 | act2[s3ListBucket] = 1; | |
358 | act2[s3ListBucketVersions] = 1; | |
359 | act2[s3ListAllMyBuckets] = 1; | |
360 | act2[s3ListBucketMultipartUploads] = 1; | |
361 | act2[s3GetObject] = 1; | |
362 | act2[s3GetObjectVersion] = 1; | |
363 | act2[s3GetObjectAcl] = 1; | |
364 | act2[s3GetObjectVersionAcl] = 1; | |
365 | act2[s3GetObjectTorrent] = 1; | |
366 | act2[s3GetObjectVersionTorrent] = 1; | |
367 | act2[s3GetAccelerateConfiguration] = 1; | |
368 | act2[s3GetBucketAcl] = 1; | |
369 | act2[s3GetBucketCORS] = 1; | |
370 | act2[s3GetBucketVersioning] = 1; | |
371 | act2[s3GetBucketRequestPayment] = 1; | |
372 | act2[s3GetBucketLocation] = 1; | |
373 | act2[s3GetBucketPolicy] = 1; | |
374 | act2[s3GetBucketNotification] = 1; | |
375 | act2[s3GetBucketLogging] = 1; | |
376 | act2[s3GetBucketTagging] = 1; | |
377 | act2[s3GetBucketWebsite] = 1; | |
378 | act2[s3GetLifecycleConfiguration] = 1; | |
379 | act2[s3GetReplicationConfiguration] = 1; | |
380 | act2[s3GetObjectTagging] = 1; | |
381 | act2[s3GetObjectVersionTagging] = 1; | |
eafe8130 TL |
382 | act2[s3GetBucketObjectLockConfiguration] = 1; |
383 | act2[s3GetObjectRetention] = 1; | |
384 | act2[s3GetObjectLegalHold] = 1; | |
9f95a23c TL |
385 | act2[s3GetBucketPolicyStatus] = 1; |
386 | act2[s3GetBucketPublicAccessBlock] = 1; | |
387 | act2[s3GetPublicAccessBlock] = 1; | |
20effc67 | 388 | act2[s3GetBucketEncryption] = 1; |
11fdf7f2 TL |
389 | |
390 | EXPECT_EQ(p->statements[2].action, act2); | |
391 | EXPECT_EQ(p->statements[2].notaction, None); | |
31f18b77 FG |
392 | ASSERT_FALSE(p->statements[2].resource.empty()); |
393 | ASSERT_EQ(p->statements[2].resource.size(), 2U); | |
394 | EXPECT_EQ(p->statements[2].resource.begin()->partition, Partition::aws); | |
395 | EXPECT_EQ(p->statements[2].resource.begin()->service, Service::s3); | |
396 | EXPECT_TRUE(p->statements[2].resource.begin()->region.empty()); | |
397 | EXPECT_EQ(p->statements[2].resource.begin()->account, arbitrary_tenant); | |
398 | EXPECT_EQ(p->statements[2].resource.begin()->resource, "confidential-data"); | |
399 | EXPECT_EQ((p->statements[2].resource.begin() + 1)->partition, | |
400 | Partition::aws); | |
401 | EXPECT_EQ((p->statements[2].resource.begin() + 1)->service, Service::s3); | |
402 | EXPECT_TRUE((p->statements[2].resource.begin() + 1)->region.empty()); | |
403 | EXPECT_EQ((p->statements[2].resource.begin() + 1)->account, | |
404 | arbitrary_tenant); | |
405 | EXPECT_EQ((p->statements[2].resource.begin() + 1)->resource, | |
406 | "confidential-data/*"); | |
407 | EXPECT_TRUE(p->statements[2].notresource.empty()); | |
408 | ASSERT_FALSE(p->statements[2].conditions.empty()); | |
409 | ASSERT_EQ(p->statements[2].conditions.size(), 1U); | |
410 | EXPECT_EQ(p->statements[2].conditions[0].op, TokenID::Bool); | |
411 | EXPECT_EQ(p->statements[2].conditions[0].key, "aws:MultiFactorAuthPresent"); | |
412 | EXPECT_FALSE(p->statements[2].conditions[0].ifexists); | |
413 | ASSERT_FALSE(p->statements[2].conditions[0].vals.empty()); | |
414 | EXPECT_EQ(p->statements[2].conditions[0].vals.size(), 1U); | |
415 | EXPECT_EQ(p->statements[2].conditions[0].vals[0], "true"); | |
416 | } | |
417 | ||
418 | TEST_F(PolicyTest, Eval3) { | |
419 | auto p = Policy(cct.get(), arbitrary_tenant, | |
420 | bufferlist::static_from_string(example3)); | |
421 | Environment em; | |
422 | Environment tr = { { "aws:MultiFactorAuthPresent", "true" } }; | |
423 | Environment fa = { { "aws:MultiFactorAuthPresent", "false" } }; | |
424 | ||
11fdf7f2 TL |
425 | Action_t s3allow; |
426 | s3allow[s3ListMultipartUploadParts] = 1; | |
427 | s3allow[s3ListBucket] = 1; | |
428 | s3allow[s3ListBucketVersions] = 1; | |
429 | s3allow[s3ListAllMyBuckets] = 1; | |
430 | s3allow[s3ListBucketMultipartUploads] = 1; | |
431 | s3allow[s3GetObject] = 1; | |
432 | s3allow[s3GetObjectVersion] = 1; | |
433 | s3allow[s3GetObjectAcl] = 1; | |
434 | s3allow[s3GetObjectVersionAcl] = 1; | |
435 | s3allow[s3GetObjectTorrent] = 1; | |
436 | s3allow[s3GetObjectVersionTorrent] = 1; | |
437 | s3allow[s3GetAccelerateConfiguration] = 1; | |
438 | s3allow[s3GetBucketAcl] = 1; | |
439 | s3allow[s3GetBucketCORS] = 1; | |
440 | s3allow[s3GetBucketVersioning] = 1; | |
441 | s3allow[s3GetBucketRequestPayment] = 1; | |
442 | s3allow[s3GetBucketLocation] = 1; | |
443 | s3allow[s3GetBucketPolicy] = 1; | |
444 | s3allow[s3GetBucketNotification] = 1; | |
445 | s3allow[s3GetBucketLogging] = 1; | |
446 | s3allow[s3GetBucketTagging] = 1; | |
447 | s3allow[s3GetBucketWebsite] = 1; | |
448 | s3allow[s3GetLifecycleConfiguration] = 1; | |
449 | s3allow[s3GetReplicationConfiguration] = 1; | |
450 | s3allow[s3GetObjectTagging] = 1; | |
451 | s3allow[s3GetObjectVersionTagging] = 1; | |
eafe8130 TL |
452 | s3allow[s3GetBucketObjectLockConfiguration] = 1; |
453 | s3allow[s3GetObjectRetention] = 1; | |
454 | s3allow[s3GetObjectLegalHold] = 1; | |
9f95a23c TL |
455 | s3allow[s3GetBucketPolicyStatus] = 1; |
456 | s3allow[s3GetBucketPublicAccessBlock] = 1; | |
457 | s3allow[s3GetPublicAccessBlock] = 1; | |
20effc67 | 458 | s3allow[s3GetBucketEncryption] = 1; |
31f18b77 | 459 | |
20effc67 TL |
460 | ARN arn1(Partition::aws, Service::s3, |
461 | "", arbitrary_tenant, "mybucket"); | |
462 | EXPECT_EQ(p.eval(em, none, s3PutBucketPolicy, arn1), | |
31f18b77 FG |
463 | Effect::Allow); |
464 | ||
20effc67 TL |
465 | ARN arn2(Partition::aws, Service::s3, |
466 | "", arbitrary_tenant, "mybucket"); | |
467 | EXPECT_EQ(p.eval(em, none, s3PutBucketPolicy, arn2), | |
31f18b77 FG |
468 | Effect::Allow); |
469 | ||
470 | ||
11fdf7f2 | 471 | for (auto op = 0ULL; op < s3Count; ++op) { |
31f18b77 FG |
472 | if ((op == s3ListAllMyBuckets) || (op == s3PutBucketPolicy)) { |
473 | continue; | |
474 | } | |
20effc67 TL |
475 | ARN arn3(Partition::aws, Service::s3, |
476 | "", arbitrary_tenant, "confidential-data"); | |
477 | EXPECT_EQ(p.eval(em, none, op, arn3), | |
31f18b77 | 478 | Effect::Pass); |
20effc67 TL |
479 | ARN arn4(Partition::aws, Service::s3, |
480 | "", arbitrary_tenant, "confidential-data"); | |
481 | EXPECT_EQ(p.eval(tr, none, op, arn4), | |
11fdf7f2 | 482 | s3allow[op] ? Effect::Allow : Effect::Pass); |
20effc67 TL |
483 | ARN arn5(Partition::aws, Service::s3, |
484 | "", arbitrary_tenant, "confidential-data"); | |
485 | EXPECT_EQ(p.eval(fa, none, op, arn5), | |
31f18b77 | 486 | Effect::Pass); |
20effc67 TL |
487 | ARN arn6(Partition::aws, Service::s3, |
488 | "", arbitrary_tenant, "confidential-data/moo"); | |
489 | EXPECT_EQ(p.eval(em, none, op, arn6), | |
31f18b77 | 490 | Effect::Pass); |
20effc67 TL |
491 | ARN arn7(Partition::aws, Service::s3, |
492 | "", arbitrary_tenant, "confidential-data/moo"); | |
493 | EXPECT_EQ(p.eval(tr, none, op, arn7), | |
11fdf7f2 | 494 | s3allow[op] ? Effect::Allow : Effect::Pass); |
20effc67 TL |
495 | ARN arn8(Partition::aws, Service::s3, |
496 | "", arbitrary_tenant, "confidential-data/moo"); | |
497 | EXPECT_EQ(p.eval(fa, none, op, arn8), | |
31f18b77 | 498 | Effect::Pass); |
20effc67 TL |
499 | ARN arn9(Partition::aws, Service::s3, |
500 | "", arbitrary_tenant, "really-confidential-data"); | |
501 | EXPECT_EQ(p.eval(em, none, op, arn9), | |
31f18b77 | 502 | Effect::Pass); |
20effc67 TL |
503 | ARN arn10(Partition::aws, Service::s3, |
504 | "", arbitrary_tenant, "really-confidential-data"); | |
505 | EXPECT_EQ(p.eval(tr, none, op, arn10), | |
31f18b77 | 506 | Effect::Pass); |
20effc67 TL |
507 | ARN arn11(Partition::aws, Service::s3, |
508 | "", arbitrary_tenant, "really-confidential-data"); | |
509 | EXPECT_EQ(p.eval(fa, none, op, arn11), | |
31f18b77 | 510 | Effect::Pass); |
20effc67 | 511 | ARN arn12(Partition::aws, Service::s3, |
31f18b77 | 512 | "", arbitrary_tenant, |
20effc67 TL |
513 | "really-confidential-data/moo"); |
514 | EXPECT_EQ(p.eval(em, none, op, arn12), Effect::Pass); | |
515 | ARN arn13(Partition::aws, Service::s3, | |
31f18b77 | 516 | "", arbitrary_tenant, |
20effc67 TL |
517 | "really-confidential-data/moo"); |
518 | EXPECT_EQ(p.eval(tr, none, op, arn13), Effect::Pass); | |
519 | ARN arn14(Partition::aws, Service::s3, | |
31f18b77 | 520 | "", arbitrary_tenant, |
20effc67 TL |
521 | "really-confidential-data/moo"); |
522 | EXPECT_EQ(p.eval(fa, none, op, arn14), Effect::Pass); | |
31f18b77 FG |
523 | |
524 | } | |
525 | } | |
526 | ||
11fdf7f2 TL |
527 | TEST_F(PolicyTest, Parse4) { |
528 | boost::optional<Policy> p; | |
529 | ||
530 | ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, | |
531 | bufferlist::static_from_string(example4))); | |
532 | ASSERT_TRUE(p); | |
533 | ||
534 | EXPECT_EQ(p->text, example4); | |
535 | EXPECT_EQ(p->version, Version::v2012_10_17); | |
536 | EXPECT_FALSE(p->id); | |
537 | EXPECT_FALSE(p->statements[0].sid); | |
538 | EXPECT_FALSE(p->statements.empty()); | |
539 | EXPECT_EQ(p->statements.size(), 1U); | |
540 | EXPECT_TRUE(p->statements[0].princ.empty()); | |
541 | EXPECT_TRUE(p->statements[0].noprinc.empty()); | |
542 | EXPECT_EQ(p->statements[0].effect, Effect::Allow); | |
543 | Action_t act; | |
544 | act[iamCreateRole] = 1; | |
545 | EXPECT_EQ(p->statements[0].action, act); | |
546 | EXPECT_EQ(p->statements[0].notaction, None); | |
547 | ASSERT_FALSE(p->statements[0].resource.empty()); | |
548 | ASSERT_EQ(p->statements[0].resource.size(), 1U); | |
549 | EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::wildcard); | |
550 | EXPECT_EQ(p->statements[0].resource.begin()->service, Service::wildcard); | |
551 | EXPECT_EQ(p->statements[0].resource.begin()->region, "*"); | |
552 | EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant); | |
553 | EXPECT_EQ(p->statements[0].resource.begin()->resource, "*"); | |
554 | EXPECT_TRUE(p->statements[0].notresource.empty()); | |
555 | EXPECT_TRUE(p->statements[0].conditions.empty()); | |
556 | } | |
557 | ||
558 | TEST_F(PolicyTest, Eval4) { | |
559 | auto p = Policy(cct.get(), arbitrary_tenant, | |
560 | bufferlist::static_from_string(example4)); | |
561 | Environment e; | |
562 | ||
20effc67 TL |
563 | ARN arn1(Partition::aws, Service::iam, |
564 | "", arbitrary_tenant, "role/example_role"); | |
565 | EXPECT_EQ(p.eval(e, none, iamCreateRole, arn1), | |
11fdf7f2 TL |
566 | Effect::Allow); |
567 | ||
20effc67 TL |
568 | ARN arn2(Partition::aws, Service::iam, |
569 | "", arbitrary_tenant, "role/example_role"); | |
570 | EXPECT_EQ(p.eval(e, none, iamDeleteRole, arn2), | |
11fdf7f2 TL |
571 | Effect::Pass); |
572 | } | |
573 | ||
574 | TEST_F(PolicyTest, Parse5) { | |
575 | boost::optional<Policy> p; | |
576 | ||
577 | ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, | |
578 | bufferlist::static_from_string(example5))); | |
579 | ASSERT_TRUE(p); | |
580 | EXPECT_EQ(p->text, example5); | |
581 | EXPECT_EQ(p->version, Version::v2012_10_17); | |
582 | EXPECT_FALSE(p->id); | |
583 | EXPECT_FALSE(p->statements[0].sid); | |
584 | EXPECT_FALSE(p->statements.empty()); | |
585 | EXPECT_EQ(p->statements.size(), 1U); | |
586 | EXPECT_TRUE(p->statements[0].princ.empty()); | |
587 | EXPECT_TRUE(p->statements[0].noprinc.empty()); | |
588 | EXPECT_EQ(p->statements[0].effect, Effect::Allow); | |
589 | Action_t act; | |
590 | for (auto i = s3All+1; i <= iamAll; i++) | |
591 | act[i] = 1; | |
592 | EXPECT_EQ(p->statements[0].action, act); | |
593 | EXPECT_EQ(p->statements[0].notaction, None); | |
594 | ASSERT_FALSE(p->statements[0].resource.empty()); | |
595 | ASSERT_EQ(p->statements[0].resource.size(), 1U); | |
596 | EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws); | |
597 | EXPECT_EQ(p->statements[0].resource.begin()->service, Service::iam); | |
598 | EXPECT_EQ(p->statements[0].resource.begin()->region, ""); | |
599 | EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant); | |
600 | EXPECT_EQ(p->statements[0].resource.begin()->resource, "role/example_role"); | |
601 | EXPECT_TRUE(p->statements[0].notresource.empty()); | |
602 | EXPECT_TRUE(p->statements[0].conditions.empty()); | |
603 | } | |
604 | ||
605 | TEST_F(PolicyTest, Eval5) { | |
606 | auto p = Policy(cct.get(), arbitrary_tenant, | |
607 | bufferlist::static_from_string(example5)); | |
608 | Environment e; | |
609 | ||
20effc67 TL |
610 | ARN arn1(Partition::aws, Service::iam, |
611 | "", arbitrary_tenant, "role/example_role"); | |
612 | EXPECT_EQ(p.eval(e, none, iamCreateRole, arn1), | |
11fdf7f2 TL |
613 | Effect::Allow); |
614 | ||
20effc67 TL |
615 | ARN arn2(Partition::aws, Service::iam, |
616 | "", arbitrary_tenant, "role/example_role"); | |
617 | EXPECT_EQ(p.eval(e, none, s3ListBucket, arn2), | |
11fdf7f2 TL |
618 | Effect::Pass); |
619 | ||
20effc67 TL |
620 | ARN arn3(Partition::aws, Service::iam, |
621 | "", "", "role/example_role"); | |
622 | EXPECT_EQ(p.eval(e, none, iamCreateRole, arn3), | |
11fdf7f2 TL |
623 | Effect::Pass); |
624 | } | |
625 | ||
626 | TEST_F(PolicyTest, Parse6) { | |
627 | boost::optional<Policy> p; | |
628 | ||
629 | ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, | |
630 | bufferlist::static_from_string(example6))); | |
631 | ASSERT_TRUE(p); | |
632 | EXPECT_EQ(p->text, example6); | |
633 | EXPECT_EQ(p->version, Version::v2012_10_17); | |
634 | EXPECT_FALSE(p->id); | |
635 | EXPECT_FALSE(p->statements[0].sid); | |
636 | EXPECT_FALSE(p->statements.empty()); | |
637 | EXPECT_EQ(p->statements.size(), 1U); | |
638 | EXPECT_TRUE(p->statements[0].princ.empty()); | |
639 | EXPECT_TRUE(p->statements[0].noprinc.empty()); | |
640 | EXPECT_EQ(p->statements[0].effect, Effect::Allow); | |
641 | Action_t act; | |
642 | for (auto i = 0U; i <= stsAll; i++) | |
643 | act[i] = 1; | |
644 | EXPECT_EQ(p->statements[0].action, act); | |
645 | EXPECT_EQ(p->statements[0].notaction, None); | |
646 | ASSERT_FALSE(p->statements[0].resource.empty()); | |
647 | ASSERT_EQ(p->statements[0].resource.size(), 1U); | |
648 | EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws); | |
649 | EXPECT_EQ(p->statements[0].resource.begin()->service, Service::iam); | |
650 | EXPECT_EQ(p->statements[0].resource.begin()->region, ""); | |
651 | EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant); | |
652 | EXPECT_EQ(p->statements[0].resource.begin()->resource, "user/A"); | |
653 | EXPECT_TRUE(p->statements[0].notresource.empty()); | |
654 | EXPECT_TRUE(p->statements[0].conditions.empty()); | |
655 | } | |
656 | ||
657 | TEST_F(PolicyTest, Eval6) { | |
658 | auto p = Policy(cct.get(), arbitrary_tenant, | |
659 | bufferlist::static_from_string(example6)); | |
660 | Environment e; | |
661 | ||
20effc67 TL |
662 | ARN arn1(Partition::aws, Service::iam, |
663 | "", arbitrary_tenant, "user/A"); | |
664 | EXPECT_EQ(p.eval(e, none, iamCreateRole, arn1), | |
11fdf7f2 TL |
665 | Effect::Allow); |
666 | ||
20effc67 TL |
667 | ARN arn2(Partition::aws, Service::iam, |
668 | "", arbitrary_tenant, "user/A"); | |
669 | EXPECT_EQ(p.eval(e, none, s3ListBucket, arn2), | |
11fdf7f2 TL |
670 | Effect::Allow); |
671 | } | |
672 | ||
9f95a23c TL |
673 | TEST_F(PolicyTest, Parse7) { |
674 | boost::optional<Policy> p; | |
675 | ||
676 | ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, | |
677 | bufferlist::static_from_string(example7))); | |
678 | ASSERT_TRUE(p); | |
679 | ||
680 | EXPECT_EQ(p->text, example7); | |
681 | EXPECT_EQ(p->version, Version::v2012_10_17); | |
682 | ASSERT_FALSE(p->statements.empty()); | |
683 | EXPECT_EQ(p->statements.size(), 1U); | |
684 | EXPECT_FALSE(p->statements[0].princ.empty()); | |
685 | EXPECT_EQ(p->statements[0].princ.size(), 1U); | |
686 | EXPECT_TRUE(p->statements[0].noprinc.empty()); | |
687 | EXPECT_EQ(p->statements[0].effect, Effect::Allow); | |
688 | Action_t act; | |
689 | act[s3ListBucket] = 1; | |
690 | EXPECT_EQ(p->statements[0].action, act); | |
691 | EXPECT_EQ(p->statements[0].notaction, None); | |
692 | ASSERT_FALSE(p->statements[0].resource.empty()); | |
693 | ASSERT_EQ(p->statements[0].resource.size(), 1U); | |
694 | EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws); | |
695 | EXPECT_EQ(p->statements[0].resource.begin()->service, Service::s3); | |
696 | EXPECT_TRUE(p->statements[0].resource.begin()->region.empty()); | |
697 | EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant); | |
698 | EXPECT_EQ(p->statements[0].resource.begin()->resource, "mybucket/*"); | |
699 | EXPECT_TRUE(p->statements[0].princ.begin()->is_user()); | |
700 | EXPECT_FALSE(p->statements[0].princ.begin()->is_wildcard()); | |
701 | EXPECT_EQ(p->statements[0].princ.begin()->get_tenant(), ""); | |
702 | EXPECT_EQ(p->statements[0].princ.begin()->get_id(), "A:subA"); | |
703 | EXPECT_TRUE(p->statements[0].notresource.empty()); | |
704 | EXPECT_TRUE(p->statements[0].conditions.empty()); | |
705 | } | |
706 | ||
707 | TEST_F(PolicyTest, Eval7) { | |
708 | auto p = Policy(cct.get(), arbitrary_tenant, | |
709 | bufferlist::static_from_string(example7)); | |
710 | Environment e; | |
711 | ||
712 | auto subacct = FakeIdentity( | |
713 | Principal::user(std::move(""), "A:subA")); | |
714 | auto parentacct = FakeIdentity( | |
715 | Principal::user(std::move(""), "A")); | |
716 | auto sub2acct = FakeIdentity( | |
717 | Principal::user(std::move(""), "A:sub2A")); | |
718 | ||
20effc67 TL |
719 | ARN arn1(Partition::aws, Service::s3, |
720 | "", arbitrary_tenant, "mybucket/*"); | |
721 | EXPECT_EQ(p.eval(e, subacct, s3ListBucket, arn1), | |
9f95a23c TL |
722 | Effect::Allow); |
723 | ||
20effc67 TL |
724 | ARN arn2(Partition::aws, Service::s3, |
725 | "", arbitrary_tenant, "mybucket/*"); | |
726 | EXPECT_EQ(p.eval(e, parentacct, s3ListBucket, arn2), | |
9f95a23c | 727 | Effect::Pass); |
20effc67 TL |
728 | |
729 | ARN arn3(Partition::aws, Service::s3, | |
730 | "", arbitrary_tenant, "mybucket/*"); | |
731 | EXPECT_EQ(p.eval(e, sub2acct, s3ListBucket, arn3), | |
9f95a23c TL |
732 | Effect::Pass); |
733 | } | |
734 | ||
31f18b77 FG |
735 | const string PolicyTest::arbitrary_tenant = "arbitrary_tenant"; |
736 | string PolicyTest::example1 = R"( | |
737 | { | |
738 | "Version": "2012-10-17", | |
739 | "Statement": { | |
740 | "Effect": "Allow", | |
741 | "Action": "s3:ListBucket", | |
742 | "Resource": "arn:aws:s3:::example_bucket" | |
743 | } | |
744 | } | |
745 | )"; | |
746 | ||
747 | string PolicyTest::example2 = R"( | |
748 | { | |
749 | "Version": "2012-10-17", | |
750 | "Id": "S3-Account-Permissions", | |
751 | "Statement": [{ | |
752 | "Sid": "1", | |
753 | "Effect": "Allow", | |
754 | "Principal": {"AWS": ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:root"]}, | |
755 | "Action": "s3:*", | |
756 | "Resource": [ | |
757 | "arn:aws:s3:::mybucket", | |
758 | "arn:aws:s3:::mybucket/*" | |
759 | ] | |
760 | }] | |
761 | } | |
762 | )"; | |
763 | ||
764 | string PolicyTest::example3 = R"( | |
765 | { | |
766 | "Version": "2012-10-17", | |
767 | "Statement": [ | |
768 | { | |
769 | "Sid": "FirstStatement", | |
770 | "Effect": "Allow", | |
771 | "Action": ["s3:PutBucketPolicy"], | |
772 | "Resource": "*" | |
773 | }, | |
774 | { | |
775 | "Sid": "SecondStatement", | |
776 | "Effect": "Allow", | |
777 | "Action": "s3:ListAllMyBuckets", | |
778 | "Resource": "*" | |
779 | }, | |
780 | { | |
781 | "Sid": "ThirdStatement", | |
782 | "Effect": "Allow", | |
783 | "Action": [ | |
784 | "s3:List*", | |
785 | "s3:Get*" | |
786 | ], | |
787 | "Resource": [ | |
788 | "arn:aws:s3:::confidential-data", | |
789 | "arn:aws:s3:::confidential-data/*" | |
790 | ], | |
791 | "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}} | |
792 | } | |
793 | ] | |
794 | } | |
795 | )"; | |
d2e6a577 | 796 | |
11fdf7f2 TL |
797 | string PolicyTest::example4 = R"( |
798 | { | |
799 | "Version": "2012-10-17", | |
800 | "Statement": { | |
801 | "Effect": "Allow", | |
802 | "Action": "iam:CreateRole", | |
803 | "Resource": "*" | |
804 | } | |
805 | } | |
806 | )"; | |
807 | ||
808 | string PolicyTest::example5 = R"( | |
809 | { | |
810 | "Version": "2012-10-17", | |
811 | "Statement": { | |
812 | "Effect": "Allow", | |
813 | "Action": "iam:*", | |
814 | "Resource": "arn:aws:iam:::role/example_role" | |
815 | } | |
816 | } | |
817 | )"; | |
818 | ||
819 | string PolicyTest::example6 = R"( | |
820 | { | |
821 | "Version": "2012-10-17", | |
822 | "Statement": { | |
823 | "Effect": "Allow", | |
824 | "Action": "*", | |
825 | "Resource": "arn:aws:iam:::user/A" | |
826 | } | |
827 | } | |
828 | )"; | |
9f95a23c TL |
829 | |
830 | string PolicyTest::example7 = R"( | |
831 | { | |
832 | "Version": "2012-10-17", | |
833 | "Statement": { | |
834 | "Effect": "Allow", | |
835 | "Principal": {"AWS": ["arn:aws:iam:::user/A:subA"]}, | |
836 | "Action": "s3:ListBucket", | |
837 | "Resource": "arn:aws:s3:::mybucket/*" | |
838 | } | |
839 | } | |
840 | )"; | |
b32b8144 FG |
841 | class IPPolicyTest : public ::testing::Test { |
842 | protected: | |
843 | intrusive_ptr<CephContext> cct; | |
844 | static const string arbitrary_tenant; | |
845 | static string ip_address_allow_example; | |
846 | static string ip_address_deny_example; | |
847 | static string ip_address_full_example; | |
848 | // 192.168.1.0/24 | |
849 | const rgw::IAM::MaskedIP allowedIPv4Range = { false, rgw::IAM::Address("11000000101010000000000100000000"), 24 }; | |
850 | // 192.168.1.1/32 | |
f67539c2 | 851 | const rgw::IAM::MaskedIP blocklistedIPv4 = { false, rgw::IAM::Address("11000000101010000000000100000001"), 32 }; |
b32b8144 FG |
852 | // 2001:db8:85a3:0:0:8a2e:370:7334/128 |
853 | const rgw::IAM::MaskedIP allowedIPv6 = { true, rgw::IAM::Address("00100000000000010000110110111000100001011010001100000000000000000000000000000000100010100010111000000011011100000111001100110100"), 128 }; | |
854 | // ::1 | |
f67539c2 | 855 | const rgw::IAM::MaskedIP blocklistedIPv6 = { true, rgw::IAM::Address(1), 128 }; |
b32b8144 FG |
856 | // 2001:db8:85a3:0:0:8a2e:370:7330/124 |
857 | const rgw::IAM::MaskedIP allowedIPv6Range = { true, rgw::IAM::Address("00100000000000010000110110111000100001011010001100000000000000000000000000000000100010100010111000000011011100000111001100110000"), 124 }; | |
858 | public: | |
859 | IPPolicyTest() { | |
860 | cct = new CephContext(CEPH_ENTITY_TYPE_CLIENT); | |
861 | } | |
862 | }; | |
863 | const string IPPolicyTest::arbitrary_tenant = "arbitrary_tenant"; | |
864 | ||
865 | TEST_F(IPPolicyTest, MaskedIPOperations) { | |
866 | EXPECT_EQ(stringify(allowedIPv4Range), "192.168.1.0/24"); | |
f67539c2 | 867 | EXPECT_EQ(stringify(blocklistedIPv4), "192.168.1.1/32"); |
b32b8144 FG |
868 | EXPECT_EQ(stringify(allowedIPv6), "2001:db8:85a3:0:0:8a2e:370:7334/128"); |
869 | EXPECT_EQ(stringify(allowedIPv6Range), "2001:db8:85a3:0:0:8a2e:370:7330/124"); | |
f67539c2 TL |
870 | EXPECT_EQ(stringify(blocklistedIPv6), "0:0:0:0:0:0:0:1/128"); |
871 | EXPECT_EQ(allowedIPv4Range, blocklistedIPv4); | |
b32b8144 FG |
872 | EXPECT_EQ(allowedIPv6Range, allowedIPv6); |
873 | } | |
874 | ||
875 | TEST_F(IPPolicyTest, asNetworkIPv4Range) { | |
876 | auto actualIPv4Range = rgw::IAM::Condition::as_network("192.168.1.0/24"); | |
877 | ASSERT_TRUE(actualIPv4Range.is_initialized()); | |
878 | EXPECT_EQ(*actualIPv4Range, allowedIPv4Range); | |
879 | } | |
880 | ||
881 | TEST_F(IPPolicyTest, asNetworkIPv4) { | |
882 | auto actualIPv4 = rgw::IAM::Condition::as_network("192.168.1.1"); | |
883 | ASSERT_TRUE(actualIPv4.is_initialized()); | |
f67539c2 | 884 | EXPECT_EQ(*actualIPv4, blocklistedIPv4); |
b32b8144 FG |
885 | } |
886 | ||
887 | TEST_F(IPPolicyTest, asNetworkIPv6Range) { | |
888 | auto actualIPv6Range = rgw::IAM::Condition::as_network("2001:db8:85a3:0:0:8a2e:370:7330/124"); | |
889 | ASSERT_TRUE(actualIPv6Range.is_initialized()); | |
890 | EXPECT_EQ(*actualIPv6Range, allowedIPv6Range); | |
891 | } | |
892 | ||
893 | TEST_F(IPPolicyTest, asNetworkIPv6) { | |
894 | auto actualIPv6 = rgw::IAM::Condition::as_network("2001:db8:85a3:0:0:8a2e:370:7334"); | |
895 | ASSERT_TRUE(actualIPv6.is_initialized()); | |
896 | EXPECT_EQ(*actualIPv6, allowedIPv6); | |
897 | } | |
898 | ||
899 | TEST_F(IPPolicyTest, asNetworkInvalid) { | |
900 | EXPECT_FALSE(rgw::IAM::Condition::as_network("")); | |
901 | EXPECT_FALSE(rgw::IAM::Condition::as_network("192.168.1.1/33")); | |
902 | EXPECT_FALSE(rgw::IAM::Condition::as_network("2001:db8:85a3:0:0:8a2e:370:7334/129")); | |
903 | EXPECT_FALSE(rgw::IAM::Condition::as_network("192.168.1.1:")); | |
904 | EXPECT_FALSE(rgw::IAM::Condition::as_network("1.2.3.10000")); | |
905 | } | |
906 | ||
907 | TEST_F(IPPolicyTest, IPEnvironment) { | |
908 | // Unfortunately RGWCivetWeb is too tightly tied to civetweb to test RGWCivetWeb::init_env. | |
909 | RGWEnv rgw_env; | |
20effc67 TL |
910 | rgw::sal::RadosStore store; |
911 | std::unique_ptr<rgw::sal::User> user = store.get_user(rgw_user()); | |
b32b8144 FG |
912 | rgw_env.set("REMOTE_ADDR", "192.168.1.1"); |
913 | rgw_env.set("HTTP_HOST", "1.2.3.4"); | |
f67539c2 TL |
914 | req_state rgw_req_state(cct.get(), &rgw_env, 0); |
915 | rgw_req_state.set_user(user); | |
9f95a23c | 916 | rgw_build_iam_environment(&store, &rgw_req_state); |
11fdf7f2 TL |
917 | auto ip = rgw_req_state.env.find("aws:SourceIp"); |
918 | ASSERT_NE(ip, rgw_req_state.env.end()); | |
b32b8144 FG |
919 | EXPECT_EQ(ip->second, "192.168.1.1"); |
920 | ||
11fdf7f2 | 921 | ASSERT_EQ(cct.get()->_conf.set_val("rgw_remote_addr_param", "SOME_VAR"), 0); |
b32b8144 | 922 | EXPECT_EQ(cct.get()->_conf->rgw_remote_addr_param, "SOME_VAR"); |
11fdf7f2 | 923 | rgw_req_state.env.clear(); |
9f95a23c | 924 | rgw_build_iam_environment(&store, &rgw_req_state); |
11fdf7f2 TL |
925 | ip = rgw_req_state.env.find("aws:SourceIp"); |
926 | EXPECT_EQ(ip, rgw_req_state.env.end()); | |
b32b8144 FG |
927 | |
928 | rgw_env.set("SOME_VAR", "192.168.1.2"); | |
11fdf7f2 | 929 | rgw_req_state.env.clear(); |
9f95a23c | 930 | rgw_build_iam_environment(&store, &rgw_req_state); |
11fdf7f2 TL |
931 | ip = rgw_req_state.env.find("aws:SourceIp"); |
932 | ASSERT_NE(ip, rgw_req_state.env.end()); | |
b32b8144 FG |
933 | EXPECT_EQ(ip->second, "192.168.1.2"); |
934 | ||
11fdf7f2 | 935 | ASSERT_EQ(cct.get()->_conf.set_val("rgw_remote_addr_param", "HTTP_X_FORWARDED_FOR"), 0); |
b32b8144 | 936 | rgw_env.set("HTTP_X_FORWARDED_FOR", "192.168.1.3"); |
11fdf7f2 | 937 | rgw_req_state.env.clear(); |
9f95a23c | 938 | rgw_build_iam_environment(&store, &rgw_req_state); |
11fdf7f2 TL |
939 | ip = rgw_req_state.env.find("aws:SourceIp"); |
940 | ASSERT_NE(ip, rgw_req_state.env.end()); | |
b32b8144 FG |
941 | EXPECT_EQ(ip->second, "192.168.1.3"); |
942 | ||
943 | rgw_env.set("HTTP_X_FORWARDED_FOR", "192.168.1.4, 4.3.2.1, 2001:db8:85a3:8d3:1319:8a2e:370:7348"); | |
11fdf7f2 | 944 | rgw_req_state.env.clear(); |
9f95a23c | 945 | rgw_build_iam_environment(&store, &rgw_req_state); |
11fdf7f2 TL |
946 | ip = rgw_req_state.env.find("aws:SourceIp"); |
947 | ASSERT_NE(ip, rgw_req_state.env.end()); | |
b32b8144 FG |
948 | EXPECT_EQ(ip->second, "192.168.1.4"); |
949 | } | |
950 | ||
951 | TEST_F(IPPolicyTest, ParseIPAddress) { | |
11fdf7f2 | 952 | boost::optional<Policy> p; |
b32b8144 FG |
953 | |
954 | ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, | |
955 | bufferlist::static_from_string(ip_address_full_example))); | |
956 | ASSERT_TRUE(p); | |
957 | ||
958 | EXPECT_EQ(p->text, ip_address_full_example); | |
959 | EXPECT_EQ(p->version, Version::v2012_10_17); | |
960 | EXPECT_EQ(*p->id, "S3IPPolicyTest"); | |
961 | EXPECT_FALSE(p->statements.empty()); | |
962 | EXPECT_EQ(p->statements.size(), 1U); | |
963 | EXPECT_EQ(*p->statements[0].sid, "IPAllow"); | |
964 | EXPECT_FALSE(p->statements[0].princ.empty()); | |
965 | EXPECT_EQ(p->statements[0].princ.size(), 1U); | |
966 | EXPECT_EQ(*p->statements[0].princ.begin(), | |
967 | Principal::wildcard()); | |
968 | EXPECT_TRUE(p->statements[0].noprinc.empty()); | |
969 | EXPECT_EQ(p->statements[0].effect, Effect::Allow); | |
11fdf7f2 TL |
970 | Action_t act; |
971 | act[s3ListBucket] = 1; | |
972 | EXPECT_EQ(p->statements[0].action, act); | |
973 | EXPECT_EQ(p->statements[0].notaction, None); | |
b32b8144 FG |
974 | ASSERT_FALSE(p->statements[0].resource.empty()); |
975 | ASSERT_EQ(p->statements[0].resource.size(), 2U); | |
976 | EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws); | |
977 | EXPECT_EQ(p->statements[0].resource.begin()->service, Service::s3); | |
978 | EXPECT_TRUE(p->statements[0].resource.begin()->region.empty()); | |
979 | EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant); | |
980 | EXPECT_EQ(p->statements[0].resource.begin()->resource, "example_bucket"); | |
981 | EXPECT_EQ((p->statements[0].resource.begin() + 1)->resource, "example_bucket/*"); | |
982 | EXPECT_TRUE(p->statements[0].notresource.empty()); | |
983 | ASSERT_FALSE(p->statements[0].conditions.empty()); | |
984 | ASSERT_EQ(p->statements[0].conditions.size(), 2U); | |
985 | EXPECT_EQ(p->statements[0].conditions[0].op, TokenID::IpAddress); | |
986 | EXPECT_EQ(p->statements[0].conditions[0].key, "aws:SourceIp"); | |
987 | ASSERT_FALSE(p->statements[0].conditions[0].vals.empty()); | |
988 | EXPECT_EQ(p->statements[0].conditions[0].vals.size(), 2U); | |
989 | EXPECT_EQ(p->statements[0].conditions[0].vals[0], "192.168.1.0/24"); | |
990 | EXPECT_EQ(p->statements[0].conditions[0].vals[1], "::1"); | |
11fdf7f2 | 991 | boost::optional<rgw::IAM::MaskedIP> convertedIPv4 = rgw::IAM::Condition::as_network(p->statements[0].conditions[0].vals[0]); |
b32b8144 FG |
992 | EXPECT_TRUE(convertedIPv4.is_initialized()); |
993 | if (convertedIPv4.is_initialized()) { | |
994 | EXPECT_EQ(*convertedIPv4, allowedIPv4Range); | |
995 | } | |
996 | ||
997 | EXPECT_EQ(p->statements[0].conditions[1].op, TokenID::NotIpAddress); | |
998 | EXPECT_EQ(p->statements[0].conditions[1].key, "aws:SourceIp"); | |
999 | ASSERT_FALSE(p->statements[0].conditions[1].vals.empty()); | |
1000 | EXPECT_EQ(p->statements[0].conditions[1].vals.size(), 2U); | |
1001 | EXPECT_EQ(p->statements[0].conditions[1].vals[0], "192.168.1.1/32"); | |
1002 | EXPECT_EQ(p->statements[0].conditions[1].vals[1], "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); | |
11fdf7f2 | 1003 | boost::optional<rgw::IAM::MaskedIP> convertedIPv6 = rgw::IAM::Condition::as_network(p->statements[0].conditions[1].vals[1]); |
b32b8144 FG |
1004 | EXPECT_TRUE(convertedIPv6.is_initialized()); |
1005 | if (convertedIPv6.is_initialized()) { | |
1006 | EXPECT_EQ(*convertedIPv6, allowedIPv6); | |
1007 | } | |
1008 | } | |
1009 | ||
1010 | TEST_F(IPPolicyTest, EvalIPAddress) { | |
1011 | auto allowp = Policy(cct.get(), arbitrary_tenant, | |
1012 | bufferlist::static_from_string(ip_address_allow_example)); | |
1013 | auto denyp = Policy(cct.get(), arbitrary_tenant, | |
1014 | bufferlist::static_from_string(ip_address_deny_example)); | |
1015 | auto fullp = Policy(cct.get(), arbitrary_tenant, | |
1016 | bufferlist::static_from_string(ip_address_full_example)); | |
1017 | Environment e; | |
f67539c2 | 1018 | Environment allowedIP, blocklistedIP, allowedIPv6, blocklistedIPv6; |
20effc67 TL |
1019 | allowedIP.emplace("aws:SourceIp","192.168.1.2"); |
1020 | allowedIPv6.emplace("aws:SourceIp", "::1"); | |
1021 | blocklistedIP.emplace("aws:SourceIp", "192.168.1.1"); | |
1022 | blocklistedIPv6.emplace("aws:SourceIp", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); | |
b32b8144 FG |
1023 | |
1024 | auto trueacct = FakeIdentity( | |
1025 | Principal::tenant("ACCOUNT-ID-WITHOUT-HYPHENS")); | |
1026 | // Without an IP address in the environment then evaluation will always pass | |
20effc67 TL |
1027 | ARN arn1(Partition::aws, Service::s3, |
1028 | "", arbitrary_tenant, "example_bucket"); | |
1029 | EXPECT_EQ(allowp.eval(e, trueacct, s3ListBucket, arn1), | |
b32b8144 | 1030 | Effect::Pass); |
20effc67 TL |
1031 | ARN arn2(Partition::aws, Service::s3, |
1032 | "", arbitrary_tenant, "example_bucket/myobject"); | |
1033 | EXPECT_EQ(fullp.eval(e, trueacct, s3ListBucket, arn2), | |
b32b8144 FG |
1034 | Effect::Pass); |
1035 | ||
20effc67 TL |
1036 | ARN arn3(Partition::aws, Service::s3, |
1037 | "", arbitrary_tenant, "example_bucket"); | |
1038 | EXPECT_EQ(allowp.eval(allowedIP, trueacct, s3ListBucket, arn3), | |
b32b8144 | 1039 | Effect::Allow); |
20effc67 TL |
1040 | ARN arn4(Partition::aws, Service::s3, |
1041 | "", arbitrary_tenant, "example_bucket"); | |
1042 | EXPECT_EQ(allowp.eval(blocklistedIPv6, trueacct, s3ListBucket, arn4), | |
b32b8144 FG |
1043 | Effect::Pass); |
1044 | ||
20effc67 TL |
1045 | ARN arn5(Partition::aws, Service::s3, |
1046 | "", arbitrary_tenant, "example_bucket"); | |
1047 | EXPECT_EQ(denyp.eval(allowedIP, trueacct, s3ListBucket, arn5), | |
b32b8144 | 1048 | Effect::Deny); |
20effc67 TL |
1049 | ARN arn6(Partition::aws, Service::s3, |
1050 | "", arbitrary_tenant, "example_bucket/myobject"); | |
1051 | EXPECT_EQ(denyp.eval(allowedIP, trueacct, s3ListBucket, arn6), | |
b32b8144 FG |
1052 | Effect::Deny); |
1053 | ||
20effc67 TL |
1054 | ARN arn7(Partition::aws, Service::s3, |
1055 | "", arbitrary_tenant, "example_bucket"); | |
1056 | EXPECT_EQ(denyp.eval(blocklistedIP, trueacct, s3ListBucket, arn7), | |
b32b8144 | 1057 | Effect::Pass); |
20effc67 TL |
1058 | ARN arn8(Partition::aws, Service::s3, |
1059 | "", arbitrary_tenant, "example_bucket/myobject"); | |
1060 | EXPECT_EQ(denyp.eval(blocklistedIP, trueacct, s3ListBucket, arn8), | |
b32b8144 FG |
1061 | Effect::Pass); |
1062 | ||
20effc67 TL |
1063 | ARN arn9(Partition::aws, Service::s3, |
1064 | "", arbitrary_tenant, "example_bucket"); | |
1065 | EXPECT_EQ(denyp.eval(blocklistedIPv6, trueacct, s3ListBucket, arn9), | |
b32b8144 | 1066 | Effect::Pass); |
20effc67 TL |
1067 | ARN arn10(Partition::aws, Service::s3, |
1068 | "", arbitrary_tenant, "example_bucket/myobject"); | |
1069 | EXPECT_EQ(denyp.eval(blocklistedIPv6, trueacct, s3ListBucket, arn10), | |
b32b8144 | 1070 | Effect::Pass); |
20effc67 TL |
1071 | ARN arn11(Partition::aws, Service::s3, |
1072 | "", arbitrary_tenant, "example_bucket"); | |
1073 | EXPECT_EQ(denyp.eval(allowedIPv6, trueacct, s3ListBucket, arn11), | |
b32b8144 | 1074 | Effect::Deny); |
20effc67 TL |
1075 | ARN arn12(Partition::aws, Service::s3, |
1076 | "", arbitrary_tenant, "example_bucket/myobject"); | |
1077 | EXPECT_EQ(denyp.eval(allowedIPv6, trueacct, s3ListBucket, arn12), | |
b32b8144 FG |
1078 | Effect::Deny); |
1079 | ||
20effc67 TL |
1080 | ARN arn13(Partition::aws, Service::s3, |
1081 | "", arbitrary_tenant, "example_bucket"); | |
1082 | EXPECT_EQ(fullp.eval(allowedIP, trueacct, s3ListBucket, arn13), | |
b32b8144 | 1083 | Effect::Allow); |
20effc67 TL |
1084 | ARN arn14(Partition::aws, Service::s3, |
1085 | "", arbitrary_tenant, "example_bucket/myobject"); | |
1086 | EXPECT_EQ(fullp.eval(allowedIP, trueacct, s3ListBucket, arn14), | |
b32b8144 FG |
1087 | Effect::Allow); |
1088 | ||
20effc67 TL |
1089 | ARN arn15(Partition::aws, Service::s3, |
1090 | "", arbitrary_tenant, "example_bucket"); | |
1091 | EXPECT_EQ(fullp.eval(blocklistedIP, trueacct, s3ListBucket, arn15), | |
b32b8144 | 1092 | Effect::Pass); |
20effc67 TL |
1093 | ARN arn16(Partition::aws, Service::s3, |
1094 | "", arbitrary_tenant, "example_bucket/myobject"); | |
1095 | EXPECT_EQ(fullp.eval(blocklistedIP, trueacct, s3ListBucket, arn16), | |
b32b8144 FG |
1096 | Effect::Pass); |
1097 | ||
20effc67 TL |
1098 | ARN arn17(Partition::aws, Service::s3, |
1099 | "", arbitrary_tenant, "example_bucket"); | |
1100 | EXPECT_EQ(fullp.eval(allowedIPv6, trueacct, s3ListBucket, arn17), | |
b32b8144 | 1101 | Effect::Allow); |
20effc67 TL |
1102 | ARN arn18(Partition::aws, Service::s3, |
1103 | "", arbitrary_tenant, "example_bucket/myobject"); | |
1104 | EXPECT_EQ(fullp.eval(allowedIPv6, trueacct, s3ListBucket, arn18), | |
b32b8144 FG |
1105 | Effect::Allow); |
1106 | ||
20effc67 TL |
1107 | ARN arn19(Partition::aws, Service::s3, |
1108 | "", arbitrary_tenant, "example_bucket"); | |
1109 | EXPECT_EQ(fullp.eval(blocklistedIPv6, trueacct, s3ListBucket, arn19), | |
b32b8144 | 1110 | Effect::Pass); |
20effc67 TL |
1111 | ARN arn20(Partition::aws, Service::s3, |
1112 | "", arbitrary_tenant, "example_bucket/myobject"); | |
1113 | EXPECT_EQ(fullp.eval(blocklistedIPv6, trueacct, s3ListBucket, arn20), | |
b32b8144 FG |
1114 | Effect::Pass); |
1115 | } | |
1116 | ||
1117 | string IPPolicyTest::ip_address_allow_example = R"( | |
1118 | { | |
1119 | "Version": "2012-10-17", | |
1120 | "Id": "S3SimpleIPPolicyTest", | |
1121 | "Statement": [{ | |
1122 | "Sid": "1", | |
1123 | "Effect": "Allow", | |
1124 | "Principal": {"AWS": ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:root"]}, | |
1125 | "Action": "s3:ListBucket", | |
1126 | "Resource": [ | |
1127 | "arn:aws:s3:::example_bucket" | |
1128 | ], | |
1129 | "Condition": { | |
1130 | "IpAddress": {"aws:SourceIp": "192.168.1.0/24"} | |
1131 | } | |
1132 | }] | |
1133 | } | |
1134 | )"; | |
1135 | ||
1136 | string IPPolicyTest::ip_address_deny_example = R"( | |
1137 | { | |
1138 | "Version": "2012-10-17", | |
1139 | "Id": "S3IPPolicyTest", | |
1140 | "Statement": { | |
1141 | "Effect": "Deny", | |
1142 | "Sid": "IPDeny", | |
1143 | "Action": "s3:ListBucket", | |
1144 | "Principal": {"AWS": ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:root"]}, | |
1145 | "Resource": [ | |
1146 | "arn:aws:s3:::example_bucket", | |
1147 | "arn:aws:s3:::example_bucket/*" | |
1148 | ], | |
1149 | "Condition": { | |
1150 | "NotIpAddress": {"aws:SourceIp": ["192.168.1.1/32", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"]} | |
1151 | } | |
1152 | } | |
1153 | } | |
1154 | )"; | |
1155 | ||
1156 | string IPPolicyTest::ip_address_full_example = R"( | |
1157 | { | |
1158 | "Version": "2012-10-17", | |
1159 | "Id": "S3IPPolicyTest", | |
1160 | "Statement": { | |
1161 | "Effect": "Allow", | |
1162 | "Sid": "IPAllow", | |
1163 | "Action": "s3:ListBucket", | |
1164 | "Principal": "*", | |
1165 | "Resource": [ | |
1166 | "arn:aws:s3:::example_bucket", | |
1167 | "arn:aws:s3:::example_bucket/*" | |
1168 | ], | |
1169 | "Condition": { | |
1170 | "IpAddress": {"aws:SourceIp": ["192.168.1.0/24", "::1"]}, | |
1171 | "NotIpAddress": {"aws:SourceIp": ["192.168.1.1/32", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"]} | |
1172 | } | |
1173 | } | |
1174 | } | |
1175 | )"; | |
1176 | ||
d2e6a577 FG |
1177 | TEST(MatchWildcards, Simple) |
1178 | { | |
1179 | EXPECT_TRUE(match_wildcards("", "")); | |
1180 | EXPECT_TRUE(match_wildcards("", "", MATCH_CASE_INSENSITIVE)); | |
1181 | EXPECT_FALSE(match_wildcards("", "abc")); | |
1182 | EXPECT_FALSE(match_wildcards("", "abc", MATCH_CASE_INSENSITIVE)); | |
1183 | EXPECT_FALSE(match_wildcards("abc", "")); | |
1184 | EXPECT_FALSE(match_wildcards("abc", "", MATCH_CASE_INSENSITIVE)); | |
1185 | EXPECT_TRUE(match_wildcards("abc", "abc")); | |
1186 | EXPECT_TRUE(match_wildcards("abc", "abc", MATCH_CASE_INSENSITIVE)); | |
1187 | EXPECT_FALSE(match_wildcards("abc", "abC")); | |
1188 | EXPECT_TRUE(match_wildcards("abc", "abC", MATCH_CASE_INSENSITIVE)); | |
1189 | EXPECT_FALSE(match_wildcards("abC", "abc")); | |
1190 | EXPECT_TRUE(match_wildcards("abC", "abc", MATCH_CASE_INSENSITIVE)); | |
1191 | EXPECT_FALSE(match_wildcards("abc", "abcd")); | |
1192 | EXPECT_FALSE(match_wildcards("abc", "abcd", MATCH_CASE_INSENSITIVE)); | |
1193 | EXPECT_FALSE(match_wildcards("abcd", "abc")); | |
1194 | EXPECT_FALSE(match_wildcards("abcd", "abc", MATCH_CASE_INSENSITIVE)); | |
1195 | } | |
1196 | ||
1197 | TEST(MatchWildcards, QuestionMark) | |
1198 | { | |
1199 | EXPECT_FALSE(match_wildcards("?", "")); | |
1200 | EXPECT_FALSE(match_wildcards("?", "", MATCH_CASE_INSENSITIVE)); | |
1201 | EXPECT_TRUE(match_wildcards("?", "a")); | |
1202 | EXPECT_TRUE(match_wildcards("?", "a", MATCH_CASE_INSENSITIVE)); | |
1203 | EXPECT_TRUE(match_wildcards("?bc", "abc")); | |
1204 | EXPECT_TRUE(match_wildcards("?bc", "abc", MATCH_CASE_INSENSITIVE)); | |
1205 | EXPECT_TRUE(match_wildcards("a?c", "abc")); | |
1206 | EXPECT_TRUE(match_wildcards("a?c", "abc", MATCH_CASE_INSENSITIVE)); | |
1207 | EXPECT_FALSE(match_wildcards("abc", "a?c")); | |
1208 | EXPECT_FALSE(match_wildcards("abc", "a?c", MATCH_CASE_INSENSITIVE)); | |
1209 | EXPECT_FALSE(match_wildcards("a?c", "abC")); | |
1210 | EXPECT_TRUE(match_wildcards("a?c", "abC", MATCH_CASE_INSENSITIVE)); | |
1211 | EXPECT_TRUE(match_wildcards("ab?", "abc")); | |
1212 | EXPECT_TRUE(match_wildcards("ab?", "abc", MATCH_CASE_INSENSITIVE)); | |
1213 | EXPECT_TRUE(match_wildcards("a?c?e", "abcde")); | |
1214 | EXPECT_TRUE(match_wildcards("a?c?e", "abcde", MATCH_CASE_INSENSITIVE)); | |
1215 | EXPECT_TRUE(match_wildcards("???", "abc")); | |
1216 | EXPECT_TRUE(match_wildcards("???", "abc", MATCH_CASE_INSENSITIVE)); | |
1217 | EXPECT_FALSE(match_wildcards("???", "abcd")); | |
1218 | EXPECT_FALSE(match_wildcards("???", "abcd", MATCH_CASE_INSENSITIVE)); | |
1219 | } | |
1220 | ||
1221 | TEST(MatchWildcards, Asterisk) | |
1222 | { | |
1223 | EXPECT_TRUE(match_wildcards("*", "")); | |
1224 | EXPECT_TRUE(match_wildcards("*", "", MATCH_CASE_INSENSITIVE)); | |
1225 | EXPECT_FALSE(match_wildcards("", "*")); | |
1226 | EXPECT_FALSE(match_wildcards("", "*", MATCH_CASE_INSENSITIVE)); | |
1227 | EXPECT_FALSE(match_wildcards("*a", "")); | |
1228 | EXPECT_FALSE(match_wildcards("*a", "", MATCH_CASE_INSENSITIVE)); | |
1229 | EXPECT_TRUE(match_wildcards("*a", "a")); | |
1230 | EXPECT_TRUE(match_wildcards("*a", "a", MATCH_CASE_INSENSITIVE)); | |
1231 | EXPECT_TRUE(match_wildcards("a*", "a")); | |
1232 | EXPECT_TRUE(match_wildcards("a*", "a", MATCH_CASE_INSENSITIVE)); | |
1233 | EXPECT_TRUE(match_wildcards("a*c", "ac")); | |
1234 | EXPECT_TRUE(match_wildcards("a*c", "ac", MATCH_CASE_INSENSITIVE)); | |
1235 | EXPECT_TRUE(match_wildcards("a*c", "abbc")); | |
1236 | EXPECT_TRUE(match_wildcards("a*c", "abbc", MATCH_CASE_INSENSITIVE)); | |
1237 | EXPECT_FALSE(match_wildcards("a*c", "abbC")); | |
1238 | EXPECT_TRUE(match_wildcards("a*c", "abbC", MATCH_CASE_INSENSITIVE)); | |
1239 | EXPECT_TRUE(match_wildcards("a*c*e", "abBce")); | |
1240 | EXPECT_TRUE(match_wildcards("a*c*e", "abBce", MATCH_CASE_INSENSITIVE)); | |
1241 | EXPECT_TRUE(match_wildcards("http://*.example.com", | |
1242 | "http://www.example.com")); | |
1243 | EXPECT_TRUE(match_wildcards("http://*.example.com", | |
1244 | "http://www.example.com", MATCH_CASE_INSENSITIVE)); | |
1245 | EXPECT_FALSE(match_wildcards("http://*.example.com", | |
1246 | "http://www.Example.com")); | |
1247 | EXPECT_TRUE(match_wildcards("http://*.example.com", | |
1248 | "http://www.Example.com", MATCH_CASE_INSENSITIVE)); | |
1249 | EXPECT_TRUE(match_wildcards("http://example.com/*", | |
1250 | "http://example.com/index.html")); | |
1251 | EXPECT_TRUE(match_wildcards("http://example.com/*/*.jpg", | |
1252 | "http://example.com/fun/smiley.jpg")); | |
1253 | // note: parsing of * is not greedy, so * does not match 'bc' here | |
1254 | EXPECT_FALSE(match_wildcards("a*c", "abcc")); | |
1255 | EXPECT_FALSE(match_wildcards("a*c", "abcc", MATCH_CASE_INSENSITIVE)); | |
1256 | } | |
1257 | ||
1258 | TEST(MatchPolicy, Action) | |
1259 | { | |
1260 | constexpr auto flag = MATCH_POLICY_ACTION; | |
1261 | EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag)); | |
1262 | EXPECT_TRUE(match_policy("a:b:c", "A:B:C", flag)); // case insensitive | |
1263 | EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag)); | |
1264 | EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments | |
1265 | } | |
1266 | ||
1267 | TEST(MatchPolicy, Resource) | |
1268 | { | |
1269 | constexpr auto flag = MATCH_POLICY_RESOURCE; | |
1270 | EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag)); | |
1271 | EXPECT_FALSE(match_policy("a:b:c", "A:B:C", flag)); // case sensitive | |
1272 | EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag)); | |
f64942e4 | 1273 | EXPECT_TRUE(match_policy("a:*", "a:b:c", flag)); // can span segments |
d2e6a577 FG |
1274 | } |
1275 | ||
1276 | TEST(MatchPolicy, ARN) | |
1277 | { | |
1278 | constexpr auto flag = MATCH_POLICY_ARN; | |
1279 | EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag)); | |
1280 | EXPECT_TRUE(match_policy("a:b:c", "A:B:C", flag)); // case insensitive | |
1281 | EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag)); | |
1282 | EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments | |
1283 | } | |
1284 | ||
1285 | TEST(MatchPolicy, String) | |
1286 | { | |
1287 | constexpr auto flag = MATCH_POLICY_STRING; | |
1288 | EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag)); | |
1289 | EXPECT_FALSE(match_policy("a:b:c", "A:B:C", flag)); // case sensitive | |
1290 | EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag)); | |
f64942e4 | 1291 | EXPECT_TRUE(match_policy("a:*", "a:b:c", flag)); // can span segments |
d2e6a577 | 1292 | } |
9f95a23c TL |
1293 | |
1294 | Action_t set_range_bits(std::uint64_t start, std::uint64_t end) | |
1295 | { | |
1296 | Action_t result; | |
1297 | for (uint64_t i = start; i < end; i++) { | |
1298 | result.set(i); | |
1299 | } | |
1300 | return result; | |
1301 | } | |
1302 | ||
1303 | using rgw::IAM::s3AllValue; | |
1304 | using rgw::IAM::stsAllValue; | |
1305 | using rgw::IAM::allValue; | |
1306 | using rgw::IAM::iamAllValue; | |
1307 | TEST(set_cont_bits, iamconsts) | |
1308 | { | |
1309 | EXPECT_EQ(s3AllValue, set_range_bits(0, s3All)); | |
1310 | EXPECT_EQ(iamAllValue, set_range_bits(s3All+1, iamAll)); | |
1311 | EXPECT_EQ(stsAllValue, set_range_bits(iamAll+1, stsAll)); | |
1312 | EXPECT_EQ(allValue , set_range_bits(0, allCount)); | |
1313 | } |