|
16 | 16 |
|
17 | 17 | package org.springframework.boot.amqp.autoconfigure; |
18 | 18 |
|
| 19 | +import java.io.IOException; |
19 | 20 | import java.security.NoSuchAlgorithmException; |
20 | 21 | import java.util.Collection; |
21 | 22 | import java.util.List; |
22 | 23 | import java.util.concurrent.ThreadFactory; |
23 | 24 | import java.util.concurrent.atomic.AtomicInteger; |
24 | 25 | import java.util.function.BiFunction; |
25 | 26 |
|
| 27 | +import javax.net.ssl.SSLEngine; |
| 28 | +import javax.net.ssl.SSLParameters; |
26 | 29 | import javax.net.ssl.SSLSocketFactory; |
27 | 30 |
|
28 | 31 | import com.rabbitmq.client.Address; |
29 | 32 | import com.rabbitmq.client.Connection; |
30 | 33 | import com.rabbitmq.client.JDKSaslConfig; |
| 34 | +import com.rabbitmq.client.SslEngineConfigurator; |
31 | 35 | import com.rabbitmq.client.impl.CredentialsProvider; |
32 | 36 | import com.rabbitmq.client.impl.CredentialsRefreshService; |
33 | 37 | import com.rabbitmq.client.impl.DefaultCredentialsProvider; |
|
39 | 43 | import org.junit.jupiter.api.extension.ExtendWith; |
40 | 44 | import org.junit.jupiter.params.ParameterizedTest; |
41 | 45 | import org.junit.jupiter.params.provider.ValueSource; |
| 46 | +import org.mockito.ArgumentCaptor; |
42 | 47 | import org.mockito.InOrder; |
43 | 48 |
|
44 | 49 | import org.springframework.amqp.core.AcknowledgeMode; |
@@ -875,6 +880,20 @@ void enableSsl() { |
875 | 880 | assertThat(rabbitConnectionFactory.isSSL()).isTrue(); |
876 | 881 | assertThat(rabbitConnectionFactory.getSocketFactory()).as("SocketFactory must use SSL") |
877 | 882 | .isInstanceOf(SSLSocketFactory.class); |
| 883 | + assertThatHostnameVerificationIsEnabled(rabbitConnectionFactory); |
| 884 | + }); |
| 885 | + } |
| 886 | + |
| 887 | + @Test |
| 888 | + void enableSslWithoutHostnameVerification() { |
| 889 | + this.contextRunner.withUserConfiguration(TestConfiguration.class) |
| 890 | + .withPropertyValues("spring.rabbitmq.ssl.enabled:true", "spring.rabbitmq.ssl.verify-hostname:false") |
| 891 | + .run((context) -> { |
| 892 | + com.rabbitmq.client.ConnectionFactory rabbitConnectionFactory = getTargetConnectionFactory(context); |
| 893 | + assertThat(rabbitConnectionFactory.isSSL()).isTrue(); |
| 894 | + assertThat(rabbitConnectionFactory.getSocketFactory()).as("SocketFactory must use SSL") |
| 895 | + .isInstanceOf(SSLSocketFactory.class); |
| 896 | + assertThatHostnameVerificationIsDisabled(rabbitConnectionFactory); |
878 | 897 | }); |
879 | 898 | } |
880 | 899 |
|
@@ -947,6 +966,20 @@ void enableSslWithBundle() { |
947 | 966 | .run((context) -> { |
948 | 967 | com.rabbitmq.client.ConnectionFactory rabbitConnectionFactory = getTargetConnectionFactory(context); |
949 | 968 | assertThat(rabbitConnectionFactory.isSSL()).isTrue(); |
| 969 | + assertThatHostnameVerificationIsEnabled(rabbitConnectionFactory); |
| 970 | + }); |
| 971 | + } |
| 972 | + |
| 973 | + @Test |
| 974 | + void enableSslWithBundleAndWithoutHostnameVerification() { |
| 975 | + this.contextRunner.withUserConfiguration(TestConfiguration.class) |
| 976 | + .withPropertyValues("spring.rabbitmq.ssl.bundle=test-bundle", "spring.rabbitmq.ssl.verify-hostname=false", |
| 977 | + "spring.ssl.bundle.jks.test-bundle.keystore.location=classpath:org/springframework/boot/amqp/autoconfigure/test.jks", |
| 978 | + "spring.ssl.bundle.jks.test-bundle.keystore.password=secret") |
| 979 | + .run((context) -> { |
| 980 | + com.rabbitmq.client.ConnectionFactory rabbitConnectionFactory = getTargetConnectionFactory(context); |
| 981 | + assertThat(rabbitConnectionFactory.isSSL()).isTrue(); |
| 982 | + assertThatHostnameVerificationIsDisabled(rabbitConnectionFactory); |
950 | 983 | }); |
951 | 984 | } |
952 | 985 |
|
@@ -1110,6 +1143,27 @@ void whenADirectContainerCustomizerIsDefinedThenItIsCalledToConfigureTheContaine |
1110 | 1143 | .configure(any(DirectMessageListenerContainer.class))); |
1111 | 1144 | } |
1112 | 1145 |
|
| 1146 | + @SuppressWarnings("deprecation") |
| 1147 | + private void assertThatHostnameVerificationIsEnabled(com.rabbitmq.client.ConnectionFactory rabbitConnectionFactory) |
| 1148 | + throws IOException { |
| 1149 | + SslEngineConfigurator sslEngineConfigurator = rabbitConnectionFactory.getNioParams().getSslEngineConfigurator(); |
| 1150 | + SSLEngine engine = mock(SSLEngine.class); |
| 1151 | + sslEngineConfigurator.configure(engine); |
| 1152 | + ArgumentCaptor<SSLParameters> sslParametersCaptor = ArgumentCaptor.forClass(SSLParameters.class); |
| 1153 | + then(engine).should().setSSLParameters(sslParametersCaptor.capture()); |
| 1154 | + SSLParameters sslParameters = sslParametersCaptor.getValue(); |
| 1155 | + assertThat(sslParameters.getEndpointIdentificationAlgorithm()).isEqualTo("HTTPS"); |
| 1156 | + } |
| 1157 | + |
| 1158 | + @SuppressWarnings("deprecation") |
| 1159 | + private void assertThatHostnameVerificationIsDisabled(com.rabbitmq.client.ConnectionFactory rabbitConnectionFactory) |
| 1160 | + throws IOException { |
| 1161 | + SslEngineConfigurator sslEngineConfigurator = rabbitConnectionFactory.getNioParams().getSslEngineConfigurator(); |
| 1162 | + SSLEngine engine = mock(SSLEngine.class); |
| 1163 | + sslEngineConfigurator.configure(engine); |
| 1164 | + then(engine).shouldHaveNoMoreInteractions(); |
| 1165 | + } |
| 1166 | + |
1113 | 1167 | private com.rabbitmq.client.ConnectionFactory getTargetConnectionFactory(AssertableApplicationContext context) { |
1114 | 1168 | CachingConnectionFactory connectionFactory = context.getBean(CachingConnectionFactory.class); |
1115 | 1169 | return connectionFactory.getRabbitConnectionFactory(); |
|
0 commit comments