X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Ftest%2Frgw%2Ftest_rgw_iam_policy.cc;fp=src%2Fceph%2Fsrc%2Ftest%2Frgw%2Ftest_rgw_iam_policy.cc;h=7751b086898bce2ffe9a81ed4d79502e0f047749;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/test/rgw/test_rgw_iam_policy.cc b/src/ceph/src/test/rgw/test_rgw_iam_policy.cc new file mode 100644 index 0000000..7751b08 --- /dev/null +++ b/src/ceph/src/test/rgw/test_rgw_iam_policy.cc @@ -0,0 +1,629 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2015 Red Hat + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#include + +#include +#include + +#include + +#include "common/code_environment.h" +#include "common/ceph_context.h" +#include "global/global_init.h" +#include "rgw/rgw_auth.h" +#include "rgw/rgw_iam_policy.h" + + +using std::string; +using std::vector; + +using boost::container::flat_set; +using boost::intrusive_ptr; +using boost::make_optional; +using boost::none; +using boost::optional; + +using rgw::auth::Identity; +using rgw::auth::Principal; + +using rgw::IAM::ARN; +using rgw::IAM::Effect; +using rgw::IAM::Environment; +using rgw::IAM::Partition; +using rgw::IAM::Policy; +using rgw::IAM::s3All; +using rgw::IAM::s3Count; +using rgw::IAM::s3GetAccelerateConfiguration; +using rgw::IAM::s3GetBucketAcl; +using rgw::IAM::s3GetBucketCORS; +using rgw::IAM::s3GetBucketLocation; +using rgw::IAM::s3GetBucketLogging; +using rgw::IAM::s3GetBucketNotification; +using rgw::IAM::s3GetBucketPolicy; +using rgw::IAM::s3GetBucketRequestPayment; +using rgw::IAM::s3GetBucketTagging; +using rgw::IAM::s3GetBucketVersioning; +using rgw::IAM::s3GetBucketWebsite; +using rgw::IAM::s3GetLifecycleConfiguration; +using rgw::IAM::s3GetObject; +using rgw::IAM::s3GetObjectAcl; +using rgw::IAM::s3GetObjectVersionAcl; +using rgw::IAM::s3GetObjectTorrent; +using rgw::IAM::s3GetObjectTagging; +using rgw::IAM::s3GetObjectVersion; +using rgw::IAM::s3GetObjectVersionTagging; +using rgw::IAM::s3GetObjectVersionTorrent; +using rgw::IAM::s3GetReplicationConfiguration; +using rgw::IAM::s3ListAllMyBuckets; +using rgw::IAM::s3ListBucket; +using rgw::IAM::s3ListBucket; +using rgw::IAM::s3ListBucketMultiPartUploads; +using rgw::IAM::s3ListBucketVersions; +using rgw::IAM::s3ListMultipartUploadParts; +using rgw::IAM::s3None; +using rgw::IAM::s3PutBucketAcl; +using rgw::IAM::s3PutBucketPolicy; +using rgw::IAM::Service; +using rgw::IAM::TokenID; +using rgw::IAM::Version; + +class FakeIdentity : public Identity { + const Principal id; +public: + + FakeIdentity(Principal&& id) : id(std::move(id)) {} + uint32_t get_perms_from_aclspec(const aclspec_t& aclspec) const override { + abort(); + return 0; + }; + + bool is_admin_of(const rgw_user& uid) const override { + abort(); + return false; + } + + bool is_owner_of(const rgw_user& uid) const override { + abort(); + return false; + } + + virtual uint32_t get_perm_mask() const override { + abort(); + return 0; + } + + void to_str(std::ostream& out) const override { + abort(); + } + + bool is_identity(const flat_set& ids) const override { + return ids.find(id) != ids.end(); + } +}; + +class PolicyTest : public ::testing::Test { +protected: + intrusive_ptr cct; + static const string arbitrary_tenant; + static string example1; + static string example2; + static string example3; +public: + PolicyTest() { + cct = new CephContext(CEPH_ENTITY_TYPE_CLIENT); + } +}; + +TEST_F(PolicyTest, Parse1) { + optional p; + + ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, + bufferlist::static_from_string(example1))); + ASSERT_TRUE(p); + + EXPECT_EQ(p->text, example1); + EXPECT_EQ(p->version, Version::v2012_10_17); + EXPECT_FALSE(p->id); + EXPECT_FALSE(p->statements[0].sid); + EXPECT_FALSE(p->statements.empty()); + EXPECT_EQ(p->statements.size(), 1U); + EXPECT_TRUE(p->statements[0].princ.empty()); + EXPECT_TRUE(p->statements[0].noprinc.empty()); + EXPECT_EQ(p->statements[0].effect, Effect::Allow); + EXPECT_EQ(p->statements[0].action, s3ListBucket); + EXPECT_EQ(p->statements[0].notaction, s3None); + ASSERT_FALSE(p->statements[0].resource.empty()); + ASSERT_EQ(p->statements[0].resource.size(), 1U); + EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws); + EXPECT_EQ(p->statements[0].resource.begin()->service, Service::s3); + EXPECT_TRUE(p->statements[0].resource.begin()->region.empty()); + EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant); + EXPECT_EQ(p->statements[0].resource.begin()->resource, "example_bucket"); + EXPECT_TRUE(p->statements[0].notresource.empty()); + EXPECT_TRUE(p->statements[0].conditions.empty()); +} + +TEST_F(PolicyTest, Eval1) { + auto p = Policy(cct.get(), arbitrary_tenant, + bufferlist::static_from_string(example1)); + Environment e; + + EXPECT_EQ(p.eval(e, none, s3ListBucket, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "example_bucket")), + Effect::Allow); + + EXPECT_EQ(p.eval(e, none, s3PutBucketAcl, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "example_bucket")), + Effect::Pass); + + EXPECT_EQ(p.eval(e, none, s3ListBucket, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "erroneous_bucket")), + Effect::Pass); + +} + +TEST_F(PolicyTest, Parse2) { + optional p; + + ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, + bufferlist::static_from_string(example2))); + ASSERT_TRUE(p); + + EXPECT_EQ(p->text, example2); + EXPECT_EQ(p->version, Version::v2012_10_17); + EXPECT_EQ(*p->id, "S3-Account-Permissions"); + ASSERT_FALSE(p->statements.empty()); + EXPECT_EQ(p->statements.size(), 1U); + EXPECT_EQ(*p->statements[0].sid, "1"); + EXPECT_FALSE(p->statements[0].princ.empty()); + EXPECT_EQ(p->statements[0].princ.size(), 1U); + EXPECT_EQ(*p->statements[0].princ.begin(), + Principal::tenant("ACCOUNT-ID-WITHOUT-HYPHENS")); + EXPECT_TRUE(p->statements[0].noprinc.empty()); + EXPECT_EQ(p->statements[0].effect, Effect::Allow); + EXPECT_EQ(p->statements[0].action, s3All); + EXPECT_EQ(p->statements[0].notaction, s3None); + ASSERT_FALSE(p->statements[0].resource.empty()); + ASSERT_EQ(p->statements[0].resource.size(), 2U); + EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws); + EXPECT_EQ(p->statements[0].resource.begin()->service, Service::s3); + EXPECT_TRUE(p->statements[0].resource.begin()->region.empty()); + EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant); + EXPECT_EQ(p->statements[0].resource.begin()->resource, "mybucket"); + EXPECT_EQ((p->statements[0].resource.begin() + 1)->partition, + Partition::aws); + EXPECT_EQ((p->statements[0].resource.begin() + 1)->service, + Service::s3); + EXPECT_TRUE((p->statements[0].resource.begin() + 1)->region.empty()); + EXPECT_EQ((p->statements[0].resource.begin() + 1)->account, + arbitrary_tenant); + EXPECT_EQ((p->statements[0].resource.begin() + 1)->resource, "mybucket/*"); + EXPECT_TRUE(p->statements[0].notresource.empty()); + EXPECT_TRUE(p->statements[0].conditions.empty()); +} + +TEST_F(PolicyTest, Eval2) { + auto p = Policy(cct.get(), arbitrary_tenant, + bufferlist::static_from_string(example2)); + Environment e; + + auto trueacct = FakeIdentity( + Principal::tenant("ACCOUNT-ID-WITHOUT-HYPHENS")); + + auto notacct = FakeIdentity( + Principal::tenant("some-other-account")); + for (auto i = 0ULL; i < s3Count; ++i) { + EXPECT_EQ(p.eval(e, trueacct, 1ULL << i, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "mybucket")), + Effect::Allow); + EXPECT_EQ(p.eval(e, trueacct, 1ULL << i, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "mybucket/myobject")), + Effect::Allow); + + EXPECT_EQ(p.eval(e, notacct, 1ULL << i, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "mybucket")), + Effect::Pass); + EXPECT_EQ(p.eval(e, notacct, 1ULL << i, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "mybucket/myobject")), + Effect::Pass); + + EXPECT_EQ(p.eval(e, trueacct, 1ULL << i, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "notyourbucket")), + Effect::Pass); + EXPECT_EQ(p.eval(e, trueacct, 1ULL << i, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "notyourbucket/notyourobject")), + Effect::Pass); + + } +} + +TEST_F(PolicyTest, Parse3) { + optional p; + + ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, + bufferlist::static_from_string(example3))); + ASSERT_TRUE(p); + + EXPECT_EQ(p->text, example3); + EXPECT_EQ(p->version, Version::v2012_10_17); + EXPECT_FALSE(p->id); + ASSERT_FALSE(p->statements.empty()); + EXPECT_EQ(p->statements.size(), 3U); + + EXPECT_EQ(*p->statements[0].sid, "FirstStatement"); + EXPECT_TRUE(p->statements[0].princ.empty()); + EXPECT_TRUE(p->statements[0].noprinc.empty()); + EXPECT_EQ(p->statements[0].effect, Effect::Allow); + EXPECT_EQ(p->statements[0].action, s3PutBucketPolicy); + EXPECT_EQ(p->statements[0].notaction, s3None); + ASSERT_FALSE(p->statements[0].resource.empty()); + ASSERT_EQ(p->statements[0].resource.size(), 1U); + EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::wildcard); + EXPECT_EQ(p->statements[0].resource.begin()->service, Service::wildcard); + EXPECT_EQ(p->statements[0].resource.begin()->region, "*"); + EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant); + EXPECT_EQ(p->statements[0].resource.begin()->resource, "*"); + EXPECT_TRUE(p->statements[0].notresource.empty()); + EXPECT_TRUE(p->statements[0].conditions.empty()); + + EXPECT_EQ(*p->statements[1].sid, "SecondStatement"); + EXPECT_TRUE(p->statements[1].princ.empty()); + EXPECT_TRUE(p->statements[1].noprinc.empty()); + EXPECT_EQ(p->statements[1].effect, Effect::Allow); + EXPECT_EQ(p->statements[1].action, s3ListAllMyBuckets); + EXPECT_EQ(p->statements[1].notaction, s3None); + ASSERT_FALSE(p->statements[1].resource.empty()); + ASSERT_EQ(p->statements[1].resource.size(), 1U); + EXPECT_EQ(p->statements[1].resource.begin()->partition, Partition::wildcard); + EXPECT_EQ(p->statements[1].resource.begin()->service, Service::wildcard); + EXPECT_EQ(p->statements[1].resource.begin()->region, "*"); + EXPECT_EQ(p->statements[1].resource.begin()->account, arbitrary_tenant); + EXPECT_EQ(p->statements[1].resource.begin()->resource, "*"); + EXPECT_TRUE(p->statements[1].notresource.empty()); + EXPECT_TRUE(p->statements[1].conditions.empty()); + + EXPECT_EQ(*p->statements[2].sid, "ThirdStatement"); + EXPECT_TRUE(p->statements[2].princ.empty()); + EXPECT_TRUE(p->statements[2].noprinc.empty()); + EXPECT_EQ(p->statements[2].effect, Effect::Allow); + EXPECT_EQ(p->statements[2].action, (s3ListMultipartUploadParts | + s3ListBucket | s3ListBucketVersions | + s3ListAllMyBuckets | + s3ListBucketMultiPartUploads | + s3GetObject | s3GetObjectVersion | + s3GetObjectAcl | s3GetObjectVersionAcl | + s3GetObjectTorrent | + s3GetObjectVersionTorrent | + s3GetAccelerateConfiguration | + s3GetBucketAcl | s3GetBucketCORS | + s3GetBucketVersioning | + s3GetBucketRequestPayment | + s3GetBucketLocation | + s3GetBucketPolicy | + s3GetBucketNotification | + s3GetBucketLogging | + s3GetBucketTagging | + s3GetBucketWebsite | + s3GetLifecycleConfiguration | + s3GetReplicationConfiguration | + s3GetObjectTagging | + s3GetObjectVersionTagging)); + EXPECT_EQ(p->statements[2].notaction, s3None); + ASSERT_FALSE(p->statements[2].resource.empty()); + ASSERT_EQ(p->statements[2].resource.size(), 2U); + EXPECT_EQ(p->statements[2].resource.begin()->partition, Partition::aws); + EXPECT_EQ(p->statements[2].resource.begin()->service, Service::s3); + EXPECT_TRUE(p->statements[2].resource.begin()->region.empty()); + EXPECT_EQ(p->statements[2].resource.begin()->account, arbitrary_tenant); + EXPECT_EQ(p->statements[2].resource.begin()->resource, "confidential-data"); + EXPECT_EQ((p->statements[2].resource.begin() + 1)->partition, + Partition::aws); + EXPECT_EQ((p->statements[2].resource.begin() + 1)->service, Service::s3); + EXPECT_TRUE((p->statements[2].resource.begin() + 1)->region.empty()); + EXPECT_EQ((p->statements[2].resource.begin() + 1)->account, + arbitrary_tenant); + EXPECT_EQ((p->statements[2].resource.begin() + 1)->resource, + "confidential-data/*"); + EXPECT_TRUE(p->statements[2].notresource.empty()); + ASSERT_FALSE(p->statements[2].conditions.empty()); + ASSERT_EQ(p->statements[2].conditions.size(), 1U); + EXPECT_EQ(p->statements[2].conditions[0].op, TokenID::Bool); + EXPECT_EQ(p->statements[2].conditions[0].key, "aws:MultiFactorAuthPresent"); + EXPECT_FALSE(p->statements[2].conditions[0].ifexists); + ASSERT_FALSE(p->statements[2].conditions[0].vals.empty()); + EXPECT_EQ(p->statements[2].conditions[0].vals.size(), 1U); + EXPECT_EQ(p->statements[2].conditions[0].vals[0], "true"); +} + +TEST_F(PolicyTest, Eval3) { + auto p = Policy(cct.get(), arbitrary_tenant, + bufferlist::static_from_string(example3)); + Environment em; + Environment tr = { { "aws:MultiFactorAuthPresent", "true" } }; + Environment fa = { { "aws:MultiFactorAuthPresent", "false" } }; + + auto s3allow = (s3ListMultipartUploadParts | s3ListBucket | + s3ListBucketVersions | s3ListAllMyBuckets | + s3ListBucketMultiPartUploads | s3GetObject | + s3GetObjectVersion | s3GetObjectAcl | s3GetObjectVersionAcl | + s3GetObjectTorrent | s3GetObjectVersionTorrent | + s3GetAccelerateConfiguration | s3GetBucketAcl | + s3GetBucketCORS | s3GetBucketVersioning | + s3GetBucketRequestPayment | s3GetBucketLocation | + s3GetBucketPolicy | s3GetBucketNotification | + s3GetBucketLogging | s3GetBucketTagging | + s3GetBucketWebsite | s3GetLifecycleConfiguration | + s3GetReplicationConfiguration | + s3GetObjectTagging | s3GetObjectVersionTagging); + + EXPECT_EQ(p.eval(em, none, s3PutBucketPolicy, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "mybucket")), + Effect::Allow); + + EXPECT_EQ(p.eval(em, none, s3PutBucketPolicy, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "mybucket")), + Effect::Allow); + + + for (auto i = 0ULL; i < s3Count; ++i) { + auto op = 1ULL << i; + if ((op == s3ListAllMyBuckets) || (op == s3PutBucketPolicy)) { + continue; + } + + EXPECT_EQ(p.eval(em, none, op, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "confidential-data")), + Effect::Pass); + EXPECT_EQ(p.eval(tr, none, op, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "confidential-data")), + op & s3allow ? Effect::Allow : Effect::Pass); + EXPECT_EQ(p.eval(fa, none, op, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "confidential-data")), + Effect::Pass); + + EXPECT_EQ(p.eval(em, none, op, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "confidential-data/moo")), + Effect::Pass); + EXPECT_EQ(p.eval(tr, none, op, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "confidential-data/moo")), + op & s3allow ? Effect::Allow : Effect::Pass); + EXPECT_EQ(p.eval(fa, none, op, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "confidential-data/moo")), + Effect::Pass); + + EXPECT_EQ(p.eval(em, none, op, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "really-confidential-data")), + Effect::Pass); + EXPECT_EQ(p.eval(tr, none, op, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "really-confidential-data")), + Effect::Pass); + EXPECT_EQ(p.eval(fa, none, op, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, "really-confidential-data")), + Effect::Pass); + + EXPECT_EQ(p.eval(em, none, op, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, + "really-confidential-data/moo")), Effect::Pass); + EXPECT_EQ(p.eval(tr, none, op, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, + "really-confidential-data/moo")), Effect::Pass); + EXPECT_EQ(p.eval(fa, none, op, + ARN(Partition::aws, Service::s3, + "", arbitrary_tenant, + "really-confidential-data/moo")), Effect::Pass); + + } +} + +const string PolicyTest::arbitrary_tenant = "arbitrary_tenant"; +string PolicyTest::example1 = R"( +{ + "Version": "2012-10-17", + "Statement": { + "Effect": "Allow", + "Action": "s3:ListBucket", + "Resource": "arn:aws:s3:::example_bucket" + } +} +)"; + +string PolicyTest::example2 = R"( +{ + "Version": "2012-10-17", + "Id": "S3-Account-Permissions", + "Statement": [{ + "Sid": "1", + "Effect": "Allow", + "Principal": {"AWS": ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:root"]}, + "Action": "s3:*", + "Resource": [ + "arn:aws:s3:::mybucket", + "arn:aws:s3:::mybucket/*" + ] + }] +} +)"; + +string PolicyTest::example3 = R"( +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "FirstStatement", + "Effect": "Allow", + "Action": ["s3:PutBucketPolicy"], + "Resource": "*" + }, + { + "Sid": "SecondStatement", + "Effect": "Allow", + "Action": "s3:ListAllMyBuckets", + "Resource": "*" + }, + { + "Sid": "ThirdStatement", + "Effect": "Allow", + "Action": [ + "s3:List*", + "s3:Get*" + ], + "Resource": [ + "arn:aws:s3:::confidential-data", + "arn:aws:s3:::confidential-data/*" + ], + "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}} + } + ] +} +)"; + +TEST(MatchWildcards, Simple) +{ + EXPECT_TRUE(match_wildcards("", "")); + EXPECT_TRUE(match_wildcards("", "", MATCH_CASE_INSENSITIVE)); + EXPECT_FALSE(match_wildcards("", "abc")); + EXPECT_FALSE(match_wildcards("", "abc", MATCH_CASE_INSENSITIVE)); + EXPECT_FALSE(match_wildcards("abc", "")); + EXPECT_FALSE(match_wildcards("abc", "", MATCH_CASE_INSENSITIVE)); + EXPECT_TRUE(match_wildcards("abc", "abc")); + EXPECT_TRUE(match_wildcards("abc", "abc", MATCH_CASE_INSENSITIVE)); + EXPECT_FALSE(match_wildcards("abc", "abC")); + EXPECT_TRUE(match_wildcards("abc", "abC", MATCH_CASE_INSENSITIVE)); + EXPECT_FALSE(match_wildcards("abC", "abc")); + EXPECT_TRUE(match_wildcards("abC", "abc", MATCH_CASE_INSENSITIVE)); + EXPECT_FALSE(match_wildcards("abc", "abcd")); + EXPECT_FALSE(match_wildcards("abc", "abcd", MATCH_CASE_INSENSITIVE)); + EXPECT_FALSE(match_wildcards("abcd", "abc")); + EXPECT_FALSE(match_wildcards("abcd", "abc", MATCH_CASE_INSENSITIVE)); +} + +TEST(MatchWildcards, QuestionMark) +{ + EXPECT_FALSE(match_wildcards("?", "")); + EXPECT_FALSE(match_wildcards("?", "", MATCH_CASE_INSENSITIVE)); + EXPECT_TRUE(match_wildcards("?", "a")); + EXPECT_TRUE(match_wildcards("?", "a", MATCH_CASE_INSENSITIVE)); + EXPECT_TRUE(match_wildcards("?bc", "abc")); + EXPECT_TRUE(match_wildcards("?bc", "abc", MATCH_CASE_INSENSITIVE)); + EXPECT_TRUE(match_wildcards("a?c", "abc")); + EXPECT_TRUE(match_wildcards("a?c", "abc", MATCH_CASE_INSENSITIVE)); + EXPECT_FALSE(match_wildcards("abc", "a?c")); + EXPECT_FALSE(match_wildcards("abc", "a?c", MATCH_CASE_INSENSITIVE)); + EXPECT_FALSE(match_wildcards("a?c", "abC")); + EXPECT_TRUE(match_wildcards("a?c", "abC", MATCH_CASE_INSENSITIVE)); + EXPECT_TRUE(match_wildcards("ab?", "abc")); + EXPECT_TRUE(match_wildcards("ab?", "abc", MATCH_CASE_INSENSITIVE)); + EXPECT_TRUE(match_wildcards("a?c?e", "abcde")); + EXPECT_TRUE(match_wildcards("a?c?e", "abcde", MATCH_CASE_INSENSITIVE)); + EXPECT_TRUE(match_wildcards("???", "abc")); + EXPECT_TRUE(match_wildcards("???", "abc", MATCH_CASE_INSENSITIVE)); + EXPECT_FALSE(match_wildcards("???", "abcd")); + EXPECT_FALSE(match_wildcards("???", "abcd", MATCH_CASE_INSENSITIVE)); +} + +TEST(MatchWildcards, Asterisk) +{ + EXPECT_TRUE(match_wildcards("*", "")); + EXPECT_TRUE(match_wildcards("*", "", MATCH_CASE_INSENSITIVE)); + EXPECT_FALSE(match_wildcards("", "*")); + EXPECT_FALSE(match_wildcards("", "*", MATCH_CASE_INSENSITIVE)); + EXPECT_FALSE(match_wildcards("*a", "")); + EXPECT_FALSE(match_wildcards("*a", "", MATCH_CASE_INSENSITIVE)); + EXPECT_TRUE(match_wildcards("*a", "a")); + EXPECT_TRUE(match_wildcards("*a", "a", MATCH_CASE_INSENSITIVE)); + EXPECT_TRUE(match_wildcards("a*", "a")); + EXPECT_TRUE(match_wildcards("a*", "a", MATCH_CASE_INSENSITIVE)); + EXPECT_TRUE(match_wildcards("a*c", "ac")); + EXPECT_TRUE(match_wildcards("a*c", "ac", MATCH_CASE_INSENSITIVE)); + EXPECT_TRUE(match_wildcards("a*c", "abbc")); + EXPECT_TRUE(match_wildcards("a*c", "abbc", MATCH_CASE_INSENSITIVE)); + EXPECT_FALSE(match_wildcards("a*c", "abbC")); + EXPECT_TRUE(match_wildcards("a*c", "abbC", MATCH_CASE_INSENSITIVE)); + EXPECT_TRUE(match_wildcards("a*c*e", "abBce")); + EXPECT_TRUE(match_wildcards("a*c*e", "abBce", MATCH_CASE_INSENSITIVE)); + EXPECT_TRUE(match_wildcards("http://*.example.com", + "http://www.example.com")); + EXPECT_TRUE(match_wildcards("http://*.example.com", + "http://www.example.com", MATCH_CASE_INSENSITIVE)); + EXPECT_FALSE(match_wildcards("http://*.example.com", + "http://www.Example.com")); + EXPECT_TRUE(match_wildcards("http://*.example.com", + "http://www.Example.com", MATCH_CASE_INSENSITIVE)); + EXPECT_TRUE(match_wildcards("http://example.com/*", + "http://example.com/index.html")); + EXPECT_TRUE(match_wildcards("http://example.com/*/*.jpg", + "http://example.com/fun/smiley.jpg")); + // note: parsing of * is not greedy, so * does not match 'bc' here + EXPECT_FALSE(match_wildcards("a*c", "abcc")); + EXPECT_FALSE(match_wildcards("a*c", "abcc", MATCH_CASE_INSENSITIVE)); +} + +TEST(MatchPolicy, Action) +{ + constexpr auto flag = MATCH_POLICY_ACTION; + EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag)); + EXPECT_TRUE(match_policy("a:b:c", "A:B:C", flag)); // case insensitive + EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag)); + EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments +} + +TEST(MatchPolicy, Resource) +{ + constexpr auto flag = MATCH_POLICY_RESOURCE; + EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag)); + EXPECT_FALSE(match_policy("a:b:c", "A:B:C", flag)); // case sensitive + EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag)); + EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments +} + +TEST(MatchPolicy, ARN) +{ + constexpr auto flag = MATCH_POLICY_ARN; + EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag)); + EXPECT_TRUE(match_policy("a:b:c", "A:B:C", flag)); // case insensitive + EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag)); + EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments +} + +TEST(MatchPolicy, String) +{ + constexpr auto flag = MATCH_POLICY_STRING; + EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag)); + EXPECT_FALSE(match_policy("a:b:c", "A:B:C", flag)); // case sensitive + EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag)); + EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments +}