]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw/iam: match value of Null condition
authorCasey Bodley <cbodley@redhat.com>
Tue, 3 Feb 2026 16:44:45 +0000 (11:44 -0500)
committerCasey Bodley <cbodley@redhat.com>
Tue, 3 Feb 2026 18:39:11 +0000 (13:39 -0500)
quoting https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html#Conditions_Null:
> Use a Null condition operator to check if a condition key is absent at the time of authorization. In the policy statement, use either true (the key doesn't exist — it is null) or false (the key exists and its value is not null).

previously, this check acted as if it was always given a value of
"true". instead, convert this decision to a "true"/"false" string
and use `typed_any()` to match that against the parsed `vals`

`runtime_vals` are ignored here because the same document says:
> You can not use a policy variable with the Null condition operator.

Fixes: https://tracker.ceph.com/issues/74736
Signed-off-by: Casey Bodley <cbodley@redhat.com>
src/rgw/rgw_iam_policy.cc
src/test/rgw/test_rgw_iam_policy.cc

index ecd704da78ed4abf76a36a5c3dd71089cbe377bd..5ef051c7a977865c0003536660d4adeca0ae2a7a 100644 (file)
@@ -875,7 +875,8 @@ bool Condition::eval(const Environment& env) const {
   std::vector<std::string> runtime_vals;
   auto i = env.find(key);
   if (op == TokenID::Null) {
-    return i == env.end() ? true : false;
+    const std::string value = (i == env.end() ? "true" : "false");
+    return typed_any(std::equal_to<bool>{}, as_bool, value, vals);
   }
 
   if (i == env.end()) {
index c67f92582bd959f47d83cf7ac48f4fe554444960..956db92c1443afc06025d45037c85fe3b7bf2a4d 100644 (file)
@@ -1763,3 +1763,26 @@ TEST_F(ConditionTest, StringNotLikeLogic)
     EXPECT_TRUE(stringNotLike.eval({{key, "public/document.pdf"}}));
   }
 }
+
+TEST_F(ConditionTest, Null)
+{
+  const std::string key = "s3:prefix";
+
+  {
+    // "Null": {"s3:prefix": "true"}
+    Condition isNull{TokenID::Null, key.data(), key.size(), false};
+    isNull.vals.push_back("true");
+
+    EXPECT_TRUE(isNull.eval({}));
+    EXPECT_FALSE(isNull.eval({{key, "admin/config.txt"}}));
+  }
+
+  {
+    // "Null": {"s3:prefix": "false"}
+    Condition notNull{TokenID::Null, key.data(), key.size(), false};
+    notNull.vals.push_back("false");
+
+    EXPECT_FALSE(notNull.eval({}));
+    EXPECT_TRUE(notNull.eval({{key, "admin/config.txt"}}));
+  }
+}