Skip to content

Commit c329c5f

Browse files
quaffphilwebb
authored andcommitted
Add spring.rabbitmq.template.allowed-list-patterns property
Update `RabbitProperties` and `RabbitTemplateConfigurer` to support a `spring.rabbitmq.template.allowed-list-patterns` property. The can be used to prevent errors of the form: java.lang.SecurityException: Attempt to deserialize unauthorized class com.example.domain.Message; add allowed class name patterns to the message converter or, if you trust the message orginiator, set environment variable 'SPRING_AMQP_DESERIALIZATION_TRUST_ALL' or system property 'spring.amqp.deserialization.trust.all' to true See gh-40421
1 parent 4ce7366 commit c329c5f

File tree

3 files changed

+52
-0
lines changed

3 files changed

+52
-0
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitProperties.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
* @author Rafael Carvalho
4949
* @author Scott Frederick
5050
* @author Lasse Wulff
51+
* @author Yanming Zhou
5152
* @since 1.0.0
5253
*/
5354
@ConfigurationProperties(prefix = "spring.rabbitmq")
@@ -1015,6 +1016,11 @@ public static class Template {
10151016
*/
10161017
private boolean observationEnabled;
10171018

1019+
/**
1020+
* Simple patterns for allowable packages/classes for deserialization.
1021+
*/
1022+
private List<String> allowedListPatterns;
1023+
10181024
public Retry getRetry() {
10191025
return this.retry;
10201026
}
@@ -1075,6 +1081,14 @@ public void setObservationEnabled(boolean observationEnabled) {
10751081
this.observationEnabled = observationEnabled;
10761082
}
10771083

1084+
public List<String> getAllowedListPatterns() {
1085+
return this.allowedListPatterns;
1086+
}
1087+
1088+
public void setAllowedListPatterns(List<String> allowedListPatterns) {
1089+
this.allowedListPatterns = allowedListPatterns;
1090+
}
1091+
10781092
}
10791093

10801094
public static class Retry {

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitTemplateConfigurer.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
2323
import org.springframework.amqp.rabbit.core.RabbitTemplate;
24+
import org.springframework.amqp.support.converter.AllowedListDeserializingMessageConverter;
2425
import org.springframework.amqp.support.converter.MessageConverter;
2526
import org.springframework.boot.context.properties.PropertyMapper;
2627
import org.springframework.util.Assert;
@@ -29,6 +30,7 @@
2930
* Configure {@link RabbitTemplate} with sensible defaults.
3031
*
3132
* @author Stephane Nicoll
33+
* @author Yanming Zhou
3234
* @since 2.3.0
3335
*/
3436
public class RabbitTemplateConfigurer {
@@ -102,6 +104,12 @@ public void configure(RabbitTemplate template, ConnectionFactory connectionFacto
102104
map.from(templateProperties::getRoutingKey).to(template::setRoutingKey);
103105
map.from(templateProperties::getDefaultReceiveQueue).whenNonNull().to(template::setDefaultReceiveQueue);
104106
map.from(templateProperties::isObservationEnabled).to(template::setObservationEnabled);
107+
if (templateProperties.getAllowedListPatterns() != null) {
108+
MessageConverter messageConverter = template.getMessageConverter();
109+
if (messageConverter instanceof AllowedListDeserializingMessageConverter mc) {
110+
mc.setAllowedListPatterns(templateProperties.getAllowedListPatterns());
111+
}
112+
}
105113
}
106114

107115
private boolean determineMandatoryFlag() {

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/amqp/RabbitAutoConfigurationTests.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.boot.autoconfigure.amqp;
1818

1919
import java.security.NoSuchAlgorithmException;
20+
import java.util.Collection;
2021
import java.util.List;
2122
import java.util.concurrent.ThreadFactory;
2223
import java.util.concurrent.atomic.AtomicInteger;
@@ -35,6 +36,8 @@
3536
import org.junit.jupiter.api.condition.EnabledForJreRange;
3637
import org.junit.jupiter.api.condition.JRE;
3738
import org.junit.jupiter.api.extension.ExtendWith;
39+
import org.junit.jupiter.params.ParameterizedTest;
40+
import org.junit.jupiter.params.provider.ValueSource;
3841
import org.mockito.InOrder;
3942

4043
import org.springframework.amqp.core.AcknowledgeMode;
@@ -59,7 +62,9 @@
5962
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
6063
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
6164
import org.springframework.amqp.rabbit.retry.MessageRecoverer;
65+
import org.springframework.amqp.support.converter.AllowedListDeserializingMessageConverter;
6266
import org.springframework.amqp.support.converter.MessageConverter;
67+
import org.springframework.amqp.support.converter.SerializerMessageConverter;
6368
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
6469
import org.springframework.boot.autoconfigure.AutoConfigurations;
6570
import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration;
@@ -107,6 +112,7 @@
107112
* @author Andy Wilkinson
108113
* @author Phillip Webb
109114
* @author Scott Frederick
115+
* @author Yanming Zhou
110116
*/
111117
@ExtendWith(OutputCaptureExtension.class)
112118
class RabbitAutoConfigurationTests {
@@ -796,6 +802,20 @@ void customizeRequestedChannelMax() {
796802
});
797803
}
798804

805+
@SuppressWarnings("unchecked")
806+
@ParameterizedTest
807+
@ValueSource(classes = { TestConfiguration.class, TestConfiguration6.class })
808+
void customizeAllowedListPatterns(Class<?> configuration) {
809+
this.contextRunner.withUserConfiguration(configuration)
810+
.withPropertyValues("spring.rabbitmq.template.allowed-list-patterns:*")
811+
.run((context) -> {
812+
MessageConverter messageConverter = context.getBean(RabbitTemplate.class).getMessageConverter();
813+
assertThat(messageConverter).isInstanceOfSatisfying(AllowedListDeserializingMessageConverter.class,
814+
(mc) -> assertThat(mc).extracting("allowedListPatterns")
815+
.isInstanceOfSatisfying(Collection.class, (set) -> assertThat(set).contains("*")));
816+
});
817+
}
818+
799819
@Test
800820
void noSslByDefault() {
801821
this.contextRunner.withUserConfiguration(TestConfiguration.class).run((context) -> {
@@ -1113,6 +1133,16 @@ RabbitListenerContainerFactory<?> rabbitListenerContainerFactory() {
11131133

11141134
}
11151135

1136+
@Configuration(proxyBeanMethods = false)
1137+
static class TestConfiguration6 {
1138+
1139+
@Bean
1140+
MessageConverter messageConverter() {
1141+
return new SerializerMessageConverter();
1142+
}
1143+
1144+
}
1145+
11161146
@Configuration(proxyBeanMethods = false)
11171147
static class MessageConvertersConfiguration {
11181148

0 commit comments

Comments
 (0)