]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/rgw/test_rgw_iam_policy.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / test / rgw / test_rgw_iam_policy.cc
CommitLineData
31f18b77
FG
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
b32b8144 22#include "include/stringify.h"
31f18b77
FG
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"
b32b8144 28#include "rgw/rgw_op.h"
f67539c2 29#include "rgw_sal_rados.h"
31f18b77
FG
30
31
32using std::string;
33using std::vector;
34
35using boost::container::flat_set;
36using boost::intrusive_ptr;
37using boost::make_optional;
38using boost::none;
31f18b77
FG
39
40using rgw::auth::Identity;
41using rgw::auth::Principal;
42
eafe8130 43using rgw::ARN;
31f18b77
FG
44using rgw::IAM::Effect;
45using rgw::IAM::Environment;
eafe8130 46using rgw::Partition;
31f18b77
FG
47using rgw::IAM::Policy;
48using rgw::IAM::s3All;
49using rgw::IAM::s3Count;
50using rgw::IAM::s3GetAccelerateConfiguration;
51using rgw::IAM::s3GetBucketAcl;
52using rgw::IAM::s3GetBucketCORS;
53using rgw::IAM::s3GetBucketLocation;
54using rgw::IAM::s3GetBucketLogging;
55using rgw::IAM::s3GetBucketNotification;
56using rgw::IAM::s3GetBucketPolicy;
9f95a23c
TL
57using rgw::IAM::s3GetBucketPolicyStatus;
58using rgw::IAM::s3GetBucketPublicAccessBlock;
20effc67 59using rgw::IAM::s3GetBucketEncryption;
31f18b77
FG
60using rgw::IAM::s3GetBucketRequestPayment;
61using rgw::IAM::s3GetBucketTagging;
62using rgw::IAM::s3GetBucketVersioning;
63using rgw::IAM::s3GetBucketWebsite;
64using rgw::IAM::s3GetLifecycleConfiguration;
65using rgw::IAM::s3GetObject;
66using rgw::IAM::s3GetObjectAcl;
67using rgw::IAM::s3GetObjectVersionAcl;
68using rgw::IAM::s3GetObjectTorrent;
d2e6a577 69using rgw::IAM::s3GetObjectTagging;
31f18b77 70using rgw::IAM::s3GetObjectVersion;
d2e6a577 71using rgw::IAM::s3GetObjectVersionTagging;
31f18b77 72using rgw::IAM::s3GetObjectVersionTorrent;
9f95a23c 73using rgw::IAM::s3GetPublicAccessBlock;
31f18b77
FG
74using rgw::IAM::s3GetReplicationConfiguration;
75using rgw::IAM::s3ListAllMyBuckets;
76using rgw::IAM::s3ListBucket;
77using rgw::IAM::s3ListBucket;
28e407b8 78using rgw::IAM::s3ListBucketMultipartUploads;
31f18b77
FG
79using rgw::IAM::s3ListBucketVersions;
80using rgw::IAM::s3ListMultipartUploadParts;
11fdf7f2 81using rgw::IAM::None;
31f18b77
FG
82using rgw::IAM::s3PutBucketAcl;
83using rgw::IAM::s3PutBucketPolicy;
eafe8130
TL
84using rgw::IAM::s3GetBucketObjectLockConfiguration;
85using rgw::IAM::s3GetObjectRetention;
86using rgw::IAM::s3GetObjectLegalHold;
9f95a23c 87using rgw::Service;
31f18b77
FG
88using rgw::IAM::TokenID;
89using rgw::IAM::Version;
11fdf7f2
TL
90using rgw::IAM::Action_t;
91using rgw::IAM::NotAction_t;
92using rgw::IAM::iamCreateRole;
93using rgw::IAM::iamDeleteRole;
94using rgw::IAM::iamAll;
95using rgw::IAM::stsAll;
9f95a23c 96using rgw::IAM::allCount;
31f18b77
FG
97
98class FakeIdentity : public Identity {
99 const Principal id;
100public:
101
11fdf7f2
TL
102 explicit FakeIdentity(Principal&& id) : id(std::move(id)) {}
103 uint32_t get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const override {
104 ceph_abort();
31f18b77
FG
105 return 0;
106 };
107
108 bool is_admin_of(const rgw_user& uid) const override {
11fdf7f2 109 ceph_abort();
31f18b77
FG
110 return false;
111 }
112
113 bool is_owner_of(const rgw_user& uid) const override {
11fdf7f2 114 ceph_abort();
31f18b77
FG
115 return false;
116 }
117
118 virtual uint32_t get_perm_mask() const override {
11fdf7f2
TL
119 ceph_abort();
120 return 0;
121 }
122
11fdf7f2 123 string get_acct_name() const override {
31f18b77
FG
124 abort();
125 return 0;
126 }
127
f6b5b4d7
TL
128 string get_subuser() const override {
129 abort();
130 return 0;
131 }
132
31f18b77 133 void to_str(std::ostream& out) const override {
b32b8144 134 out << id;
31f18b77
FG
135 }
136
137 bool is_identity(const flat_set<Principal>& ids) const override {
b32b8144
FG
138 if (id.is_wildcard() && (!ids.empty())) {
139 return true;
140 }
141 return ids.find(id) != ids.end() || ids.find(Principal::wildcard()) != ids.end();
31f18b77 142 }
522d829b
TL
143
144 uint32_t get_identity_type() const override {
145 return TYPE_RGW;
146 }
31f18b77
FG
147};
148
149class PolicyTest : public ::testing::Test {
150protected:
151 intrusive_ptr<CephContext> cct;
152 static const string arbitrary_tenant;
153 static string example1;
154 static string example2;
155 static string example3;
11fdf7f2
TL
156 static string example4;
157 static string example5;
158 static string example6;
9f95a23c 159 static string example7;
31f18b77
FG
160public:
161 PolicyTest() {
162 cct = new CephContext(CEPH_ENTITY_TYPE_CLIENT);
163 }
164};
165
166TEST_F(PolicyTest, Parse1) {
11fdf7f2 167 boost::optional<Policy> p;
31f18b77
FG
168
169 ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant,
170 bufferlist::static_from_string(example1)));
171 ASSERT_TRUE(p);
172
173 EXPECT_EQ(p->text, example1);
174 EXPECT_EQ(p->version, Version::v2012_10_17);
175 EXPECT_FALSE(p->id);
176 EXPECT_FALSE(p->statements[0].sid);
177 EXPECT_FALSE(p->statements.empty());
178 EXPECT_EQ(p->statements.size(), 1U);
179 EXPECT_TRUE(p->statements[0].princ.empty());
180 EXPECT_TRUE(p->statements[0].noprinc.empty());
181 EXPECT_EQ(p->statements[0].effect, Effect::Allow);
11fdf7f2
TL
182 Action_t act;
183 act[s3ListBucket] = 1;
184 EXPECT_EQ(p->statements[0].action, act);
185 EXPECT_EQ(p->statements[0].notaction, None);
31f18b77
FG
186 ASSERT_FALSE(p->statements[0].resource.empty());
187 ASSERT_EQ(p->statements[0].resource.size(), 1U);
188 EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws);
189 EXPECT_EQ(p->statements[0].resource.begin()->service, Service::s3);
190 EXPECT_TRUE(p->statements[0].resource.begin()->region.empty());
191 EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant);
192 EXPECT_EQ(p->statements[0].resource.begin()->resource, "example_bucket");
193 EXPECT_TRUE(p->statements[0].notresource.empty());
194 EXPECT_TRUE(p->statements[0].conditions.empty());
195}
196
197TEST_F(PolicyTest, Eval1) {
198 auto p = Policy(cct.get(), arbitrary_tenant,
199 bufferlist::static_from_string(example1));
200 Environment e;
201
20effc67
TL
202 ARN arn1(Partition::aws, Service::s3,
203 "", arbitrary_tenant, "example_bucket");
204 EXPECT_EQ(p.eval(e, none, s3ListBucket, arn1),
31f18b77
FG
205 Effect::Allow);
206
20effc67
TL
207 ARN arn2(Partition::aws, Service::s3,
208 "", arbitrary_tenant, "example_bucket");
209 EXPECT_EQ(p.eval(e, none, s3PutBucketAcl, arn2),
31f18b77
FG
210 Effect::Pass);
211
20effc67
TL
212 ARN arn3(Partition::aws, Service::s3,
213 "", arbitrary_tenant, "erroneous_bucket");
214 EXPECT_EQ(p.eval(e, none, s3ListBucket, arn3),
31f18b77
FG
215 Effect::Pass);
216
217}
218
219TEST_F(PolicyTest, Parse2) {
11fdf7f2 220 boost::optional<Policy> p;
31f18b77
FG
221
222 ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant,
223 bufferlist::static_from_string(example2)));
224 ASSERT_TRUE(p);
225
226 EXPECT_EQ(p->text, example2);
227 EXPECT_EQ(p->version, Version::v2012_10_17);
228 EXPECT_EQ(*p->id, "S3-Account-Permissions");
229 ASSERT_FALSE(p->statements.empty());
230 EXPECT_EQ(p->statements.size(), 1U);
231 EXPECT_EQ(*p->statements[0].sid, "1");
232 EXPECT_FALSE(p->statements[0].princ.empty());
233 EXPECT_EQ(p->statements[0].princ.size(), 1U);
234 EXPECT_EQ(*p->statements[0].princ.begin(),
235 Principal::tenant("ACCOUNT-ID-WITHOUT-HYPHENS"));
236 EXPECT_TRUE(p->statements[0].noprinc.empty());
237 EXPECT_EQ(p->statements[0].effect, Effect::Allow);
11fdf7f2
TL
238 Action_t act;
239 for (auto i = 0ULL; i < s3Count; i++)
240 act[i] = 1;
241 act[s3All] = 1;
242 EXPECT_EQ(p->statements[0].action, act);
243 EXPECT_EQ(p->statements[0].notaction, None);
31f18b77
FG
244 ASSERT_FALSE(p->statements[0].resource.empty());
245 ASSERT_EQ(p->statements[0].resource.size(), 2U);
246 EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws);
247 EXPECT_EQ(p->statements[0].resource.begin()->service, Service::s3);
248 EXPECT_TRUE(p->statements[0].resource.begin()->region.empty());
249 EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant);
250 EXPECT_EQ(p->statements[0].resource.begin()->resource, "mybucket");
251 EXPECT_EQ((p->statements[0].resource.begin() + 1)->partition,
252 Partition::aws);
253 EXPECT_EQ((p->statements[0].resource.begin() + 1)->service,
254 Service::s3);
255 EXPECT_TRUE((p->statements[0].resource.begin() + 1)->region.empty());
256 EXPECT_EQ((p->statements[0].resource.begin() + 1)->account,
257 arbitrary_tenant);
258 EXPECT_EQ((p->statements[0].resource.begin() + 1)->resource, "mybucket/*");
259 EXPECT_TRUE(p->statements[0].notresource.empty());
260 EXPECT_TRUE(p->statements[0].conditions.empty());
261}
262
263TEST_F(PolicyTest, Eval2) {
264 auto p = Policy(cct.get(), arbitrary_tenant,
265 bufferlist::static_from_string(example2));
266 Environment e;
267
268 auto trueacct = FakeIdentity(
269 Principal::tenant("ACCOUNT-ID-WITHOUT-HYPHENS"));
270
271 auto notacct = FakeIdentity(
272 Principal::tenant("some-other-account"));
273 for (auto i = 0ULL; i < s3Count; ++i) {
20effc67
TL
274 ARN arn1(Partition::aws, Service::s3,
275 "", arbitrary_tenant, "mybucket");
276 EXPECT_EQ(p.eval(e, trueacct, i, arn1),
31f18b77 277 Effect::Allow);
20effc67
TL
278 ARN arn2(Partition::aws, Service::s3,
279 "", arbitrary_tenant, "mybucket/myobject");
280 EXPECT_EQ(p.eval(e, trueacct, i, arn2),
31f18b77 281 Effect::Allow);
20effc67
TL
282 ARN arn3(Partition::aws, Service::s3,
283 "", arbitrary_tenant, "mybucket");
284 EXPECT_EQ(p.eval(e, notacct, i, arn3),
31f18b77 285 Effect::Pass);
20effc67
TL
286 ARN arn4(Partition::aws, Service::s3,
287 "", arbitrary_tenant, "mybucket/myobject");
288 EXPECT_EQ(p.eval(e, notacct, i, arn4),
31f18b77 289 Effect::Pass);
20effc67
TL
290 ARN arn5(Partition::aws, Service::s3,
291 "", arbitrary_tenant, "notyourbucket");
292 EXPECT_EQ(p.eval(e, trueacct, i, arn5),
31f18b77 293 Effect::Pass);
20effc67
TL
294 ARN arn6(Partition::aws, Service::s3,
295 "", arbitrary_tenant, "notyourbucket/notyourobject");
296 EXPECT_EQ(p.eval(e, trueacct, i, arn6),
31f18b77
FG
297 Effect::Pass);
298
299 }
300}
301
302TEST_F(PolicyTest, Parse3) {
11fdf7f2 303 boost::optional<Policy> p;
31f18b77
FG
304
305 ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant,
306 bufferlist::static_from_string(example3)));
307 ASSERT_TRUE(p);
308
309 EXPECT_EQ(p->text, example3);
310 EXPECT_EQ(p->version, Version::v2012_10_17);
311 EXPECT_FALSE(p->id);
312 ASSERT_FALSE(p->statements.empty());
313 EXPECT_EQ(p->statements.size(), 3U);
314
315 EXPECT_EQ(*p->statements[0].sid, "FirstStatement");
316 EXPECT_TRUE(p->statements[0].princ.empty());
317 EXPECT_TRUE(p->statements[0].noprinc.empty());
318 EXPECT_EQ(p->statements[0].effect, Effect::Allow);
11fdf7f2
TL
319 Action_t act;
320 act[s3PutBucketPolicy] = 1;
321 EXPECT_EQ(p->statements[0].action, act);
322 EXPECT_EQ(p->statements[0].notaction, None);
31f18b77
FG
323 ASSERT_FALSE(p->statements[0].resource.empty());
324 ASSERT_EQ(p->statements[0].resource.size(), 1U);
325 EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::wildcard);
326 EXPECT_EQ(p->statements[0].resource.begin()->service, Service::wildcard);
327 EXPECT_EQ(p->statements[0].resource.begin()->region, "*");
328 EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant);
329 EXPECT_EQ(p->statements[0].resource.begin()->resource, "*");
330 EXPECT_TRUE(p->statements[0].notresource.empty());
331 EXPECT_TRUE(p->statements[0].conditions.empty());
332
333 EXPECT_EQ(*p->statements[1].sid, "SecondStatement");
334 EXPECT_TRUE(p->statements[1].princ.empty());
335 EXPECT_TRUE(p->statements[1].noprinc.empty());
336 EXPECT_EQ(p->statements[1].effect, Effect::Allow);
11fdf7f2
TL
337 Action_t act1;
338 act1[s3ListAllMyBuckets] = 1;
339 EXPECT_EQ(p->statements[1].action, act1);
340 EXPECT_EQ(p->statements[1].notaction, None);
31f18b77
FG
341 ASSERT_FALSE(p->statements[1].resource.empty());
342 ASSERT_EQ(p->statements[1].resource.size(), 1U);
343 EXPECT_EQ(p->statements[1].resource.begin()->partition, Partition::wildcard);
344 EXPECT_EQ(p->statements[1].resource.begin()->service, Service::wildcard);
345 EXPECT_EQ(p->statements[1].resource.begin()->region, "*");
346 EXPECT_EQ(p->statements[1].resource.begin()->account, arbitrary_tenant);
347 EXPECT_EQ(p->statements[1].resource.begin()->resource, "*");
348 EXPECT_TRUE(p->statements[1].notresource.empty());
349 EXPECT_TRUE(p->statements[1].conditions.empty());
350
351 EXPECT_EQ(*p->statements[2].sid, "ThirdStatement");
352 EXPECT_TRUE(p->statements[2].princ.empty());
353 EXPECT_TRUE(p->statements[2].noprinc.empty());
354 EXPECT_EQ(p->statements[2].effect, Effect::Allow);
11fdf7f2
TL
355 Action_t act2;
356 act2[s3ListMultipartUploadParts] = 1;
357 act2[s3ListBucket] = 1;
358 act2[s3ListBucketVersions] = 1;
359 act2[s3ListAllMyBuckets] = 1;
360 act2[s3ListBucketMultipartUploads] = 1;
361 act2[s3GetObject] = 1;
362 act2[s3GetObjectVersion] = 1;
363 act2[s3GetObjectAcl] = 1;
364 act2[s3GetObjectVersionAcl] = 1;
365 act2[s3GetObjectTorrent] = 1;
366 act2[s3GetObjectVersionTorrent] = 1;
367 act2[s3GetAccelerateConfiguration] = 1;
368 act2[s3GetBucketAcl] = 1;
369 act2[s3GetBucketCORS] = 1;
370 act2[s3GetBucketVersioning] = 1;
371 act2[s3GetBucketRequestPayment] = 1;
372 act2[s3GetBucketLocation] = 1;
373 act2[s3GetBucketPolicy] = 1;
374 act2[s3GetBucketNotification] = 1;
375 act2[s3GetBucketLogging] = 1;
376 act2[s3GetBucketTagging] = 1;
377 act2[s3GetBucketWebsite] = 1;
378 act2[s3GetLifecycleConfiguration] = 1;
379 act2[s3GetReplicationConfiguration] = 1;
380 act2[s3GetObjectTagging] = 1;
381 act2[s3GetObjectVersionTagging] = 1;
eafe8130
TL
382 act2[s3GetBucketObjectLockConfiguration] = 1;
383 act2[s3GetObjectRetention] = 1;
384 act2[s3GetObjectLegalHold] = 1;
9f95a23c
TL
385 act2[s3GetBucketPolicyStatus] = 1;
386 act2[s3GetBucketPublicAccessBlock] = 1;
387 act2[s3GetPublicAccessBlock] = 1;
20effc67 388 act2[s3GetBucketEncryption] = 1;
11fdf7f2
TL
389
390 EXPECT_EQ(p->statements[2].action, act2);
391 EXPECT_EQ(p->statements[2].notaction, None);
31f18b77
FG
392 ASSERT_FALSE(p->statements[2].resource.empty());
393 ASSERT_EQ(p->statements[2].resource.size(), 2U);
394 EXPECT_EQ(p->statements[2].resource.begin()->partition, Partition::aws);
395 EXPECT_EQ(p->statements[2].resource.begin()->service, Service::s3);
396 EXPECT_TRUE(p->statements[2].resource.begin()->region.empty());
397 EXPECT_EQ(p->statements[2].resource.begin()->account, arbitrary_tenant);
398 EXPECT_EQ(p->statements[2].resource.begin()->resource, "confidential-data");
399 EXPECT_EQ((p->statements[2].resource.begin() + 1)->partition,
400 Partition::aws);
401 EXPECT_EQ((p->statements[2].resource.begin() + 1)->service, Service::s3);
402 EXPECT_TRUE((p->statements[2].resource.begin() + 1)->region.empty());
403 EXPECT_EQ((p->statements[2].resource.begin() + 1)->account,
404 arbitrary_tenant);
405 EXPECT_EQ((p->statements[2].resource.begin() + 1)->resource,
406 "confidential-data/*");
407 EXPECT_TRUE(p->statements[2].notresource.empty());
408 ASSERT_FALSE(p->statements[2].conditions.empty());
409 ASSERT_EQ(p->statements[2].conditions.size(), 1U);
410 EXPECT_EQ(p->statements[2].conditions[0].op, TokenID::Bool);
411 EXPECT_EQ(p->statements[2].conditions[0].key, "aws:MultiFactorAuthPresent");
412 EXPECT_FALSE(p->statements[2].conditions[0].ifexists);
413 ASSERT_FALSE(p->statements[2].conditions[0].vals.empty());
414 EXPECT_EQ(p->statements[2].conditions[0].vals.size(), 1U);
415 EXPECT_EQ(p->statements[2].conditions[0].vals[0], "true");
416}
417
418TEST_F(PolicyTest, Eval3) {
419 auto p = Policy(cct.get(), arbitrary_tenant,
420 bufferlist::static_from_string(example3));
421 Environment em;
422 Environment tr = { { "aws:MultiFactorAuthPresent", "true" } };
423 Environment fa = { { "aws:MultiFactorAuthPresent", "false" } };
424
11fdf7f2
TL
425 Action_t s3allow;
426 s3allow[s3ListMultipartUploadParts] = 1;
427 s3allow[s3ListBucket] = 1;
428 s3allow[s3ListBucketVersions] = 1;
429 s3allow[s3ListAllMyBuckets] = 1;
430 s3allow[s3ListBucketMultipartUploads] = 1;
431 s3allow[s3GetObject] = 1;
432 s3allow[s3GetObjectVersion] = 1;
433 s3allow[s3GetObjectAcl] = 1;
434 s3allow[s3GetObjectVersionAcl] = 1;
435 s3allow[s3GetObjectTorrent] = 1;
436 s3allow[s3GetObjectVersionTorrent] = 1;
437 s3allow[s3GetAccelerateConfiguration] = 1;
438 s3allow[s3GetBucketAcl] = 1;
439 s3allow[s3GetBucketCORS] = 1;
440 s3allow[s3GetBucketVersioning] = 1;
441 s3allow[s3GetBucketRequestPayment] = 1;
442 s3allow[s3GetBucketLocation] = 1;
443 s3allow[s3GetBucketPolicy] = 1;
444 s3allow[s3GetBucketNotification] = 1;
445 s3allow[s3GetBucketLogging] = 1;
446 s3allow[s3GetBucketTagging] = 1;
447 s3allow[s3GetBucketWebsite] = 1;
448 s3allow[s3GetLifecycleConfiguration] = 1;
449 s3allow[s3GetReplicationConfiguration] = 1;
450 s3allow[s3GetObjectTagging] = 1;
451 s3allow[s3GetObjectVersionTagging] = 1;
eafe8130
TL
452 s3allow[s3GetBucketObjectLockConfiguration] = 1;
453 s3allow[s3GetObjectRetention] = 1;
454 s3allow[s3GetObjectLegalHold] = 1;
9f95a23c
TL
455 s3allow[s3GetBucketPolicyStatus] = 1;
456 s3allow[s3GetBucketPublicAccessBlock] = 1;
457 s3allow[s3GetPublicAccessBlock] = 1;
20effc67 458 s3allow[s3GetBucketEncryption] = 1;
31f18b77 459
20effc67
TL
460 ARN arn1(Partition::aws, Service::s3,
461 "", arbitrary_tenant, "mybucket");
462 EXPECT_EQ(p.eval(em, none, s3PutBucketPolicy, arn1),
31f18b77
FG
463 Effect::Allow);
464
20effc67
TL
465 ARN arn2(Partition::aws, Service::s3,
466 "", arbitrary_tenant, "mybucket");
467 EXPECT_EQ(p.eval(em, none, s3PutBucketPolicy, arn2),
31f18b77
FG
468 Effect::Allow);
469
470
11fdf7f2 471 for (auto op = 0ULL; op < s3Count; ++op) {
31f18b77
FG
472 if ((op == s3ListAllMyBuckets) || (op == s3PutBucketPolicy)) {
473 continue;
474 }
20effc67
TL
475 ARN arn3(Partition::aws, Service::s3,
476 "", arbitrary_tenant, "confidential-data");
477 EXPECT_EQ(p.eval(em, none, op, arn3),
31f18b77 478 Effect::Pass);
20effc67
TL
479 ARN arn4(Partition::aws, Service::s3,
480 "", arbitrary_tenant, "confidential-data");
481 EXPECT_EQ(p.eval(tr, none, op, arn4),
11fdf7f2 482 s3allow[op] ? Effect::Allow : Effect::Pass);
20effc67
TL
483 ARN arn5(Partition::aws, Service::s3,
484 "", arbitrary_tenant, "confidential-data");
485 EXPECT_EQ(p.eval(fa, none, op, arn5),
31f18b77 486 Effect::Pass);
20effc67
TL
487 ARN arn6(Partition::aws, Service::s3,
488 "", arbitrary_tenant, "confidential-data/moo");
489 EXPECT_EQ(p.eval(em, none, op, arn6),
31f18b77 490 Effect::Pass);
20effc67
TL
491 ARN arn7(Partition::aws, Service::s3,
492 "", arbitrary_tenant, "confidential-data/moo");
493 EXPECT_EQ(p.eval(tr, none, op, arn7),
11fdf7f2 494 s3allow[op] ? Effect::Allow : Effect::Pass);
20effc67
TL
495 ARN arn8(Partition::aws, Service::s3,
496 "", arbitrary_tenant, "confidential-data/moo");
497 EXPECT_EQ(p.eval(fa, none, op, arn8),
31f18b77 498 Effect::Pass);
20effc67
TL
499 ARN arn9(Partition::aws, Service::s3,
500 "", arbitrary_tenant, "really-confidential-data");
501 EXPECT_EQ(p.eval(em, none, op, arn9),
31f18b77 502 Effect::Pass);
20effc67
TL
503 ARN arn10(Partition::aws, Service::s3,
504 "", arbitrary_tenant, "really-confidential-data");
505 EXPECT_EQ(p.eval(tr, none, op, arn10),
31f18b77 506 Effect::Pass);
20effc67
TL
507 ARN arn11(Partition::aws, Service::s3,
508 "", arbitrary_tenant, "really-confidential-data");
509 EXPECT_EQ(p.eval(fa, none, op, arn11),
31f18b77 510 Effect::Pass);
20effc67 511 ARN arn12(Partition::aws, Service::s3,
31f18b77 512 "", arbitrary_tenant,
20effc67
TL
513 "really-confidential-data/moo");
514 EXPECT_EQ(p.eval(em, none, op, arn12), Effect::Pass);
515 ARN arn13(Partition::aws, Service::s3,
31f18b77 516 "", arbitrary_tenant,
20effc67
TL
517 "really-confidential-data/moo");
518 EXPECT_EQ(p.eval(tr, none, op, arn13), Effect::Pass);
519 ARN arn14(Partition::aws, Service::s3,
31f18b77 520 "", arbitrary_tenant,
20effc67
TL
521 "really-confidential-data/moo");
522 EXPECT_EQ(p.eval(fa, none, op, arn14), Effect::Pass);
31f18b77
FG
523
524 }
525}
526
11fdf7f2
TL
527TEST_F(PolicyTest, Parse4) {
528 boost::optional<Policy> p;
529
530 ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant,
531 bufferlist::static_from_string(example4)));
532 ASSERT_TRUE(p);
533
534 EXPECT_EQ(p->text, example4);
535 EXPECT_EQ(p->version, Version::v2012_10_17);
536 EXPECT_FALSE(p->id);
537 EXPECT_FALSE(p->statements[0].sid);
538 EXPECT_FALSE(p->statements.empty());
539 EXPECT_EQ(p->statements.size(), 1U);
540 EXPECT_TRUE(p->statements[0].princ.empty());
541 EXPECT_TRUE(p->statements[0].noprinc.empty());
542 EXPECT_EQ(p->statements[0].effect, Effect::Allow);
543 Action_t act;
544 act[iamCreateRole] = 1;
545 EXPECT_EQ(p->statements[0].action, act);
546 EXPECT_EQ(p->statements[0].notaction, None);
547 ASSERT_FALSE(p->statements[0].resource.empty());
548 ASSERT_EQ(p->statements[0].resource.size(), 1U);
549 EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::wildcard);
550 EXPECT_EQ(p->statements[0].resource.begin()->service, Service::wildcard);
551 EXPECT_EQ(p->statements[0].resource.begin()->region, "*");
552 EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant);
553 EXPECT_EQ(p->statements[0].resource.begin()->resource, "*");
554 EXPECT_TRUE(p->statements[0].notresource.empty());
555 EXPECT_TRUE(p->statements[0].conditions.empty());
556}
557
558TEST_F(PolicyTest, Eval4) {
559 auto p = Policy(cct.get(), arbitrary_tenant,
560 bufferlist::static_from_string(example4));
561 Environment e;
562
20effc67
TL
563 ARN arn1(Partition::aws, Service::iam,
564 "", arbitrary_tenant, "role/example_role");
565 EXPECT_EQ(p.eval(e, none, iamCreateRole, arn1),
11fdf7f2
TL
566 Effect::Allow);
567
20effc67
TL
568 ARN arn2(Partition::aws, Service::iam,
569 "", arbitrary_tenant, "role/example_role");
570 EXPECT_EQ(p.eval(e, none, iamDeleteRole, arn2),
11fdf7f2
TL
571 Effect::Pass);
572}
573
574TEST_F(PolicyTest, Parse5) {
575 boost::optional<Policy> p;
576
577 ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant,
578 bufferlist::static_from_string(example5)));
579 ASSERT_TRUE(p);
580 EXPECT_EQ(p->text, example5);
581 EXPECT_EQ(p->version, Version::v2012_10_17);
582 EXPECT_FALSE(p->id);
583 EXPECT_FALSE(p->statements[0].sid);
584 EXPECT_FALSE(p->statements.empty());
585 EXPECT_EQ(p->statements.size(), 1U);
586 EXPECT_TRUE(p->statements[0].princ.empty());
587 EXPECT_TRUE(p->statements[0].noprinc.empty());
588 EXPECT_EQ(p->statements[0].effect, Effect::Allow);
589 Action_t act;
590 for (auto i = s3All+1; i <= iamAll; i++)
591 act[i] = 1;
592 EXPECT_EQ(p->statements[0].action, act);
593 EXPECT_EQ(p->statements[0].notaction, None);
594 ASSERT_FALSE(p->statements[0].resource.empty());
595 ASSERT_EQ(p->statements[0].resource.size(), 1U);
596 EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws);
597 EXPECT_EQ(p->statements[0].resource.begin()->service, Service::iam);
598 EXPECT_EQ(p->statements[0].resource.begin()->region, "");
599 EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant);
600 EXPECT_EQ(p->statements[0].resource.begin()->resource, "role/example_role");
601 EXPECT_TRUE(p->statements[0].notresource.empty());
602 EXPECT_TRUE(p->statements[0].conditions.empty());
603}
604
605TEST_F(PolicyTest, Eval5) {
606 auto p = Policy(cct.get(), arbitrary_tenant,
607 bufferlist::static_from_string(example5));
608 Environment e;
609
20effc67
TL
610 ARN arn1(Partition::aws, Service::iam,
611 "", arbitrary_tenant, "role/example_role");
612 EXPECT_EQ(p.eval(e, none, iamCreateRole, arn1),
11fdf7f2
TL
613 Effect::Allow);
614
20effc67
TL
615 ARN arn2(Partition::aws, Service::iam,
616 "", arbitrary_tenant, "role/example_role");
617 EXPECT_EQ(p.eval(e, none, s3ListBucket, arn2),
11fdf7f2
TL
618 Effect::Pass);
619
20effc67
TL
620 ARN arn3(Partition::aws, Service::iam,
621 "", "", "role/example_role");
622 EXPECT_EQ(p.eval(e, none, iamCreateRole, arn3),
11fdf7f2
TL
623 Effect::Pass);
624}
625
626TEST_F(PolicyTest, Parse6) {
627 boost::optional<Policy> p;
628
629 ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant,
630 bufferlist::static_from_string(example6)));
631 ASSERT_TRUE(p);
632 EXPECT_EQ(p->text, example6);
633 EXPECT_EQ(p->version, Version::v2012_10_17);
634 EXPECT_FALSE(p->id);
635 EXPECT_FALSE(p->statements[0].sid);
636 EXPECT_FALSE(p->statements.empty());
637 EXPECT_EQ(p->statements.size(), 1U);
638 EXPECT_TRUE(p->statements[0].princ.empty());
639 EXPECT_TRUE(p->statements[0].noprinc.empty());
640 EXPECT_EQ(p->statements[0].effect, Effect::Allow);
641 Action_t act;
642 for (auto i = 0U; i <= stsAll; i++)
643 act[i] = 1;
644 EXPECT_EQ(p->statements[0].action, act);
645 EXPECT_EQ(p->statements[0].notaction, None);
646 ASSERT_FALSE(p->statements[0].resource.empty());
647 ASSERT_EQ(p->statements[0].resource.size(), 1U);
648 EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws);
649 EXPECT_EQ(p->statements[0].resource.begin()->service, Service::iam);
650 EXPECT_EQ(p->statements[0].resource.begin()->region, "");
651 EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant);
652 EXPECT_EQ(p->statements[0].resource.begin()->resource, "user/A");
653 EXPECT_TRUE(p->statements[0].notresource.empty());
654 EXPECT_TRUE(p->statements[0].conditions.empty());
655}
656
657TEST_F(PolicyTest, Eval6) {
658 auto p = Policy(cct.get(), arbitrary_tenant,
659 bufferlist::static_from_string(example6));
660 Environment e;
661
20effc67
TL
662 ARN arn1(Partition::aws, Service::iam,
663 "", arbitrary_tenant, "user/A");
664 EXPECT_EQ(p.eval(e, none, iamCreateRole, arn1),
11fdf7f2
TL
665 Effect::Allow);
666
20effc67
TL
667 ARN arn2(Partition::aws, Service::iam,
668 "", arbitrary_tenant, "user/A");
669 EXPECT_EQ(p.eval(e, none, s3ListBucket, arn2),
11fdf7f2
TL
670 Effect::Allow);
671}
672
9f95a23c
TL
673TEST_F(PolicyTest, Parse7) {
674 boost::optional<Policy> p;
675
676 ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant,
677 bufferlist::static_from_string(example7)));
678 ASSERT_TRUE(p);
679
680 EXPECT_EQ(p->text, example7);
681 EXPECT_EQ(p->version, Version::v2012_10_17);
682 ASSERT_FALSE(p->statements.empty());
683 EXPECT_EQ(p->statements.size(), 1U);
684 EXPECT_FALSE(p->statements[0].princ.empty());
685 EXPECT_EQ(p->statements[0].princ.size(), 1U);
686 EXPECT_TRUE(p->statements[0].noprinc.empty());
687 EXPECT_EQ(p->statements[0].effect, Effect::Allow);
688 Action_t act;
689 act[s3ListBucket] = 1;
690 EXPECT_EQ(p->statements[0].action, act);
691 EXPECT_EQ(p->statements[0].notaction, None);
692 ASSERT_FALSE(p->statements[0].resource.empty());
693 ASSERT_EQ(p->statements[0].resource.size(), 1U);
694 EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws);
695 EXPECT_EQ(p->statements[0].resource.begin()->service, Service::s3);
696 EXPECT_TRUE(p->statements[0].resource.begin()->region.empty());
697 EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant);
698 EXPECT_EQ(p->statements[0].resource.begin()->resource, "mybucket/*");
699 EXPECT_TRUE(p->statements[0].princ.begin()->is_user());
700 EXPECT_FALSE(p->statements[0].princ.begin()->is_wildcard());
701 EXPECT_EQ(p->statements[0].princ.begin()->get_tenant(), "");
702 EXPECT_EQ(p->statements[0].princ.begin()->get_id(), "A:subA");
703 EXPECT_TRUE(p->statements[0].notresource.empty());
704 EXPECT_TRUE(p->statements[0].conditions.empty());
705}
706
707TEST_F(PolicyTest, Eval7) {
708 auto p = Policy(cct.get(), arbitrary_tenant,
709 bufferlist::static_from_string(example7));
710 Environment e;
711
712 auto subacct = FakeIdentity(
713 Principal::user(std::move(""), "A:subA"));
714 auto parentacct = FakeIdentity(
715 Principal::user(std::move(""), "A"));
716 auto sub2acct = FakeIdentity(
717 Principal::user(std::move(""), "A:sub2A"));
718
20effc67
TL
719 ARN arn1(Partition::aws, Service::s3,
720 "", arbitrary_tenant, "mybucket/*");
721 EXPECT_EQ(p.eval(e, subacct, s3ListBucket, arn1),
9f95a23c
TL
722 Effect::Allow);
723
20effc67
TL
724 ARN arn2(Partition::aws, Service::s3,
725 "", arbitrary_tenant, "mybucket/*");
726 EXPECT_EQ(p.eval(e, parentacct, s3ListBucket, arn2),
9f95a23c 727 Effect::Pass);
20effc67
TL
728
729 ARN arn3(Partition::aws, Service::s3,
730 "", arbitrary_tenant, "mybucket/*");
731 EXPECT_EQ(p.eval(e, sub2acct, s3ListBucket, arn3),
9f95a23c
TL
732 Effect::Pass);
733}
734
31f18b77
FG
735const string PolicyTest::arbitrary_tenant = "arbitrary_tenant";
736string PolicyTest::example1 = R"(
737{
738 "Version": "2012-10-17",
739 "Statement": {
740 "Effect": "Allow",
741 "Action": "s3:ListBucket",
742 "Resource": "arn:aws:s3:::example_bucket"
743 }
744}
745)";
746
747string PolicyTest::example2 = R"(
748{
749 "Version": "2012-10-17",
750 "Id": "S3-Account-Permissions",
751 "Statement": [{
752 "Sid": "1",
753 "Effect": "Allow",
754 "Principal": {"AWS": ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:root"]},
755 "Action": "s3:*",
756 "Resource": [
757 "arn:aws:s3:::mybucket",
758 "arn:aws:s3:::mybucket/*"
759 ]
760 }]
761}
762)";
763
764string PolicyTest::example3 = R"(
765{
766 "Version": "2012-10-17",
767 "Statement": [
768 {
769 "Sid": "FirstStatement",
770 "Effect": "Allow",
771 "Action": ["s3:PutBucketPolicy"],
772 "Resource": "*"
773 },
774 {
775 "Sid": "SecondStatement",
776 "Effect": "Allow",
777 "Action": "s3:ListAllMyBuckets",
778 "Resource": "*"
779 },
780 {
781 "Sid": "ThirdStatement",
782 "Effect": "Allow",
783 "Action": [
784 "s3:List*",
785 "s3:Get*"
786 ],
787 "Resource": [
788 "arn:aws:s3:::confidential-data",
789 "arn:aws:s3:::confidential-data/*"
790 ],
791 "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
792 }
793 ]
794}
795)";
d2e6a577 796
11fdf7f2
TL
797string PolicyTest::example4 = R"(
798{
799 "Version": "2012-10-17",
800 "Statement": {
801 "Effect": "Allow",
802 "Action": "iam:CreateRole",
803 "Resource": "*"
804 }
805}
806)";
807
808string PolicyTest::example5 = R"(
809{
810 "Version": "2012-10-17",
811 "Statement": {
812 "Effect": "Allow",
813 "Action": "iam:*",
814 "Resource": "arn:aws:iam:::role/example_role"
815 }
816}
817)";
818
819string PolicyTest::example6 = R"(
820{
821 "Version": "2012-10-17",
822 "Statement": {
823 "Effect": "Allow",
824 "Action": "*",
825 "Resource": "arn:aws:iam:::user/A"
826 }
827}
828)";
9f95a23c
TL
829
830string PolicyTest::example7 = R"(
831{
832 "Version": "2012-10-17",
833 "Statement": {
834 "Effect": "Allow",
835 "Principal": {"AWS": ["arn:aws:iam:::user/A:subA"]},
836 "Action": "s3:ListBucket",
837 "Resource": "arn:aws:s3:::mybucket/*"
838 }
839}
840)";
b32b8144
FG
841class IPPolicyTest : public ::testing::Test {
842protected:
843 intrusive_ptr<CephContext> cct;
844 static const string arbitrary_tenant;
845 static string ip_address_allow_example;
846 static string ip_address_deny_example;
847 static string ip_address_full_example;
848 // 192.168.1.0/24
849 const rgw::IAM::MaskedIP allowedIPv4Range = { false, rgw::IAM::Address("11000000101010000000000100000000"), 24 };
850 // 192.168.1.1/32
f67539c2 851 const rgw::IAM::MaskedIP blocklistedIPv4 = { false, rgw::IAM::Address("11000000101010000000000100000001"), 32 };
b32b8144
FG
852 // 2001:db8:85a3:0:0:8a2e:370:7334/128
853 const rgw::IAM::MaskedIP allowedIPv6 = { true, rgw::IAM::Address("00100000000000010000110110111000100001011010001100000000000000000000000000000000100010100010111000000011011100000111001100110100"), 128 };
854 // ::1
f67539c2 855 const rgw::IAM::MaskedIP blocklistedIPv6 = { true, rgw::IAM::Address(1), 128 };
b32b8144
FG
856 // 2001:db8:85a3:0:0:8a2e:370:7330/124
857 const rgw::IAM::MaskedIP allowedIPv6Range = { true, rgw::IAM::Address("00100000000000010000110110111000100001011010001100000000000000000000000000000000100010100010111000000011011100000111001100110000"), 124 };
858public:
859 IPPolicyTest() {
860 cct = new CephContext(CEPH_ENTITY_TYPE_CLIENT);
861 }
862};
863const string IPPolicyTest::arbitrary_tenant = "arbitrary_tenant";
864
865TEST_F(IPPolicyTest, MaskedIPOperations) {
866 EXPECT_EQ(stringify(allowedIPv4Range), "192.168.1.0/24");
f67539c2 867 EXPECT_EQ(stringify(blocklistedIPv4), "192.168.1.1/32");
b32b8144
FG
868 EXPECT_EQ(stringify(allowedIPv6), "2001:db8:85a3:0:0:8a2e:370:7334/128");
869 EXPECT_EQ(stringify(allowedIPv6Range), "2001:db8:85a3:0:0:8a2e:370:7330/124");
f67539c2
TL
870 EXPECT_EQ(stringify(blocklistedIPv6), "0:0:0:0:0:0:0:1/128");
871 EXPECT_EQ(allowedIPv4Range, blocklistedIPv4);
b32b8144
FG
872 EXPECT_EQ(allowedIPv6Range, allowedIPv6);
873}
874
875TEST_F(IPPolicyTest, asNetworkIPv4Range) {
876 auto actualIPv4Range = rgw::IAM::Condition::as_network("192.168.1.0/24");
877 ASSERT_TRUE(actualIPv4Range.is_initialized());
878 EXPECT_EQ(*actualIPv4Range, allowedIPv4Range);
879}
880
881TEST_F(IPPolicyTest, asNetworkIPv4) {
882 auto actualIPv4 = rgw::IAM::Condition::as_network("192.168.1.1");
883 ASSERT_TRUE(actualIPv4.is_initialized());
f67539c2 884 EXPECT_EQ(*actualIPv4, blocklistedIPv4);
b32b8144
FG
885}
886
887TEST_F(IPPolicyTest, asNetworkIPv6Range) {
888 auto actualIPv6Range = rgw::IAM::Condition::as_network("2001:db8:85a3:0:0:8a2e:370:7330/124");
889 ASSERT_TRUE(actualIPv6Range.is_initialized());
890 EXPECT_EQ(*actualIPv6Range, allowedIPv6Range);
891}
892
893TEST_F(IPPolicyTest, asNetworkIPv6) {
894 auto actualIPv6 = rgw::IAM::Condition::as_network("2001:db8:85a3:0:0:8a2e:370:7334");
895 ASSERT_TRUE(actualIPv6.is_initialized());
896 EXPECT_EQ(*actualIPv6, allowedIPv6);
897}
898
899TEST_F(IPPolicyTest, asNetworkInvalid) {
900 EXPECT_FALSE(rgw::IAM::Condition::as_network(""));
901 EXPECT_FALSE(rgw::IAM::Condition::as_network("192.168.1.1/33"));
902 EXPECT_FALSE(rgw::IAM::Condition::as_network("2001:db8:85a3:0:0:8a2e:370:7334/129"));
903 EXPECT_FALSE(rgw::IAM::Condition::as_network("192.168.1.1:"));
904 EXPECT_FALSE(rgw::IAM::Condition::as_network("1.2.3.10000"));
905}
906
907TEST_F(IPPolicyTest, IPEnvironment) {
908 // Unfortunately RGWCivetWeb is too tightly tied to civetweb to test RGWCivetWeb::init_env.
909 RGWEnv rgw_env;
20effc67
TL
910 rgw::sal::RadosStore store;
911 std::unique_ptr<rgw::sal::User> user = store.get_user(rgw_user());
b32b8144
FG
912 rgw_env.set("REMOTE_ADDR", "192.168.1.1");
913 rgw_env.set("HTTP_HOST", "1.2.3.4");
f67539c2
TL
914 req_state rgw_req_state(cct.get(), &rgw_env, 0);
915 rgw_req_state.set_user(user);
9f95a23c 916 rgw_build_iam_environment(&store, &rgw_req_state);
11fdf7f2
TL
917 auto ip = rgw_req_state.env.find("aws:SourceIp");
918 ASSERT_NE(ip, rgw_req_state.env.end());
b32b8144
FG
919 EXPECT_EQ(ip->second, "192.168.1.1");
920
11fdf7f2 921 ASSERT_EQ(cct.get()->_conf.set_val("rgw_remote_addr_param", "SOME_VAR"), 0);
b32b8144 922 EXPECT_EQ(cct.get()->_conf->rgw_remote_addr_param, "SOME_VAR");
11fdf7f2 923 rgw_req_state.env.clear();
9f95a23c 924 rgw_build_iam_environment(&store, &rgw_req_state);
11fdf7f2
TL
925 ip = rgw_req_state.env.find("aws:SourceIp");
926 EXPECT_EQ(ip, rgw_req_state.env.end());
b32b8144
FG
927
928 rgw_env.set("SOME_VAR", "192.168.1.2");
11fdf7f2 929 rgw_req_state.env.clear();
9f95a23c 930 rgw_build_iam_environment(&store, &rgw_req_state);
11fdf7f2
TL
931 ip = rgw_req_state.env.find("aws:SourceIp");
932 ASSERT_NE(ip, rgw_req_state.env.end());
b32b8144
FG
933 EXPECT_EQ(ip->second, "192.168.1.2");
934
11fdf7f2 935 ASSERT_EQ(cct.get()->_conf.set_val("rgw_remote_addr_param", "HTTP_X_FORWARDED_FOR"), 0);
b32b8144 936 rgw_env.set("HTTP_X_FORWARDED_FOR", "192.168.1.3");
11fdf7f2 937 rgw_req_state.env.clear();
9f95a23c 938 rgw_build_iam_environment(&store, &rgw_req_state);
11fdf7f2
TL
939 ip = rgw_req_state.env.find("aws:SourceIp");
940 ASSERT_NE(ip, rgw_req_state.env.end());
b32b8144
FG
941 EXPECT_EQ(ip->second, "192.168.1.3");
942
943 rgw_env.set("HTTP_X_FORWARDED_FOR", "192.168.1.4, 4.3.2.1, 2001:db8:85a3:8d3:1319:8a2e:370:7348");
11fdf7f2 944 rgw_req_state.env.clear();
9f95a23c 945 rgw_build_iam_environment(&store, &rgw_req_state);
11fdf7f2
TL
946 ip = rgw_req_state.env.find("aws:SourceIp");
947 ASSERT_NE(ip, rgw_req_state.env.end());
b32b8144
FG
948 EXPECT_EQ(ip->second, "192.168.1.4");
949}
950
951TEST_F(IPPolicyTest, ParseIPAddress) {
11fdf7f2 952 boost::optional<Policy> p;
b32b8144
FG
953
954 ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant,
955 bufferlist::static_from_string(ip_address_full_example)));
956 ASSERT_TRUE(p);
957
958 EXPECT_EQ(p->text, ip_address_full_example);
959 EXPECT_EQ(p->version, Version::v2012_10_17);
960 EXPECT_EQ(*p->id, "S3IPPolicyTest");
961 EXPECT_FALSE(p->statements.empty());
962 EXPECT_EQ(p->statements.size(), 1U);
963 EXPECT_EQ(*p->statements[0].sid, "IPAllow");
964 EXPECT_FALSE(p->statements[0].princ.empty());
965 EXPECT_EQ(p->statements[0].princ.size(), 1U);
966 EXPECT_EQ(*p->statements[0].princ.begin(),
967 Principal::wildcard());
968 EXPECT_TRUE(p->statements[0].noprinc.empty());
969 EXPECT_EQ(p->statements[0].effect, Effect::Allow);
11fdf7f2
TL
970 Action_t act;
971 act[s3ListBucket] = 1;
972 EXPECT_EQ(p->statements[0].action, act);
973 EXPECT_EQ(p->statements[0].notaction, None);
b32b8144
FG
974 ASSERT_FALSE(p->statements[0].resource.empty());
975 ASSERT_EQ(p->statements[0].resource.size(), 2U);
976 EXPECT_EQ(p->statements[0].resource.begin()->partition, Partition::aws);
977 EXPECT_EQ(p->statements[0].resource.begin()->service, Service::s3);
978 EXPECT_TRUE(p->statements[0].resource.begin()->region.empty());
979 EXPECT_EQ(p->statements[0].resource.begin()->account, arbitrary_tenant);
980 EXPECT_EQ(p->statements[0].resource.begin()->resource, "example_bucket");
981 EXPECT_EQ((p->statements[0].resource.begin() + 1)->resource, "example_bucket/*");
982 EXPECT_TRUE(p->statements[0].notresource.empty());
983 ASSERT_FALSE(p->statements[0].conditions.empty());
984 ASSERT_EQ(p->statements[0].conditions.size(), 2U);
985 EXPECT_EQ(p->statements[0].conditions[0].op, TokenID::IpAddress);
986 EXPECT_EQ(p->statements[0].conditions[0].key, "aws:SourceIp");
987 ASSERT_FALSE(p->statements[0].conditions[0].vals.empty());
988 EXPECT_EQ(p->statements[0].conditions[0].vals.size(), 2U);
989 EXPECT_EQ(p->statements[0].conditions[0].vals[0], "192.168.1.0/24");
990 EXPECT_EQ(p->statements[0].conditions[0].vals[1], "::1");
11fdf7f2 991 boost::optional<rgw::IAM::MaskedIP> convertedIPv4 = rgw::IAM::Condition::as_network(p->statements[0].conditions[0].vals[0]);
b32b8144
FG
992 EXPECT_TRUE(convertedIPv4.is_initialized());
993 if (convertedIPv4.is_initialized()) {
994 EXPECT_EQ(*convertedIPv4, allowedIPv4Range);
995 }
996
997 EXPECT_EQ(p->statements[0].conditions[1].op, TokenID::NotIpAddress);
998 EXPECT_EQ(p->statements[0].conditions[1].key, "aws:SourceIp");
999 ASSERT_FALSE(p->statements[0].conditions[1].vals.empty());
1000 EXPECT_EQ(p->statements[0].conditions[1].vals.size(), 2U);
1001 EXPECT_EQ(p->statements[0].conditions[1].vals[0], "192.168.1.1/32");
1002 EXPECT_EQ(p->statements[0].conditions[1].vals[1], "2001:0db8:85a3:0000:0000:8a2e:0370:7334");
11fdf7f2 1003 boost::optional<rgw::IAM::MaskedIP> convertedIPv6 = rgw::IAM::Condition::as_network(p->statements[0].conditions[1].vals[1]);
b32b8144
FG
1004 EXPECT_TRUE(convertedIPv6.is_initialized());
1005 if (convertedIPv6.is_initialized()) {
1006 EXPECT_EQ(*convertedIPv6, allowedIPv6);
1007 }
1008}
1009
1010TEST_F(IPPolicyTest, EvalIPAddress) {
1011 auto allowp = Policy(cct.get(), arbitrary_tenant,
1012 bufferlist::static_from_string(ip_address_allow_example));
1013 auto denyp = Policy(cct.get(), arbitrary_tenant,
1014 bufferlist::static_from_string(ip_address_deny_example));
1015 auto fullp = Policy(cct.get(), arbitrary_tenant,
1016 bufferlist::static_from_string(ip_address_full_example));
1017 Environment e;
f67539c2 1018 Environment allowedIP, blocklistedIP, allowedIPv6, blocklistedIPv6;
20effc67
TL
1019 allowedIP.emplace("aws:SourceIp","192.168.1.2");
1020 allowedIPv6.emplace("aws:SourceIp", "::1");
1021 blocklistedIP.emplace("aws:SourceIp", "192.168.1.1");
1022 blocklistedIPv6.emplace("aws:SourceIp", "2001:0db8:85a3:0000:0000:8a2e:0370:7334");
b32b8144
FG
1023
1024 auto trueacct = FakeIdentity(
1025 Principal::tenant("ACCOUNT-ID-WITHOUT-HYPHENS"));
1026 // Without an IP address in the environment then evaluation will always pass
20effc67
TL
1027 ARN arn1(Partition::aws, Service::s3,
1028 "", arbitrary_tenant, "example_bucket");
1029 EXPECT_EQ(allowp.eval(e, trueacct, s3ListBucket, arn1),
b32b8144 1030 Effect::Pass);
20effc67
TL
1031 ARN arn2(Partition::aws, Service::s3,
1032 "", arbitrary_tenant, "example_bucket/myobject");
1033 EXPECT_EQ(fullp.eval(e, trueacct, s3ListBucket, arn2),
b32b8144
FG
1034 Effect::Pass);
1035
20effc67
TL
1036 ARN arn3(Partition::aws, Service::s3,
1037 "", arbitrary_tenant, "example_bucket");
1038 EXPECT_EQ(allowp.eval(allowedIP, trueacct, s3ListBucket, arn3),
b32b8144 1039 Effect::Allow);
20effc67
TL
1040 ARN arn4(Partition::aws, Service::s3,
1041 "", arbitrary_tenant, "example_bucket");
1042 EXPECT_EQ(allowp.eval(blocklistedIPv6, trueacct, s3ListBucket, arn4),
b32b8144
FG
1043 Effect::Pass);
1044
20effc67
TL
1045 ARN arn5(Partition::aws, Service::s3,
1046 "", arbitrary_tenant, "example_bucket");
1047 EXPECT_EQ(denyp.eval(allowedIP, trueacct, s3ListBucket, arn5),
b32b8144 1048 Effect::Deny);
20effc67
TL
1049 ARN arn6(Partition::aws, Service::s3,
1050 "", arbitrary_tenant, "example_bucket/myobject");
1051 EXPECT_EQ(denyp.eval(allowedIP, trueacct, s3ListBucket, arn6),
b32b8144
FG
1052 Effect::Deny);
1053
20effc67
TL
1054 ARN arn7(Partition::aws, Service::s3,
1055 "", arbitrary_tenant, "example_bucket");
1056 EXPECT_EQ(denyp.eval(blocklistedIP, trueacct, s3ListBucket, arn7),
b32b8144 1057 Effect::Pass);
20effc67
TL
1058 ARN arn8(Partition::aws, Service::s3,
1059 "", arbitrary_tenant, "example_bucket/myobject");
1060 EXPECT_EQ(denyp.eval(blocklistedIP, trueacct, s3ListBucket, arn8),
b32b8144
FG
1061 Effect::Pass);
1062
20effc67
TL
1063 ARN arn9(Partition::aws, Service::s3,
1064 "", arbitrary_tenant, "example_bucket");
1065 EXPECT_EQ(denyp.eval(blocklistedIPv6, trueacct, s3ListBucket, arn9),
b32b8144 1066 Effect::Pass);
20effc67
TL
1067 ARN arn10(Partition::aws, Service::s3,
1068 "", arbitrary_tenant, "example_bucket/myobject");
1069 EXPECT_EQ(denyp.eval(blocklistedIPv6, trueacct, s3ListBucket, arn10),
b32b8144 1070 Effect::Pass);
20effc67
TL
1071 ARN arn11(Partition::aws, Service::s3,
1072 "", arbitrary_tenant, "example_bucket");
1073 EXPECT_EQ(denyp.eval(allowedIPv6, trueacct, s3ListBucket, arn11),
b32b8144 1074 Effect::Deny);
20effc67
TL
1075 ARN arn12(Partition::aws, Service::s3,
1076 "", arbitrary_tenant, "example_bucket/myobject");
1077 EXPECT_EQ(denyp.eval(allowedIPv6, trueacct, s3ListBucket, arn12),
b32b8144
FG
1078 Effect::Deny);
1079
20effc67
TL
1080 ARN arn13(Partition::aws, Service::s3,
1081 "", arbitrary_tenant, "example_bucket");
1082 EXPECT_EQ(fullp.eval(allowedIP, trueacct, s3ListBucket, arn13),
b32b8144 1083 Effect::Allow);
20effc67
TL
1084 ARN arn14(Partition::aws, Service::s3,
1085 "", arbitrary_tenant, "example_bucket/myobject");
1086 EXPECT_EQ(fullp.eval(allowedIP, trueacct, s3ListBucket, arn14),
b32b8144
FG
1087 Effect::Allow);
1088
20effc67
TL
1089 ARN arn15(Partition::aws, Service::s3,
1090 "", arbitrary_tenant, "example_bucket");
1091 EXPECT_EQ(fullp.eval(blocklistedIP, trueacct, s3ListBucket, arn15),
b32b8144 1092 Effect::Pass);
20effc67
TL
1093 ARN arn16(Partition::aws, Service::s3,
1094 "", arbitrary_tenant, "example_bucket/myobject");
1095 EXPECT_EQ(fullp.eval(blocklistedIP, trueacct, s3ListBucket, arn16),
b32b8144
FG
1096 Effect::Pass);
1097
20effc67
TL
1098 ARN arn17(Partition::aws, Service::s3,
1099 "", arbitrary_tenant, "example_bucket");
1100 EXPECT_EQ(fullp.eval(allowedIPv6, trueacct, s3ListBucket, arn17),
b32b8144 1101 Effect::Allow);
20effc67
TL
1102 ARN arn18(Partition::aws, Service::s3,
1103 "", arbitrary_tenant, "example_bucket/myobject");
1104 EXPECT_EQ(fullp.eval(allowedIPv6, trueacct, s3ListBucket, arn18),
b32b8144
FG
1105 Effect::Allow);
1106
20effc67
TL
1107 ARN arn19(Partition::aws, Service::s3,
1108 "", arbitrary_tenant, "example_bucket");
1109 EXPECT_EQ(fullp.eval(blocklistedIPv6, trueacct, s3ListBucket, arn19),
b32b8144 1110 Effect::Pass);
20effc67
TL
1111 ARN arn20(Partition::aws, Service::s3,
1112 "", arbitrary_tenant, "example_bucket/myobject");
1113 EXPECT_EQ(fullp.eval(blocklistedIPv6, trueacct, s3ListBucket, arn20),
b32b8144
FG
1114 Effect::Pass);
1115}
1116
1117string IPPolicyTest::ip_address_allow_example = R"(
1118{
1119 "Version": "2012-10-17",
1120 "Id": "S3SimpleIPPolicyTest",
1121 "Statement": [{
1122 "Sid": "1",
1123 "Effect": "Allow",
1124 "Principal": {"AWS": ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:root"]},
1125 "Action": "s3:ListBucket",
1126 "Resource": [
1127 "arn:aws:s3:::example_bucket"
1128 ],
1129 "Condition": {
1130 "IpAddress": {"aws:SourceIp": "192.168.1.0/24"}
1131 }
1132 }]
1133}
1134)";
1135
1136string IPPolicyTest::ip_address_deny_example = R"(
1137{
1138 "Version": "2012-10-17",
1139 "Id": "S3IPPolicyTest",
1140 "Statement": {
1141 "Effect": "Deny",
1142 "Sid": "IPDeny",
1143 "Action": "s3:ListBucket",
1144 "Principal": {"AWS": ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:root"]},
1145 "Resource": [
1146 "arn:aws:s3:::example_bucket",
1147 "arn:aws:s3:::example_bucket/*"
1148 ],
1149 "Condition": {
1150 "NotIpAddress": {"aws:SourceIp": ["192.168.1.1/32", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"]}
1151 }
1152 }
1153}
1154)";
1155
1156string IPPolicyTest::ip_address_full_example = R"(
1157{
1158 "Version": "2012-10-17",
1159 "Id": "S3IPPolicyTest",
1160 "Statement": {
1161 "Effect": "Allow",
1162 "Sid": "IPAllow",
1163 "Action": "s3:ListBucket",
1164 "Principal": "*",
1165 "Resource": [
1166 "arn:aws:s3:::example_bucket",
1167 "arn:aws:s3:::example_bucket/*"
1168 ],
1169 "Condition": {
1170 "IpAddress": {"aws:SourceIp": ["192.168.1.0/24", "::1"]},
1171 "NotIpAddress": {"aws:SourceIp": ["192.168.1.1/32", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"]}
1172 }
1173 }
1174}
1175)";
1176
d2e6a577
FG
1177TEST(MatchWildcards, Simple)
1178{
1179 EXPECT_TRUE(match_wildcards("", ""));
1180 EXPECT_TRUE(match_wildcards("", "", MATCH_CASE_INSENSITIVE));
1181 EXPECT_FALSE(match_wildcards("", "abc"));
1182 EXPECT_FALSE(match_wildcards("", "abc", MATCH_CASE_INSENSITIVE));
1183 EXPECT_FALSE(match_wildcards("abc", ""));
1184 EXPECT_FALSE(match_wildcards("abc", "", MATCH_CASE_INSENSITIVE));
1185 EXPECT_TRUE(match_wildcards("abc", "abc"));
1186 EXPECT_TRUE(match_wildcards("abc", "abc", MATCH_CASE_INSENSITIVE));
1187 EXPECT_FALSE(match_wildcards("abc", "abC"));
1188 EXPECT_TRUE(match_wildcards("abc", "abC", MATCH_CASE_INSENSITIVE));
1189 EXPECT_FALSE(match_wildcards("abC", "abc"));
1190 EXPECT_TRUE(match_wildcards("abC", "abc", MATCH_CASE_INSENSITIVE));
1191 EXPECT_FALSE(match_wildcards("abc", "abcd"));
1192 EXPECT_FALSE(match_wildcards("abc", "abcd", MATCH_CASE_INSENSITIVE));
1193 EXPECT_FALSE(match_wildcards("abcd", "abc"));
1194 EXPECT_FALSE(match_wildcards("abcd", "abc", MATCH_CASE_INSENSITIVE));
1195}
1196
1197TEST(MatchWildcards, QuestionMark)
1198{
1199 EXPECT_FALSE(match_wildcards("?", ""));
1200 EXPECT_FALSE(match_wildcards("?", "", MATCH_CASE_INSENSITIVE));
1201 EXPECT_TRUE(match_wildcards("?", "a"));
1202 EXPECT_TRUE(match_wildcards("?", "a", MATCH_CASE_INSENSITIVE));
1203 EXPECT_TRUE(match_wildcards("?bc", "abc"));
1204 EXPECT_TRUE(match_wildcards("?bc", "abc", MATCH_CASE_INSENSITIVE));
1205 EXPECT_TRUE(match_wildcards("a?c", "abc"));
1206 EXPECT_TRUE(match_wildcards("a?c", "abc", MATCH_CASE_INSENSITIVE));
1207 EXPECT_FALSE(match_wildcards("abc", "a?c"));
1208 EXPECT_FALSE(match_wildcards("abc", "a?c", MATCH_CASE_INSENSITIVE));
1209 EXPECT_FALSE(match_wildcards("a?c", "abC"));
1210 EXPECT_TRUE(match_wildcards("a?c", "abC", MATCH_CASE_INSENSITIVE));
1211 EXPECT_TRUE(match_wildcards("ab?", "abc"));
1212 EXPECT_TRUE(match_wildcards("ab?", "abc", MATCH_CASE_INSENSITIVE));
1213 EXPECT_TRUE(match_wildcards("a?c?e", "abcde"));
1214 EXPECT_TRUE(match_wildcards("a?c?e", "abcde", MATCH_CASE_INSENSITIVE));
1215 EXPECT_TRUE(match_wildcards("???", "abc"));
1216 EXPECT_TRUE(match_wildcards("???", "abc", MATCH_CASE_INSENSITIVE));
1217 EXPECT_FALSE(match_wildcards("???", "abcd"));
1218 EXPECT_FALSE(match_wildcards("???", "abcd", MATCH_CASE_INSENSITIVE));
1219}
1220
1221TEST(MatchWildcards, Asterisk)
1222{
1223 EXPECT_TRUE(match_wildcards("*", ""));
1224 EXPECT_TRUE(match_wildcards("*", "", MATCH_CASE_INSENSITIVE));
1225 EXPECT_FALSE(match_wildcards("", "*"));
1226 EXPECT_FALSE(match_wildcards("", "*", MATCH_CASE_INSENSITIVE));
1227 EXPECT_FALSE(match_wildcards("*a", ""));
1228 EXPECT_FALSE(match_wildcards("*a", "", MATCH_CASE_INSENSITIVE));
1229 EXPECT_TRUE(match_wildcards("*a", "a"));
1230 EXPECT_TRUE(match_wildcards("*a", "a", MATCH_CASE_INSENSITIVE));
1231 EXPECT_TRUE(match_wildcards("a*", "a"));
1232 EXPECT_TRUE(match_wildcards("a*", "a", MATCH_CASE_INSENSITIVE));
1233 EXPECT_TRUE(match_wildcards("a*c", "ac"));
1234 EXPECT_TRUE(match_wildcards("a*c", "ac", MATCH_CASE_INSENSITIVE));
1235 EXPECT_TRUE(match_wildcards("a*c", "abbc"));
1236 EXPECT_TRUE(match_wildcards("a*c", "abbc", MATCH_CASE_INSENSITIVE));
1237 EXPECT_FALSE(match_wildcards("a*c", "abbC"));
1238 EXPECT_TRUE(match_wildcards("a*c", "abbC", MATCH_CASE_INSENSITIVE));
1239 EXPECT_TRUE(match_wildcards("a*c*e", "abBce"));
1240 EXPECT_TRUE(match_wildcards("a*c*e", "abBce", MATCH_CASE_INSENSITIVE));
1241 EXPECT_TRUE(match_wildcards("http://*.example.com",
1242 "http://www.example.com"));
1243 EXPECT_TRUE(match_wildcards("http://*.example.com",
1244 "http://www.example.com", MATCH_CASE_INSENSITIVE));
1245 EXPECT_FALSE(match_wildcards("http://*.example.com",
1246 "http://www.Example.com"));
1247 EXPECT_TRUE(match_wildcards("http://*.example.com",
1248 "http://www.Example.com", MATCH_CASE_INSENSITIVE));
1249 EXPECT_TRUE(match_wildcards("http://example.com/*",
1250 "http://example.com/index.html"));
1251 EXPECT_TRUE(match_wildcards("http://example.com/*/*.jpg",
1252 "http://example.com/fun/smiley.jpg"));
1253 // note: parsing of * is not greedy, so * does not match 'bc' here
1254 EXPECT_FALSE(match_wildcards("a*c", "abcc"));
1255 EXPECT_FALSE(match_wildcards("a*c", "abcc", MATCH_CASE_INSENSITIVE));
1256}
1257
1258TEST(MatchPolicy, Action)
1259{
1260 constexpr auto flag = MATCH_POLICY_ACTION;
1261 EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag));
1262 EXPECT_TRUE(match_policy("a:b:c", "A:B:C", flag)); // case insensitive
1263 EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag));
1264 EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments
1265}
1266
1267TEST(MatchPolicy, Resource)
1268{
1269 constexpr auto flag = MATCH_POLICY_RESOURCE;
1270 EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag));
1271 EXPECT_FALSE(match_policy("a:b:c", "A:B:C", flag)); // case sensitive
1272 EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag));
f64942e4 1273 EXPECT_TRUE(match_policy("a:*", "a:b:c", flag)); // can span segments
d2e6a577
FG
1274}
1275
1276TEST(MatchPolicy, ARN)
1277{
1278 constexpr auto flag = MATCH_POLICY_ARN;
1279 EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag));
1280 EXPECT_TRUE(match_policy("a:b:c", "A:B:C", flag)); // case insensitive
1281 EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag));
1282 EXPECT_FALSE(match_policy("a:*", "a:b:c", flag)); // cannot span segments
1283}
1284
1285TEST(MatchPolicy, String)
1286{
1287 constexpr auto flag = MATCH_POLICY_STRING;
1288 EXPECT_TRUE(match_policy("a:b:c", "a:b:c", flag));
1289 EXPECT_FALSE(match_policy("a:b:c", "A:B:C", flag)); // case sensitive
1290 EXPECT_TRUE(match_policy("a:*:e", "a:bcd:e", flag));
f64942e4 1291 EXPECT_TRUE(match_policy("a:*", "a:b:c", flag)); // can span segments
d2e6a577 1292}
9f95a23c
TL
1293
1294Action_t set_range_bits(std::uint64_t start, std::uint64_t end)
1295{
1296 Action_t result;
1297 for (uint64_t i = start; i < end; i++) {
1298 result.set(i);
1299 }
1300 return result;
1301}
1302
1303using rgw::IAM::s3AllValue;
1304using rgw::IAM::stsAllValue;
1305using rgw::IAM::allValue;
1306using rgw::IAM::iamAllValue;
1307TEST(set_cont_bits, iamconsts)
1308{
1309 EXPECT_EQ(s3AllValue, set_range_bits(0, s3All));
1310 EXPECT_EQ(iamAllValue, set_range_bits(s3All+1, iamAll));
1311 EXPECT_EQ(stsAllValue, set_range_bits(iamAll+1, stsAll));
1312 EXPECT_EQ(allValue , set_range_bits(0, allCount));
1313}