From df1845c4baa1d6707c6e0657cd7c9d46245f570f Mon Sep 17 00:00:00 2001 From: Chris Bono Date: Tue, 23 Apr 2024 18:15:42 -0500 Subject: [PATCH] Encode JSON string in Pulsar auth params The values in the `spring.pulsar.client.authentication.param` config props map are not currently JSON encoded. For simple values this is fine. However, some custom auth modules may require more complex parameter values that may contain special characters that results in invalid JSON. This commmit encodes the parameter values using a very simple hand-rolled escape function. Fixes #40492 --- .../pulsar/PulsarPropertiesMapper.java | 13 ++++++++++++- .../pulsar/PulsarPropertiesMapperTests.java | 12 ++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapper.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapper.java index 9c33ad4d099a..cad895b269dd 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapper.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapper.java @@ -137,7 +137,7 @@ private String getAuthenticationParamsJson(Map params) { try { return sortedParams.entrySet() .stream() - .map((entry) -> "\"%s\":\"%s\"".formatted(entry.getKey(), entry.getValue())) + .map((entry) -> "\"%s\":\"%s\"".formatted(entry.getKey(), escapeJson(entry.getValue()))) .collect(Collectors.joining(",", "{", "}")); } catch (Exception ex) { @@ -145,6 +145,17 @@ private String getAuthenticationParamsJson(Map params) { } } + private String escapeJson(String raw) { + return raw.replace("\\", "\\\\") + .replace("\"", "\\\"") + .replace("/", "\\/") + .replace("\b", "\\b") + .replace("\t", "\\t") + .replace("\n", "\\n") + .replace("\f", "\\f") + .replace("\r", "\\r"); + } + void customizeProducerBuilder(ProducerBuilder producerBuilder) { PulsarProperties.Producer properties = this.properties.getProducer(); PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapperTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapperTests.java index ea055faa002d..f23584aab0ab 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapperTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapperTests.java @@ -81,8 +81,10 @@ void customizeClientBuilderWhenHasNoAuthentication() { @Test void customizeClientBuilderWhenHasAuthentication() throws UnsupportedAuthenticationException { PulsarProperties properties = new PulsarProperties(); - Map params = Map.of("param", "name"); - String authParamString = "{\"param\":\"name\"}"; + Map params = Map.of("simpleParam", "foo", "complexParam", + "{\n\t\"k1\" : \"v1\",\n\t\"k2\":\"v2\"\n}"); + String authParamString = "{\"complexParam\":\"{\\n\\t\\\"k1\\\" : \\\"v1\\\",\\n\\t\\\"k2\\\":\\\"v2\\\"\\n}\"" + + ",\"simpleParam\":\"foo\"}"; properties.getClient().getAuthentication().setPluginClassName("myclass"); properties.getClient().getAuthentication().setParam(params); ClientBuilder builder = mock(ClientBuilder.class); @@ -166,8 +168,10 @@ void customizeAdminBuilderWhenHasNoAuthentication() { @Test void customizeAdminBuilderWhenHasAuthentication() throws UnsupportedAuthenticationException { PulsarProperties properties = new PulsarProperties(); - Map params = Map.of("param", "name"); - String authParamString = "{\"param\":\"name\"}"; + Map params = Map.of("simpleParam", "foo", "complexParam", + "{\n\t\"k1\" : \"v1\",\n\t\"k2\":\"v2\"\n}"); + String authParamString = "{\"complexParam\":\"{\\n\\t\\\"k1\\\" : \\\"v1\\\",\\n\\t\\\"k2\\\":\\\"v2\\\"\\n}\"" + + ",\"simpleParam\":\"foo\"}"; properties.getAdmin().getAuthentication().setPluginClassName("myclass"); properties.getAdmin().getAuthentication().setParam(params); PulsarAdminBuilder builder = mock(PulsarAdminBuilder.class);