]>
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 | ||
22 | #include "common/code_environment.h" | |
23 | #include "common/ceph_context.h" | |
24 | #include "global/global_init.h" | |
25 | #include "rgw/rgw_auth.h" | |
26 | #include "rgw/rgw_iam_policy.h" | |
27 | ||
28 | ||
29 | using std::string; | |
30 | using std::vector; | |
31 | ||
32 | using boost::container::flat_set; | |
33 | using boost::intrusive_ptr; | |
34 | using boost::make_optional; | |
35 | using boost::none; | |
36 | using boost::optional; | |
37 | ||
38 | using rgw::auth::Identity; | |
39 | using rgw::auth::Principal; | |
40 | ||
41 | using rgw::IAM::ARN; | |
42 | using rgw::IAM::Effect; | |
43 | using rgw::IAM::Environment; | |
44 | using rgw::IAM::Partition; | |
45 | using rgw::IAM::Policy; | |
46 | using rgw::IAM::s3All; | |
47 | using rgw::IAM::s3Count; | |
48 | using rgw::IAM::s3GetAccelerateConfiguration; | |
49 | using rgw::IAM::s3GetBucketAcl; | |
50 | using rgw::IAM::s3GetBucketCORS; | |
51 | using rgw::IAM::s3GetBucketLocation; | |
52 | using rgw::IAM::s3GetBucketLogging; | |
53 | using rgw::IAM::s3GetBucketNotification; | |
54 | using rgw::IAM::s3GetBucketPolicy; | |
55 | using rgw::IAM::s3GetBucketRequestPayment; | |
56 | using rgw::IAM::s3GetBucketTagging; | |
57 | using rgw::IAM::s3GetBucketVersioning; | |
58 | using rgw::IAM::s3GetBucketWebsite; | |
59 | using rgw::IAM::s3GetLifecycleConfiguration; | |
60 | using rgw::IAM::s3GetObject; | |
61 | using rgw::IAM::s3GetObjectAcl; | |
62 | using rgw::IAM::s3GetObjectVersionAcl; | |
63 | using rgw::IAM::s3GetObjectTorrent; | |
d2e6a577 | 64 | using rgw::IAM::s3GetObjectTagging; |
31f18b77 | 65 | using rgw::IAM::s3GetObjectVersion; |
d2e6a577 | 66 | using rgw::IAM::s3GetObjectVersionTagging; |
31f18b77 FG |
67 | using rgw::IAM::s3GetObjectVersionTorrent; |
68 | using rgw::IAM::s3GetReplicationConfiguration; | |
69 | using rgw::IAM::s3ListAllMyBuckets; | |
70 | using rgw::IAM::s3ListBucket; | |
71 | using rgw::IAM::s3ListBucket; | |
72 | using rgw::IAM::s3ListBucketMultiPartUploads; | |
73 | using rgw::IAM::s3ListBucketVersions; | |
74 | using rgw::IAM::s3ListMultipartUploadParts; | |
75 | using rgw::IAM::s3None; | |
76 | using rgw::IAM::s3PutBucketAcl; | |
77 | using rgw::IAM::s3PutBucketPolicy; | |
78 | using rgw::IAM::Service; | |
79 | using rgw::IAM::TokenID; | |
80 | using rgw::IAM::Version; | |
81 | ||
82 | class FakeIdentity : public Identity { | |
83 | const Principal id; | |
84 | public: | |
85 | ||
86 | FakeIdentity(Principal&& id) : id(std::move(id)) {} | |
87 | uint32_t get_perms_from_aclspec(const aclspec_t& aclspec) const override { | |
88 | abort(); | |
89 | return 0; | |
90 | }; | |
91 | ||
92 | bool is_admin_of(const rgw_user& uid) const override { | |
93 | abort(); | |
94 | return false; | |
95 | } | |
96 | ||
97 | bool is_owner_of(const rgw_user& uid) const override { | |
98 | abort(); | |
99 | return false; | |
100 | } | |
101 | ||
102 | virtual uint32_t get_perm_mask() const override { | |
103 | abort(); | |
104 | return 0; | |
105 | } | |
106 | ||
107 | void to_str(std::ostream& out) const override { | |
108 | abort(); | |
109 | } | |
110 | ||
111 | bool is_identity(const flat_set<Principal>& ids) const override { | |
112 | return ids.find(id) != ids.end(); | |
113 | } | |
114 | }; | |
115 | ||
116 | class PolicyTest : public ::testing::Test { | |
117 | protected: | |
118 | intrusive_ptr<CephContext> cct; | |
119 | static const string arbitrary_tenant; | |
120 | static string example1; | |
121 | static string example2; | |
122 | static string example3; | |
123 | public: | |
124 | PolicyTest() { | |
125 | cct = new CephContext(CEPH_ENTITY_TYPE_CLIENT); | |
126 | } | |
127 | }; | |
128 | ||
129 | TEST_F(PolicyTest, Parse1) { | |
130 | optional<Policy> p; | |
131 | ||
132 | ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, | |
133 | bufferlist::static_from_string(example1))); | |
134 | ASSERT_TRUE(p); | |
135 | ||
136 | EXPECT_EQ(p->text, example1); | |
137 | EXPECT_EQ(p->version, Version::v2012_10_17); | |
138 | EXPECT_FALSE(p->id); | |
139 | EXPECT_FALSE(p->statements[0].sid); | |
140 | EXPECT_FALSE(p->statements.empty()); | |
141 | EXPECT_EQ(p->statements.size(), 1U); | |
142 | EXPECT_TRUE(p->statements[0].princ.empty()); | |
143 | EXPECT_TRUE(p->statements[0].noprinc.empty()); | |
144 | EXPECT_EQ(p->statements[0].effect, Effect::Allow); | |
145 | EXPECT_EQ(p->statements[0].action, s3ListBucket); | |
146 | EXPECT_EQ(p->statements[0].notaction, s3None); | |
147 | ASSERT_FALSE(p->statements[0].resource.empty()); | |
148 | ASSERT_EQ(p->statements[0].resource.size(), 1U); | |
149 | EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws); | |
150 | EXPECT_EQ(p->statements[0].resource.begin()->service, Service::s3); | |
151 | EXPECT_TRUE(p->statements[0].resource.begin()->region.empty()); | |
152 | EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant); | |
153 | EXPECT_EQ(p->statements[0].resource.begin()->resource, "example_bucket"); | |
154 | EXPECT_TRUE(p->statements[0].notresource.empty()); | |
155 | EXPECT_TRUE(p->statements[0].conditions.empty()); | |
156 | } | |
157 | ||
158 | TEST_F(PolicyTest, Eval1) { | |
159 | auto p = Policy(cct.get(), arbitrary_tenant, | |
160 | bufferlist::static_from_string(example1)); | |
161 | Environment e; | |
162 | ||
163 | EXPECT_EQ(p.eval(e, none, s3ListBucket, | |
164 | ARN(Partition::aws, Service::s3, | |
165 | "", arbitrary_tenant, "example_bucket")), | |
166 | Effect::Allow); | |
167 | ||
168 | EXPECT_EQ(p.eval(e, none, s3PutBucketAcl, | |
169 | ARN(Partition::aws, Service::s3, | |
170 | "", arbitrary_tenant, "example_bucket")), | |
171 | Effect::Pass); | |
172 | ||
173 | EXPECT_EQ(p.eval(e, none, s3ListBucket, | |
174 | ARN(Partition::aws, Service::s3, | |
175 | "", arbitrary_tenant, "erroneous_bucket")), | |
176 | Effect::Pass); | |
177 | ||
178 | } | |
179 | ||
180 | TEST_F(PolicyTest, Parse2) { | |
181 | optional<Policy> p; | |
182 | ||
183 | ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, | |
184 | bufferlist::static_from_string(example2))); | |
185 | ASSERT_TRUE(p); | |
186 | ||
187 | EXPECT_EQ(p->text, example2); | |
188 | EXPECT_EQ(p->version, Version::v2012_10_17); | |
189 | EXPECT_EQ(*p->id, "S3-Account-Permissions"); | |
190 | ASSERT_FALSE(p->statements.empty()); | |
191 | EXPECT_EQ(p->statements.size(), 1U); | |
192 | EXPECT_EQ(*p->statements[0].sid, "1"); | |
193 | EXPECT_FALSE(p->statements[0].princ.empty()); | |
194 | EXPECT_EQ(p->statements[0].princ.size(), 1U); | |
195 | EXPECT_EQ(*p->statements[0].princ.begin(), | |
196 | Principal::tenant("ACCOUNT-ID-WITHOUT-HYPHENS")); | |
197 | EXPECT_TRUE(p->statements[0].noprinc.empty()); | |
198 | EXPECT_EQ(p->statements[0].effect, Effect::Allow); | |
199 | EXPECT_EQ(p->statements[0].action, s3All); | |
200 | EXPECT_EQ(p->statements[0].notaction, s3None); | |
201 | ASSERT_FALSE(p->statements[0].resource.empty()); | |
202 | ASSERT_EQ(p->statements[0].resource.size(), 2U); | |
203 | EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws); | |
204 | EXPECT_EQ(p->statements[0].resource.begin()->service, Service::s3); | |
205 | EXPECT_TRUE(p->statements[0].resource.begin()->region.empty()); | |
206 | EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant); | |
207 | EXPECT_EQ(p->statements[0].resource.begin()->resource, "mybucket"); | |
208 | EXPECT_EQ((p->statements[0].resource.begin() + 1)->partition, | |
209 | Partition::aws); | |
210 | EXPECT_EQ((p->statements[0].resource.begin() + 1)->service, | |
211 | Service::s3); | |
212 | EXPECT_TRUE((p->statements[0].resource.begin() + 1)->region.empty()); | |
213 | EXPECT_EQ((p->statements[0].resource.begin() + 1)->account, | |
214 | arbitrary_tenant); | |
215 | EXPECT_EQ((p->statements[0].resource.begin() + 1)->resource, "mybucket/*"); | |
216 | EXPECT_TRUE(p->statements[0].notresource.empty()); | |
217 | EXPECT_TRUE(p->statements[0].conditions.empty()); | |
218 | } | |
219 | ||
220 | TEST_F(PolicyTest, Eval2) { | |
221 | auto p = Policy(cct.get(), arbitrary_tenant, | |
222 | bufferlist::static_from_string(example2)); | |
223 | Environment e; | |
224 | ||
225 | auto trueacct = FakeIdentity( | |
226 | Principal::tenant("ACCOUNT-ID-WITHOUT-HYPHENS")); | |
227 | ||
228 | auto notacct = FakeIdentity( | |
229 | Principal::tenant("some-other-account")); | |
230 | for (auto i = 0ULL; i < s3Count; ++i) { | |
231 | EXPECT_EQ(p.eval(e, trueacct, 1ULL << i, | |
232 | ARN(Partition::aws, Service::s3, | |
233 | "", arbitrary_tenant, "mybucket")), | |
234 | Effect::Allow); | |
235 | EXPECT_EQ(p.eval(e, trueacct, 1ULL << i, | |
236 | ARN(Partition::aws, Service::s3, | |
237 | "", arbitrary_tenant, "mybucket/myobject")), | |
238 | Effect::Allow); | |
239 | ||
240 | EXPECT_EQ(p.eval(e, notacct, 1ULL << i, | |
241 | ARN(Partition::aws, Service::s3, | |
242 | "", arbitrary_tenant, "mybucket")), | |
243 | Effect::Pass); | |
244 | EXPECT_EQ(p.eval(e, notacct, 1ULL << i, | |
245 | ARN(Partition::aws, Service::s3, | |
246 | "", arbitrary_tenant, "mybucket/myobject")), | |
247 | Effect::Pass); | |
248 | ||
249 | EXPECT_EQ(p.eval(e, trueacct, 1ULL << i, | |
250 | ARN(Partition::aws, Service::s3, | |
251 | "", arbitrary_tenant, "notyourbucket")), | |
252 | Effect::Pass); | |
253 | EXPECT_EQ(p.eval(e, trueacct, 1ULL << i, | |
254 | ARN(Partition::aws, Service::s3, | |
255 | "", arbitrary_tenant, "notyourbucket/notyourobject")), | |
256 | Effect::Pass); | |
257 | ||
258 | } | |
259 | } | |
260 | ||
261 | TEST_F(PolicyTest, Parse3) { | |
262 | optional<Policy> p; | |
263 | ||
264 | ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, | |
265 | bufferlist::static_from_string(example3))); | |
266 | ASSERT_TRUE(p); | |
267 | ||
268 | EXPECT_EQ(p->text, example3); | |
269 | EXPECT_EQ(p->version, Version::v2012_10_17); | |
270 | EXPECT_FALSE(p->id); | |
271 | ASSERT_FALSE(p->statements.empty()); | |
272 | EXPECT_EQ(p->statements.size(), 3U); | |
273 | ||
274 | EXPECT_EQ(*p->statements[0].sid, "FirstStatement"); | |
275 | EXPECT_TRUE(p->statements[0].princ.empty()); | |
276 | EXPECT_TRUE(p->statements[0].noprinc.empty()); | |
277 | EXPECT_EQ(p->statements[0].effect, Effect::Allow); | |
278 | EXPECT_EQ(p->statements[0].action, s3PutBucketPolicy); | |
279 | EXPECT_EQ(p->statements[0].notaction, s3None); | |
280 | ASSERT_FALSE(p->statements[0].resource.empty()); | |
281 | ASSERT_EQ(p->statements[0].resource.size(), 1U); | |
282 | EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::wildcard); | |
283 | EXPECT_EQ(p->statements[0].resource.begin()->service, Service::wildcard); | |
284 | EXPECT_EQ(p->statements[0].resource.begin()->region, "*"); | |
285 | EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant); | |
286 | EXPECT_EQ(p->statements[0].resource.begin()->resource, "*"); | |
287 | EXPECT_TRUE(p->statements[0].notresource.empty()); | |
288 | EXPECT_TRUE(p->statements[0].conditions.empty()); | |
289 | ||
290 | EXPECT_EQ(*p->statements[1].sid, "SecondStatement"); | |
291 | EXPECT_TRUE(p->statements[1].princ.empty()); | |
292 | EXPECT_TRUE(p->statements[1].noprinc.empty()); | |
293 | EXPECT_EQ(p->statements[1].effect, Effect::Allow); | |
294 | EXPECT_EQ(p->statements[1].action, s3ListAllMyBuckets); | |
295 | EXPECT_EQ(p->statements[1].notaction, s3None); | |
296 | ASSERT_FALSE(p->statements[1].resource.empty()); | |
297 | ASSERT_EQ(p->statements[1].resource.size(), 1U); | |
298 | EXPECT_EQ(p->statements[1].resource.begin()->partition, Partition::wildcard); | |
299 | EXPECT_EQ(p->statements[1].resource.begin()->service, Service::wildcard); | |
300 | EXPECT_EQ(p->statements[1].resource.begin()->region, "*"); | |
301 | EXPECT_EQ(p->statements[1].resource.begin()->account, arbitrary_tenant); | |
302 | EXPECT_EQ(p->statements[1].resource.begin()->resource, "*"); | |
303 | EXPECT_TRUE(p->statements[1].notresource.empty()); | |
304 | EXPECT_TRUE(p->statements[1].conditions.empty()); | |
305 | ||
306 | EXPECT_EQ(*p->statements[2].sid, "ThirdStatement"); | |
307 | EXPECT_TRUE(p->statements[2].princ.empty()); | |
308 | EXPECT_TRUE(p->statements[2].noprinc.empty()); | |
309 | EXPECT_EQ(p->statements[2].effect, Effect::Allow); | |
310 | EXPECT_EQ(p->statements[2].action, (s3ListMultipartUploadParts | | |
311 | s3ListBucket | s3ListBucketVersions | | |
312 | s3ListAllMyBuckets | | |
313 | s3ListBucketMultiPartUploads | | |
314 | s3GetObject | s3GetObjectVersion | | |
315 | s3GetObjectAcl | s3GetObjectVersionAcl | | |
316 | s3GetObjectTorrent | | |
317 | s3GetObjectVersionTorrent | | |
318 | s3GetAccelerateConfiguration | | |
319 | s3GetBucketAcl | s3GetBucketCORS | | |
320 | s3GetBucketVersioning | | |
321 | s3GetBucketRequestPayment | | |
322 | s3GetBucketLocation | | |
323 | s3GetBucketPolicy | | |
324 | s3GetBucketNotification | | |
325 | s3GetBucketLogging | | |
326 | s3GetBucketTagging | | |
327 | s3GetBucketWebsite | | |
328 | s3GetLifecycleConfiguration | | |
d2e6a577 FG |
329 | s3GetReplicationConfiguration | |
330 | s3GetObjectTagging | | |
331 | s3GetObjectVersionTagging)); | |
31f18b77 FG |
332 | EXPECT_EQ(p->statements[2].notaction, s3None); |
333 | ASSERT_FALSE(p->statements[2].resource.empty()); | |
334 | ASSERT_EQ(p->statements[2].resource.size(), 2U); | |
335 | EXPECT_EQ(p->statements[2].resource.begin()->partition, Partition::aws); | |
336 | EXPECT_EQ(p->statements[2].resource.begin()->service, Service::s3); | |
337 | EXPECT_TRUE(p->statements[2].resource.begin()->region.empty()); | |
338 | EXPECT_EQ(p->statements[2].resource.begin()->account, arbitrary_tenant); | |
339 | EXPECT_EQ(p->statements[2].resource.begin()->resource, "confidential-data"); | |
340 | EXPECT_EQ((p->statements[2].resource.begin() + 1)->partition, | |
341 | Partition::aws); | |
342 | EXPECT_EQ((p->statements[2].resource.begin() + 1)->service, Service::s3); | |
343 | EXPECT_TRUE((p->statements[2].resource.begin() + 1)->region.empty()); | |
344 | EXPECT_EQ((p->statements[2].resource.begin() + 1)->account, | |
345 | arbitrary_tenant); | |
346 | EXPECT_EQ((p->statements[2].resource.begin() + 1)->resource, | |
347 | "confidential-data/*"); | |
348 | EXPECT_TRUE(p->statements[2].notresource.empty()); | |
349 | ASSERT_FALSE(p->statements[2].conditions.empty()); | |
350 | ASSERT_EQ(p->statements[2].conditions.size(), 1U); | |
351 | EXPECT_EQ(p->statements[2].conditions[0].op, TokenID::Bool); | |
352 | EXPECT_EQ(p->statements[2].conditions[0].key, "aws:MultiFactorAuthPresent"); | |
353 | EXPECT_FALSE(p->statements[2].conditions[0].ifexists); | |
354 | ASSERT_FALSE(p->statements[2].conditions[0].vals.empty()); | |
355 | EXPECT_EQ(p->statements[2].conditions[0].vals.size(), 1U); | |
356 | EXPECT_EQ(p->statements[2].conditions[0].vals[0], "true"); | |
357 | } | |
358 | ||
359 | TEST_F(PolicyTest, Eval3) { | |
360 | auto p = Policy(cct.get(), arbitrary_tenant, | |
361 | bufferlist::static_from_string(example3)); | |
362 | Environment em; | |
363 | Environment tr = { { "aws:MultiFactorAuthPresent", "true" } }; | |
364 | Environment fa = { { "aws:MultiFactorAuthPresent", "false" } }; | |
365 | ||
366 | auto s3allow = (s3ListMultipartUploadParts | s3ListBucket | | |
367 | s3ListBucketVersions | s3ListAllMyBuckets | | |
368 | s3ListBucketMultiPartUploads | s3GetObject | | |
369 | s3GetObjectVersion | s3GetObjectAcl | s3GetObjectVersionAcl | | |
370 | s3GetObjectTorrent | s3GetObjectVersionTorrent | | |
371 | s3GetAccelerateConfiguration | s3GetBucketAcl | | |
372 | s3GetBucketCORS | s3GetBucketVersioning | | |
373 | s3GetBucketRequestPayment | s3GetBucketLocation | | |
374 | s3GetBucketPolicy | s3GetBucketNotification | | |
375 | s3GetBucketLogging | s3GetBucketTagging | | |
376 | s3GetBucketWebsite | s3GetLifecycleConfiguration | | |
d2e6a577 FG |
377 | s3GetReplicationConfiguration | |
378 | s3GetObjectTagging | s3GetObjectVersionTagging); | |
31f18b77 FG |
379 | |
380 | EXPECT_EQ(p.eval(em, none, s3PutBucketPolicy, | |
381 | ARN(Partition::aws, Service::s3, | |
382 | "", arbitrary_tenant, "mybucket")), | |
383 | Effect::Allow); | |
384 | ||
385 | EXPECT_EQ(p.eval(em, none, s3PutBucketPolicy, | |
386 | ARN(Partition::aws, Service::s3, | |
387 | "", arbitrary_tenant, "mybucket")), | |
388 | Effect::Allow); | |
389 | ||
390 | ||
391 | for (auto i = 0ULL; i < s3Count; ++i) { | |
392 | auto op = 1ULL << i; | |
393 | if ((op == s3ListAllMyBuckets) || (op == s3PutBucketPolicy)) { | |
394 | continue; | |
395 | } | |
396 | ||
397 | EXPECT_EQ(p.eval(em, none, op, | |
398 | ARN(Partition::aws, Service::s3, | |
399 | "", arbitrary_tenant, "confidential-data")), | |
400 | Effect::Pass); | |
401 | EXPECT_EQ(p.eval(tr, none, op, | |
402 | ARN(Partition::aws, Service::s3, | |
403 | "", arbitrary_tenant, "confidential-data")), | |
404 | op & s3allow ? Effect::Allow : Effect::Pass); | |
405 | EXPECT_EQ(p.eval(fa, none, op, | |
406 | ARN(Partition::aws, Service::s3, | |
407 | "", arbitrary_tenant, "confidential-data")), | |
408 | Effect::Pass); | |
409 | ||
410 | EXPECT_EQ(p.eval(em, none, op, | |
411 | ARN(Partition::aws, Service::s3, | |
412 | "", arbitrary_tenant, "confidential-data/moo")), | |
413 | Effect::Pass); | |
414 | EXPECT_EQ(p.eval(tr, none, op, | |
415 | ARN(Partition::aws, Service::s3, | |
416 | "", arbitrary_tenant, "confidential-data/moo")), | |
417 | op & s3allow ? Effect::Allow : Effect::Pass); | |
418 | EXPECT_EQ(p.eval(fa, none, op, | |
419 | ARN(Partition::aws, Service::s3, | |
420 | "", arbitrary_tenant, "confidential-data/moo")), | |
421 | Effect::Pass); | |
422 | ||
423 | EXPECT_EQ(p.eval(em, none, op, | |
424 | ARN(Partition::aws, Service::s3, | |
425 | "", arbitrary_tenant, "really-confidential-data")), | |
426 | Effect::Pass); | |
427 | EXPECT_EQ(p.eval(tr, none, op, | |
428 | ARN(Partition::aws, Service::s3, | |
429 | "", arbitrary_tenant, "really-confidential-data")), | |
430 | Effect::Pass); | |
431 | EXPECT_EQ(p.eval(fa, none, op, | |
432 | ARN(Partition::aws, Service::s3, | |
433 | "", arbitrary_tenant, "really-confidential-data")), | |
434 | Effect::Pass); | |
435 | ||
436 | EXPECT_EQ(p.eval(em, none, op, | |
437 | ARN(Partition::aws, Service::s3, | |
438 | "", arbitrary_tenant, | |
439 | "really-confidential-data/moo")), Effect::Pass); | |
440 | EXPECT_EQ(p.eval(tr, none, op, | |
441 | ARN(Partition::aws, Service::s3, | |
442 | "", arbitrary_tenant, | |
443 | "really-confidential-data/moo")), Effect::Pass); | |
444 | EXPECT_EQ(p.eval(fa, none, op, | |
445 | ARN(Partition::aws, Service::s3, | |
446 | "", arbitrary_tenant, | |
447 | "really-confidential-data/moo")), Effect::Pass); | |
448 | ||
449 | } | |
450 | } | |
451 | ||
452 | const string PolicyTest::arbitrary_tenant = "arbitrary_tenant"; | |
453 | string PolicyTest::example1 = R"( | |
454 | { | |
455 | "Version": "2012-10-17", | |
456 | "Statement": { | |
457 | "Effect": "Allow", | |
458 | "Action": "s3:ListBucket", | |
459 | "Resource": "arn:aws:s3:::example_bucket" | |
460 | } | |
461 | } | |
462 | )"; | |
463 | ||
464 | string PolicyTest::example2 = R"( | |
465 | { | |
466 | "Version": "2012-10-17", | |
467 | "Id": "S3-Account-Permissions", | |
468 | "Statement": [{ | |
469 | "Sid": "1", | |
470 | "Effect": "Allow", | |
471 | "Principal": {"AWS": ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:root"]}, | |
472 | "Action": "s3:*", | |
473 | "Resource": [ | |
474 | "arn:aws:s3:::mybucket", | |
475 | "arn:aws:s3:::mybucket/*" | |
476 | ] | |
477 | }] | |
478 | } | |
479 | )"; | |
480 | ||
481 | string PolicyTest::example3 = R"( | |
482 | { | |
483 | "Version": "2012-10-17", | |
484 | "Statement": [ | |
485 | { | |
486 | "Sid": "FirstStatement", | |
487 | "Effect": "Allow", | |
488 | "Action": ["s3:PutBucketPolicy"], | |
489 | "Resource": "*" | |
490 | }, | |
491 | { | |
492 | "Sid": "SecondStatement", | |
493 | "Effect": "Allow", | |
494 | "Action": "s3:ListAllMyBuckets", | |
495 | "Resource": "*" | |
496 | }, | |
497 | { | |
498 | "Sid": "ThirdStatement", | |
499 | "Effect": "Allow", | |
500 | "Action": [ | |
501 | "s3:List*", | |
502 | "s3:Get*" | |
503 | ], | |
504 | "Resource": [ | |
505 | "arn:aws:s3:::confidential-data", | |
506 | "arn:aws:s3:::confidential-data/*" | |
507 | ], | |
508 | "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}} | |
509 | } | |
510 | ] | |
511 | } | |
512 | )"; | |
d2e6a577 FG |
513 | |
514 | TEST(MatchWildcards, Simple) | |
515 | { | |
516 | EXPECT_TRUE(match_wildcards("", "")); | |
517 | EXPECT_TRUE(match_wildcards("", "", MATCH_CASE_INSENSITIVE)); | |
518 | EXPECT_FALSE(match_wildcards("", "abc")); | |
519 | EXPECT_FALSE(match_wildcards("", "abc", MATCH_CASE_INSENSITIVE)); | |
520 | EXPECT_FALSE(match_wildcards("abc", "")); | |
521 | EXPECT_FALSE(match_wildcards("abc", "", MATCH_CASE_INSENSITIVE)); | |
522 | EXPECT_TRUE(match_wildcards("abc", "abc")); | |
523 | EXPECT_TRUE(match_wildcards("abc", "abc", MATCH_CASE_INSENSITIVE)); | |
524 | EXPECT_FALSE(match_wildcards("abc", "abC")); | |
525 | EXPECT_TRUE(match_wildcards("abc", "abC", MATCH_CASE_INSENSITIVE)); | |
526 | EXPECT_FALSE(match_wildcards("abC", "abc")); | |
527 | EXPECT_TRUE(match_wildcards("abC", "abc", MATCH_CASE_INSENSITIVE)); | |
528 | EXPECT_FALSE(match_wildcards("abc", "abcd")); | |
529 | EXPECT_FALSE(match_wildcards("abc", "abcd", MATCH_CASE_INSENSITIVE)); | |
530 | EXPECT_FALSE(match_wildcards("abcd", "abc")); | |
531 | EXPECT_FALSE(match_wildcards("abcd", "abc", MATCH_CASE_INSENSITIVE)); | |
532 | } | |
533 | ||
534 | TEST(MatchWildcards, QuestionMark) | |
535 | { | |
536 | EXPECT_FALSE(match_wildcards("?", "")); | |
537 | EXPECT_FALSE(match_wildcards("?", "", MATCH_CASE_INSENSITIVE)); | |
538 | EXPECT_TRUE(match_wildcards("?", "a")); | |
539 | EXPECT_TRUE(match_wildcards("?", "a", MATCH_CASE_INSENSITIVE)); | |
540 | EXPECT_TRUE(match_wildcards("?bc", "abc")); | |
541 | EXPECT_TRUE(match_wildcards("?bc", "abc", MATCH_CASE_INSENSITIVE)); | |
542 | EXPECT_TRUE(match_wildcards("a?c", "abc")); | |
543 | EXPECT_TRUE(match_wildcards("a?c", "abc", MATCH_CASE_INSENSITIVE)); | |
544 | EXPECT_FALSE(match_wildcards("abc", "a?c")); | |
545 | EXPECT_FALSE(match_wildcards("abc", "a?c", MATCH_CASE_INSENSITIVE)); | |
546 | EXPECT_FALSE(match_wildcards("a?c", "abC")); | |
547 | EXPECT_TRUE(match_wildcards("a?c", "abC", MATCH_CASE_INSENSITIVE)); | |
548 | EXPECT_TRUE(match_wildcards("ab?", "abc")); | |
549 | EXPECT_TRUE(match_wildcards("ab?", "abc", MATCH_CASE_INSENSITIVE)); | |
550 | EXPECT_TRUE(match_wildcards("a?c?e", "abcde")); | |
551 | EXPECT_TRUE(match_wildcards("a?c?e", "abcde", MATCH_CASE_INSENSITIVE)); | |
552 | EXPECT_TRUE(match_wildcards("???", "abc")); | |
553 | EXPECT_TRUE(match_wildcards("???", "abc", MATCH_CASE_INSENSITIVE)); | |
554 | EXPECT_FALSE(match_wildcards("???", "abcd")); | |
555 | EXPECT_FALSE(match_wildcards("???", "abcd", MATCH_CASE_INSENSITIVE)); | |
556 | } | |
557 | ||
558 | TEST(MatchWildcards, Asterisk) | |
559 | { | |
560 | EXPECT_TRUE(match_wildcards("*", "")); | |
561 | EXPECT_TRUE(match_wildcards("*", "", MATCH_CASE_INSENSITIVE)); | |
562 | EXPECT_FALSE(match_wildcards("", "*")); | |
563 | EXPECT_FALSE(match_wildcards("", "*", MATCH_CASE_INSENSITIVE)); | |
564 | EXPECT_FALSE(match_wildcards("*a", "")); | |
565 | EXPECT_FALSE(match_wildcards("*a", "", MATCH_CASE_INSENSITIVE)); | |
566 | EXPECT_TRUE(match_wildcards("*a", "a")); | |
567 | EXPECT_TRUE(match_wildcards("*a", "a", MATCH_CASE_INSENSITIVE)); | |
568 | EXPECT_TRUE(match_wildcards("a*", "a")); | |
569 | EXPECT_TRUE(match_wildcards("a*", "a", MATCH_CASE_INSENSITIVE)); | |
570 | EXPECT_TRUE(match_wildcards("a*c", "ac")); | |
571 | EXPECT_TRUE(match_wildcards("a*c", "ac", MATCH_CASE_INSENSITIVE)); | |
572 | EXPECT_TRUE(match_wildcards("a*c", "abbc")); | |
573 | EXPECT_TRUE(match_wildcards("a*c", "abbc", MATCH_CASE_INSENSITIVE)); | |
574 | EXPECT_FALSE(match_wildcards("a*c", "abbC")); | |
575 | EXPECT_TRUE(match_wildcards("a*c", "abbC", MATCH_CASE_INSENSITIVE)); | |
576 | EXPECT_TRUE(match_wildcards("a*c*e", "abBce")); | |
577 | EXPECT_TRUE(match_wildcards("a*c*e", "abBce", MATCH_CASE_INSENSITIVE)); | |
578 | EXPECT_TRUE(match_wildcards("http://*.example.com", | |
579 | "http://www.example.com")); | |
580 | EXPECT_TRUE(match_wildcards("http://*.example.com", | |
581 | "http://www.example.com", MATCH_CASE_INSENSITIVE)); | |
582 | EXPECT_FALSE(match_wildcards("http://*.example.com", | |
583 | "http://www.Example.com")); | |
584 | EXPECT_TRUE(match_wildcards("http://*.example.com", | |
585 | "http://www.Example.com", MATCH_CASE_INSENSITIVE)); | |
586 | EXPECT_TRUE(match_wildcards("http://example.com/*", | |
587 | "http://example.com/index.html")); | |
588 | EXPECT_TRUE(match_wildcards("http://example.com/*/*.jpg", | |
589 | "http://example.com/fun/smiley.jpg")); | |
590 | // note: parsing of * is not greedy, so * does not match 'bc' here | |
591 | EXPECT_FALSE(match_wildcards("a*c", "abcc")); | |
592 | EXPECT_FALSE(match_wildcards("a*c", "abcc", MATCH_CASE_INSENSITIVE)); | |
593 | } | |
594 | ||
595 | TEST(MatchPolicy, Action) | |
596 | { | |
597 | constexpr auto flag = MATCH_POLICY_ACTION; | |
598 | EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag)); | |
599 | EXPECT_TRUE(match_policy("a:b:c", "A:B:C", flag)); // case insensitive | |
600 | EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag)); | |
601 | EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments | |
602 | } | |
603 | ||
604 | TEST(MatchPolicy, Resource) | |
605 | { | |
606 | constexpr auto flag = MATCH_POLICY_RESOURCE; | |
607 | EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag)); | |
608 | EXPECT_FALSE(match_policy("a:b:c", "A:B:C", flag)); // case sensitive | |
609 | EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag)); | |
610 | EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments | |
611 | } | |
612 | ||
613 | TEST(MatchPolicy, ARN) | |
614 | { | |
615 | constexpr auto flag = MATCH_POLICY_ARN; | |
616 | EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag)); | |
617 | EXPECT_TRUE(match_policy("a:b:c", "A:B:C", flag)); // case insensitive | |
618 | EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag)); | |
619 | EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments | |
620 | } | |
621 | ||
622 | TEST(MatchPolicy, String) | |
623 | { | |
624 | constexpr auto flag = MATCH_POLICY_STRING; | |
625 | EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag)); | |
626 | EXPECT_FALSE(match_policy("a:b:c", "A:B:C", flag)); // case sensitive | |
627 | EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag)); | |
628 | EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments | |
629 | } |