From: liubingrun Date: Fri, 19 Sep 2025 19:17:07 +0000 (+0800) Subject: rgw/iam: add NotEquals UT X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c8372be8800ef3df729cc31b1df2b366c6ec35c7;p=ceph.git rgw/iam: add NotEquals UT Signed-off-by: liubingrun --- diff --git a/src/test/rgw/test_rgw_iam_policy.cc b/src/test/rgw/test_rgw_iam_policy.cc index f90d70c8cc18..5e8c9d54586d 100644 --- a/src/test/rgw/test_rgw_iam_policy.cc +++ b/src/test/rgw/test_rgw_iam_policy.cc @@ -1566,3 +1566,199 @@ TEST(Condition, ArnLike) EXPECT_FALSE(ArnLike.eval({{key, "arn:aws:s3:::user"}})); } } + + +class ConditionTest : public ::testing::Test { +protected: + intrusive_ptr cct; + + ConditionTest() { + cct.reset(new CephContext(CEPH_ENTITY_TYPE_CLIENT), false); + } +}; + +// Test cases for NotEquals condition logic fix +// These tests verify that NotEquals conditions use correct AND logic +// instead of incorrect OR logic (requiring mismatch with ALL values, not ANY) + +TEST_F(ConditionTest, StringNotEqualsLogic) +{ + std::string key = "aws:UserName"; + + // Test case: value matches one of multiple condition values + // Should return false because value equals at least one condition value + { + Condition stringNotEquals{TokenID::StringNotEquals, key.data(), key.size(), false}; + stringNotEquals.vals.push_back("alice"); + stringNotEquals.vals.push_back("bob"); + stringNotEquals.vals.push_back("charlie"); + + // Input "bob" matches second condition value, should return false + EXPECT_FALSE(stringNotEquals.eval({{key, "bob"}})); + // Input "alice" matches first condition value, should return false + EXPECT_FALSE(stringNotEquals.eval({{key, "alice"}})); + } + + // Test case: value doesn't match any condition values + // Should return true because value differs from all condition values + { + Condition stringNotEquals{TokenID::StringNotEquals, key.data(), key.size(), false}; + stringNotEquals.vals.push_back("alice"); + stringNotEquals.vals.push_back("bob"); + stringNotEquals.vals.push_back("charlie"); + + // Input "david" doesn't match any condition value, should return true + EXPECT_TRUE(stringNotEquals.eval({{key, "david"}})); + } +} + +TEST_F(ConditionTest, NumericNotEqualsLogic) +{ + std::string key = "aws:RequestedRegion"; + + // Test case: value matches one of multiple condition values + // Should return false because value equals at least one condition value + { + Condition numericNotEquals{TokenID::NumericNotEquals, key.data(), key.size(), false}; + numericNotEquals.vals.push_back("10"); + numericNotEquals.vals.push_back("20"); + numericNotEquals.vals.push_back("30"); + + // Input "20" matches second condition value, should return false + EXPECT_FALSE(numericNotEquals.eval({{key, "20"}})); + // Input "10" matches first condition value, should return false + EXPECT_FALSE(numericNotEquals.eval({{key, "10"}})); + } + + // Test case: value doesn't match any condition values + // Should return true because value differs from all condition values + { + Condition numericNotEquals{TokenID::NumericNotEquals, key.data(), key.size(), false}; + numericNotEquals.vals.push_back("10"); + numericNotEquals.vals.push_back("20"); + numericNotEquals.vals.push_back("30"); + + // Input "40" doesn't match any condition value, should return true + EXPECT_TRUE(numericNotEquals.eval({{key, "40"}})); + } +} + +TEST_F(ConditionTest, DateNotEqualsLogic) +{ + std::string key = "aws:CurrentTime"; + + // Test case: value matches one of multiple condition values + // Should return false because value equals at least one condition value + { + Condition dateNotEquals{TokenID::DateNotEquals, key.data(), key.size(), false}; + dateNotEquals.vals.push_back("2023-01-01T00:00:00Z"); + dateNotEquals.vals.push_back("2023-06-01T00:00:00Z"); + dateNotEquals.vals.push_back("2023-12-01T00:00:00Z"); + + // Input matches second condition value, should return false + EXPECT_FALSE(dateNotEquals.eval({{key, "2023-06-01T00:00:00Z"}})); + } + + // Test case: value doesn't match any condition values + // Should return true because value differs from all condition values + { + Condition dateNotEquals{TokenID::DateNotEquals, key.data(), key.size(), false}; + dateNotEquals.vals.push_back("2023-01-01T00:00:00Z"); + dateNotEquals.vals.push_back("2023-06-01T00:00:00Z"); + dateNotEquals.vals.push_back("2023-12-01T00:00:00Z"); + + // Input doesn't match any condition value, should return true + EXPECT_TRUE(dateNotEquals.eval({{key, "2024-01-01T00:00:00Z"}})); + } +} + +TEST_F(ConditionTest, NotIpAddressLogic) +{ + std::string key = "aws:SourceIp"; + + // Test case: value matches one of multiple condition values + // Should return false because value equals at least one condition value + { + Condition notIpAddress{TokenID::NotIpAddress, key.data(), key.size(), false}; + notIpAddress.vals.push_back("192.168.1.1"); + notIpAddress.vals.push_back("10.0.0.1"); + notIpAddress.vals.push_back("172.16.0.1"); + + // Input matches second condition value, should return false + EXPECT_FALSE(notIpAddress.eval({{key, "10.0.0.1"}})); + // Input matches first condition value, should return false + EXPECT_FALSE(notIpAddress.eval({{key, "192.168.1.1"}})); + } + + // Test case: value doesn't match any condition values + // Should return true because value differs from all condition values + { + Condition notIpAddress{TokenID::NotIpAddress, key.data(), key.size(), false}; + notIpAddress.vals.push_back("192.168.1.1"); + notIpAddress.vals.push_back("10.0.0.1"); + notIpAddress.vals.push_back("172.16.0.1"); + + // Input doesn't match any condition value, should return true + EXPECT_TRUE(notIpAddress.eval({{key, "8.8.8.8"}})); + } +} + +TEST_F(ConditionTest, ArnNotEqualsLogic) +{ + std::string key = "aws:SourceArn"; + + // Test case: value matches one of multiple condition values + // Should return false because value equals at least one condition value + { + Condition arnNotEquals{TokenID::ArnNotEquals, key.data(), key.size(), false}; + arnNotEquals.vals.push_back("arn:aws:s3:::bucket1"); + arnNotEquals.vals.push_back("arn:aws:s3:::bucket2"); + arnNotEquals.vals.push_back("arn:aws:s3:::bucket3"); + + // Input matches second condition value, should return false + EXPECT_FALSE(arnNotEquals.eval({{key, "arn:aws:s3:::bucket2"}})); + } + + // Test case: value doesn't match any condition values + // Should return true because value differs from all condition values + { + Condition arnNotEquals{TokenID::ArnNotEquals, key.data(), key.size(), false}; + arnNotEquals.vals.push_back("arn:aws:s3:::bucket1"); + arnNotEquals.vals.push_back("arn:aws:s3:::bucket2"); + arnNotEquals.vals.push_back("arn:aws:s3:::bucket3"); + + // Input doesn't match any condition value, should return true + EXPECT_TRUE(arnNotEquals.eval({{key, "arn:aws:s3:::other-bucket"}})); + } +} + +TEST_F(ConditionTest, StringNotLikeLogic) +{ + std::string key = "s3:prefix"; + + // Test case: value matches one of multiple condition patterns + // Should return false because value matches at least one condition pattern + { + Condition stringNotLike{TokenID::StringNotLike, key.data(), key.size(), false}; + stringNotLike.vals.push_back("user/*"); + stringNotLike.vals.push_back("admin/*"); + stringNotLike.vals.push_back("temp/*"); + + // Input matches second condition pattern, should return false + EXPECT_FALSE(stringNotLike.eval({{key, "admin/config.txt"}})); + // Input matches first condition pattern, should return false + EXPECT_FALSE(stringNotLike.eval({{key, "user/profile.jpg"}})); + } + + // Test case: value doesn't match any condition patterns + // Should return true because value differs from all condition patterns + { + Condition stringNotLike{TokenID::StringNotLike, key.data(), key.size(), false}; + stringNotLike.vals.push_back("user/*"); + stringNotLike.vals.push_back("admin/*"); + stringNotLike.vals.push_back("temp/*"); + + // Input doesn't match any condition pattern, should return true + EXPECT_TRUE(stringNotLike.eval({{key, "public/document.pdf"}})); + } +}