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 "common/code_environment.h"
23 #include "common/ceph_context.h"
24 #include "global/global_init.h"
25 #include "rgw/rgw_auth.h"
26 #include "rgw/rgw_iam_policy.h"
32 using boost::container::flat_set
;
33 using boost::intrusive_ptr
;
34 using boost::make_optional
;
36 using boost::optional
;
38 using rgw::auth::Identity
;
39 using rgw::auth::Principal
;
42 using rgw::IAM::Effect
;
43 using rgw::IAM::Environment
;
44 using rgw::IAM::Partition
;
45 using rgw::IAM::Policy
;
46 using rgw::IAM::s3All
;
47 using rgw::IAM::s3Count
;
48 using rgw::IAM::s3GetAccelerateConfiguration
;
49 using rgw::IAM::s3GetBucketAcl
;
50 using rgw::IAM::s3GetBucketCORS
;
51 using rgw::IAM::s3GetBucketLocation
;
52 using rgw::IAM::s3GetBucketLogging
;
53 using rgw::IAM::s3GetBucketNotification
;
54 using rgw::IAM::s3GetBucketPolicy
;
55 using rgw::IAM::s3GetBucketRequestPayment
;
56 using rgw::IAM::s3GetBucketTagging
;
57 using rgw::IAM::s3GetBucketVersioning
;
58 using rgw::IAM::s3GetBucketWebsite
;
59 using rgw::IAM::s3GetLifecycleConfiguration
;
60 using rgw::IAM::s3GetObject
;
61 using rgw::IAM::s3GetObjectAcl
;
62 using rgw::IAM::s3GetObjectVersionAcl
;
63 using rgw::IAM::s3GetObjectTorrent
;
64 using rgw::IAM::s3GetObjectTagging
;
65 using rgw::IAM::s3GetObjectVersion
;
66 using rgw::IAM::s3GetObjectVersionTagging
;
67 using rgw::IAM::s3GetObjectVersionTorrent
;
68 using rgw::IAM::s3GetReplicationConfiguration
;
69 using rgw::IAM::s3ListAllMyBuckets
;
70 using rgw::IAM::s3ListBucket
;
71 using rgw::IAM::s3ListBucket
;
72 using rgw::IAM::s3ListBucketMultiPartUploads
;
73 using rgw::IAM::s3ListBucketVersions
;
74 using rgw::IAM::s3ListMultipartUploadParts
;
75 using rgw::IAM::s3None
;
76 using rgw::IAM::s3PutBucketAcl
;
77 using rgw::IAM::s3PutBucketPolicy
;
78 using rgw::IAM::Service
;
79 using rgw::IAM::TokenID
;
80 using rgw::IAM::Version
;
82 class FakeIdentity
: public Identity
{
86 FakeIdentity(Principal
&& id
) : id(std::move(id
)) {}
87 uint32_t get_perms_from_aclspec(const aclspec_t
& aclspec
) const override
{
92 bool is_admin_of(const rgw_user
& uid
) const override
{
97 bool is_owner_of(const rgw_user
& uid
) const override
{
102 virtual uint32_t get_perm_mask() const override
{
107 void to_str(std::ostream
& out
) const override
{
111 bool is_identity(const flat_set
<Principal
>& ids
) const override
{
112 return ids
.find(id
) != ids
.end();
116 class PolicyTest
: public ::testing::Test
{
118 intrusive_ptr
<CephContext
> cct
;
119 static const string arbitrary_tenant
;
120 static string example1
;
121 static string example2
;
122 static string example3
;
125 cct
= new CephContext(CEPH_ENTITY_TYPE_CLIENT
);
129 TEST_F(PolicyTest
, Parse1
) {
132 ASSERT_NO_THROW(p
= Policy(cct
.get(), arbitrary_tenant
,
133 bufferlist::static_from_string(example1
)));
136 EXPECT_EQ(p
->text
, example1
);
137 EXPECT_EQ(p
->version
, Version::v2012_10_17
);
139 EXPECT_FALSE(p
->statements
[0].sid
);
140 EXPECT_FALSE(p
->statements
.empty());
141 EXPECT_EQ(p
->statements
.size(), 1U);
142 EXPECT_TRUE(p
->statements
[0].princ
.empty());
143 EXPECT_TRUE(p
->statements
[0].noprinc
.empty());
144 EXPECT_EQ(p
->statements
[0].effect
, Effect::Allow
);
145 EXPECT_EQ(p
->statements
[0].action
, s3ListBucket
);
146 EXPECT_EQ(p
->statements
[0].notaction
, s3None
);
147 ASSERT_FALSE(p
->statements
[0].resource
.empty());
148 ASSERT_EQ(p
->statements
[0].resource
.size(), 1U);
149 EXPECT_EQ(p
->statements
[0].resource
.begin()->partition
, Partition::aws
);
150 EXPECT_EQ(p
->statements
[0].resource
.begin()->service
, Service::s3
);
151 EXPECT_TRUE(p
->statements
[0].resource
.begin()->region
.empty());
152 EXPECT_EQ(p
->statements
[0].resource
.begin()->account
, arbitrary_tenant
);
153 EXPECT_EQ(p
->statements
[0].resource
.begin()->resource
, "example_bucket");
154 EXPECT_TRUE(p
->statements
[0].notresource
.empty());
155 EXPECT_TRUE(p
->statements
[0].conditions
.empty());
158 TEST_F(PolicyTest
, Eval1
) {
159 auto p
= Policy(cct
.get(), arbitrary_tenant
,
160 bufferlist::static_from_string(example1
));
163 EXPECT_EQ(p
.eval(e
, none
, s3ListBucket
,
164 ARN(Partition::aws
, Service::s3
,
165 "", arbitrary_tenant
, "example_bucket")),
168 EXPECT_EQ(p
.eval(e
, none
, s3PutBucketAcl
,
169 ARN(Partition::aws
, Service::s3
,
170 "", arbitrary_tenant
, "example_bucket")),
173 EXPECT_EQ(p
.eval(e
, none
, s3ListBucket
,
174 ARN(Partition::aws
, Service::s3
,
175 "", arbitrary_tenant
, "erroneous_bucket")),
180 TEST_F(PolicyTest
, Parse2
) {
183 ASSERT_NO_THROW(p
= Policy(cct
.get(), arbitrary_tenant
,
184 bufferlist::static_from_string(example2
)));
187 EXPECT_EQ(p
->text
, example2
);
188 EXPECT_EQ(p
->version
, Version::v2012_10_17
);
189 EXPECT_EQ(*p
->id
, "S3-Account-Permissions");
190 ASSERT_FALSE(p
->statements
.empty());
191 EXPECT_EQ(p
->statements
.size(), 1U);
192 EXPECT_EQ(*p
->statements
[0].sid
, "1");
193 EXPECT_FALSE(p
->statements
[0].princ
.empty());
194 EXPECT_EQ(p
->statements
[0].princ
.size(), 1U);
195 EXPECT_EQ(*p
->statements
[0].princ
.begin(),
196 Principal::tenant("ACCOUNT-ID-WITHOUT-HYPHENS"));
197 EXPECT_TRUE(p
->statements
[0].noprinc
.empty());
198 EXPECT_EQ(p
->statements
[0].effect
, Effect::Allow
);
199 EXPECT_EQ(p
->statements
[0].action
, s3All
);
200 EXPECT_EQ(p
->statements
[0].notaction
, s3None
);
201 ASSERT_FALSE(p
->statements
[0].resource
.empty());
202 ASSERT_EQ(p
->statements
[0].resource
.size(), 2U);
203 EXPECT_EQ(p
->statements
[0].resource
.begin()->partition
, Partition::aws
);
204 EXPECT_EQ(p
->statements
[0].resource
.begin()->service
, Service::s3
);
205 EXPECT_TRUE(p
->statements
[0].resource
.begin()->region
.empty());
206 EXPECT_EQ(p
->statements
[0].resource
.begin()->account
, arbitrary_tenant
);
207 EXPECT_EQ(p
->statements
[0].resource
.begin()->resource
, "mybucket");
208 EXPECT_EQ((p
->statements
[0].resource
.begin() + 1)->partition
,
210 EXPECT_EQ((p
->statements
[0].resource
.begin() + 1)->service
,
212 EXPECT_TRUE((p
->statements
[0].resource
.begin() + 1)->region
.empty());
213 EXPECT_EQ((p
->statements
[0].resource
.begin() + 1)->account
,
215 EXPECT_EQ((p
->statements
[0].resource
.begin() + 1)->resource
, "mybucket/*");
216 EXPECT_TRUE(p
->statements
[0].notresource
.empty());
217 EXPECT_TRUE(p
->statements
[0].conditions
.empty());
220 TEST_F(PolicyTest
, Eval2
) {
221 auto p
= Policy(cct
.get(), arbitrary_tenant
,
222 bufferlist::static_from_string(example2
));
225 auto trueacct
= FakeIdentity(
226 Principal::tenant("ACCOUNT-ID-WITHOUT-HYPHENS"));
228 auto notacct
= FakeIdentity(
229 Principal::tenant("some-other-account"));
230 for (auto i
= 0ULL; i
< s3Count
; ++i
) {
231 EXPECT_EQ(p
.eval(e
, trueacct
, 1ULL << i
,
232 ARN(Partition::aws
, Service::s3
,
233 "", arbitrary_tenant
, "mybucket")),
235 EXPECT_EQ(p
.eval(e
, trueacct
, 1ULL << i
,
236 ARN(Partition::aws
, Service::s3
,
237 "", arbitrary_tenant
, "mybucket/myobject")),
240 EXPECT_EQ(p
.eval(e
, notacct
, 1ULL << i
,
241 ARN(Partition::aws
, Service::s3
,
242 "", arbitrary_tenant
, "mybucket")),
244 EXPECT_EQ(p
.eval(e
, notacct
, 1ULL << i
,
245 ARN(Partition::aws
, Service::s3
,
246 "", arbitrary_tenant
, "mybucket/myobject")),
249 EXPECT_EQ(p
.eval(e
, trueacct
, 1ULL << i
,
250 ARN(Partition::aws
, Service::s3
,
251 "", arbitrary_tenant
, "notyourbucket")),
253 EXPECT_EQ(p
.eval(e
, trueacct
, 1ULL << i
,
254 ARN(Partition::aws
, Service::s3
,
255 "", arbitrary_tenant
, "notyourbucket/notyourobject")),
261 TEST_F(PolicyTest
, Parse3
) {
264 ASSERT_NO_THROW(p
= Policy(cct
.get(), arbitrary_tenant
,
265 bufferlist::static_from_string(example3
)));
268 EXPECT_EQ(p
->text
, example3
);
269 EXPECT_EQ(p
->version
, Version::v2012_10_17
);
271 ASSERT_FALSE(p
->statements
.empty());
272 EXPECT_EQ(p
->statements
.size(), 3U);
274 EXPECT_EQ(*p
->statements
[0].sid
, "FirstStatement");
275 EXPECT_TRUE(p
->statements
[0].princ
.empty());
276 EXPECT_TRUE(p
->statements
[0].noprinc
.empty());
277 EXPECT_EQ(p
->statements
[0].effect
, Effect::Allow
);
278 EXPECT_EQ(p
->statements
[0].action
, s3PutBucketPolicy
);
279 EXPECT_EQ(p
->statements
[0].notaction
, s3None
);
280 ASSERT_FALSE(p
->statements
[0].resource
.empty());
281 ASSERT_EQ(p
->statements
[0].resource
.size(), 1U);
282 EXPECT_EQ(p
->statements
[0].resource
.begin()->partition
, Partition::wildcard
);
283 EXPECT_EQ(p
->statements
[0].resource
.begin()->service
, Service::wildcard
);
284 EXPECT_EQ(p
->statements
[0].resource
.begin()->region
, "*");
285 EXPECT_EQ(p
->statements
[0].resource
.begin()->account
, arbitrary_tenant
);
286 EXPECT_EQ(p
->statements
[0].resource
.begin()->resource
, "*");
287 EXPECT_TRUE(p
->statements
[0].notresource
.empty());
288 EXPECT_TRUE(p
->statements
[0].conditions
.empty());
290 EXPECT_EQ(*p
->statements
[1].sid
, "SecondStatement");
291 EXPECT_TRUE(p
->statements
[1].princ
.empty());
292 EXPECT_TRUE(p
->statements
[1].noprinc
.empty());
293 EXPECT_EQ(p
->statements
[1].effect
, Effect::Allow
);
294 EXPECT_EQ(p
->statements
[1].action
, s3ListAllMyBuckets
);
295 EXPECT_EQ(p
->statements
[1].notaction
, s3None
);
296 ASSERT_FALSE(p
->statements
[1].resource
.empty());
297 ASSERT_EQ(p
->statements
[1].resource
.size(), 1U);
298 EXPECT_EQ(p
->statements
[1].resource
.begin()->partition
, Partition::wildcard
);
299 EXPECT_EQ(p
->statements
[1].resource
.begin()->service
, Service::wildcard
);
300 EXPECT_EQ(p
->statements
[1].resource
.begin()->region
, "*");
301 EXPECT_EQ(p
->statements
[1].resource
.begin()->account
, arbitrary_tenant
);
302 EXPECT_EQ(p
->statements
[1].resource
.begin()->resource
, "*");
303 EXPECT_TRUE(p
->statements
[1].notresource
.empty());
304 EXPECT_TRUE(p
->statements
[1].conditions
.empty());
306 EXPECT_EQ(*p
->statements
[2].sid
, "ThirdStatement");
307 EXPECT_TRUE(p
->statements
[2].princ
.empty());
308 EXPECT_TRUE(p
->statements
[2].noprinc
.empty());
309 EXPECT_EQ(p
->statements
[2].effect
, Effect::Allow
);
310 EXPECT_EQ(p
->statements
[2].action
, (s3ListMultipartUploadParts
|
311 s3ListBucket
| s3ListBucketVersions
|
313 s3ListBucketMultiPartUploads
|
314 s3GetObject
| s3GetObjectVersion
|
315 s3GetObjectAcl
| s3GetObjectVersionAcl
|
317 s3GetObjectVersionTorrent
|
318 s3GetAccelerateConfiguration
|
319 s3GetBucketAcl
| s3GetBucketCORS
|
320 s3GetBucketVersioning
|
321 s3GetBucketRequestPayment
|
322 s3GetBucketLocation
|
324 s3GetBucketNotification
|
328 s3GetLifecycleConfiguration
|
329 s3GetReplicationConfiguration
|
331 s3GetObjectVersionTagging
));
332 EXPECT_EQ(p
->statements
[2].notaction
, s3None
);
333 ASSERT_FALSE(p
->statements
[2].resource
.empty());
334 ASSERT_EQ(p
->statements
[2].resource
.size(), 2U);
335 EXPECT_EQ(p
->statements
[2].resource
.begin()->partition
, Partition::aws
);
336 EXPECT_EQ(p
->statements
[2].resource
.begin()->service
, Service::s3
);
337 EXPECT_TRUE(p
->statements
[2].resource
.begin()->region
.empty());
338 EXPECT_EQ(p
->statements
[2].resource
.begin()->account
, arbitrary_tenant
);
339 EXPECT_EQ(p
->statements
[2].resource
.begin()->resource
, "confidential-data");
340 EXPECT_EQ((p
->statements
[2].resource
.begin() + 1)->partition
,
342 EXPECT_EQ((p
->statements
[2].resource
.begin() + 1)->service
, Service::s3
);
343 EXPECT_TRUE((p
->statements
[2].resource
.begin() + 1)->region
.empty());
344 EXPECT_EQ((p
->statements
[2].resource
.begin() + 1)->account
,
346 EXPECT_EQ((p
->statements
[2].resource
.begin() + 1)->resource
,
347 "confidential-data/*");
348 EXPECT_TRUE(p
->statements
[2].notresource
.empty());
349 ASSERT_FALSE(p
->statements
[2].conditions
.empty());
350 ASSERT_EQ(p
->statements
[2].conditions
.size(), 1U);
351 EXPECT_EQ(p
->statements
[2].conditions
[0].op
, TokenID::Bool
);
352 EXPECT_EQ(p
->statements
[2].conditions
[0].key
, "aws:MultiFactorAuthPresent");
353 EXPECT_FALSE(p
->statements
[2].conditions
[0].ifexists
);
354 ASSERT_FALSE(p
->statements
[2].conditions
[0].vals
.empty());
355 EXPECT_EQ(p
->statements
[2].conditions
[0].vals
.size(), 1U);
356 EXPECT_EQ(p
->statements
[2].conditions
[0].vals
[0], "true");
359 TEST_F(PolicyTest
, Eval3
) {
360 auto p
= Policy(cct
.get(), arbitrary_tenant
,
361 bufferlist::static_from_string(example3
));
363 Environment tr
= { { "aws:MultiFactorAuthPresent", "true" } };
364 Environment fa
= { { "aws:MultiFactorAuthPresent", "false" } };
366 auto s3allow
= (s3ListMultipartUploadParts
| s3ListBucket
|
367 s3ListBucketVersions
| s3ListAllMyBuckets
|
368 s3ListBucketMultiPartUploads
| s3GetObject
|
369 s3GetObjectVersion
| s3GetObjectAcl
| s3GetObjectVersionAcl
|
370 s3GetObjectTorrent
| s3GetObjectVersionTorrent
|
371 s3GetAccelerateConfiguration
| s3GetBucketAcl
|
372 s3GetBucketCORS
| s3GetBucketVersioning
|
373 s3GetBucketRequestPayment
| s3GetBucketLocation
|
374 s3GetBucketPolicy
| s3GetBucketNotification
|
375 s3GetBucketLogging
| s3GetBucketTagging
|
376 s3GetBucketWebsite
| s3GetLifecycleConfiguration
|
377 s3GetReplicationConfiguration
|
378 s3GetObjectTagging
| s3GetObjectVersionTagging
);
380 EXPECT_EQ(p
.eval(em
, none
, s3PutBucketPolicy
,
381 ARN(Partition::aws
, Service::s3
,
382 "", arbitrary_tenant
, "mybucket")),
385 EXPECT_EQ(p
.eval(em
, none
, s3PutBucketPolicy
,
386 ARN(Partition::aws
, Service::s3
,
387 "", arbitrary_tenant
, "mybucket")),
391 for (auto i
= 0ULL; i
< s3Count
; ++i
) {
393 if ((op
== s3ListAllMyBuckets
) || (op
== s3PutBucketPolicy
)) {
397 EXPECT_EQ(p
.eval(em
, none
, op
,
398 ARN(Partition::aws
, Service::s3
,
399 "", arbitrary_tenant
, "confidential-data")),
401 EXPECT_EQ(p
.eval(tr
, none
, op
,
402 ARN(Partition::aws
, Service::s3
,
403 "", arbitrary_tenant
, "confidential-data")),
404 op
& s3allow
? Effect::Allow
: Effect::Pass
);
405 EXPECT_EQ(p
.eval(fa
, none
, op
,
406 ARN(Partition::aws
, Service::s3
,
407 "", arbitrary_tenant
, "confidential-data")),
410 EXPECT_EQ(p
.eval(em
, none
, op
,
411 ARN(Partition::aws
, Service::s3
,
412 "", arbitrary_tenant
, "confidential-data/moo")),
414 EXPECT_EQ(p
.eval(tr
, none
, op
,
415 ARN(Partition::aws
, Service::s3
,
416 "", arbitrary_tenant
, "confidential-data/moo")),
417 op
& s3allow
? Effect::Allow
: Effect::Pass
);
418 EXPECT_EQ(p
.eval(fa
, none
, op
,
419 ARN(Partition::aws
, Service::s3
,
420 "", arbitrary_tenant
, "confidential-data/moo")),
423 EXPECT_EQ(p
.eval(em
, none
, op
,
424 ARN(Partition::aws
, Service::s3
,
425 "", arbitrary_tenant
, "really-confidential-data")),
427 EXPECT_EQ(p
.eval(tr
, none
, op
,
428 ARN(Partition::aws
, Service::s3
,
429 "", arbitrary_tenant
, "really-confidential-data")),
431 EXPECT_EQ(p
.eval(fa
, none
, op
,
432 ARN(Partition::aws
, Service::s3
,
433 "", arbitrary_tenant
, "really-confidential-data")),
436 EXPECT_EQ(p
.eval(em
, none
, op
,
437 ARN(Partition::aws
, Service::s3
,
438 "", arbitrary_tenant
,
439 "really-confidential-data/moo")), Effect::Pass
);
440 EXPECT_EQ(p
.eval(tr
, none
, op
,
441 ARN(Partition::aws
, Service::s3
,
442 "", arbitrary_tenant
,
443 "really-confidential-data/moo")), Effect::Pass
);
444 EXPECT_EQ(p
.eval(fa
, none
, op
,
445 ARN(Partition::aws
, Service::s3
,
446 "", arbitrary_tenant
,
447 "really-confidential-data/moo")), Effect::Pass
);
452 const string
PolicyTest::arbitrary_tenant
= "arbitrary_tenant";
453 string
PolicyTest::example1
= R
"(
455 "Version
": "2012-10-17",
458 "Action
": "s3
:ListBucket
",
459 "Resource
": "arn
:aws
:s3:::example_bucket
"
464 string
PolicyTest::example2
= R
"(
466 "Version
": "2012-10-17",
467 "Id
": "S3
-Account
-Permissions
",
471 "Principal
": {"AWS
": ["arn
:aws
:iam::ACCOUNT
-ID
-WITHOUT
-HYPHENS
:root
"]},
474 "arn
:aws
:s3:::mybucket
",
475 "arn
:aws
:s3:::mybucket
/*"
481 string PolicyTest::example3 = R"(
483 "Version": "2012-10-17",
486 "Sid": "FirstStatement",
488 "Action": ["s3:PutBucketPolicy"],
492 "Sid": "SecondStatement",
494 "Action": "s3:ListAllMyBuckets",
498 "Sid": "ThirdStatement",
505 "arn:aws:s3:::confidential-data",
506 "arn:aws:s3:::confidential-data/*"
508 "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
514 TEST(MatchWildcards, Simple)
516 EXPECT_TRUE(match_wildcards("", ""));
517 EXPECT_TRUE(match_wildcards("", "", MATCH_CASE_INSENSITIVE));
518 EXPECT_FALSE(match_wildcards("", "abc"));
519 EXPECT_FALSE(match_wildcards("", "abc", MATCH_CASE_INSENSITIVE));
520 EXPECT_FALSE(match_wildcards("abc", ""));
521 EXPECT_FALSE(match_wildcards("abc", "", MATCH_CASE_INSENSITIVE));
522 EXPECT_TRUE(match_wildcards("abc", "abc"));
523 EXPECT_TRUE(match_wildcards("abc", "abc", MATCH_CASE_INSENSITIVE));
524 EXPECT_FALSE(match_wildcards("abc", "abC"));
525 EXPECT_TRUE(match_wildcards("abc", "abC", MATCH_CASE_INSENSITIVE));
526 EXPECT_FALSE(match_wildcards("abC", "abc"));
527 EXPECT_TRUE(match_wildcards("abC", "abc", MATCH_CASE_INSENSITIVE));
528 EXPECT_FALSE(match_wildcards("abc", "abcd"));
529 EXPECT_FALSE(match_wildcards("abc", "abcd", MATCH_CASE_INSENSITIVE));
530 EXPECT_FALSE(match_wildcards("abcd", "abc"));
531 EXPECT_FALSE(match_wildcards("abcd", "abc", MATCH_CASE_INSENSITIVE));
534 TEST(MatchWildcards, QuestionMark)
536 EXPECT_FALSE(match_wildcards("?", ""));
537 EXPECT_FALSE(match_wildcards("?", "", MATCH_CASE_INSENSITIVE));
538 EXPECT_TRUE(match_wildcards("?", "a"));
539 EXPECT_TRUE(match_wildcards("?", "a", MATCH_CASE_INSENSITIVE));
540 EXPECT_TRUE(match_wildcards("?bc", "abc"));
541 EXPECT_TRUE(match_wildcards("?bc", "abc", MATCH_CASE_INSENSITIVE));
542 EXPECT_TRUE(match_wildcards("a?c", "abc"));
543 EXPECT_TRUE(match_wildcards("a?c", "abc", MATCH_CASE_INSENSITIVE));
544 EXPECT_FALSE(match_wildcards("abc", "a?c"));
545 EXPECT_FALSE(match_wildcards("abc", "a?c", MATCH_CASE_INSENSITIVE));
546 EXPECT_FALSE(match_wildcards("a?c", "abC"));
547 EXPECT_TRUE(match_wildcards("a?c", "abC", MATCH_CASE_INSENSITIVE));
548 EXPECT_TRUE(match_wildcards("ab?", "abc"));
549 EXPECT_TRUE(match_wildcards("ab?", "abc", MATCH_CASE_INSENSITIVE));
550 EXPECT_TRUE(match_wildcards("a?c?e", "abcde"));
551 EXPECT_TRUE(match_wildcards("a?c?e", "abcde", MATCH_CASE_INSENSITIVE));
552 EXPECT_TRUE(match_wildcards("???", "abc"));
553 EXPECT_TRUE(match_wildcards("???", "abc", MATCH_CASE_INSENSITIVE));
554 EXPECT_FALSE(match_wildcards("???", "abcd"));
555 EXPECT_FALSE(match_wildcards("???", "abcd", MATCH_CASE_INSENSITIVE));
558 TEST(MatchWildcards, Asterisk)
560 EXPECT_TRUE(match_wildcards("*", ""));
561 EXPECT_TRUE(match_wildcards("*", "", MATCH_CASE_INSENSITIVE));
562 EXPECT_FALSE(match_wildcards("", "*"));
563 EXPECT_FALSE(match_wildcards("", "*", MATCH_CASE_INSENSITIVE));
564 EXPECT_FALSE(match_wildcards("*a", ""));
565 EXPECT_FALSE(match_wildcards("*a", "", MATCH_CASE_INSENSITIVE));
566 EXPECT_TRUE(match_wildcards("*a", "a"));
567 EXPECT_TRUE(match_wildcards("*a", "a", MATCH_CASE_INSENSITIVE));
568 EXPECT_TRUE(match_wildcards("a*", "a"));
569 EXPECT_TRUE(match_wildcards("a*", "a", MATCH_CASE_INSENSITIVE));
570 EXPECT_TRUE(match_wildcards("a*c", "ac"));
571 EXPECT_TRUE(match_wildcards("a*c", "ac", MATCH_CASE_INSENSITIVE));
572 EXPECT_TRUE(match_wildcards("a*c", "abbc"));
573 EXPECT_TRUE(match_wildcards("a*c", "abbc", MATCH_CASE_INSENSITIVE));
574 EXPECT_FALSE(match_wildcards("a*c", "abbC"));
575 EXPECT_TRUE(match_wildcards("a*c", "abbC", MATCH_CASE_INSENSITIVE));
576 EXPECT_TRUE(match_wildcards("a*c*e", "abBce"));
577 EXPECT_TRUE(match_wildcards("a*c*e", "abBce", MATCH_CASE_INSENSITIVE));
578 EXPECT_TRUE(match_wildcards("http://*.example.com",
579 "http://www.example.com"));
580 EXPECT_TRUE(match_wildcards("http://*.example.com",
581 "http://www.example.com", MATCH_CASE_INSENSITIVE));
582 EXPECT_FALSE(match_wildcards("http://*.example.com",
583 "http://www.Example.com"));
584 EXPECT_TRUE(match_wildcards("http://*.example.com",
585 "http://www.Example.com", MATCH_CASE_INSENSITIVE));
586 EXPECT_TRUE(match_wildcards("http://example.com/*",
587 "http://example.com/index.html"));
588 EXPECT_TRUE(match_wildcards("http://example.com/*/*.jpg",
589 "http://example.com/fun/smiley.jpg"));
590 // note: parsing of * is not greedy, so * does not match 'bc' here
591 EXPECT_FALSE(match_wildcards("a*c", "abcc"));
592 EXPECT_FALSE(match_wildcards("a*c", "abcc", MATCH_CASE_INSENSITIVE));
595 TEST(MatchPolicy, Action)
597 constexpr auto flag = MATCH_POLICY_ACTION;
598 EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag));
599 EXPECT_TRUE(match_policy("a:b:c", "A:B:C", flag)); // case insensitive
600 EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag));
601 EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments
604 TEST(MatchPolicy, Resource)
606 constexpr auto flag = MATCH_POLICY_RESOURCE;
607 EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag));
608 EXPECT_FALSE(match_policy("a:b:c", "A:B:C", flag)); // case sensitive
609 EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag));
610 EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments
613 TEST(MatchPolicy, ARN)
615 constexpr auto flag = MATCH_POLICY_ARN;
616 EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag));
617 EXPECT_TRUE(match_policy("a:b:c", "A:B:C", flag)); // case insensitive
618 EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag));
619 EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments
622 TEST(MatchPolicy, String)
624 constexpr auto flag = MATCH_POLICY_STRING;
625 EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag));
626 EXPECT_FALSE(match_policy("a:b:c", "A:B:C", flag)); // case sensitive
627 EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag));
628 EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments