Skip to content

Commit 62c3e5e

Browse files
committed
rgw/iam: add policy evaluation for Arn-based Conditions
arn-based conditions like ArnEquals etc are recognized by the policy parser, but not enforced during policy evaluation Fixes: https://tracker.ceph.com/issues/70481 Signed-off-by: Casey Bodley <[email protected]>
1 parent a7a63aa commit 62c3e5e

File tree

3 files changed

+47
-5
lines changed

3 files changed

+47
-5
lines changed

PendingReleaseNotes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
* RGW: For compatibility with AWS S3, LastModified timestamps are now truncated
1515
to the second. Note that during upgrade, users may observe these timestamps
1616
moving backwards as a result.
17+
* RGW: IAM policy evaluation now supports conditions ArnEquals and ArnLike, along
18+
with their Not and IfExists variants.
1719

1820
* RBD: All Python APIs that produce timestamps now return "aware" `datetime`
1921
objects instead of "naive" ones (i.e. those including time zone information

src/rgw/rgw_iam_policy.cc

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,18 @@ ostream& operator <<(ostream& m, const MaskedIP& ip) {
852852
return m;
853853
}
854854

855+
// Case-sensitive matching of the ARN. Each of the six colon-delimited
856+
// components of the ARN is checked separately and each can include multi-
857+
// character match wildcards (*) or single-character match wildcards (?).
858+
static bool arn_like(const std::string& input, const std::string& pattern)
859+
{
860+
constexpr auto delim = [] (char c) { return c == ':'; };
861+
if (std::count_if(input.begin(), input.end(), delim) != 5) {
862+
return false;
863+
}
864+
return match_policy(pattern, input, MATCH_POLICY_ARN);
865+
}
866+
855867
bool Condition::eval(const Environment& env) const {
856868
std::vector<std::string> runtime_vals;
857869
auto i = env.find(key);
@@ -992,11 +1004,14 @@ bool Condition::eval(const Environment& env) const {
9921004
return true;
9931005
}
9941006

995-
#if 0
996-
// Amazon Resource Names! (Does S3 need this?)
997-
TokenID::ArnEquals, TokenID::ArnNotEquals, TokenID::ArnLike,
998-
TokenID::ArnNotLike,
999-
#endif
1007+
// Amazon Resource Names!
1008+
// The ArnEquals and ArnLike condition operators behave identically.
1009+
case TokenID::ArnEquals:
1010+
case TokenID::ArnLike:
1011+
return orrible(arn_like, itr, isruntime? runtime_vals : vals);
1012+
case TokenID::ArnNotEquals:
1013+
case TokenID::ArnNotLike:
1014+
return orrible(std::not_fn(arn_like), itr, isruntime? runtime_vals : vals);
10001015

10011016
default:
10021017
return false;

src/test/rgw/test_rgw_iam_policy.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ using rgw::IAM::Effect;
4949
using rgw::IAM::Environment;
5050
using rgw::Partition;
5151
using rgw::IAM::Policy;
52+
using rgw::IAM::Condition;
5253
using rgw::IAM::s3All;
5354
using rgw::IAM::s3objectlambdaAll;
5455
using rgw::IAM::s3GetAccelerateConfiguration;
@@ -1492,3 +1493,27 @@ TEST(set_cont_bits, iamconsts)
14921493
EXPECT_EQ(organizationsAllValue, set_range_bits(snsAll+1, organizationsAll));
14931494
EXPECT_EQ(allValue , set_range_bits(0, allCount));
14941495
}
1496+
1497+
TEST(Condition, ArnLike)
1498+
{
1499+
const std::string key = "aws:SourceArn";
1500+
{
1501+
Condition ArnLike{TokenID::ArnLike, key.data(), key.size(), false};
1502+
ArnLike.vals.push_back("arn:aws:s3:::bucket");
1503+
1504+
EXPECT_FALSE(ArnLike.eval({}));
1505+
EXPECT_TRUE(ArnLike.eval({{key, "arn:aws:s3:::bucket"}}));
1506+
EXPECT_FALSE(ArnLike.eval({{key, "arn:aws:s3:::BUCKET"}}));
1507+
EXPECT_FALSE(ArnLike.eval({{key, "arn:aws:s3:::user"}}));
1508+
}
1509+
{
1510+
Condition ArnLike{TokenID::ArnLike, key.data(), key.size(), false};
1511+
ArnLike.vals.push_back("arn:aws:s3:::b*");
1512+
1513+
EXPECT_FALSE(ArnLike.eval({}));
1514+
EXPECT_TRUE(ArnLike.eval({{key, "arn:aws:s3:::b"}}));
1515+
EXPECT_TRUE(ArnLike.eval({{key, "arn:aws:s3:::bucket"}}));
1516+
EXPECT_FALSE(ArnLike.eval({{key, "arn:aws:s3:::BUCKET"}}));
1517+
EXPECT_FALSE(ArnLike.eval({{key, "arn:aws:s3:::user"}}));
1518+
}
1519+
}

0 commit comments

Comments
 (0)