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