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