]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/rgw/test_rgw_iam_policy.cc
update sources to 12.2.7
[ceph.git] / ceph / src / test / rgw / test_rgw_iam_policy.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2015 Red Hat
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15 #include <string>
16
17 #include <boost/intrusive_ptr.hpp>
18 #include <boost/optional.hpp>
19
20 #include <gtest/gtest.h>
21
22 #include "include/stringify.h"
23 #include "common/code_environment.h"
24 #include "common/ceph_context.h"
25 #include "global/global_init.h"
26 #include "rgw/rgw_auth.h"
27 #include "rgw/rgw_iam_policy.h"
28 #include "rgw/rgw_op.h"
29
30
31 using std::string;
32 using std::vector;
33
34 using boost::container::flat_set;
35 using boost::intrusive_ptr;
36 using boost::make_optional;
37 using boost::none;
38 using boost::optional;
39
40 using rgw::auth::Identity;
41 using rgw::auth::Principal;
42
43 using rgw::IAM::ARN;
44 using rgw::IAM::Effect;
45 using rgw::IAM::Environment;
46 using rgw::IAM::Partition;
47 using rgw::IAM::Policy;
48 using rgw::IAM::s3All;
49 using rgw::IAM::s3Count;
50 using rgw::IAM::s3GetAccelerateConfiguration;
51 using rgw::IAM::s3GetBucketAcl;
52 using rgw::IAM::s3GetBucketCORS;
53 using rgw::IAM::s3GetBucketLocation;
54 using rgw::IAM::s3GetBucketLogging;
55 using rgw::IAM::s3GetBucketNotification;
56 using rgw::IAM::s3GetBucketPolicy;
57 using rgw::IAM::s3GetBucketRequestPayment;
58 using rgw::IAM::s3GetBucketTagging;
59 using rgw::IAM::s3GetBucketVersioning;
60 using rgw::IAM::s3GetBucketWebsite;
61 using rgw::IAM::s3GetLifecycleConfiguration;
62 using rgw::IAM::s3GetObject;
63 using rgw::IAM::s3GetObjectAcl;
64 using rgw::IAM::s3GetObjectVersionAcl;
65 using rgw::IAM::s3GetObjectTorrent;
66 using rgw::IAM::s3GetObjectTagging;
67 using rgw::IAM::s3GetObjectVersion;
68 using rgw::IAM::s3GetObjectVersionTagging;
69 using rgw::IAM::s3GetObjectVersionTorrent;
70 using rgw::IAM::s3GetReplicationConfiguration;
71 using rgw::IAM::s3ListAllMyBuckets;
72 using rgw::IAM::s3ListBucket;
73 using rgw::IAM::s3ListBucket;
74 using rgw::IAM::s3ListBucketMultipartUploads;
75 using rgw::IAM::s3ListBucketVersions;
76 using rgw::IAM::s3ListMultipartUploadParts;
77 using rgw::IAM::s3None;
78 using rgw::IAM::s3PutBucketAcl;
79 using rgw::IAM::s3PutBucketPolicy;
80 using rgw::IAM::Service;
81 using rgw::IAM::TokenID;
82 using rgw::IAM::Version;
83
84 class FakeIdentity : public Identity {
85 const Principal id;
86 public:
87
88 FakeIdentity(Principal&& id) : id(std::move(id)) {}
89 uint32_t get_perms_from_aclspec(const aclspec_t& aclspec) const override {
90 abort();
91 return 0;
92 };
93
94 bool is_admin_of(const rgw_user& uid) const override {
95 abort();
96 return false;
97 }
98
99 bool is_owner_of(const rgw_user& uid) const override {
100 abort();
101 return false;
102 }
103
104 virtual uint32_t get_perm_mask() const override {
105 abort();
106 return 0;
107 }
108
109 void to_str(std::ostream& out) const override {
110 out << id;
111 }
112
113 bool is_identity(const flat_set<Principal>& ids) const override {
114 if (id.is_wildcard() && (!ids.empty())) {
115 return true;
116 }
117 return ids.find(id) != ids.end() || ids.find(Principal::wildcard()) != ids.end();
118 }
119 };
120
121 class PolicyTest : public ::testing::Test {
122 protected:
123 intrusive_ptr<CephContext> cct;
124 static const string arbitrary_tenant;
125 static string example1;
126 static string example2;
127 static string example3;
128 public:
129 PolicyTest() {
130 cct = new CephContext(CEPH_ENTITY_TYPE_CLIENT);
131 }
132 };
133
134 TEST_F(PolicyTest, Parse1) {
135 optional<Policy> p;
136
137 ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant,
138 bufferlist::static_from_string(example1)));
139 ASSERT_TRUE(p);
140
141 EXPECT_EQ(p->text, example1);
142 EXPECT_EQ(p->version, Version::v2012_10_17);
143 EXPECT_FALSE(p->id);
144 EXPECT_FALSE(p->statements[0].sid);
145 EXPECT_FALSE(p->statements.empty());
146 EXPECT_EQ(p->statements.size(), 1U);
147 EXPECT_TRUE(p->statements[0].princ.empty());
148 EXPECT_TRUE(p->statements[0].noprinc.empty());
149 EXPECT_EQ(p->statements[0].effect, Effect::Allow);
150 EXPECT_EQ(p->statements[0].action, s3ListBucket);
151 EXPECT_EQ(p->statements[0].notaction, s3None);
152 ASSERT_FALSE(p->statements[0].resource.empty());
153 ASSERT_EQ(p->statements[0].resource.size(), 1U);
154 EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws);
155 EXPECT_EQ(p->statements[0].resource.begin()->service, Service::s3);
156 EXPECT_TRUE(p->statements[0].resource.begin()->region.empty());
157 EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant);
158 EXPECT_EQ(p->statements[0].resource.begin()->resource, "example_bucket");
159 EXPECT_TRUE(p->statements[0].notresource.empty());
160 EXPECT_TRUE(p->statements[0].conditions.empty());
161 }
162
163 TEST_F(PolicyTest, Eval1) {
164 auto p = Policy(cct.get(), arbitrary_tenant,
165 bufferlist::static_from_string(example1));
166 Environment e;
167
168 EXPECT_EQ(p.eval(e, none, s3ListBucket,
169 ARN(Partition::aws, Service::s3,
170 "", arbitrary_tenant, "example_bucket")),
171 Effect::Allow);
172
173 EXPECT_EQ(p.eval(e, none, s3PutBucketAcl,
174 ARN(Partition::aws, Service::s3,
175 "", arbitrary_tenant, "example_bucket")),
176 Effect::Pass);
177
178 EXPECT_EQ(p.eval(e, none, s3ListBucket,
179 ARN(Partition::aws, Service::s3,
180 "", arbitrary_tenant, "erroneous_bucket")),
181 Effect::Pass);
182
183 }
184
185 TEST_F(PolicyTest, Parse2) {
186 optional<Policy> p;
187
188 ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant,
189 bufferlist::static_from_string(example2)));
190 ASSERT_TRUE(p);
191
192 EXPECT_EQ(p->text, example2);
193 EXPECT_EQ(p->version, Version::v2012_10_17);
194 EXPECT_EQ(*p->id, "S3-Account-Permissions");
195 ASSERT_FALSE(p->statements.empty());
196 EXPECT_EQ(p->statements.size(), 1U);
197 EXPECT_EQ(*p->statements[0].sid, "1");
198 EXPECT_FALSE(p->statements[0].princ.empty());
199 EXPECT_EQ(p->statements[0].princ.size(), 1U);
200 EXPECT_EQ(*p->statements[0].princ.begin(),
201 Principal::tenant("ACCOUNT-ID-WITHOUT-HYPHENS"));
202 EXPECT_TRUE(p->statements[0].noprinc.empty());
203 EXPECT_EQ(p->statements[0].effect, Effect::Allow);
204 EXPECT_EQ(p->statements[0].action, s3All);
205 EXPECT_EQ(p->statements[0].notaction, s3None);
206 ASSERT_FALSE(p->statements[0].resource.empty());
207 ASSERT_EQ(p->statements[0].resource.size(), 2U);
208 EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws);
209 EXPECT_EQ(p->statements[0].resource.begin()->service, Service::s3);
210 EXPECT_TRUE(p->statements[0].resource.begin()->region.empty());
211 EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant);
212 EXPECT_EQ(p->statements[0].resource.begin()->resource, "mybucket");
213 EXPECT_EQ((p->statements[0].resource.begin() + 1)->partition,
214 Partition::aws);
215 EXPECT_EQ((p->statements[0].resource.begin() + 1)->service,
216 Service::s3);
217 EXPECT_TRUE((p->statements[0].resource.begin() + 1)->region.empty());
218 EXPECT_EQ((p->statements[0].resource.begin() + 1)->account,
219 arbitrary_tenant);
220 EXPECT_EQ((p->statements[0].resource.begin() + 1)->resource, "mybucket/*");
221 EXPECT_TRUE(p->statements[0].notresource.empty());
222 EXPECT_TRUE(p->statements[0].conditions.empty());
223 }
224
225 TEST_F(PolicyTest, Eval2) {
226 auto p = Policy(cct.get(), arbitrary_tenant,
227 bufferlist::static_from_string(example2));
228 Environment e;
229
230 auto trueacct = FakeIdentity(
231 Principal::tenant("ACCOUNT-ID-WITHOUT-HYPHENS"));
232
233 auto notacct = FakeIdentity(
234 Principal::tenant("some-other-account"));
235 for (auto i = 0ULL; i < s3Count; ++i) {
236 EXPECT_EQ(p.eval(e, trueacct, 1ULL << i,
237 ARN(Partition::aws, Service::s3,
238 "", arbitrary_tenant, "mybucket")),
239 Effect::Allow);
240 EXPECT_EQ(p.eval(e, trueacct, 1ULL << i,
241 ARN(Partition::aws, Service::s3,
242 "", arbitrary_tenant, "mybucket/myobject")),
243 Effect::Allow);
244
245 EXPECT_EQ(p.eval(e, notacct, 1ULL << i,
246 ARN(Partition::aws, Service::s3,
247 "", arbitrary_tenant, "mybucket")),
248 Effect::Pass);
249 EXPECT_EQ(p.eval(e, notacct, 1ULL << i,
250 ARN(Partition::aws, Service::s3,
251 "", arbitrary_tenant, "mybucket/myobject")),
252 Effect::Pass);
253
254 EXPECT_EQ(p.eval(e, trueacct, 1ULL << i,
255 ARN(Partition::aws, Service::s3,
256 "", arbitrary_tenant, "notyourbucket")),
257 Effect::Pass);
258 EXPECT_EQ(p.eval(e, trueacct, 1ULL << i,
259 ARN(Partition::aws, Service::s3,
260 "", arbitrary_tenant, "notyourbucket/notyourobject")),
261 Effect::Pass);
262
263 }
264 }
265
266 TEST_F(PolicyTest, Parse3) {
267 optional<Policy> p;
268
269 ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant,
270 bufferlist::static_from_string(example3)));
271 ASSERT_TRUE(p);
272
273 EXPECT_EQ(p->text, example3);
274 EXPECT_EQ(p->version, Version::v2012_10_17);
275 EXPECT_FALSE(p->id);
276 ASSERT_FALSE(p->statements.empty());
277 EXPECT_EQ(p->statements.size(), 3U);
278
279 EXPECT_EQ(*p->statements[0].sid, "FirstStatement");
280 EXPECT_TRUE(p->statements[0].princ.empty());
281 EXPECT_TRUE(p->statements[0].noprinc.empty());
282 EXPECT_EQ(p->statements[0].effect, Effect::Allow);
283 EXPECT_EQ(p->statements[0].action, s3PutBucketPolicy);
284 EXPECT_EQ(p->statements[0].notaction, s3None);
285 ASSERT_FALSE(p->statements[0].resource.empty());
286 ASSERT_EQ(p->statements[0].resource.size(), 1U);
287 EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::wildcard);
288 EXPECT_EQ(p->statements[0].resource.begin()->service, Service::wildcard);
289 EXPECT_EQ(p->statements[0].resource.begin()->region, "*");
290 EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant);
291 EXPECT_EQ(p->statements[0].resource.begin()->resource, "*");
292 EXPECT_TRUE(p->statements[0].notresource.empty());
293 EXPECT_TRUE(p->statements[0].conditions.empty());
294
295 EXPECT_EQ(*p->statements[1].sid, "SecondStatement");
296 EXPECT_TRUE(p->statements[1].princ.empty());
297 EXPECT_TRUE(p->statements[1].noprinc.empty());
298 EXPECT_EQ(p->statements[1].effect, Effect::Allow);
299 EXPECT_EQ(p->statements[1].action, s3ListAllMyBuckets);
300 EXPECT_EQ(p->statements[1].notaction, s3None);
301 ASSERT_FALSE(p->statements[1].resource.empty());
302 ASSERT_EQ(p->statements[1].resource.size(), 1U);
303 EXPECT_EQ(p->statements[1].resource.begin()->partition, Partition::wildcard);
304 EXPECT_EQ(p->statements[1].resource.begin()->service, Service::wildcard);
305 EXPECT_EQ(p->statements[1].resource.begin()->region, "*");
306 EXPECT_EQ(p->statements[1].resource.begin()->account, arbitrary_tenant);
307 EXPECT_EQ(p->statements[1].resource.begin()->resource, "*");
308 EXPECT_TRUE(p->statements[1].notresource.empty());
309 EXPECT_TRUE(p->statements[1].conditions.empty());
310
311 EXPECT_EQ(*p->statements[2].sid, "ThirdStatement");
312 EXPECT_TRUE(p->statements[2].princ.empty());
313 EXPECT_TRUE(p->statements[2].noprinc.empty());
314 EXPECT_EQ(p->statements[2].effect, Effect::Allow);
315 EXPECT_EQ(p->statements[2].action, (s3ListMultipartUploadParts |
316 s3ListBucket | s3ListBucketVersions |
317 s3ListAllMyBuckets |
318 s3ListBucketMultipartUploads |
319 s3GetObject | s3GetObjectVersion |
320 s3GetObjectAcl | s3GetObjectVersionAcl |
321 s3GetObjectTorrent |
322 s3GetObjectVersionTorrent |
323 s3GetAccelerateConfiguration |
324 s3GetBucketAcl | s3GetBucketCORS |
325 s3GetBucketVersioning |
326 s3GetBucketRequestPayment |
327 s3GetBucketLocation |
328 s3GetBucketPolicy |
329 s3GetBucketNotification |
330 s3GetBucketLogging |
331 s3GetBucketTagging |
332 s3GetBucketWebsite |
333 s3GetLifecycleConfiguration |
334 s3GetReplicationConfiguration |
335 s3GetObjectTagging |
336 s3GetObjectVersionTagging));
337 EXPECT_EQ(p->statements[2].notaction, s3None);
338 ASSERT_FALSE(p->statements[2].resource.empty());
339 ASSERT_EQ(p->statements[2].resource.size(), 2U);
340 EXPECT_EQ(p->statements[2].resource.begin()->partition, Partition::aws);
341 EXPECT_EQ(p->statements[2].resource.begin()->service, Service::s3);
342 EXPECT_TRUE(p->statements[2].resource.begin()->region.empty());
343 EXPECT_EQ(p->statements[2].resource.begin()->account, arbitrary_tenant);
344 EXPECT_EQ(p->statements[2].resource.begin()->resource, "confidential-data");
345 EXPECT_EQ((p->statements[2].resource.begin() + 1)->partition,
346 Partition::aws);
347 EXPECT_EQ((p->statements[2].resource.begin() + 1)->service, Service::s3);
348 EXPECT_TRUE((p->statements[2].resource.begin() + 1)->region.empty());
349 EXPECT_EQ((p->statements[2].resource.begin() + 1)->account,
350 arbitrary_tenant);
351 EXPECT_EQ((p->statements[2].resource.begin() + 1)->resource,
352 "confidential-data/*");
353 EXPECT_TRUE(p->statements[2].notresource.empty());
354 ASSERT_FALSE(p->statements[2].conditions.empty());
355 ASSERT_EQ(p->statements[2].conditions.size(), 1U);
356 EXPECT_EQ(p->statements[2].conditions[0].op, TokenID::Bool);
357 EXPECT_EQ(p->statements[2].conditions[0].key, "aws:MultiFactorAuthPresent");
358 EXPECT_FALSE(p->statements[2].conditions[0].ifexists);
359 ASSERT_FALSE(p->statements[2].conditions[0].vals.empty());
360 EXPECT_EQ(p->statements[2].conditions[0].vals.size(), 1U);
361 EXPECT_EQ(p->statements[2].conditions[0].vals[0], "true");
362 }
363
364 TEST_F(PolicyTest, Eval3) {
365 auto p = Policy(cct.get(), arbitrary_tenant,
366 bufferlist::static_from_string(example3));
367 Environment em;
368 Environment tr = { { "aws:MultiFactorAuthPresent", "true" } };
369 Environment fa = { { "aws:MultiFactorAuthPresent", "false" } };
370
371 auto s3allow = (s3ListMultipartUploadParts | s3ListBucket |
372 s3ListBucketVersions | s3ListAllMyBuckets |
373 s3ListBucketMultipartUploads | s3GetObject |
374 s3GetObjectVersion | s3GetObjectAcl | s3GetObjectVersionAcl |
375 s3GetObjectTorrent | s3GetObjectVersionTorrent |
376 s3GetAccelerateConfiguration | s3GetBucketAcl |
377 s3GetBucketCORS | s3GetBucketVersioning |
378 s3GetBucketRequestPayment | s3GetBucketLocation |
379 s3GetBucketPolicy | s3GetBucketNotification |
380 s3GetBucketLogging | s3GetBucketTagging |
381 s3GetBucketWebsite | s3GetLifecycleConfiguration |
382 s3GetReplicationConfiguration |
383 s3GetObjectTagging | s3GetObjectVersionTagging);
384
385 EXPECT_EQ(p.eval(em, none, s3PutBucketPolicy,
386 ARN(Partition::aws, Service::s3,
387 "", arbitrary_tenant, "mybucket")),
388 Effect::Allow);
389
390 EXPECT_EQ(p.eval(em, none, s3PutBucketPolicy,
391 ARN(Partition::aws, Service::s3,
392 "", arbitrary_tenant, "mybucket")),
393 Effect::Allow);
394
395
396 for (auto i = 0ULL; i < s3Count; ++i) {
397 auto op = 1ULL << i;
398 if ((op == s3ListAllMyBuckets) || (op == s3PutBucketPolicy)) {
399 continue;
400 }
401
402 EXPECT_EQ(p.eval(em, none, op,
403 ARN(Partition::aws, Service::s3,
404 "", arbitrary_tenant, "confidential-data")),
405 Effect::Pass);
406 EXPECT_EQ(p.eval(tr, none, op,
407 ARN(Partition::aws, Service::s3,
408 "", arbitrary_tenant, "confidential-data")),
409 op & s3allow ? Effect::Allow : Effect::Pass);
410 EXPECT_EQ(p.eval(fa, none, op,
411 ARN(Partition::aws, Service::s3,
412 "", arbitrary_tenant, "confidential-data")),
413 Effect::Pass);
414
415 EXPECT_EQ(p.eval(em, none, op,
416 ARN(Partition::aws, Service::s3,
417 "", arbitrary_tenant, "confidential-data/moo")),
418 Effect::Pass);
419 EXPECT_EQ(p.eval(tr, none, op,
420 ARN(Partition::aws, Service::s3,
421 "", arbitrary_tenant, "confidential-data/moo")),
422 op & s3allow ? Effect::Allow : Effect::Pass);
423 EXPECT_EQ(p.eval(fa, none, op,
424 ARN(Partition::aws, Service::s3,
425 "", arbitrary_tenant, "confidential-data/moo")),
426 Effect::Pass);
427
428 EXPECT_EQ(p.eval(em, none, op,
429 ARN(Partition::aws, Service::s3,
430 "", arbitrary_tenant, "really-confidential-data")),
431 Effect::Pass);
432 EXPECT_EQ(p.eval(tr, none, op,
433 ARN(Partition::aws, Service::s3,
434 "", arbitrary_tenant, "really-confidential-data")),
435 Effect::Pass);
436 EXPECT_EQ(p.eval(fa, none, op,
437 ARN(Partition::aws, Service::s3,
438 "", arbitrary_tenant, "really-confidential-data")),
439 Effect::Pass);
440
441 EXPECT_EQ(p.eval(em, none, op,
442 ARN(Partition::aws, Service::s3,
443 "", arbitrary_tenant,
444 "really-confidential-data/moo")), Effect::Pass);
445 EXPECT_EQ(p.eval(tr, none, op,
446 ARN(Partition::aws, Service::s3,
447 "", arbitrary_tenant,
448 "really-confidential-data/moo")), Effect::Pass);
449 EXPECT_EQ(p.eval(fa, none, op,
450 ARN(Partition::aws, Service::s3,
451 "", arbitrary_tenant,
452 "really-confidential-data/moo")), Effect::Pass);
453
454 }
455 }
456
457 const string PolicyTest::arbitrary_tenant = "arbitrary_tenant";
458 string PolicyTest::example1 = R"(
459 {
460 "Version": "2012-10-17",
461 "Statement": {
462 "Effect": "Allow",
463 "Action": "s3:ListBucket",
464 "Resource": "arn:aws:s3:::example_bucket"
465 }
466 }
467 )";
468
469 string PolicyTest::example2 = R"(
470 {
471 "Version": "2012-10-17",
472 "Id": "S3-Account-Permissions",
473 "Statement": [{
474 "Sid": "1",
475 "Effect": "Allow",
476 "Principal": {"AWS": ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:root"]},
477 "Action": "s3:*",
478 "Resource": [
479 "arn:aws:s3:::mybucket",
480 "arn:aws:s3:::mybucket/*"
481 ]
482 }]
483 }
484 )";
485
486 string PolicyTest::example3 = R"(
487 {
488 "Version": "2012-10-17",
489 "Statement": [
490 {
491 "Sid": "FirstStatement",
492 "Effect": "Allow",
493 "Action": ["s3:PutBucketPolicy"],
494 "Resource": "*"
495 },
496 {
497 "Sid": "SecondStatement",
498 "Effect": "Allow",
499 "Action": "s3:ListAllMyBuckets",
500 "Resource": "*"
501 },
502 {
503 "Sid": "ThirdStatement",
504 "Effect": "Allow",
505 "Action": [
506 "s3:List*",
507 "s3:Get*"
508 ],
509 "Resource": [
510 "arn:aws:s3:::confidential-data",
511 "arn:aws:s3:::confidential-data/*"
512 ],
513 "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
514 }
515 ]
516 }
517 )";
518
519 class IPPolicyTest : public ::testing::Test {
520 protected:
521 intrusive_ptr<CephContext> cct;
522 static const string arbitrary_tenant;
523 static string ip_address_allow_example;
524 static string ip_address_deny_example;
525 static string ip_address_full_example;
526 // 192.168.1.0/24
527 const rgw::IAM::MaskedIP allowedIPv4Range = { false, rgw::IAM::Address("11000000101010000000000100000000"), 24 };
528 // 192.168.1.1/32
529 const rgw::IAM::MaskedIP blacklistedIPv4 = { false, rgw::IAM::Address("11000000101010000000000100000001"), 32 };
530 // 2001:db8:85a3:0:0:8a2e:370:7334/128
531 const rgw::IAM::MaskedIP allowedIPv6 = { true, rgw::IAM::Address("00100000000000010000110110111000100001011010001100000000000000000000000000000000100010100010111000000011011100000111001100110100"), 128 };
532 // ::1
533 const rgw::IAM::MaskedIP blacklistedIPv6 = { true, rgw::IAM::Address(1), 128 };
534 // 2001:db8:85a3:0:0:8a2e:370:7330/124
535 const rgw::IAM::MaskedIP allowedIPv6Range = { true, rgw::IAM::Address("00100000000000010000110110111000100001011010001100000000000000000000000000000000100010100010111000000011011100000111001100110000"), 124 };
536 public:
537 IPPolicyTest() {
538 cct = new CephContext(CEPH_ENTITY_TYPE_CLIENT);
539 }
540 };
541 const string IPPolicyTest::arbitrary_tenant = "arbitrary_tenant";
542
543 TEST_F(IPPolicyTest, MaskedIPOperations) {
544 EXPECT_EQ(stringify(allowedIPv4Range), "192.168.1.0/24");
545 EXPECT_EQ(stringify(blacklistedIPv4), "192.168.1.1/32");
546 EXPECT_EQ(stringify(allowedIPv6), "2001:db8:85a3:0:0:8a2e:370:7334/128");
547 EXPECT_EQ(stringify(allowedIPv6Range), "2001:db8:85a3:0:0:8a2e:370:7330/124");
548 EXPECT_EQ(stringify(blacklistedIPv6), "0:0:0:0:0:0:0:1/128");
549 EXPECT_EQ(allowedIPv4Range, blacklistedIPv4);
550 EXPECT_EQ(allowedIPv6Range, allowedIPv6);
551 }
552
553 TEST_F(IPPolicyTest, asNetworkIPv4Range) {
554 auto actualIPv4Range = rgw::IAM::Condition::as_network("192.168.1.0/24");
555 ASSERT_TRUE(actualIPv4Range.is_initialized());
556 EXPECT_EQ(*actualIPv4Range, allowedIPv4Range);
557 }
558
559 TEST_F(IPPolicyTest, asNetworkIPv4) {
560 auto actualIPv4 = rgw::IAM::Condition::as_network("192.168.1.1");
561 ASSERT_TRUE(actualIPv4.is_initialized());
562 EXPECT_EQ(*actualIPv4, blacklistedIPv4);
563 }
564
565 TEST_F(IPPolicyTest, asNetworkIPv6Range) {
566 auto actualIPv6Range = rgw::IAM::Condition::as_network("2001:db8:85a3:0:0:8a2e:370:7330/124");
567 ASSERT_TRUE(actualIPv6Range.is_initialized());
568 EXPECT_EQ(*actualIPv6Range, allowedIPv6Range);
569 }
570
571 TEST_F(IPPolicyTest, asNetworkIPv6) {
572 auto actualIPv6 = rgw::IAM::Condition::as_network("2001:db8:85a3:0:0:8a2e:370:7334");
573 ASSERT_TRUE(actualIPv6.is_initialized());
574 EXPECT_EQ(*actualIPv6, allowedIPv6);
575 }
576
577 TEST_F(IPPolicyTest, asNetworkInvalid) {
578 EXPECT_FALSE(rgw::IAM::Condition::as_network(""));
579 EXPECT_FALSE(rgw::IAM::Condition::as_network("192.168.1.1/33"));
580 EXPECT_FALSE(rgw::IAM::Condition::as_network("2001:db8:85a3:0:0:8a2e:370:7334/129"));
581 EXPECT_FALSE(rgw::IAM::Condition::as_network("192.168.1.1:"));
582 EXPECT_FALSE(rgw::IAM::Condition::as_network("1.2.3.10000"));
583 }
584
585 TEST_F(IPPolicyTest, IPEnvironment) {
586 // Unfortunately RGWCivetWeb is too tightly tied to civetweb to test RGWCivetWeb::init_env.
587 RGWEnv rgw_env;
588 RGWUserInfo user;
589 RGWRados rgw_rados;
590 rgw_env.set("REMOTE_ADDR", "192.168.1.1");
591 rgw_env.set("HTTP_HOST", "1.2.3.4");
592 req_state rgw_req_state(cct.get(), &rgw_env, &user);
593 Environment iam_env = rgw_build_iam_environment(&rgw_rados, &rgw_req_state);
594 auto ip = iam_env.find("aws:SourceIp");
595 ASSERT_NE(ip, iam_env.end());
596 EXPECT_EQ(ip->second, "192.168.1.1");
597
598 ASSERT_EQ(cct.get()->_conf->set_val("rgw_remote_addr_param", "SOME_VAR"), 0);
599 EXPECT_EQ(cct.get()->_conf->rgw_remote_addr_param, "SOME_VAR");
600 iam_env = rgw_build_iam_environment(&rgw_rados, &rgw_req_state);
601 ip = iam_env.find("aws:SourceIp");
602 EXPECT_EQ(ip, iam_env.end());
603
604 rgw_env.set("SOME_VAR", "192.168.1.2");
605 iam_env = rgw_build_iam_environment(&rgw_rados, &rgw_req_state);
606 ip = iam_env.find("aws:SourceIp");
607 ASSERT_NE(ip, iam_env.end());
608 EXPECT_EQ(ip->second, "192.168.1.2");
609
610 ASSERT_EQ(cct.get()->_conf->set_val("rgw_remote_addr_param", "HTTP_X_FORWARDED_FOR"), 0);
611 rgw_env.set("HTTP_X_FORWARDED_FOR", "192.168.1.3");
612 iam_env = rgw_build_iam_environment(&rgw_rados, &rgw_req_state);
613 ip = iam_env.find("aws:SourceIp");
614 ASSERT_NE(ip, iam_env.end());
615 EXPECT_EQ(ip->second, "192.168.1.3");
616
617 rgw_env.set("HTTP_X_FORWARDED_FOR", "192.168.1.4, 4.3.2.1, 2001:db8:85a3:8d3:1319:8a2e:370:7348");
618 iam_env = rgw_build_iam_environment(&rgw_rados, &rgw_req_state);
619 ip = iam_env.find("aws:SourceIp");
620 ASSERT_NE(ip, iam_env.end());
621 EXPECT_EQ(ip->second, "192.168.1.4");
622 }
623
624 TEST_F(IPPolicyTest, ParseIPAddress) {
625 optional<Policy> p;
626
627 ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant,
628 bufferlist::static_from_string(ip_address_full_example)));
629 ASSERT_TRUE(p);
630
631 EXPECT_EQ(p->text, ip_address_full_example);
632 EXPECT_EQ(p->version, Version::v2012_10_17);
633 EXPECT_EQ(*p->id, "S3IPPolicyTest");
634 EXPECT_FALSE(p->statements.empty());
635 EXPECT_EQ(p->statements.size(), 1U);
636 EXPECT_EQ(*p->statements[0].sid, "IPAllow");
637 EXPECT_FALSE(p->statements[0].princ.empty());
638 EXPECT_EQ(p->statements[0].princ.size(), 1U);
639 EXPECT_EQ(*p->statements[0].princ.begin(),
640 Principal::wildcard());
641 EXPECT_TRUE(p->statements[0].noprinc.empty());
642 EXPECT_EQ(p->statements[0].effect, Effect::Allow);
643 EXPECT_EQ(p->statements[0].action, s3ListBucket);
644 EXPECT_EQ(p->statements[0].notaction, s3None);
645 ASSERT_FALSE(p->statements[0].resource.empty());
646 ASSERT_EQ(p->statements[0].resource.size(), 2U);
647 EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws);
648 EXPECT_EQ(p->statements[0].resource.begin()->service, Service::s3);
649 EXPECT_TRUE(p->statements[0].resource.begin()->region.empty());
650 EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant);
651 EXPECT_EQ(p->statements[0].resource.begin()->resource, "example_bucket");
652 EXPECT_EQ((p->statements[0].resource.begin() + 1)->resource, "example_bucket/*");
653 EXPECT_TRUE(p->statements[0].notresource.empty());
654 ASSERT_FALSE(p->statements[0].conditions.empty());
655 ASSERT_EQ(p->statements[0].conditions.size(), 2U);
656 EXPECT_EQ(p->statements[0].conditions[0].op, TokenID::IpAddress);
657 EXPECT_EQ(p->statements[0].conditions[0].key, "aws:SourceIp");
658 ASSERT_FALSE(p->statements[0].conditions[0].vals.empty());
659 EXPECT_EQ(p->statements[0].conditions[0].vals.size(), 2U);
660 EXPECT_EQ(p->statements[0].conditions[0].vals[0], "192.168.1.0/24");
661 EXPECT_EQ(p->statements[0].conditions[0].vals[1], "::1");
662 optional<rgw::IAM::MaskedIP> convertedIPv4 = rgw::IAM::Condition::as_network(p->statements[0].conditions[0].vals[0]);
663 EXPECT_TRUE(convertedIPv4.is_initialized());
664 if (convertedIPv4.is_initialized()) {
665 EXPECT_EQ(*convertedIPv4, allowedIPv4Range);
666 }
667
668 EXPECT_EQ(p->statements[0].conditions[1].op, TokenID::NotIpAddress);
669 EXPECT_EQ(p->statements[0].conditions[1].key, "aws:SourceIp");
670 ASSERT_FALSE(p->statements[0].conditions[1].vals.empty());
671 EXPECT_EQ(p->statements[0].conditions[1].vals.size(), 2U);
672 EXPECT_EQ(p->statements[0].conditions[1].vals[0], "192.168.1.1/32");
673 EXPECT_EQ(p->statements[0].conditions[1].vals[1], "2001:0db8:85a3:0000:0000:8a2e:0370:7334");
674 optional<rgw::IAM::MaskedIP> convertedIPv6 = rgw::IAM::Condition::as_network(p->statements[0].conditions[1].vals[1]);
675 EXPECT_TRUE(convertedIPv6.is_initialized());
676 if (convertedIPv6.is_initialized()) {
677 EXPECT_EQ(*convertedIPv6, allowedIPv6);
678 }
679 }
680
681 TEST_F(IPPolicyTest, EvalIPAddress) {
682 auto allowp = Policy(cct.get(), arbitrary_tenant,
683 bufferlist::static_from_string(ip_address_allow_example));
684 auto denyp = Policy(cct.get(), arbitrary_tenant,
685 bufferlist::static_from_string(ip_address_deny_example));
686 auto fullp = Policy(cct.get(), arbitrary_tenant,
687 bufferlist::static_from_string(ip_address_full_example));
688 Environment e;
689 Environment allowedIP, blacklistedIP, allowedIPv6, blacklistedIPv6;
690 allowedIP["aws:SourceIp"] = "192.168.1.2";
691 allowedIPv6["aws:SourceIp"] = "::1";
692 blacklistedIP["aws:SourceIp"] = "192.168.1.1";
693 blacklistedIPv6["aws:SourceIp"] = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
694
695 auto trueacct = FakeIdentity(
696 Principal::tenant("ACCOUNT-ID-WITHOUT-HYPHENS"));
697 // Without an IP address in the environment then evaluation will always pass
698 EXPECT_EQ(allowp.eval(e, trueacct, s3ListBucket,
699 ARN(Partition::aws, Service::s3,
700 "", arbitrary_tenant, "example_bucket")),
701 Effect::Pass);
702 EXPECT_EQ(fullp.eval(e, trueacct, s3ListBucket,
703 ARN(Partition::aws, Service::s3,
704 "", arbitrary_tenant, "example_bucket/myobject")),
705 Effect::Pass);
706
707 EXPECT_EQ(allowp.eval(allowedIP, trueacct, s3ListBucket,
708 ARN(Partition::aws, Service::s3,
709 "", arbitrary_tenant, "example_bucket")),
710 Effect::Allow);
711 EXPECT_EQ(allowp.eval(blacklistedIPv6, trueacct, s3ListBucket,
712 ARN(Partition::aws, Service::s3,
713 "", arbitrary_tenant, "example_bucket")),
714 Effect::Pass);
715
716
717 EXPECT_EQ(denyp.eval(allowedIP, trueacct, s3ListBucket,
718 ARN(Partition::aws, Service::s3,
719 "", arbitrary_tenant, "example_bucket")),
720 Effect::Deny);
721 EXPECT_EQ(denyp.eval(allowedIP, trueacct, s3ListBucket,
722 ARN(Partition::aws, Service::s3,
723 "", arbitrary_tenant, "example_bucket/myobject")),
724 Effect::Deny);
725
726 EXPECT_EQ(denyp.eval(blacklistedIP, trueacct, s3ListBucket,
727 ARN(Partition::aws, Service::s3,
728 "", arbitrary_tenant, "example_bucket")),
729 Effect::Pass);
730 EXPECT_EQ(denyp.eval(blacklistedIP, trueacct, s3ListBucket,
731 ARN(Partition::aws, Service::s3,
732 "", arbitrary_tenant, "example_bucket/myobject")),
733 Effect::Pass);
734
735 EXPECT_EQ(denyp.eval(blacklistedIPv6, trueacct, s3ListBucket,
736 ARN(Partition::aws, Service::s3,
737 "", arbitrary_tenant, "example_bucket")),
738 Effect::Pass);
739 EXPECT_EQ(denyp.eval(blacklistedIPv6, trueacct, s3ListBucket,
740 ARN(Partition::aws, Service::s3,
741 "", arbitrary_tenant, "example_bucket/myobject")),
742 Effect::Pass);
743 EXPECT_EQ(denyp.eval(allowedIPv6, trueacct, s3ListBucket,
744 ARN(Partition::aws, Service::s3,
745 "", arbitrary_tenant, "example_bucket")),
746 Effect::Deny);
747 EXPECT_EQ(denyp.eval(allowedIPv6, trueacct, s3ListBucket,
748 ARN(Partition::aws, Service::s3,
749 "", arbitrary_tenant, "example_bucket/myobject")),
750 Effect::Deny);
751
752 EXPECT_EQ(fullp.eval(allowedIP, trueacct, s3ListBucket,
753 ARN(Partition::aws, Service::s3,
754 "", arbitrary_tenant, "example_bucket")),
755 Effect::Allow);
756 EXPECT_EQ(fullp.eval(allowedIP, trueacct, s3ListBucket,
757 ARN(Partition::aws, Service::s3,
758 "", arbitrary_tenant, "example_bucket/myobject")),
759 Effect::Allow);
760
761 EXPECT_EQ(fullp.eval(blacklistedIP, trueacct, s3ListBucket,
762 ARN(Partition::aws, Service::s3,
763 "", arbitrary_tenant, "example_bucket")),
764 Effect::Pass);
765 EXPECT_EQ(fullp.eval(blacklistedIP, trueacct, s3ListBucket,
766 ARN(Partition::aws, Service::s3,
767 "", arbitrary_tenant, "example_bucket/myobject")),
768 Effect::Pass);
769
770 EXPECT_EQ(fullp.eval(allowedIPv6, trueacct, s3ListBucket,
771 ARN(Partition::aws, Service::s3,
772 "", arbitrary_tenant, "example_bucket")),
773 Effect::Allow);
774 EXPECT_EQ(fullp.eval(allowedIPv6, trueacct, s3ListBucket,
775 ARN(Partition::aws, Service::s3,
776 "", arbitrary_tenant, "example_bucket/myobject")),
777 Effect::Allow);
778
779 EXPECT_EQ(fullp.eval(blacklistedIPv6, trueacct, s3ListBucket,
780 ARN(Partition::aws, Service::s3,
781 "", arbitrary_tenant, "example_bucket")),
782 Effect::Pass);
783 EXPECT_EQ(fullp.eval(blacklistedIPv6, trueacct, s3ListBucket,
784 ARN(Partition::aws, Service::s3,
785 "", arbitrary_tenant, "example_bucket/myobject")),
786 Effect::Pass);
787 }
788
789 string IPPolicyTest::ip_address_allow_example = R"(
790 {
791 "Version": "2012-10-17",
792 "Id": "S3SimpleIPPolicyTest",
793 "Statement": [{
794 "Sid": "1",
795 "Effect": "Allow",
796 "Principal": {"AWS": ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:root"]},
797 "Action": "s3:ListBucket",
798 "Resource": [
799 "arn:aws:s3:::example_bucket"
800 ],
801 "Condition": {
802 "IpAddress": {"aws:SourceIp": "192.168.1.0/24"}
803 }
804 }]
805 }
806 )";
807
808 string IPPolicyTest::ip_address_deny_example = R"(
809 {
810 "Version": "2012-10-17",
811 "Id": "S3IPPolicyTest",
812 "Statement": {
813 "Effect": "Deny",
814 "Sid": "IPDeny",
815 "Action": "s3:ListBucket",
816 "Principal": {"AWS": ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:root"]},
817 "Resource": [
818 "arn:aws:s3:::example_bucket",
819 "arn:aws:s3:::example_bucket/*"
820 ],
821 "Condition": {
822 "NotIpAddress": {"aws:SourceIp": ["192.168.1.1/32", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"]}
823 }
824 }
825 }
826 )";
827
828 string IPPolicyTest::ip_address_full_example = R"(
829 {
830 "Version": "2012-10-17",
831 "Id": "S3IPPolicyTest",
832 "Statement": {
833 "Effect": "Allow",
834 "Sid": "IPAllow",
835 "Action": "s3:ListBucket",
836 "Principal": "*",
837 "Resource": [
838 "arn:aws:s3:::example_bucket",
839 "arn:aws:s3:::example_bucket/*"
840 ],
841 "Condition": {
842 "IpAddress": {"aws:SourceIp": ["192.168.1.0/24", "::1"]},
843 "NotIpAddress": {"aws:SourceIp": ["192.168.1.1/32", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"]}
844 }
845 }
846 }
847 )";
848
849 TEST(MatchWildcards, Simple)
850 {
851 EXPECT_TRUE(match_wildcards("", ""));
852 EXPECT_TRUE(match_wildcards("", "", MATCH_CASE_INSENSITIVE));
853 EXPECT_FALSE(match_wildcards("", "abc"));
854 EXPECT_FALSE(match_wildcards("", "abc", MATCH_CASE_INSENSITIVE));
855 EXPECT_FALSE(match_wildcards("abc", ""));
856 EXPECT_FALSE(match_wildcards("abc", "", MATCH_CASE_INSENSITIVE));
857 EXPECT_TRUE(match_wildcards("abc", "abc"));
858 EXPECT_TRUE(match_wildcards("abc", "abc", MATCH_CASE_INSENSITIVE));
859 EXPECT_FALSE(match_wildcards("abc", "abC"));
860 EXPECT_TRUE(match_wildcards("abc", "abC", MATCH_CASE_INSENSITIVE));
861 EXPECT_FALSE(match_wildcards("abC", "abc"));
862 EXPECT_TRUE(match_wildcards("abC", "abc", MATCH_CASE_INSENSITIVE));
863 EXPECT_FALSE(match_wildcards("abc", "abcd"));
864 EXPECT_FALSE(match_wildcards("abc", "abcd", MATCH_CASE_INSENSITIVE));
865 EXPECT_FALSE(match_wildcards("abcd", "abc"));
866 EXPECT_FALSE(match_wildcards("abcd", "abc", MATCH_CASE_INSENSITIVE));
867 }
868
869 TEST(MatchWildcards, QuestionMark)
870 {
871 EXPECT_FALSE(match_wildcards("?", ""));
872 EXPECT_FALSE(match_wildcards("?", "", MATCH_CASE_INSENSITIVE));
873 EXPECT_TRUE(match_wildcards("?", "a"));
874 EXPECT_TRUE(match_wildcards("?", "a", MATCH_CASE_INSENSITIVE));
875 EXPECT_TRUE(match_wildcards("?bc", "abc"));
876 EXPECT_TRUE(match_wildcards("?bc", "abc", MATCH_CASE_INSENSITIVE));
877 EXPECT_TRUE(match_wildcards("a?c", "abc"));
878 EXPECT_TRUE(match_wildcards("a?c", "abc", MATCH_CASE_INSENSITIVE));
879 EXPECT_FALSE(match_wildcards("abc", "a?c"));
880 EXPECT_FALSE(match_wildcards("abc", "a?c", MATCH_CASE_INSENSITIVE));
881 EXPECT_FALSE(match_wildcards("a?c", "abC"));
882 EXPECT_TRUE(match_wildcards("a?c", "abC", MATCH_CASE_INSENSITIVE));
883 EXPECT_TRUE(match_wildcards("ab?", "abc"));
884 EXPECT_TRUE(match_wildcards("ab?", "abc", MATCH_CASE_INSENSITIVE));
885 EXPECT_TRUE(match_wildcards("a?c?e", "abcde"));
886 EXPECT_TRUE(match_wildcards("a?c?e", "abcde", MATCH_CASE_INSENSITIVE));
887 EXPECT_TRUE(match_wildcards("???", "abc"));
888 EXPECT_TRUE(match_wildcards("???", "abc", MATCH_CASE_INSENSITIVE));
889 EXPECT_FALSE(match_wildcards("???", "abcd"));
890 EXPECT_FALSE(match_wildcards("???", "abcd", MATCH_CASE_INSENSITIVE));
891 }
892
893 TEST(MatchWildcards, Asterisk)
894 {
895 EXPECT_TRUE(match_wildcards("*", ""));
896 EXPECT_TRUE(match_wildcards("*", "", MATCH_CASE_INSENSITIVE));
897 EXPECT_FALSE(match_wildcards("", "*"));
898 EXPECT_FALSE(match_wildcards("", "*", MATCH_CASE_INSENSITIVE));
899 EXPECT_FALSE(match_wildcards("*a", ""));
900 EXPECT_FALSE(match_wildcards("*a", "", MATCH_CASE_INSENSITIVE));
901 EXPECT_TRUE(match_wildcards("*a", "a"));
902 EXPECT_TRUE(match_wildcards("*a", "a", MATCH_CASE_INSENSITIVE));
903 EXPECT_TRUE(match_wildcards("a*", "a"));
904 EXPECT_TRUE(match_wildcards("a*", "a", MATCH_CASE_INSENSITIVE));
905 EXPECT_TRUE(match_wildcards("a*c", "ac"));
906 EXPECT_TRUE(match_wildcards("a*c", "ac", MATCH_CASE_INSENSITIVE));
907 EXPECT_TRUE(match_wildcards("a*c", "abbc"));
908 EXPECT_TRUE(match_wildcards("a*c", "abbc", MATCH_CASE_INSENSITIVE));
909 EXPECT_FALSE(match_wildcards("a*c", "abbC"));
910 EXPECT_TRUE(match_wildcards("a*c", "abbC", MATCH_CASE_INSENSITIVE));
911 EXPECT_TRUE(match_wildcards("a*c*e", "abBce"));
912 EXPECT_TRUE(match_wildcards("a*c*e", "abBce", MATCH_CASE_INSENSITIVE));
913 EXPECT_TRUE(match_wildcards("http://*.example.com",
914 "http://www.example.com"));
915 EXPECT_TRUE(match_wildcards("http://*.example.com",
916 "http://www.example.com", MATCH_CASE_INSENSITIVE));
917 EXPECT_FALSE(match_wildcards("http://*.example.com",
918 "http://www.Example.com"));
919 EXPECT_TRUE(match_wildcards("http://*.example.com",
920 "http://www.Example.com", MATCH_CASE_INSENSITIVE));
921 EXPECT_TRUE(match_wildcards("http://example.com/*",
922 "http://example.com/index.html"));
923 EXPECT_TRUE(match_wildcards("http://example.com/*/*.jpg",
924 "http://example.com/fun/smiley.jpg"));
925 // note: parsing of * is not greedy, so * does not match 'bc' here
926 EXPECT_FALSE(match_wildcards("a*c", "abcc"));
927 EXPECT_FALSE(match_wildcards("a*c", "abcc", MATCH_CASE_INSENSITIVE));
928 }
929
930 TEST(MatchPolicy, Action)
931 {
932 constexpr auto flag = MATCH_POLICY_ACTION;
933 EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag));
934 EXPECT_TRUE(match_policy("a:b:c", "A:B:C", flag)); // case insensitive
935 EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag));
936 EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments
937 }
938
939 TEST(MatchPolicy, Resource)
940 {
941 constexpr auto flag = MATCH_POLICY_RESOURCE;
942 EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag));
943 EXPECT_FALSE(match_policy("a:b:c", "A:B:C", flag)); // case sensitive
944 EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag));
945 EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments
946 }
947
948 TEST(MatchPolicy, ARN)
949 {
950 constexpr auto flag = MATCH_POLICY_ARN;
951 EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag));
952 EXPECT_TRUE(match_policy("a:b:c", "A:B:C", flag)); // case insensitive
953 EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag));
954 EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments
955 }
956
957 TEST(MatchPolicy, String)
958 {
959 constexpr auto flag = MATCH_POLICY_STRING;
960 EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag));
961 EXPECT_FALSE(match_policy("a:b:c", "A:B:C", flag)); // case sensitive
962 EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag));
963 EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments
964 }