1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2015 Red Hat
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.
17 #include <boost/intrusive_ptr.hpp>
18 #include <boost/optional.hpp>
20 #include <gtest/gtest.h>
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"
34 using boost::container::flat_set
;
35 using boost::intrusive_ptr
;
36 using boost::make_optional
;
39 using rgw::auth::Identity
;
40 using rgw::auth::Principal
;
43 using rgw::IAM::Effect
;
44 using rgw::IAM::Environment
;
45 using rgw::IAM::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
;
77 using rgw::IAM::s3PutBucketAcl
;
78 using rgw::IAM::s3PutBucketPolicy
;
79 using rgw::IAM::Service
;
80 using rgw::IAM::TokenID
;
81 using rgw::IAM::Version
;
82 using rgw::IAM::Action_t
;
83 using rgw::IAM::NotAction_t
;
84 using rgw::IAM::iamCreateRole
;
85 using rgw::IAM::iamDeleteRole
;
86 using rgw::IAM::iamAll
;
87 using rgw::IAM::stsAll
;
89 class FakeIdentity
: public Identity
{
93 explicit FakeIdentity(Principal
&& id
) : id(std::move(id
)) {}
94 uint32_t get_perms_from_aclspec(const DoutPrefixProvider
* dpp
, const aclspec_t
& aclspec
) const override
{
99 bool is_admin_of(const rgw_user
& uid
) const override
{
104 bool is_owner_of(const rgw_user
& uid
) const override
{
109 virtual uint32_t get_perm_mask() const override
{
114 uint32_t get_identity_type() const override
{
119 string
get_acct_name() const override
{
124 void to_str(std::ostream
& out
) const override
{
128 bool is_identity(const flat_set
<Principal
>& ids
) const override
{
129 if (id
.is_wildcard() && (!ids
.empty())) {
132 return ids
.find(id
) != ids
.end() || ids
.find(Principal::wildcard()) != ids
.end();
136 class PolicyTest
: public ::testing::Test
{
138 intrusive_ptr
<CephContext
> cct
;
139 static const string arbitrary_tenant
;
140 static string example1
;
141 static string example2
;
142 static string example3
;
143 static string example4
;
144 static string example5
;
145 static string example6
;
148 cct
= new CephContext(CEPH_ENTITY_TYPE_CLIENT
);
152 TEST_F(PolicyTest
, Parse1
) {
153 boost::optional
<Policy
> p
;
155 ASSERT_NO_THROW(p
= Policy(cct
.get(), arbitrary_tenant
,
156 bufferlist::static_from_string(example1
)));
159 EXPECT_EQ(p
->text
, example1
);
160 EXPECT_EQ(p
->version
, Version::v2012_10_17
);
162 EXPECT_FALSE(p
->statements
[0].sid
);
163 EXPECT_FALSE(p
->statements
.empty());
164 EXPECT_EQ(p
->statements
.size(), 1U);
165 EXPECT_TRUE(p
->statements
[0].princ
.empty());
166 EXPECT_TRUE(p
->statements
[0].noprinc
.empty());
167 EXPECT_EQ(p
->statements
[0].effect
, Effect::Allow
);
169 act
[s3ListBucket
] = 1;
170 EXPECT_EQ(p
->statements
[0].action
, act
);
171 EXPECT_EQ(p
->statements
[0].notaction
, None
);
172 ASSERT_FALSE(p
->statements
[0].resource
.empty());
173 ASSERT_EQ(p
->statements
[0].resource
.size(), 1U);
174 EXPECT_EQ(p
->statements
[0].resource
.begin()->partition
, Partition::aws
);
175 EXPECT_EQ(p
->statements
[0].resource
.begin()->service
, Service::s3
);
176 EXPECT_TRUE(p
->statements
[0].resource
.begin()->region
.empty());
177 EXPECT_EQ(p
->statements
[0].resource
.begin()->account
, arbitrary_tenant
);
178 EXPECT_EQ(p
->statements
[0].resource
.begin()->resource
, "example_bucket");
179 EXPECT_TRUE(p
->statements
[0].notresource
.empty());
180 EXPECT_TRUE(p
->statements
[0].conditions
.empty());
183 TEST_F(PolicyTest
, Eval1
) {
184 auto p
= Policy(cct
.get(), arbitrary_tenant
,
185 bufferlist::static_from_string(example1
));
188 EXPECT_EQ(p
.eval(e
, none
, s3ListBucket
,
189 ARN(Partition::aws
, Service::s3
,
190 "", arbitrary_tenant
, "example_bucket")),
193 EXPECT_EQ(p
.eval(e
, none
, s3PutBucketAcl
,
194 ARN(Partition::aws
, Service::s3
,
195 "", arbitrary_tenant
, "example_bucket")),
198 EXPECT_EQ(p
.eval(e
, none
, s3ListBucket
,
199 ARN(Partition::aws
, Service::s3
,
200 "", arbitrary_tenant
, "erroneous_bucket")),
205 TEST_F(PolicyTest
, Parse2
) {
206 boost::optional
<Policy
> p
;
208 ASSERT_NO_THROW(p
= Policy(cct
.get(), arbitrary_tenant
,
209 bufferlist::static_from_string(example2
)));
212 EXPECT_EQ(p
->text
, example2
);
213 EXPECT_EQ(p
->version
, Version::v2012_10_17
);
214 EXPECT_EQ(*p
->id
, "S3-Account-Permissions");
215 ASSERT_FALSE(p
->statements
.empty());
216 EXPECT_EQ(p
->statements
.size(), 1U);
217 EXPECT_EQ(*p
->statements
[0].sid
, "1");
218 EXPECT_FALSE(p
->statements
[0].princ
.empty());
219 EXPECT_EQ(p
->statements
[0].princ
.size(), 1U);
220 EXPECT_EQ(*p
->statements
[0].princ
.begin(),
221 Principal::tenant("ACCOUNT-ID-WITHOUT-HYPHENS"));
222 EXPECT_TRUE(p
->statements
[0].noprinc
.empty());
223 EXPECT_EQ(p
->statements
[0].effect
, Effect::Allow
);
225 for (auto i
= 0ULL; i
< s3Count
; i
++)
228 EXPECT_EQ(p
->statements
[0].action
, act
);
229 EXPECT_EQ(p
->statements
[0].notaction
, None
);
230 ASSERT_FALSE(p
->statements
[0].resource
.empty());
231 ASSERT_EQ(p
->statements
[0].resource
.size(), 2U);
232 EXPECT_EQ(p
->statements
[0].resource
.begin()->partition
, Partition::aws
);
233 EXPECT_EQ(p
->statements
[0].resource
.begin()->service
, Service::s3
);
234 EXPECT_TRUE(p
->statements
[0].resource
.begin()->region
.empty());
235 EXPECT_EQ(p
->statements
[0].resource
.begin()->account
, arbitrary_tenant
);
236 EXPECT_EQ(p
->statements
[0].resource
.begin()->resource
, "mybucket");
237 EXPECT_EQ((p
->statements
[0].resource
.begin() + 1)->partition
,
239 EXPECT_EQ((p
->statements
[0].resource
.begin() + 1)->service
,
241 EXPECT_TRUE((p
->statements
[0].resource
.begin() + 1)->region
.empty());
242 EXPECT_EQ((p
->statements
[0].resource
.begin() + 1)->account
,
244 EXPECT_EQ((p
->statements
[0].resource
.begin() + 1)->resource
, "mybucket/*");
245 EXPECT_TRUE(p
->statements
[0].notresource
.empty());
246 EXPECT_TRUE(p
->statements
[0].conditions
.empty());
249 TEST_F(PolicyTest
, Eval2
) {
250 auto p
= Policy(cct
.get(), arbitrary_tenant
,
251 bufferlist::static_from_string(example2
));
254 auto trueacct
= FakeIdentity(
255 Principal::tenant("ACCOUNT-ID-WITHOUT-HYPHENS"));
257 auto notacct
= FakeIdentity(
258 Principal::tenant("some-other-account"));
259 for (auto i
= 0ULL; i
< s3Count
; ++i
) {
260 EXPECT_EQ(p
.eval(e
, trueacct
, i
,
261 ARN(Partition::aws
, Service::s3
,
262 "", arbitrary_tenant
, "mybucket")),
264 EXPECT_EQ(p
.eval(e
, trueacct
, i
,
265 ARN(Partition::aws
, Service::s3
,
266 "", arbitrary_tenant
, "mybucket/myobject")),
269 EXPECT_EQ(p
.eval(e
, notacct
, i
,
270 ARN(Partition::aws
, Service::s3
,
271 "", arbitrary_tenant
, "mybucket")),
273 EXPECT_EQ(p
.eval(e
, notacct
, i
,
274 ARN(Partition::aws
, Service::s3
,
275 "", arbitrary_tenant
, "mybucket/myobject")),
278 EXPECT_EQ(p
.eval(e
, trueacct
, i
,
279 ARN(Partition::aws
, Service::s3
,
280 "", arbitrary_tenant
, "notyourbucket")),
282 EXPECT_EQ(p
.eval(e
, trueacct
, i
,
283 ARN(Partition::aws
, Service::s3
,
284 "", arbitrary_tenant
, "notyourbucket/notyourobject")),
290 TEST_F(PolicyTest
, Parse3
) {
291 boost::optional
<Policy
> p
;
293 ASSERT_NO_THROW(p
= Policy(cct
.get(), arbitrary_tenant
,
294 bufferlist::static_from_string(example3
)));
297 EXPECT_EQ(p
->text
, example3
);
298 EXPECT_EQ(p
->version
, Version::v2012_10_17
);
300 ASSERT_FALSE(p
->statements
.empty());
301 EXPECT_EQ(p
->statements
.size(), 3U);
303 EXPECT_EQ(*p
->statements
[0].sid
, "FirstStatement");
304 EXPECT_TRUE(p
->statements
[0].princ
.empty());
305 EXPECT_TRUE(p
->statements
[0].noprinc
.empty());
306 EXPECT_EQ(p
->statements
[0].effect
, Effect::Allow
);
308 act
[s3PutBucketPolicy
] = 1;
309 EXPECT_EQ(p
->statements
[0].action
, act
);
310 EXPECT_EQ(p
->statements
[0].notaction
, None
);
311 ASSERT_FALSE(p
->statements
[0].resource
.empty());
312 ASSERT_EQ(p
->statements
[0].resource
.size(), 1U);
313 EXPECT_EQ(p
->statements
[0].resource
.begin()->partition
, Partition::wildcard
);
314 EXPECT_EQ(p
->statements
[0].resource
.begin()->service
, Service::wildcard
);
315 EXPECT_EQ(p
->statements
[0].resource
.begin()->region
, "*");
316 EXPECT_EQ(p
->statements
[0].resource
.begin()->account
, arbitrary_tenant
);
317 EXPECT_EQ(p
->statements
[0].resource
.begin()->resource
, "*");
318 EXPECT_TRUE(p
->statements
[0].notresource
.empty());
319 EXPECT_TRUE(p
->statements
[0].conditions
.empty());
321 EXPECT_EQ(*p
->statements
[1].sid
, "SecondStatement");
322 EXPECT_TRUE(p
->statements
[1].princ
.empty());
323 EXPECT_TRUE(p
->statements
[1].noprinc
.empty());
324 EXPECT_EQ(p
->statements
[1].effect
, Effect::Allow
);
326 act1
[s3ListAllMyBuckets
] = 1;
327 EXPECT_EQ(p
->statements
[1].action
, act1
);
328 EXPECT_EQ(p
->statements
[1].notaction
, None
);
329 ASSERT_FALSE(p
->statements
[1].resource
.empty());
330 ASSERT_EQ(p
->statements
[1].resource
.size(), 1U);
331 EXPECT_EQ(p
->statements
[1].resource
.begin()->partition
, Partition::wildcard
);
332 EXPECT_EQ(p
->statements
[1].resource
.begin()->service
, Service::wildcard
);
333 EXPECT_EQ(p
->statements
[1].resource
.begin()->region
, "*");
334 EXPECT_EQ(p
->statements
[1].resource
.begin()->account
, arbitrary_tenant
);
335 EXPECT_EQ(p
->statements
[1].resource
.begin()->resource
, "*");
336 EXPECT_TRUE(p
->statements
[1].notresource
.empty());
337 EXPECT_TRUE(p
->statements
[1].conditions
.empty());
339 EXPECT_EQ(*p
->statements
[2].sid
, "ThirdStatement");
340 EXPECT_TRUE(p
->statements
[2].princ
.empty());
341 EXPECT_TRUE(p
->statements
[2].noprinc
.empty());
342 EXPECT_EQ(p
->statements
[2].effect
, Effect::Allow
);
344 act2
[s3ListMultipartUploadParts
] = 1;
345 act2
[s3ListBucket
] = 1;
346 act2
[s3ListBucketVersions
] = 1;
347 act2
[s3ListAllMyBuckets
] = 1;
348 act2
[s3ListBucketMultipartUploads
] = 1;
349 act2
[s3GetObject
] = 1;
350 act2
[s3GetObjectVersion
] = 1;
351 act2
[s3GetObjectAcl
] = 1;
352 act2
[s3GetObjectVersionAcl
] = 1;
353 act2
[s3GetObjectTorrent
] = 1;
354 act2
[s3GetObjectVersionTorrent
] = 1;
355 act2
[s3GetAccelerateConfiguration
] = 1;
356 act2
[s3GetBucketAcl
] = 1;
357 act2
[s3GetBucketCORS
] = 1;
358 act2
[s3GetBucketVersioning
] = 1;
359 act2
[s3GetBucketRequestPayment
] = 1;
360 act2
[s3GetBucketLocation
] = 1;
361 act2
[s3GetBucketPolicy
] = 1;
362 act2
[s3GetBucketNotification
] = 1;
363 act2
[s3GetBucketLogging
] = 1;
364 act2
[s3GetBucketTagging
] = 1;
365 act2
[s3GetBucketWebsite
] = 1;
366 act2
[s3GetLifecycleConfiguration
] = 1;
367 act2
[s3GetReplicationConfiguration
] = 1;
368 act2
[s3GetObjectTagging
] = 1;
369 act2
[s3GetObjectVersionTagging
] = 1;
371 EXPECT_EQ(p
->statements
[2].action
, act2
);
372 EXPECT_EQ(p
->statements
[2].notaction
, None
);
373 ASSERT_FALSE(p
->statements
[2].resource
.empty());
374 ASSERT_EQ(p
->statements
[2].resource
.size(), 2U);
375 EXPECT_EQ(p
->statements
[2].resource
.begin()->partition
, Partition::aws
);
376 EXPECT_EQ(p
->statements
[2].resource
.begin()->service
, Service::s3
);
377 EXPECT_TRUE(p
->statements
[2].resource
.begin()->region
.empty());
378 EXPECT_EQ(p
->statements
[2].resource
.begin()->account
, arbitrary_tenant
);
379 EXPECT_EQ(p
->statements
[2].resource
.begin()->resource
, "confidential-data");
380 EXPECT_EQ((p
->statements
[2].resource
.begin() + 1)->partition
,
382 EXPECT_EQ((p
->statements
[2].resource
.begin() + 1)->service
, Service::s3
);
383 EXPECT_TRUE((p
->statements
[2].resource
.begin() + 1)->region
.empty());
384 EXPECT_EQ((p
->statements
[2].resource
.begin() + 1)->account
,
386 EXPECT_EQ((p
->statements
[2].resource
.begin() + 1)->resource
,
387 "confidential-data/*");
388 EXPECT_TRUE(p
->statements
[2].notresource
.empty());
389 ASSERT_FALSE(p
->statements
[2].conditions
.empty());
390 ASSERT_EQ(p
->statements
[2].conditions
.size(), 1U);
391 EXPECT_EQ(p
->statements
[2].conditions
[0].op
, TokenID::Bool
);
392 EXPECT_EQ(p
->statements
[2].conditions
[0].key
, "aws:MultiFactorAuthPresent");
393 EXPECT_FALSE(p
->statements
[2].conditions
[0].ifexists
);
394 ASSERT_FALSE(p
->statements
[2].conditions
[0].vals
.empty());
395 EXPECT_EQ(p
->statements
[2].conditions
[0].vals
.size(), 1U);
396 EXPECT_EQ(p
->statements
[2].conditions
[0].vals
[0], "true");
399 TEST_F(PolicyTest
, Eval3
) {
400 auto p
= Policy(cct
.get(), arbitrary_tenant
,
401 bufferlist::static_from_string(example3
));
403 Environment tr
= { { "aws:MultiFactorAuthPresent", "true" } };
404 Environment fa
= { { "aws:MultiFactorAuthPresent", "false" } };
407 s3allow
[s3ListMultipartUploadParts
] = 1;
408 s3allow
[s3ListBucket
] = 1;
409 s3allow
[s3ListBucketVersions
] = 1;
410 s3allow
[s3ListAllMyBuckets
] = 1;
411 s3allow
[s3ListBucketMultipartUploads
] = 1;
412 s3allow
[s3GetObject
] = 1;
413 s3allow
[s3GetObjectVersion
] = 1;
414 s3allow
[s3GetObjectAcl
] = 1;
415 s3allow
[s3GetObjectVersionAcl
] = 1;
416 s3allow
[s3GetObjectTorrent
] = 1;
417 s3allow
[s3GetObjectVersionTorrent
] = 1;
418 s3allow
[s3GetAccelerateConfiguration
] = 1;
419 s3allow
[s3GetBucketAcl
] = 1;
420 s3allow
[s3GetBucketCORS
] = 1;
421 s3allow
[s3GetBucketVersioning
] = 1;
422 s3allow
[s3GetBucketRequestPayment
] = 1;
423 s3allow
[s3GetBucketLocation
] = 1;
424 s3allow
[s3GetBucketPolicy
] = 1;
425 s3allow
[s3GetBucketNotification
] = 1;
426 s3allow
[s3GetBucketLogging
] = 1;
427 s3allow
[s3GetBucketTagging
] = 1;
428 s3allow
[s3GetBucketWebsite
] = 1;
429 s3allow
[s3GetLifecycleConfiguration
] = 1;
430 s3allow
[s3GetReplicationConfiguration
] = 1;
431 s3allow
[s3GetObjectTagging
] = 1;
432 s3allow
[s3GetObjectVersionTagging
] = 1;
434 EXPECT_EQ(p
.eval(em
, none
, s3PutBucketPolicy
,
435 ARN(Partition::aws
, Service::s3
,
436 "", arbitrary_tenant
, "mybucket")),
439 EXPECT_EQ(p
.eval(em
, none
, s3PutBucketPolicy
,
440 ARN(Partition::aws
, Service::s3
,
441 "", arbitrary_tenant
, "mybucket")),
445 for (auto op
= 0ULL; op
< s3Count
; ++op
) {
446 if ((op
== s3ListAllMyBuckets
) || (op
== s3PutBucketPolicy
)) {
449 EXPECT_EQ(p
.eval(em
, none
, op
,
450 ARN(Partition::aws
, Service::s3
,
451 "", arbitrary_tenant
, "confidential-data")),
453 EXPECT_EQ(p
.eval(tr
, none
, op
,
454 ARN(Partition::aws
, Service::s3
,
455 "", arbitrary_tenant
, "confidential-data")),
456 s3allow
[op
] ? Effect::Allow
: Effect::Pass
);
457 EXPECT_EQ(p
.eval(fa
, none
, op
,
458 ARN(Partition::aws
, Service::s3
,
459 "", arbitrary_tenant
, "confidential-data")),
462 EXPECT_EQ(p
.eval(em
, none
, op
,
463 ARN(Partition::aws
, Service::s3
,
464 "", arbitrary_tenant
, "confidential-data/moo")),
466 EXPECT_EQ(p
.eval(tr
, none
, op
,
467 ARN(Partition::aws
, Service::s3
,
468 "", arbitrary_tenant
, "confidential-data/moo")),
469 s3allow
[op
] ? Effect::Allow
: Effect::Pass
);
470 EXPECT_EQ(p
.eval(fa
, none
, op
,
471 ARN(Partition::aws
, Service::s3
,
472 "", arbitrary_tenant
, "confidential-data/moo")),
475 EXPECT_EQ(p
.eval(em
, none
, op
,
476 ARN(Partition::aws
, Service::s3
,
477 "", arbitrary_tenant
, "really-confidential-data")),
479 EXPECT_EQ(p
.eval(tr
, none
, op
,
480 ARN(Partition::aws
, Service::s3
,
481 "", arbitrary_tenant
, "really-confidential-data")),
483 EXPECT_EQ(p
.eval(fa
, none
, op
,
484 ARN(Partition::aws
, Service::s3
,
485 "", arbitrary_tenant
, "really-confidential-data")),
488 EXPECT_EQ(p
.eval(em
, none
, op
,
489 ARN(Partition::aws
, Service::s3
,
490 "", arbitrary_tenant
,
491 "really-confidential-data/moo")), Effect::Pass
);
492 EXPECT_EQ(p
.eval(tr
, none
, op
,
493 ARN(Partition::aws
, Service::s3
,
494 "", arbitrary_tenant
,
495 "really-confidential-data/moo")), Effect::Pass
);
496 EXPECT_EQ(p
.eval(fa
, none
, op
,
497 ARN(Partition::aws
, Service::s3
,
498 "", arbitrary_tenant
,
499 "really-confidential-data/moo")), Effect::Pass
);
504 TEST_F(PolicyTest
, Parse4
) {
505 boost::optional
<Policy
> p
;
507 ASSERT_NO_THROW(p
= Policy(cct
.get(), arbitrary_tenant
,
508 bufferlist::static_from_string(example4
)));
511 EXPECT_EQ(p
->text
, example4
);
512 EXPECT_EQ(p
->version
, Version::v2012_10_17
);
514 EXPECT_FALSE(p
->statements
[0].sid
);
515 EXPECT_FALSE(p
->statements
.empty());
516 EXPECT_EQ(p
->statements
.size(), 1U);
517 EXPECT_TRUE(p
->statements
[0].princ
.empty());
518 EXPECT_TRUE(p
->statements
[0].noprinc
.empty());
519 EXPECT_EQ(p
->statements
[0].effect
, Effect::Allow
);
521 act
[iamCreateRole
] = 1;
522 EXPECT_EQ(p
->statements
[0].action
, act
);
523 EXPECT_EQ(p
->statements
[0].notaction
, None
);
524 ASSERT_FALSE(p
->statements
[0].resource
.empty());
525 ASSERT_EQ(p
->statements
[0].resource
.size(), 1U);
526 EXPECT_EQ(p
->statements
[0].resource
.begin()->partition
, Partition::wildcard
);
527 EXPECT_EQ(p
->statements
[0].resource
.begin()->service
, Service::wildcard
);
528 EXPECT_EQ(p
->statements
[0].resource
.begin()->region
, "*");
529 EXPECT_EQ(p
->statements
[0].resource
.begin()->account
, arbitrary_tenant
);
530 EXPECT_EQ(p
->statements
[0].resource
.begin()->resource
, "*");
531 EXPECT_TRUE(p
->statements
[0].notresource
.empty());
532 EXPECT_TRUE(p
->statements
[0].conditions
.empty());
535 TEST_F(PolicyTest
, Eval4
) {
536 auto p
= Policy(cct
.get(), arbitrary_tenant
,
537 bufferlist::static_from_string(example4
));
540 EXPECT_EQ(p
.eval(e
, none
, iamCreateRole
,
541 ARN(Partition::aws
, Service::iam
,
542 "", arbitrary_tenant
, "role/example_role")),
545 EXPECT_EQ(p
.eval(e
, none
, iamDeleteRole
,
546 ARN(Partition::aws
, Service::iam
,
547 "", arbitrary_tenant
, "role/example_role")),
551 TEST_F(PolicyTest
, Parse5
) {
552 boost::optional
<Policy
> p
;
554 ASSERT_NO_THROW(p
= Policy(cct
.get(), arbitrary_tenant
,
555 bufferlist::static_from_string(example5
)));
557 EXPECT_EQ(p
->text
, example5
);
558 EXPECT_EQ(p
->version
, Version::v2012_10_17
);
560 EXPECT_FALSE(p
->statements
[0].sid
);
561 EXPECT_FALSE(p
->statements
.empty());
562 EXPECT_EQ(p
->statements
.size(), 1U);
563 EXPECT_TRUE(p
->statements
[0].princ
.empty());
564 EXPECT_TRUE(p
->statements
[0].noprinc
.empty());
565 EXPECT_EQ(p
->statements
[0].effect
, Effect::Allow
);
567 for (auto i
= s3All
+1; i
<= iamAll
; i
++)
569 EXPECT_EQ(p
->statements
[0].action
, act
);
570 EXPECT_EQ(p
->statements
[0].notaction
, None
);
571 ASSERT_FALSE(p
->statements
[0].resource
.empty());
572 ASSERT_EQ(p
->statements
[0].resource
.size(), 1U);
573 EXPECT_EQ(p
->statements
[0].resource
.begin()->partition
, Partition::aws
);
574 EXPECT_EQ(p
->statements
[0].resource
.begin()->service
, Service::iam
);
575 EXPECT_EQ(p
->statements
[0].resource
.begin()->region
, "");
576 EXPECT_EQ(p
->statements
[0].resource
.begin()->account
, arbitrary_tenant
);
577 EXPECT_EQ(p
->statements
[0].resource
.begin()->resource
, "role/example_role");
578 EXPECT_TRUE(p
->statements
[0].notresource
.empty());
579 EXPECT_TRUE(p
->statements
[0].conditions
.empty());
582 TEST_F(PolicyTest
, Eval5
) {
583 auto p
= Policy(cct
.get(), arbitrary_tenant
,
584 bufferlist::static_from_string(example5
));
587 EXPECT_EQ(p
.eval(e
, none
, iamCreateRole
,
588 ARN(Partition::aws
, Service::iam
,
589 "", arbitrary_tenant
, "role/example_role")),
592 EXPECT_EQ(p
.eval(e
, none
, s3ListBucket
,
593 ARN(Partition::aws
, Service::iam
,
594 "", arbitrary_tenant
, "role/example_role")),
597 EXPECT_EQ(p
.eval(e
, none
, iamCreateRole
,
598 ARN(Partition::aws
, Service::iam
,
599 "", "", "role/example_role")),
603 TEST_F(PolicyTest
, Parse6
) {
604 boost::optional
<Policy
> p
;
606 ASSERT_NO_THROW(p
= Policy(cct
.get(), arbitrary_tenant
,
607 bufferlist::static_from_string(example6
)));
609 EXPECT_EQ(p
->text
, example6
);
610 EXPECT_EQ(p
->version
, Version::v2012_10_17
);
612 EXPECT_FALSE(p
->statements
[0].sid
);
613 EXPECT_FALSE(p
->statements
.empty());
614 EXPECT_EQ(p
->statements
.size(), 1U);
615 EXPECT_TRUE(p
->statements
[0].princ
.empty());
616 EXPECT_TRUE(p
->statements
[0].noprinc
.empty());
617 EXPECT_EQ(p
->statements
[0].effect
, Effect::Allow
);
619 for (auto i
= 0U; i
<= stsAll
; i
++)
621 EXPECT_EQ(p
->statements
[0].action
, act
);
622 EXPECT_EQ(p
->statements
[0].notaction
, None
);
623 ASSERT_FALSE(p
->statements
[0].resource
.empty());
624 ASSERT_EQ(p
->statements
[0].resource
.size(), 1U);
625 EXPECT_EQ(p
->statements
[0].resource
.begin()->partition
, Partition::aws
);
626 EXPECT_EQ(p
->statements
[0].resource
.begin()->service
, Service::iam
);
627 EXPECT_EQ(p
->statements
[0].resource
.begin()->region
, "");
628 EXPECT_EQ(p
->statements
[0].resource
.begin()->account
, arbitrary_tenant
);
629 EXPECT_EQ(p
->statements
[0].resource
.begin()->resource
, "user/A");
630 EXPECT_TRUE(p
->statements
[0].notresource
.empty());
631 EXPECT_TRUE(p
->statements
[0].conditions
.empty());
634 TEST_F(PolicyTest
, Eval6
) {
635 auto p
= Policy(cct
.get(), arbitrary_tenant
,
636 bufferlist::static_from_string(example6
));
639 EXPECT_EQ(p
.eval(e
, none
, iamCreateRole
,
640 ARN(Partition::aws
, Service::iam
,
641 "", arbitrary_tenant
, "user/A")),
644 EXPECT_EQ(p
.eval(e
, none
, s3ListBucket
,
645 ARN(Partition::aws
, Service::iam
,
646 "", arbitrary_tenant
, "user/A")),
650 const string
PolicyTest::arbitrary_tenant
= "arbitrary_tenant";
651 string
PolicyTest::example1
= R
"(
653 "Version
": "2012-10-17",
656 "Action
": "s3
:ListBucket
",
657 "Resource
": "arn
:aws
:s3:::example_bucket
"
662 string
PolicyTest::example2
= R
"(
664 "Version
": "2012-10-17",
665 "Id
": "S3
-Account
-Permissions
",
669 "Principal
": {"AWS
": ["arn
:aws
:iam::ACCOUNT
-ID
-WITHOUT
-HYPHENS
:root
"]},
672 "arn
:aws
:s3:::mybucket
",
673 "arn
:aws
:s3:::mybucket
/*"
679 string PolicyTest::example3 = R"(
681 "Version": "2012-10-17",
684 "Sid": "FirstStatement",
686 "Action": ["s3:PutBucketPolicy"],
690 "Sid": "SecondStatement",
692 "Action": "s3:ListAllMyBuckets",
696 "Sid": "ThirdStatement",
703 "arn:aws:s3:::confidential-data",
704 "arn:aws:s3:::confidential-data/*"
706 "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
712 string PolicyTest::example4 = R"(
714 "Version": "2012-10-17",
717 "Action": "iam:CreateRole",
723 string PolicyTest::example5 = R"(
725 "Version": "2012-10-17",
729 "Resource": "arn:aws:iam:::role/example_role"
734 string PolicyTest::example6 = R"(
736 "Version": "2012-10-17",
740 "Resource": "arn:aws:iam:::user/A"
744 class IPPolicyTest : public ::testing::Test {
746 intrusive_ptr<CephContext> cct;
747 static const string arbitrary_tenant;
748 static string ip_address_allow_example;
749 static string ip_address_deny_example;
750 static string ip_address_full_example;
752 const rgw::IAM::MaskedIP allowedIPv4Range = { false, rgw::IAM::Address("11000000101010000000000100000000"), 24 };
754 const rgw::IAM::MaskedIP blacklistedIPv4 = { false, rgw::IAM::Address("11000000101010000000000100000001"), 32 };
755 // 2001:db8:85a3:0:0:8a2e:370:7334/128
756 const rgw::IAM::MaskedIP allowedIPv6 = { true, rgw::IAM::Address("00100000000000010000110110111000100001011010001100000000000000000000000000000000100010100010111000000011011100000111001100110100"), 128 };
758 const rgw::IAM::MaskedIP blacklistedIPv6 = { true, rgw::IAM::Address(1), 128 };
759 // 2001:db8:85a3:0:0:8a2e:370:7330/124
760 const rgw::IAM::MaskedIP allowedIPv6Range = { true, rgw::IAM::Address("00100000000000010000110110111000100001011010001100000000000000000000000000000000100010100010111000000011011100000111001100110000"), 124 };
763 cct = new CephContext(CEPH_ENTITY_TYPE_CLIENT);
766 const string IPPolicyTest::arbitrary_tenant = "arbitrary_tenant";
768 TEST_F(IPPolicyTest, MaskedIPOperations) {
769 EXPECT_EQ(stringify(allowedIPv4Range), "192.168.1.0/24");
770 EXPECT_EQ(stringify(blacklistedIPv4), "192.168.1.1/32");
771 EXPECT_EQ(stringify(allowedIPv6), "2001:db8:85a3:0:0:8a2e:370:7334/128");
772 EXPECT_EQ(stringify(allowedIPv6Range), "2001:db8:85a3:0:0:8a2e:370:7330/124");
773 EXPECT_EQ(stringify(blacklistedIPv6), "0:0:0:0:0:0:0:1/128");
774 EXPECT_EQ(allowedIPv4Range, blacklistedIPv4);
775 EXPECT_EQ(allowedIPv6Range, allowedIPv6);
778 TEST_F(IPPolicyTest, asNetworkIPv4Range) {
779 auto actualIPv4Range = rgw::IAM::Condition::as_network("192.168.1.0/24");
780 ASSERT_TRUE(actualIPv4Range.is_initialized());
781 EXPECT_EQ(*actualIPv4Range, allowedIPv4Range);
784 TEST_F(IPPolicyTest, asNetworkIPv4) {
785 auto actualIPv4 = rgw::IAM::Condition::as_network("192.168.1.1");
786 ASSERT_TRUE(actualIPv4.is_initialized());
787 EXPECT_EQ(*actualIPv4, blacklistedIPv4);
790 TEST_F(IPPolicyTest, asNetworkIPv6Range) {
791 auto actualIPv6Range = rgw::IAM::Condition::as_network("2001:db8:85a3:0:0:8a2e:370:7330/124");
792 ASSERT_TRUE(actualIPv6Range.is_initialized());
793 EXPECT_EQ(*actualIPv6Range, allowedIPv6Range);
796 TEST_F(IPPolicyTest, asNetworkIPv6) {
797 auto actualIPv6 = rgw::IAM::Condition::as_network("2001:db8:85a3:0:0:8a2e:370:7334");
798 ASSERT_TRUE(actualIPv6.is_initialized());
799 EXPECT_EQ(*actualIPv6, allowedIPv6);
802 TEST_F(IPPolicyTest, asNetworkInvalid) {
803 EXPECT_FALSE(rgw::IAM::Condition::as_network(""));
804 EXPECT_FALSE(rgw::IAM::Condition::as_network("192.168.1.1/33"));
805 EXPECT_FALSE(rgw::IAM::Condition::as_network("2001:db8:85a3:0:0:8a2e:370:7334/129"));
806 EXPECT_FALSE(rgw::IAM::Condition::as_network("192.168.1.1:"));
807 EXPECT_FALSE(rgw::IAM::Condition::as_network("1.2.3.10000"));
810 TEST_F(IPPolicyTest, IPEnvironment) {
811 // Unfortunately RGWCivetWeb is too tightly tied to civetweb to test RGWCivetWeb::init_env.
815 rgw_env.set("REMOTE_ADDR", "192.168.1.1");
816 rgw_env.set("HTTP_HOST", "1.2.3.4");
817 req_state rgw_req_state(cct.get(), &rgw_env, &user, 0);
818 rgw_build_iam_environment(&rgw_rados, &rgw_req_state);
819 auto ip = rgw_req_state.env.find("aws:SourceIp");
820 ASSERT_NE(ip, rgw_req_state.env.end());
821 EXPECT_EQ(ip->second, "192.168.1.1");
823 ASSERT_EQ(cct.get()->_conf.set_val("rgw_remote_addr_param", "SOME_VAR"), 0);
824 EXPECT_EQ(cct.get()->_conf->rgw_remote_addr_param, "SOME_VAR");
825 rgw_req_state.env.clear();
826 rgw_build_iam_environment(&rgw_rados, &rgw_req_state);
827 ip = rgw_req_state.env.find("aws:SourceIp");
828 EXPECT_EQ(ip, rgw_req_state.env.end());
830 rgw_env.set("SOME_VAR", "192.168.1.2");
831 rgw_req_state.env.clear();
832 rgw_build_iam_environment(&rgw_rados, &rgw_req_state);
833 ip = rgw_req_state.env.find("aws:SourceIp");
834 ASSERT_NE(ip, rgw_req_state.env.end());
835 EXPECT_EQ(ip->second, "192.168.1.2");
837 ASSERT_EQ(cct.get()->_conf.set_val("rgw_remote_addr_param", "HTTP_X_FORWARDED_FOR"), 0);
838 rgw_env.set("HTTP_X_FORWARDED_FOR", "192.168.1.3");
839 rgw_req_state.env.clear();
840 rgw_build_iam_environment(&rgw_rados, &rgw_req_state);
841 ip = rgw_req_state.env.find("aws:SourceIp");
842 ASSERT_NE(ip, rgw_req_state.env.end());
843 EXPECT_EQ(ip->second, "192.168.1.3");
845 rgw_env.set("HTTP_X_FORWARDED_FOR", "192.168.1.4, 4.3.2.1, 2001:db8:85a3:8d3:1319:8a2e:370:7348");
846 rgw_req_state.env.clear();
847 rgw_build_iam_environment(&rgw_rados, &rgw_req_state);
848 ip = rgw_req_state.env.find("aws:SourceIp");
849 ASSERT_NE(ip, rgw_req_state.env.end());
850 EXPECT_EQ(ip->second, "192.168.1.4");
853 TEST_F(IPPolicyTest, ParseIPAddress) {
854 boost::optional<Policy> p;
856 ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant,
857 bufferlist::static_from_string(ip_address_full_example)));
860 EXPECT_EQ(p->text, ip_address_full_example);
861 EXPECT_EQ(p->version, Version::v2012_10_17);
862 EXPECT_EQ(*p->id, "S3IPPolicyTest");
863 EXPECT_FALSE(p->statements.empty());
864 EXPECT_EQ(p->statements.size(), 1U);
865 EXPECT_EQ(*p->statements[0].sid, "IPAllow");
866 EXPECT_FALSE(p->statements[0].princ.empty());
867 EXPECT_EQ(p->statements[0].princ.size(), 1U);
868 EXPECT_EQ(*p->statements[0].princ.begin(),
869 Principal::wildcard());
870 EXPECT_TRUE(p->statements[0].noprinc.empty());
871 EXPECT_EQ(p->statements[0].effect, Effect::Allow);
873 act[s3ListBucket] = 1;
874 EXPECT_EQ(p->statements[0].action, act);
875 EXPECT_EQ(p->statements[0].notaction, None);
876 ASSERT_FALSE(p->statements[0].resource.empty());
877 ASSERT_EQ(p->statements[0].resource.size(), 2U);
878 EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws);
879 EXPECT_EQ(p->statements[0].resource.begin()->service, Service::s3);
880 EXPECT_TRUE(p->statements[0].resource.begin()->region.empty());
881 EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant);
882 EXPECT_EQ(p->statements[0].resource.begin()->resource, "example_bucket");
883 EXPECT_EQ((p->statements[0].resource.begin() + 1)->resource, "example_bucket/*");
884 EXPECT_TRUE(p->statements[0].notresource.empty());
885 ASSERT_FALSE(p->statements[0].conditions.empty());
886 ASSERT_EQ(p->statements[0].conditions.size(), 2U);
887 EXPECT_EQ(p->statements[0].conditions[0].op, TokenID::IpAddress);
888 EXPECT_EQ(p->statements[0].conditions[0].key, "aws:SourceIp");
889 ASSERT_FALSE(p->statements[0].conditions[0].vals.empty());
890 EXPECT_EQ(p->statements[0].conditions[0].vals.size(), 2U);
891 EXPECT_EQ(p->statements[0].conditions[0].vals[0], "192.168.1.0/24");
892 EXPECT_EQ(p->statements[0].conditions[0].vals[1], "::1");
893 boost::optional<rgw::IAM::MaskedIP> convertedIPv4 = rgw::IAM::Condition::as_network(p->statements[0].conditions[0].vals[0]);
894 EXPECT_TRUE(convertedIPv4.is_initialized());
895 if (convertedIPv4.is_initialized()) {
896 EXPECT_EQ(*convertedIPv4, allowedIPv4Range);
899 EXPECT_EQ(p->statements[0].conditions[1].op, TokenID::NotIpAddress);
900 EXPECT_EQ(p->statements[0].conditions[1].key, "aws:SourceIp");
901 ASSERT_FALSE(p->statements[0].conditions[1].vals.empty());
902 EXPECT_EQ(p->statements[0].conditions[1].vals.size(), 2U);
903 EXPECT_EQ(p->statements[0].conditions[1].vals[0], "192.168.1.1/32");
904 EXPECT_EQ(p->statements[0].conditions[1].vals[1], "2001:0db8:85a3:0000:0000:8a2e:0370:7334");
905 boost::optional<rgw::IAM::MaskedIP> convertedIPv6 = rgw::IAM::Condition::as_network(p->statements[0].conditions[1].vals[1]);
906 EXPECT_TRUE(convertedIPv6.is_initialized());
907 if (convertedIPv6.is_initialized()) {
908 EXPECT_EQ(*convertedIPv6, allowedIPv6);
912 TEST_F(IPPolicyTest, EvalIPAddress) {
913 auto allowp = Policy(cct.get(), arbitrary_tenant,
914 bufferlist::static_from_string(ip_address_allow_example));
915 auto denyp = Policy(cct.get(), arbitrary_tenant,
916 bufferlist::static_from_string(ip_address_deny_example));
917 auto fullp = Policy(cct.get(), arbitrary_tenant,
918 bufferlist::static_from_string(ip_address_full_example));
920 Environment allowedIP, blacklistedIP, allowedIPv6, blacklistedIPv6;
921 allowedIP["aws:SourceIp"] = "192.168.1.2";
922 allowedIPv6["aws:SourceIp"] = "::1";
923 blacklistedIP["aws:SourceIp"] = "192.168.1.1";
924 blacklistedIPv6["aws:SourceIp"] = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
926 auto trueacct = FakeIdentity(
927 Principal::tenant("ACCOUNT-ID-WITHOUT-HYPHENS"));
928 // Without an IP address in the environment then evaluation will always pass
929 EXPECT_EQ(allowp.eval(e, trueacct, s3ListBucket,
930 ARN(Partition::aws, Service::s3,
931 "", arbitrary_tenant, "example_bucket")),
933 EXPECT_EQ(fullp.eval(e, trueacct, s3ListBucket,
934 ARN(Partition::aws, Service::s3,
935 "", arbitrary_tenant, "example_bucket/myobject")),
938 EXPECT_EQ(allowp.eval(allowedIP, trueacct, s3ListBucket,
939 ARN(Partition::aws, Service::s3,
940 "", arbitrary_tenant, "example_bucket")),
942 EXPECT_EQ(allowp.eval(blacklistedIPv6, trueacct, s3ListBucket,
943 ARN(Partition::aws, Service::s3,
944 "", arbitrary_tenant, "example_bucket")),
948 EXPECT_EQ(denyp.eval(allowedIP, trueacct, s3ListBucket,
949 ARN(Partition::aws, Service::s3,
950 "", arbitrary_tenant, "example_bucket")),
952 EXPECT_EQ(denyp.eval(allowedIP, trueacct, s3ListBucket,
953 ARN(Partition::aws, Service::s3,
954 "", arbitrary_tenant, "example_bucket/myobject")),
957 EXPECT_EQ(denyp.eval(blacklistedIP, trueacct, s3ListBucket,
958 ARN(Partition::aws, Service::s3,
959 "", arbitrary_tenant, "example_bucket")),
961 EXPECT_EQ(denyp.eval(blacklistedIP, trueacct, s3ListBucket,
962 ARN(Partition::aws, Service::s3,
963 "", arbitrary_tenant, "example_bucket/myobject")),
966 EXPECT_EQ(denyp.eval(blacklistedIPv6, trueacct, s3ListBucket,
967 ARN(Partition::aws, Service::s3,
968 "", arbitrary_tenant, "example_bucket")),
970 EXPECT_EQ(denyp.eval(blacklistedIPv6, trueacct, s3ListBucket,
971 ARN(Partition::aws, Service::s3,
972 "", arbitrary_tenant, "example_bucket/myobject")),
974 EXPECT_EQ(denyp.eval(allowedIPv6, trueacct, s3ListBucket,
975 ARN(Partition::aws, Service::s3,
976 "", arbitrary_tenant, "example_bucket")),
978 EXPECT_EQ(denyp.eval(allowedIPv6, trueacct, s3ListBucket,
979 ARN(Partition::aws, Service::s3,
980 "", arbitrary_tenant, "example_bucket/myobject")),
983 EXPECT_EQ(fullp.eval(allowedIP, trueacct, s3ListBucket,
984 ARN(Partition::aws, Service::s3,
985 "", arbitrary_tenant, "example_bucket")),
987 EXPECT_EQ(fullp.eval(allowedIP, trueacct, s3ListBucket,
988 ARN(Partition::aws, Service::s3,
989 "", arbitrary_tenant, "example_bucket/myobject")),
992 EXPECT_EQ(fullp.eval(blacklistedIP, trueacct, s3ListBucket,
993 ARN(Partition::aws, Service::s3,
994 "", arbitrary_tenant, "example_bucket")),
996 EXPECT_EQ(fullp.eval(blacklistedIP, trueacct, s3ListBucket,
997 ARN(Partition::aws, Service::s3,
998 "", arbitrary_tenant, "example_bucket/myobject")),
1001 EXPECT_EQ(fullp.eval(allowedIPv6, trueacct, s3ListBucket,
1002 ARN(Partition::aws, Service::s3,
1003 "", arbitrary_tenant, "example_bucket")),
1005 EXPECT_EQ(fullp.eval(allowedIPv6, trueacct, s3ListBucket,
1006 ARN(Partition::aws, Service::s3,
1007 "", arbitrary_tenant, "example_bucket/myobject")),
1010 EXPECT_EQ(fullp.eval(blacklistedIPv6, trueacct, s3ListBucket,
1011 ARN(Partition::aws, Service::s3,
1012 "", arbitrary_tenant, "example_bucket")),
1014 EXPECT_EQ(fullp.eval(blacklistedIPv6, trueacct, s3ListBucket,
1015 ARN(Partition::aws, Service::s3,
1016 "", arbitrary_tenant, "example_bucket/myobject")),
1020 string IPPolicyTest::ip_address_allow_example = R"(
1022 "Version": "2012-10-17",
1023 "Id": "S3SimpleIPPolicyTest",
1027 "Principal": {"AWS": ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:root"]},
1028 "Action": "s3:ListBucket",
1030 "arn:aws:s3:::example_bucket"
1033 "IpAddress": {"aws:SourceIp": "192.168.1.0/24"}
1039 string IPPolicyTest::ip_address_deny_example = R"(
1041 "Version": "2012-10-17",
1042 "Id": "S3IPPolicyTest",
1046 "Action": "s3:ListBucket",
1047 "Principal": {"AWS": ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:root"]},
1049 "arn:aws:s3:::example_bucket",
1050 "arn:aws:s3:::example_bucket/*"
1053 "NotIpAddress": {"aws:SourceIp": ["192.168.1.1/32", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"]}
1059 string IPPolicyTest::ip_address_full_example = R"(
1061 "Version": "2012-10-17",
1062 "Id": "S3IPPolicyTest",
1066 "Action": "s3:ListBucket",
1069 "arn:aws:s3:::example_bucket",
1070 "arn:aws:s3:::example_bucket/*"
1073 "IpAddress": {"aws:SourceIp": ["192.168.1.0/24", "::1"]},
1074 "NotIpAddress": {"aws:SourceIp": ["192.168.1.1/32", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"]}
1080 TEST(MatchWildcards, Simple)
1082 EXPECT_TRUE(match_wildcards("", ""));
1083 EXPECT_TRUE(match_wildcards("", "", MATCH_CASE_INSENSITIVE));
1084 EXPECT_FALSE(match_wildcards("", "abc"));
1085 EXPECT_FALSE(match_wildcards("", "abc", MATCH_CASE_INSENSITIVE));
1086 EXPECT_FALSE(match_wildcards("abc", ""));
1087 EXPECT_FALSE(match_wildcards("abc", "", MATCH_CASE_INSENSITIVE));
1088 EXPECT_TRUE(match_wildcards("abc", "abc"));
1089 EXPECT_TRUE(match_wildcards("abc", "abc", MATCH_CASE_INSENSITIVE));
1090 EXPECT_FALSE(match_wildcards("abc", "abC"));
1091 EXPECT_TRUE(match_wildcards("abc", "abC", MATCH_CASE_INSENSITIVE));
1092 EXPECT_FALSE(match_wildcards("abC", "abc"));
1093 EXPECT_TRUE(match_wildcards("abC", "abc", MATCH_CASE_INSENSITIVE));
1094 EXPECT_FALSE(match_wildcards("abc", "abcd"));
1095 EXPECT_FALSE(match_wildcards("abc", "abcd", MATCH_CASE_INSENSITIVE));
1096 EXPECT_FALSE(match_wildcards("abcd", "abc"));
1097 EXPECT_FALSE(match_wildcards("abcd", "abc", MATCH_CASE_INSENSITIVE));
1100 TEST(MatchWildcards, QuestionMark)
1102 EXPECT_FALSE(match_wildcards("?", ""));
1103 EXPECT_FALSE(match_wildcards("?", "", MATCH_CASE_INSENSITIVE));
1104 EXPECT_TRUE(match_wildcards("?", "a"));
1105 EXPECT_TRUE(match_wildcards("?", "a", MATCH_CASE_INSENSITIVE));
1106 EXPECT_TRUE(match_wildcards("?bc", "abc"));
1107 EXPECT_TRUE(match_wildcards("?bc", "abc", MATCH_CASE_INSENSITIVE));
1108 EXPECT_TRUE(match_wildcards("a?c", "abc"));
1109 EXPECT_TRUE(match_wildcards("a?c", "abc", MATCH_CASE_INSENSITIVE));
1110 EXPECT_FALSE(match_wildcards("abc", "a?c"));
1111 EXPECT_FALSE(match_wildcards("abc", "a?c", MATCH_CASE_INSENSITIVE));
1112 EXPECT_FALSE(match_wildcards("a?c", "abC"));
1113 EXPECT_TRUE(match_wildcards("a?c", "abC", MATCH_CASE_INSENSITIVE));
1114 EXPECT_TRUE(match_wildcards("ab?", "abc"));
1115 EXPECT_TRUE(match_wildcards("ab?", "abc", MATCH_CASE_INSENSITIVE));
1116 EXPECT_TRUE(match_wildcards("a?c?e", "abcde"));
1117 EXPECT_TRUE(match_wildcards("a?c?e", "abcde", MATCH_CASE_INSENSITIVE));
1118 EXPECT_TRUE(match_wildcards("???", "abc"));
1119 EXPECT_TRUE(match_wildcards("???", "abc", MATCH_CASE_INSENSITIVE));
1120 EXPECT_FALSE(match_wildcards("???", "abcd"));
1121 EXPECT_FALSE(match_wildcards("???", "abcd", MATCH_CASE_INSENSITIVE));
1124 TEST(MatchWildcards, Asterisk)
1126 EXPECT_TRUE(match_wildcards("*", ""));
1127 EXPECT_TRUE(match_wildcards("*", "", MATCH_CASE_INSENSITIVE));
1128 EXPECT_FALSE(match_wildcards("", "*"));
1129 EXPECT_FALSE(match_wildcards("", "*", MATCH_CASE_INSENSITIVE));
1130 EXPECT_FALSE(match_wildcards("*a", ""));
1131 EXPECT_FALSE(match_wildcards("*a", "", MATCH_CASE_INSENSITIVE));
1132 EXPECT_TRUE(match_wildcards("*a", "a"));
1133 EXPECT_TRUE(match_wildcards("*a", "a", MATCH_CASE_INSENSITIVE));
1134 EXPECT_TRUE(match_wildcards("a*", "a"));
1135 EXPECT_TRUE(match_wildcards("a*", "a", MATCH_CASE_INSENSITIVE));
1136 EXPECT_TRUE(match_wildcards("a*c", "ac"));
1137 EXPECT_TRUE(match_wildcards("a*c", "ac", MATCH_CASE_INSENSITIVE));
1138 EXPECT_TRUE(match_wildcards("a*c", "abbc"));
1139 EXPECT_TRUE(match_wildcards("a*c", "abbc", MATCH_CASE_INSENSITIVE));
1140 EXPECT_FALSE(match_wildcards("a*c", "abbC"));
1141 EXPECT_TRUE(match_wildcards("a*c", "abbC", MATCH_CASE_INSENSITIVE));
1142 EXPECT_TRUE(match_wildcards("a*c*e", "abBce"));
1143 EXPECT_TRUE(match_wildcards("a*c*e", "abBce", MATCH_CASE_INSENSITIVE));
1144 EXPECT_TRUE(match_wildcards("http://*.example.com",
1145 "http://www.example.com"));
1146 EXPECT_TRUE(match_wildcards("http://*.example.com",
1147 "http://www.example.com", MATCH_CASE_INSENSITIVE));
1148 EXPECT_FALSE(match_wildcards("http://*.example.com",
1149 "http://www.Example.com"));
1150 EXPECT_TRUE(match_wildcards("http://*.example.com",
1151 "http://www.Example.com", MATCH_CASE_INSENSITIVE));
1152 EXPECT_TRUE(match_wildcards("http://example.com/*",
1153 "http://example.com/index.html"));
1154 EXPECT_TRUE(match_wildcards("http://example.com/*/*.jpg",
1155 "http://example.com/fun/smiley.jpg"));
1156 // note: parsing of * is not greedy, so * does not match 'bc' here
1157 EXPECT_FALSE(match_wildcards("a*c", "abcc"));
1158 EXPECT_FALSE(match_wildcards("a*c", "abcc", MATCH_CASE_INSENSITIVE));
1161 TEST(MatchPolicy, Action)
1163 constexpr auto flag = MATCH_POLICY_ACTION;
1164 EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag));
1165 EXPECT_TRUE(match_policy("a:b:c", "A:B:C", flag)); // case insensitive
1166 EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag));
1167 EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments
1170 TEST(MatchPolicy, Resource)
1172 constexpr auto flag = MATCH_POLICY_RESOURCE;
1173 EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag));
1174 EXPECT_FALSE(match_policy("a:b:c", "A:B:C", flag)); // case sensitive
1175 EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag));
1176 EXPECT_TRUE(match_policy("a:*", "a:b:c", flag)); // can span segments
1179 TEST(MatchPolicy, ARN)
1181 constexpr auto flag = MATCH_POLICY_ARN;
1182 EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag));
1183 EXPECT_TRUE(match_policy("a:b:c", "A:B:C", flag)); // case insensitive
1184 EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag));
1185 EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments
1188 TEST(MatchPolicy, String)
1190 constexpr auto flag = MATCH_POLICY_STRING;
1191 EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag));
1192 EXPECT_FALSE(match_policy("a:b:c", "A:B:C", flag)); // case sensitive
1193 EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag));
1194 EXPECT_TRUE(match_policy("a:*", "a:b:c", flag)); // can span segments