|
16 | 16 |
|
17 | 17 | package org.springframework.boot.autoconfigure.amqp; |
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 |
|
| 26 | +import javax.net.ssl.SSLEngine; |
| 27 | +import javax.net.ssl.SSLParameters; |
25 | 28 | import javax.net.ssl.SSLSocketFactory; |
26 | 29 |
|
27 | 30 | import com.rabbitmq.client.Address; |
28 | 31 | import com.rabbitmq.client.Connection; |
29 | 32 | import com.rabbitmq.client.JDKSaslConfig; |
| 33 | +import com.rabbitmq.client.SslEngineConfigurator; |
30 | 34 | import com.rabbitmq.client.impl.CredentialsProvider; |
31 | 35 | import com.rabbitmq.client.impl.CredentialsRefreshService; |
32 | 36 | import com.rabbitmq.client.impl.DefaultCredentialsProvider; |
|
38 | 42 | import org.junit.jupiter.api.extension.ExtendWith; |
39 | 43 | import org.junit.jupiter.params.ParameterizedTest; |
40 | 44 | import org.junit.jupiter.params.provider.ValueSource; |
| 45 | +import org.mockito.ArgumentCaptor; |
41 | 46 | import org.mockito.InOrder; |
42 | 47 |
|
43 | 48 | import org.springframework.amqp.core.AcknowledgeMode; |
@@ -843,6 +848,20 @@ void enableSsl() { |
843 | 848 | assertThat(rabbitConnectionFactory.isSSL()).isTrue(); |
844 | 849 | assertThat(rabbitConnectionFactory.getSocketFactory()).as("SocketFactory must use SSL") |
845 | 850 | .isInstanceOf(SSLSocketFactory.class); |
| 851 | + assertThatHostnameVerificationIsEnabled(rabbitConnectionFactory); |
| 852 | + }); |
| 853 | + } |
| 854 | + |
| 855 | + @Test |
| 856 | + void enableSslWithoutHostnameVerification() { |
| 857 | + this.contextRunner.withUserConfiguration(TestConfiguration.class) |
| 858 | + .withPropertyValues("spring.rabbitmq.ssl.enabled:true", "spring.rabbitmq.ssl.verify-hostname:false") |
| 859 | + .run((context) -> { |
| 860 | + com.rabbitmq.client.ConnectionFactory rabbitConnectionFactory = getTargetConnectionFactory(context); |
| 861 | + assertThat(rabbitConnectionFactory.isSSL()).isTrue(); |
| 862 | + assertThat(rabbitConnectionFactory.getSocketFactory()).as("SocketFactory must use SSL") |
| 863 | + .isInstanceOf(SSLSocketFactory.class); |
| 864 | + assertThatHostnameVerificationIsDisabled(rabbitConnectionFactory); |
846 | 865 | }); |
847 | 866 | } |
848 | 867 |
|
@@ -915,6 +934,20 @@ void enableSslWithBundle() { |
915 | 934 | .run((context) -> { |
916 | 935 | com.rabbitmq.client.ConnectionFactory rabbitConnectionFactory = getTargetConnectionFactory(context); |
917 | 936 | assertThat(rabbitConnectionFactory.isSSL()).isTrue(); |
| 937 | + assertThatHostnameVerificationIsEnabled(rabbitConnectionFactory); |
| 938 | + }); |
| 939 | + } |
| 940 | + |
| 941 | + @Test |
| 942 | + void enableSslWithBundleAndWithoutHostnameVerification() { |
| 943 | + this.contextRunner.withUserConfiguration(TestConfiguration.class) |
| 944 | + .withPropertyValues("spring.rabbitmq.ssl.bundle=test-bundle", "spring.rabbitmq.ssl.verify-hostname=false", |
| 945 | + "spring.ssl.bundle.jks.test-bundle.keystore.location=classpath:org/springframework/boot/autoconfigure/amqp/test.jks", |
| 946 | + "spring.ssl.bundle.jks.test-bundle.keystore.password=secret") |
| 947 | + .run((context) -> { |
| 948 | + com.rabbitmq.client.ConnectionFactory rabbitConnectionFactory = getTargetConnectionFactory(context); |
| 949 | + assertThat(rabbitConnectionFactory.isSSL()).isTrue(); |
| 950 | + assertThatHostnameVerificationIsDisabled(rabbitConnectionFactory); |
918 | 951 | }); |
919 | 952 | } |
920 | 953 |
|
@@ -1078,6 +1111,25 @@ void whenADirectContainerCustomizerIsDefinedThenItIsCalledToConfigureTheContaine |
1078 | 1111 | .configure(any(DirectMessageListenerContainer.class))); |
1079 | 1112 | } |
1080 | 1113 |
|
| 1114 | + private void assertThatHostnameVerificationIsEnabled(com.rabbitmq.client.ConnectionFactory rabbitConnectionFactory) |
| 1115 | + throws IOException { |
| 1116 | + SslEngineConfigurator sslEngineConfigurator = rabbitConnectionFactory.getNioParams().getSslEngineConfigurator(); |
| 1117 | + SSLEngine engine = mock(SSLEngine.class); |
| 1118 | + sslEngineConfigurator.configure(engine); |
| 1119 | + ArgumentCaptor<SSLParameters> sslParametersCaptor = ArgumentCaptor.forClass(SSLParameters.class); |
| 1120 | + then(engine).should().setSSLParameters(sslParametersCaptor.capture()); |
| 1121 | + SSLParameters sslParameters = sslParametersCaptor.getValue(); |
| 1122 | + assertThat(sslParameters.getEndpointIdentificationAlgorithm()).isEqualTo("HTTPS"); |
| 1123 | + } |
| 1124 | + |
| 1125 | + private void assertThatHostnameVerificationIsDisabled(com.rabbitmq.client.ConnectionFactory rabbitConnectionFactory) |
| 1126 | + throws IOException { |
| 1127 | + SslEngineConfigurator sslEngineConfigurator = rabbitConnectionFactory.getNioParams().getSslEngineConfigurator(); |
| 1128 | + SSLEngine engine = mock(SSLEngine.class); |
| 1129 | + sslEngineConfigurator.configure(engine); |
| 1130 | + then(engine).shouldHaveNoMoreInteractions(); |
| 1131 | + } |
| 1132 | + |
1081 | 1133 | private com.rabbitmq.client.ConnectionFactory getTargetConnectionFactory(AssertableApplicationContext context) { |
1082 | 1134 | CachingConnectionFactory connectionFactory = context.getBean(CachingConnectionFactory.class); |
1083 | 1135 | return connectionFactory.getRabbitConnectionFactory(); |
|
0 commit comments