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