From: Marcel Lauhoff Date: Tue, 5 May 2026 12:21:03 +0000 (+0200) Subject: rgw: SSE-KMS: Handle Testing Key Per Object X-Git-Tag: v21.0.1~14^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F61256%2Fhead;p=ceph.git rgw: SSE-KMS: Handle Testing Key Per Object The testing backend uses a 'keysel' attribute to derive a per object key from the KEK in the config. A single key_id with distinct keysel has different keys and need to be cached as such. Add the keysel to the cache key id to handle these collisions. Signed-off-by: Marcel Lauhoff On-behalf-of: SAP marcel.lauhoff@sap.com --- diff --git a/src/rgw/rgw_kms.cc b/src/rgw/rgw_kms.cc index c35459d0d85..1961d256123 100644 --- a/src/rgw/rgw_kms.cc +++ b/src/rgw/rgw_kms.cc @@ -1223,6 +1223,15 @@ int reconstitute_actual_key_from_kms( cache_key_id = string_cat_reserve( key_id, "T", calc_hash_sha256(wrapped_key).to_str()); } + } else if (RGW_SSE_KMS_BACKEND_TESTING == kms_backend) { + // The testing backend uses keysel to derive per-object keys with + // the same keyid. + const std::string key_selector = + get_str_attribute(attrs, RGW_ATTR_CRYPT_KEYSEL); + if (!key_selector.empty()) { + cache_key_id = string_cat_reserve( + key_id, "S", calc_hash_sha256(key_selector).to_str()); + } } const auto fetch = [&](std::string& out_secret) -> int { diff --git a/src/test/rgw/test_rgw_kms.cc b/src/test/rgw/test_rgw_kms.cc index e47348419de..f32c0e648e8 100644 --- a/src/test/rgw/test_rgw_kms.cc +++ b/src/test/rgw/test_rgw_kms.cc @@ -2,6 +2,7 @@ // vim: ts=8 sw=2 sts=2 expandtab #include "gtest/gtest.h" +#include #include #include #include "common/ceph_context.h" @@ -316,3 +317,14 @@ TEST_F(TestSSEKMS, test_transit_backend_empty_response) ASSERT_EQ(res, -EINVAL); ASSERT_EQ(actual_key, from_base64("")); } + +TEST_F(TestSSEKMS, TestingBackendDifferentKeyselSameKeyIdDoNotCollide) { + map attrs; + const NoDoutPrefix no_dpp(cct, 1); + cct->_conf->rgw_crypt_s3_kms_encryption_keys = + "foo=IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyM="; + std::string out_a, out_b; + ASSERT_EQ(0, get_actual_key_from_conf(&no_dpp, "foo", gen_rand_alphanumeric(cct, AES_256_KEYSIZE), out_a)); + ASSERT_EQ(0, get_actual_key_from_conf(&no_dpp, "foo", gen_rand_alphanumeric(cct, AES_256_KEYSIZE), out_b)); + ASSERT_NE(out_a, out_b); +} diff --git a/src/test/rgw/test_rgw_kms_cache.cc b/src/test/rgw/test_rgw_kms_cache.cc index 15004a02e5f..7fc3f18fc34 100644 --- a/src/test/rgw/test_rgw_kms_cache.cc +++ b/src/test/rgw/test_rgw_kms_cache.cc @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -351,6 +352,37 @@ TEST_F(TestSSEKMSWithTestingKMS, TestRuntimeEnableDisable) { EXPECT_EQ(cache_perf->get(static_cast(webcache::Metric::size)), 0); } +TEST_F(TestSSEKMSWithTestingKMS, KeyselCollisionAfterClearCache) { + cct->_conf.set_val("rgw_crypt_s3_kms_cache_enabled", "true"); + auto attrs_A = attrs; + auto attrs_B = attrs; + set_attr(attrs_B, RGW_ATTR_CRYPT_KEYSEL, + "\x3a\xa8\x16\xc2\x48\x0e\xb4\x3e\x9b\xff\xab\x7b\xfc\xc2\xc7\xfd" + "\x3a\xa8\x16\xc2\x48\x0e\xb4\x3e\x9b\xff\xab\x7b\xfc\xc2\xc7\xfd"); + + std::string out_A1; + ASSERT_EQ(reconstitute_actual_key_from_kms( + &no_dpp, attrs_A, uut, null_yield, out_A1), + 0); + EXPECT_EQ(out_A1, std::string(32, '*')); + + uut->clear_cache(); + EXPECT_EQ(cache_perf->get(static_cast(webcache::Metric::size)), 0); + + std::string out_B1; + ASSERT_EQ(reconstitute_actual_key_from_kms( + &no_dpp, attrs_B, uut, null_yield, out_B1), + 0); + EXPECT_EQ(out_B1, std::string(32, '+')); + + std::string out_A2; + ASSERT_EQ(reconstitute_actual_key_from_kms( + &no_dpp, attrs_A, uut, null_yield, out_A2), + 0); + EXPECT_EQ(out_A2, out_A1); + EXPECT_NE(out_A2, out_B1); +} + int main(int argc, char** argv) { auto args = argv_to_vec(argc, argv); std::map defaults{