diff --git a/buildSrc/src/main/groovy/io.micronaut.build.internal.rabbitmq-examples.gradle b/buildSrc/src/main/groovy/io.micronaut.build.internal.rabbitmq-examples.gradle index 2602b05be..716645658 100644 --- a/buildSrc/src/main/groovy/io.micronaut.build.internal.rabbitmq-examples.gradle +++ b/buildSrc/src/main/groovy/io.micronaut.build.internal.rabbitmq-examples.gradle @@ -10,7 +10,7 @@ dependencies { testImplementation mnSerde.micronaut.serde.support testImplementation mnSerde.micronaut.serde.jackson testImplementation libs.awaitility - testImplementation 'io.micronaut.testresources:micronaut-test-resources-client' + testImplementation mnTestResources.micronaut.test.resources.client } configurations.all { resolutionStrategy.dependencySubstitution { diff --git a/settings.gradle b/settings.gradle index 515581782..024a3cfdc 100644 --- a/settings.gradle +++ b/settings.gradle @@ -18,6 +18,8 @@ include 'docs-examples:example-groovy' include 'docs-examples:example-java' include 'docs-examples:example-kotlin' +include 'tests:rabbitmq-ssl' + enableFeaturePreview 'TYPESAFE_PROJECT_ACCESSORS' micronautBuild { diff --git a/tests/rabbitmq-ssl/build.gradle.kts b/tests/rabbitmq-ssl/build.gradle.kts new file mode 100644 index 000000000..c68f108c3 --- /dev/null +++ b/tests/rabbitmq-ssl/build.gradle.kts @@ -0,0 +1,24 @@ +plugins { + groovy + id("io.micronaut.build.internal.rabbitmq-base") + id("io.micronaut.minimal.application") +} + +dependencies { + testImplementation(projects.micronautRabbitmq) + + testImplementation(mnSerde.micronaut.serde.support) + testImplementation(mnSerde.micronaut.serde.jackson) + testImplementation(mn.micronaut.management) + testImplementation(mn.reactor) + + testImplementation(mnTest.micronaut.test.spock) + testImplementation(mnTestResources.testcontainers.core) + testImplementation(mnTestResources.testcontainers.rabbitmq) + testImplementation(libs.awaitility) +} + +micronaut { + version(libs.versions.micronaut.platform.get()) + testRuntime("junit5") +} diff --git a/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/AbstractRabbitMQSSLTest.groovy b/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/AbstractRabbitMQSSLTest.groovy new file mode 100644 index 000000000..ddc62c2c2 --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/AbstractRabbitMQSSLTest.groovy @@ -0,0 +1,77 @@ +package io.micronaut.rabbitmq.ssl + +import com.rabbitmq.client.ConnectionFactory +import io.micronaut.context.ApplicationContext +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.testcontainers.containers.RabbitMQContainer +import spock.lang.AutoCleanup +import spock.lang.Shared +import spock.lang.Specification +import spock.util.concurrent.PollingConditions + +import javax.net.ssl.KeyManagerFactory +import javax.net.ssl.SSLContext +import javax.net.ssl.TrustManagerFactory +import java.security.KeyStore + +abstract class AbstractRabbitMQSSLTest extends Specification { + private static final Logger log = LoggerFactory.getLogger(AbstractRabbitMQSSLTest) + + private static final int AMQP_PORT = 5672 + private static final int AMQPS_PORT = 5671 + + public static final String RABBIT_CONTAINER_VERSION = "3.13.1" + + @Shared + @AutoCleanup + RabbitMQContainer rabbitContainer = new RabbitMQContainer("rabbitmq:" + RABBIT_CONTAINER_VERSION) + + def setupSpec() { + rabbitContainer.start() + } + + protected ApplicationContext applicationContext + protected PollingConditions conditions = new PollingConditions(timeout: 5) + + protected void startContext(Map additionalConfig = [:]) { + applicationContext = ApplicationContext.run( + ["rabbitmq.port": rabbitContainer.getMappedPort(AMQPS_PORT), + "spec.name": getClass().simpleName] << additionalConfig, "test") + } + + protected void waitFor(Closure conditionEvaluator) { + conditions.eventually conditionEvaluator + } + + void cleanup() { + applicationContext?.close() + } + + // TODO this is example from rabbitmq TLS docs to integrate, and change test to use the connection + // https://www.rabbitmq.com/ssl.html#java-client-connecting-with-peer-verification + void configureForSsl(ConnectionFactory factory) { + char[] keyPassphrase = "MySecretPassword".toCharArray() + KeyStore ks = KeyStore.getInstance("PKCS12") + ks.load(new FileInputStream("/path/to/client_key.p12"), keyPassphrase) + + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509") + kmf.init(ks, keyPassphrase) + + char[] trustPassphrase = "rabbitstore".toCharArray() + KeyStore tks = KeyStore.getInstance("JKS") + tks.load(new FileInputStream("/path/to/trustStore"), trustPassphrase) + + TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509") + tmf.init(tks) + + SSLContext sslContext = SSLContext.getInstance("TLSv1.2") + sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null) + + factory.setHost("localhost") + factory.setPort(AMQPS_PORT) + factory.enableHostnameVerification() + // this is the key part, using no-arg factory.useSslProtocol() is not adequate for prod use + factory.useSslProtocol(sslContext) + } +} diff --git a/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/RabbitSSLHealthIndicatorSpec.groovy b/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/RabbitSSLHealthIndicatorSpec.groovy new file mode 100644 index 000000000..c27230eac --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/RabbitSSLHealthIndicatorSpec.groovy @@ -0,0 +1,60 @@ +package io.micronaut.rabbitmq.ssl + +import io.micronaut.context.ApplicationContext +import io.micronaut.health.HealthStatus +import io.micronaut.management.health.indicator.HealthResult +import io.micronaut.rabbitmq.health.RabbitMQHealthIndicator +import reactor.core.publisher.Mono + +class RabbitSSLHealthIndicatorSpec extends AbstractRabbitMQSSLTest { + + void "test rabbitmq health indicator"() { + given: + startContext() + + when: + RabbitMQHealthIndicator healthIndicator = applicationContext.getBean(RabbitMQHealthIndicator) + HealthResult result = Mono.from(healthIndicator.result).block() + def details = result.details + + then: + result.status == HealthStatus.UP + details.version.toString() == RABBIT_CONTAINER_VERSION + } + + void "test rabbitmq health indicator with 2 connections"() { + given: + applicationContext = ApplicationContext.run([ + "rabbitmq.servers.one.port": rabbitContainer.getMappedPort(5672), + "rabbitmq.servers.two.port": rabbitContainer.getMappedPort(5672) + ], "test") + + when: + RabbitMQHealthIndicator healthIndicator = applicationContext.getBean(RabbitMQHealthIndicator) + HealthResult result = Mono.from(healthIndicator.result).block() + def details = result.details + + then: + result.status == HealthStatus.UP + details.get("connections")[0].get("version").toString() == RABBIT_CONTAINER_VERSION + details.get("connections")[1].get("version").toString() == RABBIT_CONTAINER_VERSION + } + + void "test rabbitmq health indicator shows down"() { + given: + startContext() + + when: + RabbitMQHealthIndicator healthIndicator = applicationContext.getBean(RabbitMQHealthIndicator) + rabbitContainer.stop() + HealthResult result = Mono.from(healthIndicator.result).block() + def details = result.details + + then: + result.status == HealthStatus.DOWN + details.get("error").toString().contains("RabbitMQ connection is not open") + + cleanup: + rabbitContainer.start() + } +} diff --git a/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/Animal.groovy b/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/Animal.groovy new file mode 100644 index 000000000..ebeca5f44 --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/Animal.groovy @@ -0,0 +1,12 @@ +package io.micronaut.rabbitmq.ssl.exchange + +abstract class Animal { + + String name + + Animal(String name) { + this.name = name + } + + Animal() {} +} diff --git a/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/AnimalClient.groovy b/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/AnimalClient.groovy new file mode 100644 index 000000000..3a79bb974 --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/AnimalClient.groovy @@ -0,0 +1,16 @@ +package io.micronaut.rabbitmq.ssl.exchange + +import io.micronaut.context.annotation.Requires +import io.micronaut.messaging.annotation.MessageHeader +import io.micronaut.rabbitmq.annotation.RabbitClient + +@Requires(property = "spec.name", value = "CustomSSLExchangeSpec") +@RabbitClient("animals") +abstract class AnimalClient { + + abstract void send(@MessageHeader String animalType, Animal animal) + + void send(Animal animal) { + send(animal.getClass().simpleName, animal) + } +} diff --git a/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/AnimalListener.groovy b/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/AnimalListener.groovy new file mode 100644 index 000000000..e6c7e8668 --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/AnimalListener.groovy @@ -0,0 +1,23 @@ +package io.micronaut.rabbitmq.ssl.exchange + +import io.micronaut.context.annotation.Requires +import io.micronaut.rabbitmq.annotation.Queue +import io.micronaut.rabbitmq.annotation.RabbitListener +import java.util.concurrent.CopyOnWriteArrayList + +@Requires(property = "spec.name", value = "CustomSSLExchangeSpec") +@RabbitListener +class AnimalListener { + + CopyOnWriteArrayList receivedAnimals = [] + + @Queue("cats") + void receive(Cat cat) { + receivedAnimals << cat + } + + @Queue("snakes") + void receive(Snake snake) { + receivedAnimals << snake + } +} diff --git a/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/Cat.groovy b/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/Cat.groovy new file mode 100644 index 000000000..2ed85ede5 --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/Cat.groovy @@ -0,0 +1,16 @@ +package io.micronaut.rabbitmq.ssl.exchange + +import io.micronaut.serde.annotation.Serdeable + +@Serdeable +class Cat extends Animal { + + int lives + + Cat(String name, int lives) { + super(name) + this.lives = lives + } + + Cat() {} +} diff --git a/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/ChannelPoolListener.groovy b/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/ChannelPoolListener.groovy new file mode 100644 index 000000000..aaf2a3aeb --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/ChannelPoolListener.groovy @@ -0,0 +1,29 @@ +package io.micronaut.rabbitmq.ssl.exchange + +import com.rabbitmq.client.Channel +import io.micronaut.context.annotation.Requires +import io.micronaut.rabbitmq.connect.ChannelInitializer +import jakarta.inject.Singleton + +@Requires(property = "spec.name", value = "CustomSSLExchangeSpec") +@Singleton +class ChannelPoolListener extends ChannelInitializer { + + @Override + void initialize(Channel channel, String name) throws IOException { + + channel.exchangeDeclare("animals", "headers", false) + channel.queueDeclare("snakes", false, false, false, null) + channel.queueDeclare("cats", false, false, false, null) + + Map catArgs = [:] + catArgs.put("x-match", "all") + catArgs.put("animalType", "Cat") + channel.queueBind("cats", "animals", "", catArgs) + + Map snakeArgs = [:] + snakeArgs.put("x-match", "all") + snakeArgs.put("animalType", "Snake") + channel.queueBind("snakes", "animals", "", snakeArgs) + } +} diff --git a/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/CustomSSLExchangeSpec.groovy b/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/CustomSSLExchangeSpec.groovy new file mode 100644 index 000000000..241cff567 --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/CustomSSLExchangeSpec.groovy @@ -0,0 +1,46 @@ +package io.micronaut.rabbitmq.ssl.exchange + +import io.micronaut.context.annotation.Property +import io.micronaut.rabbitmq.ssl.AbstractRabbitMQSSLTest + +import static java.util.concurrent.TimeUnit.SECONDS +import static org.awaitility.Awaitility.await + +@Property(name = "spec.name", value = "CustomSSLExchangeSpec") +class CustomSSLExchangeSpec extends AbstractRabbitMQSSLTest { + + void "test using a custom exchange"() { + given: + startContext() + AnimalClient client = applicationContext.getBean(AnimalClient) + AnimalListener listener = applicationContext.getBean(AnimalListener) + + when: + client.send(new Cat("Whiskers", 9)) + client.send(new Cat("Mr. Bigglesworth", 8)) + client.send(new Snake("Buttercup", false)) + client.send(new Snake("Monty the Python", true)) + await().atMost(10, SECONDS).until { + listener.receivedAnimals.size() == 4 + } + + then: + assert listener.receivedAnimals.size() == 4 + + assert listener.receivedAnimals.find({ animal -> + animal instanceof Cat && animal.name == "Whiskers" && ((Cat) animal).lives == 9 + }) != null + + assert listener.receivedAnimals.find({ animal -> + animal instanceof Cat && animal.name == "Mr. Bigglesworth" && ((Cat) animal).lives == 8 + }) != null + + assert listener.receivedAnimals.find({ animal -> + animal instanceof Snake && animal.name == "Buttercup" && !((Snake) animal).venomous + }) != null + + assert listener.receivedAnimals.find({ animal -> + animal instanceof Snake && animal.name == "Monty the Python" && ((Snake) animal).venomous + }) != null + } +} diff --git a/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/Snake.groovy b/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/Snake.groovy new file mode 100644 index 000000000..fcf54df39 --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/groovy/io/micronaut/rabbitmq/ssl/exchange/Snake.groovy @@ -0,0 +1,16 @@ +package io.micronaut.rabbitmq.ssl.exchange + +import io.micronaut.serde.annotation.Serdeable + +@Serdeable +class Snake extends Animal { + + boolean venomous + + Snake(String name, boolean venomous) { + super(name) + this.venomous = venomous + } + + Snake() {} +} diff --git a/tests/rabbitmq-ssl/src/test/resources/certs/README.md b/tests/rabbitmq-ssl/src/test/resources/certs/README.md new file mode 100644 index 000000000..5029f2e5c --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/resources/certs/README.md @@ -0,0 +1,34 @@ +These long-lived certificates were created to test the SSL, they are in no way secure. + +To create them, [I followed the instructions here](https://www.rabbitmq.com/ssl.html#automated-certificate-generation-transcript) and [here](https://github.com/rabbitmq/tls-gen): + +Which are: + +``` +git clone https://github.com/rabbitmq/tls-gen tls-gen +``` + +then: + +``` +cd tls-gen/basic +``` + +then: + +``` +# pass a private key password using the PASSWORD variable if needed +make + +## copy or move files to use hostname-neutral filenames +## such as client_certificate.pem and client_key.pem, +## this step is optional +make alias-leaf-artifacts +``` + +with output in + +``` +# results will be under the ./result directory +ls -lha ./result +``` diff --git a/tests/rabbitmq-ssl/src/test/resources/certs/ca_certificate.pem b/tests/rabbitmq-ssl/src/test/resources/certs/ca_certificate.pem new file mode 100644 index 000000000..f2624773d --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/resources/certs/ca_certificate.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDhjCCAm6gAwIBAgIUL3ko+j/fKeQcunx4z8GTOFVJnr4wDQYJKoZIhvcNAQEL +BQAwTDE7MDkGA1UEAwwyVExTR2VuU2VsZlNpZ25lZHRSb290Q0EgMjAyNC0wMS0z +MVQxMjo0NToxMi4zMDU5MjcxDTALBgNVBAcMBCQkJCQwHhcNMjQwMTMxMTg0NTEy +WhcNMzQwMTI4MTg0NTEyWjBMMTswOQYDVQQDDDJUTFNHZW5TZWxmU2lnbmVkdFJv +b3RDQSAyMDI0LTAxLTMxVDEyOjQ1OjEyLjMwNTkyNzENMAsGA1UEBwwEJCQkJDCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMuZ40lG2vNxmZgQXbHdcsO2 +fyjqb3BYKzyYU4TTVtdeiFhsPah09xysxKnH3x2QvsSsu9OufC3lrncOsxQy9Blq +4oftSoEaoPzu6AF/XpQIgoiFGMfRGhgu418kfw83Q6FVBTci5bScM1WpVupUeaq4 +UsCJQg9N1XVKneSB7XYFlscWgZ7Q4lTF4XgxYv51m+U15TcRGfufBCZjJ7q6hjmJ +3F2fS8mdzN80pGIH5F0d9oIgWbWlW35GvZBsARzWloUmSx17ct143nC/+ZGSjPb4 +GfnLduiKQhOgCQpJxvhFA+FAGsxJEUMw5y47fjgFqpgUzn3NRn+gOwaF9wVtOBsC +AwEAAaNgMF4wDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYE +FFpQX25GFoEkCJ80NujkEqf+bW0zMB8GA1UdIwQYMBaAFFpQX25GFoEkCJ80Nujk +Eqf+bW0zMA0GCSqGSIb3DQEBCwUAA4IBAQClBkxZ4x2wbg355jf3XR3pY1zq6AFr +1/+PX/spnFSVW/JcJChDyAvUbDmqTn+NQoWAqJruo0S3YXJ8uHY44ybc1UE/WUnb +I//hy11WPEU615rvgINRWvZiv+9zRHVnN9oeIV/egfKhTkbOxFq2vCBHD3oIKvzs +f89eIpT4o65wiXgfZo3yDY/69wCfUvSp2r0mI/c//d9haz30bEjlyy8twZn3WW9b +D1H5dlYiIj1/iQm1viiwFsM5hD1byYcF/vl1yRReoTdyTXMQc/K4YbdLPeyJMdee +2aJXrflCCGATDR0amspESgfpbUWE60aT4oPeiehxulNlKNPd2UwLdGrA +-----END CERTIFICATE----- diff --git a/tests/rabbitmq-ssl/src/test/resources/certs/ca_key.pem b/tests/rabbitmq-ssl/src/test/resources/certs/ca_key.pem new file mode 100644 index 000000000..0b2c0d21e --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/resources/certs/ca_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDLmeNJRtrzcZmY +EF2x3XLDtn8o6m9wWCs8mFOE01bXXohYbD2odPccrMSpx98dkL7ErLvTrnwt5a53 +DrMUMvQZauKH7UqBGqD87ugBf16UCIKIhRjH0RoYLuNfJH8PN0OhVQU3IuW0nDNV +qVbqVHmquFLAiUIPTdV1Sp3kge12BZbHFoGe0OJUxeF4MWL+dZvlNeU3ERn7nwQm +Yye6uoY5idxdn0vJnczfNKRiB+RdHfaCIFm1pVt+Rr2QbAEc1paFJksde3LdeN5w +v/mRkoz2+Bn5y3boikIToAkKScb4RQPhQBrMSRFDMOcuO344BaqYFM59zUZ/oDsG +hfcFbTgbAgMBAAECggEAW4FNz/yq4hfv1pKgcZScBE8Mpoh6zkyqHgE+JCfR01jW +wZrgOUpcV4RknQPKCKEpw/34KsK0Z/Je735pSM4/u/64Uiv5PL4JlbQQDMBAcxrC +A/aBtSiK6EyGfxfJjT6ixCsQfX/PKlW7kqfZeta9mddexc7KpFMweRcwkGc+oLhD +7tMGJ8T5XaYYGepbVb9SKmJuWX766ggqTUhERgSwTGg0eHydOlybz5cOudLDUJ2C +kiOFl0C0JX4VNUfgjYajWncHMwhmgAF2UyChrWcGAOlB9g6unEyGtbMnetmyyDf5 +LfPJZYEc3w4XopzQsDEesbfar5kWDcJ+LyZG58YggQKBgQDuD2TVBe8TUMP7ATas +ojKC4A5rEzISCP+9s1Ux7TgiGPrzdMh/P7W375EMYZgb7gdDU7ok13YNaHRlE6ma +eFBQtFrR4vzqPL6O7sNxP8+VTqXIb7jBeIskBrnan/I8gUL86fyX0YvlGmXRn9ov +Fic+p96h9pIsgV/l1mFXA8demwKBgQDa8bfPfHSv852n+UWlrSj3xzf5w814jZR2 +7ivrOQ+go9iBSy5iaJgN8k3Ypi+AF6V0Puhe76SoI6FYp1ZxST3hBVgIiAMB3nMr +OHL67qS45c5vzwQhwP2BS5HIPVYj8k9oScRQkkFr5oEoeJ4Ks2LDBMHx749KCB60 +0oP+tiZkgQKBgQDsyP8AK7DKw5DLfz+EoqgfKQDuW993tN+7Lj7VNCCbOcGSmlw6 +xYHX/D+H0yLa1P0AaK1Dq9POLlFnoBEYhgdM3rdfAKmTyuu3e6GGaXPuDJY1MXrR +ZTbwlIgT/veQWvnoWkxWLaU6MfGIebkpEJ3kYlC9RGXMQrrB/2Q+ipGpdQKBgAny +5elVvG+qYEWbvCB1J+Fqeg6taQ7LUC2/UNuVcjJYf6QQaIEsQ4yOsB7iHlJxwKDx +otl9hjvlspU2tWTccSVieseYdpqFIzKZlA/2/CEywBiwjX2DKYHQj0VMFDf58MXK +ZFNM8hAXH1NZd8UAtcIq2y1FN3ujttF8p2bRnBkBAoGAKJkJXKjdL7zLPjbZ0+8k +cLMuhiPEf0N8jQKhV2gdlY6taxCgclGibxTvKfLAWel5iNjObsLzmHp49nue0WEM +B0c20n2dBL24tIhkI2ZgGKtsBxpte2f6xRcyLjcP5E7agioA65JKOBMn/e4Egi95 +pSMwTYNa/yKzqAcfD+TXGA4= +-----END PRIVATE KEY----- diff --git a/tests/rabbitmq-ssl/src/test/resources/certs/client_certificate.pem b/tests/rabbitmq-ssl/src/test/resources/certs/client_certificate.pem new file mode 100644 index 000000000..2611ee18e --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/resources/certs/client_certificate.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIID9TCCAt2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADBMMTswOQYDVQQDDDJUTFNH +ZW5TZWxmU2lnbmVkdFJvb3RDQSAyMDI0LTAxLTMxVDEyOjQ1OjEyLjMwNTkyNzEN +MAsGA1UEBwwEJCQkJDAeFw0yNDAxMzExODQ1MTJaFw0zNDAxMjgxODQ1MTJaMDgx +JTAjBgNVBAMMHE9DSTE5NjJNQlAxNElOQ0gyMDIxLTIubG9jYWwxDzANBgNVBAoM +BmNsaWVudDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANrFrnEtjP+k +G4M3htnTTSZQPwtNS5cDiPjmGrucUpWtottmBh8VxkLxrHUI47yZPEvBvn+IPAh3 +wiZV9+52p0AUCjoYIEU+sbCcbiX+CpIwwoTgZl0ueVT3XJYcB8qbwPWxMJY4TTXf +BrLBGZK7IhrVgQZfnBmXFb4ZM1qViys7Ej7euB5i4x9jehknVOfXiRDm0QRbhjD7 +rciBXv1Xan2AaFEpPyCIl2U2Jnx8BPvNfUOnz7w2b3iYWTyLg2XYgYPLjdPZte/8 +jU2cuyEDPKBbEXyY/nIynXm2LgJKVYNmX05ephTBUUYLlwcj5/Dm0W3vzQUkElrj +TqMJvzvrcckCAwEAAaOB9TCB8jAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDATBgNV +HSUEDDAKBggrBgEFBQcDAjBQBgNVHREESTBHghxPQ0kxOTYyTUJQMTRJTkNIMjAy +MS0yLmxvY2FsghxPQ0kxOTYyTUJQMTRJTkNIMjAyMS0yLmxvY2Fsgglsb2NhbGhv +c3QwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDovL2NybC1zZXJ2ZXI6ODAwMC9iYXNp +Yy5jcmwwHQYDVR0OBBYEFHGRR6Ljf5bxZvrq8Ov2kPM18cUrMB8GA1UdIwQYMBaA +FFpQX25GFoEkCJ80NujkEqf+bW0zMA0GCSqGSIb3DQEBCwUAA4IBAQCocmWrhcMn +RghbEvbTBWd9aLbLhKxarXydryRYGOznvKXDNhA4282T1NPfQYrNAlm2FzikD8UR +g1q8pvXyr56KKcgh/jAzRMtNzG1A3CUrkTzRTBPlVTDvykMdgArt8Mt34BHzN+Fc +YIp//preToBqtNUPj5/o4apUO9CnjLFERfDKz4j7jU+mXW/UOAGL6RSC3t7ytN8v +YTX4V3KtAysp8S08CQvi7qOiy4agt9z/ae95aEDmMDOTGC57Jn3ULAPyQ9RYjyis +gYUHo/009KkYSRXgQ90N9EqY9yeMZLRulWrycqtwaWACOrFhAl7j3hDejbJHPTOg +uZrB58/oPkIR +-----END CERTIFICATE----- diff --git a/tests/rabbitmq-ssl/src/test/resources/certs/client_key.pem b/tests/rabbitmq-ssl/src/test/resources/certs/client_key.pem new file mode 100644 index 000000000..96f4848e4 --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/resources/certs/client_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDaxa5xLYz/pBuD +N4bZ000mUD8LTUuXA4j45hq7nFKVraLbZgYfFcZC8ax1COO8mTxLwb5/iDwId8Im +VffudqdAFAo6GCBFPrGwnG4l/gqSMMKE4GZdLnlU91yWHAfKm8D1sTCWOE013way +wRmSuyIa1YEGX5wZlxW+GTNalYsrOxI+3rgeYuMfY3oZJ1Tn14kQ5tEEW4Yw+63I +gV79V2p9gGhRKT8giJdlNiZ8fAT7zX1Dp8+8Nm94mFk8i4Nl2IGDy43T2bXv/I1N +nLshAzygWxF8mP5yMp15ti4CSlWDZl9OXqYUwVFGC5cHI+fw5tFt780FJBJa406j +Cb8763HJAgMBAAECggEABsMQxutwgz+loLhTpmHzQtmSHp2kq3tEKDqnMuCnENH4 +HwNCnIKwyRrtM1ozUn4DW21r9PHXYS+fxE2TRz9K9h5oc9k7uMgyTSeDTrtRGlRV +ftlCG2PiA4VNyvn80lS0HHlTQMwRXuE7iho72cmHnqq2EpCxTifZrTGG4Sg5eqbf +IfqeR6QvEjWRkYxldMV+t7qc8D/0I7BCWdm43d5NLBSDqV9Iyes3SLR8nvPZ0lpJ +3QHS6m+aFb2KawGhVv95qqpsEEwF+HcG4ErqTLzpImjOBEEd+0tDgoyclgQh/6j7 +RcaFDIqiiCwEs331xuuzUIDrzGCkGVw4PDvPPW867QKBgQDxJ1G0GLP5RSjeap2a +CbC0H2oEIXhif8pucU9ZTtTwNKo8kw5lC0wcfptAndzLH7mO71oUs5/g2kwmRpET ++o8WioYsNXHbMZ5DhYT4lONfzH22s/rDKT4863GnPie3dZA1CP4rgRKbLgGiFAB2 +SULJ8XtiVJssO3ef+E9i3QnYrwKBgQDoPZ9EBV80iM181KqhO+NpEoPARAsm8F+J ++V8XNzrGJb472V4FyLwYrD9RG/CkXuhNn4nFHGf77y9SnNVc2Ktcduv7X0o0v1Zo +31SkN+NNLfAWyOVlEG68agYe42LblZG4A4SaX9K4REk0PipnI25UuDOsSMPQrjAK +ccSUaNkLBwKBgQDLFIeTmLIHGxy9oR8zlzF9nm7TJ7SPjnpU44sk9GQSHOe3t0eK +BCeGX4AyvD4xuHe1TQ+ZG2NqIau7F/YY0woou2MeW6uUIYbb6db+17Na+4Rqlcp5 +C4RkHQpLAubDcneMkhQpYrref7HUYe+5rRxXn8p+Fi3O5A1rY9rGsMoX9QKBgGPx +GNfh4+2srZl5v5AxQJUYBaC453+zU7oBmb1Y5C8fUPVafo7IqsGHZpwWBQIHYbr9 +3AD6T3lonhnUKjGRgHUDLFx5zmpSqPHqofcloei1yytS+vz6DF2C1u119zX98L6a +rPbuI7VulX4o/oByC+njd0E98x6bx0rHWMxxLm4DAoGBAOWwMtoFOGgob8AEsjWK +JAY6xCmRvMy8X6fJMPAUu5UPs5YienH/lOAA9NimGiKorv2po66IbUIHZKcB0u9q +8tjVKLBLpk0pcbvVjXVOaCbIe9o95zx32/6q9urbxEwXfOaSbPUkHOlFNL9aUcM7 +/QX2VQP692OkBfnFbz7b+6+5 +-----END PRIVATE KEY----- diff --git a/tests/rabbitmq-ssl/src/test/resources/certs/server_certificate.pem b/tests/rabbitmq-ssl/src/test/resources/certs/server_certificate.pem new file mode 100644 index 000000000..ab6348ee9 --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/resources/certs/server_certificate.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIID9TCCAt2gAwIBAgIBATANBgkqhkiG9w0BAQsFADBMMTswOQYDVQQDDDJUTFNH +ZW5TZWxmU2lnbmVkdFJvb3RDQSAyMDI0LTAxLTMxVDEyOjQ1OjEyLjMwNTkyNzEN +MAsGA1UEBwwEJCQkJDAeFw0yNDAxMzExODQ1MTJaFw0zNDAxMjgxODQ1MTJaMDgx +JTAjBgNVBAMMHE9DSTE5NjJNQlAxNElOQ0gyMDIxLTIubG9jYWwxDzANBgNVBAoM +BnNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKH6/fuEPTxE +gwo2f/QwVNraHAuUq6sMAmEVt32vpIuowGBfGF+vY/lbxIkth+xxcwd6MJsj2+6j +nYqhshR4sP4nkAibBWLCkoyhvyCVNYUKZE2d1O9KKPCb8qLQWT+HUa1Aoj2Y3VtP +r/nLVtOdOcuQlg9TXQO+0VHWNc79M7+2OVlNOuQhd242KmhdoBlmKt08v8AqFUrr +/A7tNFBpIJzgLWWSsd0oOyro3la5BiWayUaiLJ4duEObfaEhVcdNQ7y4F+V7zQ7k +qYoXWUoVMm64rrLm2xbFYFyVO+Kg5afSuzDv1Rpxs/uC9N9/iqGfVQ+VmTvdo9bB +hHz5YCBURb8CAwEAAaOB9TCB8jAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDATBgNV +HSUEDDAKBggrBgEFBQcDATBQBgNVHREESTBHghxPQ0kxOTYyTUJQMTRJTkNIMjAy +MS0yLmxvY2FsghxPQ0kxOTYyTUJQMTRJTkNIMjAyMS0yLmxvY2Fsgglsb2NhbGhv +c3QwHQYDVR0OBBYEFJUg4IXhSInutFaGhubhCSp+SAdmMB8GA1UdIwQYMBaAFFpQ +X25GFoEkCJ80NujkEqf+bW0zMDEGA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly9jcmwt +c2VydmVyOjgwMDAvYmFzaWMuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQBYn2uzM0Ac +LjcXFK30AHkjjcy2MFil9soWTC2lfU6Xo4/voSKUm66J4O+7+7r9HsM1uag14ZJE +iiK1qsDICx10sTIcz1/gvzvrrK+h9xUZOu/upEyITvBlB4qvdqw8hE9yaYhriODf +19FKAZ6yyGilJieytmVm6RZCbLD16ZlPmCeIRRbvNnc5H+5ghhqWGghF9hZp7Dsx +JStWe8IwhDdIPmUVGjzOiu/cbBDPmfMbj+MVCAqiqDVylNVoz5dXgVranwbFCTf7 +wa0CGZzYft903q602fqv8Bfo8iWAqfhNMqZn8wBvzsst+CNEOQt9ySaxUvMOZC06 +wmzFTCQD2OhI +-----END CERTIFICATE----- diff --git a/tests/rabbitmq-ssl/src/test/resources/certs/server_key.pem b/tests/rabbitmq-ssl/src/test/resources/certs/server_key.pem new file mode 100644 index 000000000..c432670e5 --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/resources/certs/server_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCh+v37hD08RIMK +Nn/0MFTa2hwLlKurDAJhFbd9r6SLqMBgXxhfr2P5W8SJLYfscXMHejCbI9vuo52K +obIUeLD+J5AImwViwpKMob8glTWFCmRNndTvSijwm/Ki0Fk/h1GtQKI9mN1bT6/5 +y1bTnTnLkJYPU10DvtFR1jXO/TO/tjlZTTrkIXduNipoXaAZZirdPL/AKhVK6/wO +7TRQaSCc4C1lkrHdKDsq6N5WuQYlmslGoiyeHbhDm32hIVXHTUO8uBfle80O5KmK +F1lKFTJuuK6y5tsWxWBclTvioOWn0rsw79UacbP7gvTff4qhn1UPlZk73aPWwYR8 ++WAgVEW/AgMBAAECggEAAKzx+jvm9Xq5ATCRAA0OODYd/9Oy6O0NOtJtstHUtzBm +UlXoiB2h0Rxs3sBDMjKW7uUM5ti+G2oF8i9nyrtmIZPl/ziGS+R72qeiCxoUNbss +B+wsmILlViY7BirQSc+Kq6pQAunBopaGfrLhEyjeC4H4M5V+wdE965V1IVPfr2EA +Jn5cC/YoDDY1s2VHs5LwHj8tRWMSCLUSyGV2XNdMb+XiZaQfcC6Fq/jywAmlXG7q +B0lkR8d6fleT7SjO4HUipzB29GGUIwEE6WCI9rKyWYIybJWIOTJEchlS35ZQ4FWQ +6r3OD8tvZ0q+MVFkv8Gyjjizz6wUbTjwdxXFMKz3IQKBgQDSUKEdKSfOVALEgi8M +Ed3/vbXwbrUm1lGP67uk1Px0uXp28bmPSCa4Pxv8mlpXefgSCQ0pMeIksVInzGra +XztBerom+Pq3ycncLjSrYtU3/F1vKw5dL9nqUq3tjYDqryP47uv+mrho6np5G4Q0 +VryKgFJipCShtz0urN4g62bWjQKBgQDFKolExCabpTLbB5rRqyXNmpFAbdvfraJk +hF5uGvYWyX8JUQUUj2xrWvxIdhEyV7WjskL/1Bt6I7Pawoq9p78saYfL6sGI3F+Q +bANz7c/bCPJp4cx/F8l0cmSFrKyokT5yDEQFtAT4lyPQoCebJaDwGVLK2MLn7Yj/ +n87QRaPwewKBgHK2a8peAko15HSOlV69+BpfvXbwy3ntd/tKFsUnLrPz3uo1moKe +VhA0y+0Ru6ju6/HaYgVQIgrldOwkQTvuqYFjkVlkgEvyklm4Eh5Q//9TdRsHnwQQ +74kxo5BomCJpePN0TeBHP8Jp8ndQHOH3VUsuBsGqyhgyu/pTa60E+MiZAoGAUrfI +xS/h3rTNBDVJj6NVBdBOFhDBCTOIiNE76Meo7OB2SotSLVEKtHOEmkXmaw9/JgE4 +uKndKT3nS+UIXg8NVm2jyjpgHbIO6cFXJYDlDkjPovpXWA67tv3zDF3oRgRBhYl9 +1EK1PzHxlapLU3zS60hEgtOz2ae/LTd3hcthvxcCgYBr58v24iXhzQkAJ7t7QjX0 +Su/Mr9pm5p2Gao27aDui4meksQyIA8z/Cvqh7MGxH/REJyQCb+dsrj7MtLBW3Hzb +ORVQIBQ9zuYoDl4KLUBEkWROynmkxdMJFs35l2Hv4+X10uRO73VnS7ERjfjZ/yyO +b2qcoIWmU5XfGXf0L7Y58w== +-----END PRIVATE KEY----- diff --git a/tests/rabbitmq-ssl/src/test/resources/logback.xml b/tests/rabbitmq-ssl/src/test/resources/logback.xml new file mode 100644 index 000000000..23b8f36f9 --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/resources/logback.xml @@ -0,0 +1,17 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + diff --git a/tests/rabbitmq-ssl/src/test/resources/rabbit/definitions.json b/tests/rabbitmq-ssl/src/test/resources/rabbit/definitions.json new file mode 100644 index 000000000..5a2d9bc38 --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/resources/rabbit/definitions.json @@ -0,0 +1,67 @@ +{ + "rabbit_version": "3.8.2", + "rabbitmq_version": "3.8.2", + "users": [ + { + "name": "guest", + "password_hash": "G0NloEh/Nnuyyqh0X3GZG2o3yaiokMXzK7PMaZYSSv4NZesQ", + "hashing_algorithm": "rabbit_password_hashing_sha256", + "tags": "administrator" + } + ], + "vhosts": [ + { + "name": "/" + } + ], + "permissions": [ + { + "user": "guest", + "vhost": "/", + "configure": ".*", + "write": ".*", + "read": ".*" + } + ], + "topic_permissions": [], + "parameters": [], + "global_parameters": [ + { + "name": "cluster_name", + "value": "rabbit@e0d6c0a4fb65" + } + ], + "policies": [], + "queues": [ + { + "name": "test-durable-queue", + "vhost": "/", + "durable": true, + "auto_delete": false, + "arguments": { + "x-queue-type": "classic" + } + } + ], + "exchanges": [ + { + "name": "test-exchange", + "vhost": "/", + "type": "fanout", + "durable": true, + "auto_delete": false, + "internal": false, + "arguments": {} + } + ], + "bindings": [ + { + "source": "test-exchange", + "vhost": "/", + "destination": "test-durable-queue", + "destination_type": "queue", + "routing_key": "", + "arguments": {} + } + ] +} diff --git a/tests/rabbitmq-ssl/src/test/resources/rabbit/rabbitmq.conf b/tests/rabbitmq-ssl/src/test/resources/rabbit/rabbitmq.conf new file mode 100644 index 000000000..a1535dd1f --- /dev/null +++ b/tests/rabbitmq-ssl/src/test/resources/rabbit/rabbitmq.conf @@ -0,0 +1,19 @@ +loopback_users.guest = false +listeners.ssl.default = 5671 +listeners.tcp.default = 5672 +management.tcp.port = 15672 + +consumer_timeout = 5000 + +management.load_definitions = /etc/rabbitmq/definitions.json + +cluster_formation.peer_discovery_backend = classic_config +cluster_formation.classic_config.nodes.1 = rabbit@rabbitmq1 +cluster_formation.classic_config.nodes.2 = rabbit@rabbitmq2 +cluster_formation.classic_config.nodes.3 = rabbit@rabbitmq3 + +ssl_options.cacertfile = /path/to/ca_certificate.pem +ssl_options.certfile = /path/to/server_certificate.pem +ssl_options.keyfile = /path/to/server_key.pem +ssl_options.verify = verify_peer +ssl_options.fail_if_no_peer_cert = true