diff --git a/metadata/src/main/java/org/apache/kafka/image/ScramImage.java b/metadata/src/main/java/org/apache/kafka/image/ScramImage.java index 60c28d8f72ec3..e33e60cf65efb 100644 --- a/metadata/src/main/java/org/apache/kafka/image/ScramImage.java +++ b/metadata/src/main/java/org/apache/kafka/image/ScramImage.java @@ -46,7 +46,11 @@ public record ScramImage(Map> m public static final ScramImage EMPTY = new ScramImage(Map.of()); public ScramImage { - mechanisms = Collections.unmodifiableMap(mechanisms); + Map> wrapped = new HashMap<>(mechanisms.size()); + for (var entry : mechanisms.entrySet()) { + wrapped.put(entry.getKey(), Collections.unmodifiableMap(entry.getValue())); + } + mechanisms = Collections.unmodifiableMap(wrapped); } public void write(ImageWriter writer, ImageWriterOptions options) { diff --git a/metadata/src/main/java/org/apache/kafka/metadata/ScramCredentialData.java b/metadata/src/main/java/org/apache/kafka/metadata/ScramCredentialData.java index ff35881baaa22..685e225ecbbad 100644 --- a/metadata/src/main/java/org/apache/kafka/metadata/ScramCredentialData.java +++ b/metadata/src/main/java/org/apache/kafka/metadata/ScramCredentialData.java @@ -25,7 +25,7 @@ import java.util.Objects; /** - * Represents the ACLs in the metadata image. + * Represents SCRAM credential data in the metadata image. *

* This class is thread-safe. */ diff --git a/metadata/src/test/java/org/apache/kafka/image/ScramImageTest.java b/metadata/src/test/java/org/apache/kafka/image/ScramImageTest.java index 4ee6d2e9b0bec..da5641531b0ed 100644 --- a/metadata/src/test/java/org/apache/kafka/image/ScramImageTest.java +++ b/metadata/src/test/java/org/apache/kafka/image/ScramImageTest.java @@ -17,16 +17,20 @@ package org.apache.kafka.image; +import org.apache.kafka.clients.admin.ScramMechanism; import org.apache.kafka.image.writer.ImageWriterOptions; import org.apache.kafka.image.writer.RecordListWriter; import org.apache.kafka.metadata.RecordTestUtils; +import org.apache.kafka.metadata.ScramCredentialData; import org.apache.kafka.server.common.ApiMessageAndVersion; import org.apache.kafka.server.common.MetadataVersion; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -67,6 +71,22 @@ public void testImage2RoundTrip() { testToImage(IMAGE2); } + @Test + public void testMechanismMapsAreUnmodifiable() { + ScramCredentialData credential = new ScramCredentialData( + new byte[] {1}, new byte[] {2}, new byte[] {3}, 4096); + Map credentials = new HashMap<>(); + credentials.put("alice", credential); + Map> mechanisms = new HashMap<>(); + mechanisms.put(ScramMechanism.SCRAM_SHA_256, credentials); + + ScramImage image = new ScramImage(mechanisms); + + assertThrows(UnsupportedOperationException.class, () -> image.mechanisms().clear()); + assertThrows(UnsupportedOperationException.class, + () -> image.mechanisms().get(ScramMechanism.SCRAM_SHA_256).clear()); + } + private static void testToImage(ScramImage image) { testToImage(image, Optional.empty()); }