Возникла потребность подключаться из Java приложения к брокеру RabbitMQ с использованием защищенного соединения. Приложение на Spring Boot, живёт в контейнере Docker и должно слушать два узла Rabbit параллельно.На входе: сертификат клиентского узла – контейнер client-cert.pfx, корневой сертификат для него root-cert.crtОткрытый серверный сертификат шлюза Rabbit: выкачивается автоматически (можно подложить вручную)Используемая версия java поддерживает форматы хранилищ и JKS, и PKCS12Требуется: создать и положить сертификаты в Key Store (сертификаты приложения “клиентские”) и Trust Store (доверенные “серверные” сертификаты). В чём разница.Команды для создания KeyStore и TrustStoreНастройки вынесены в переменные в начале списка команд, можно заполнить значения и скопировать всё в консоль целиком.export CLIENT_APP_CRT_NAME=client-cert; # Пароль, заданный при выпуске клиентского сертификата # Он же используется в кач-ве пароля для хранилищ export CRT_STORAGES_PASSWORD='changeit'; export RABBIT_GATEWAY_CRT_NAME=rabbit-gw-dev; export RABBIT_GATEWAY_URL=rabbit-gw-dev.url; export RABBIT_GATEWAY_PORT=1234; export ROOT_CRT_NAME=root-cert; # Извлечь ключ pem и сертификат crt из pfx openssl pkcs12 -in "${CLIENT_APP_CRT_NAME}".pfx -passin pass:"${CRT_STORAGES_PASSWORD}" -nocerts -nodes -out "${CLIENT_APP_CRT_NAME}".pem; openssl pkcs12 -in "${CLIENT_APP_CRT_NAME}".pfx -passin pass:"${CRT_STORAGES_PASSWORD}" -clcerts -nokeys -out "${CLIENT_APP_CRT_NAME}".crt; # Key Store (сертификат приложения) openssl pkcs12 -export -in "${CLIENT_APP_CRT_NAME}".crt -inkey "${CLIENT_APP_CRT_NAME}".pem \ -out "${RABBIT_GATEWAY_CRT_NAME}"_key_store.p12 -name "${RABBIT_GATEWAY_CRT_NAME}" -passout pass:"${CRT_STORAGES_PASSWORD}" \ -CAfile "${ROOT_CRT_NAME}".crt -caname root; # Trust Store (сертификат шлюза) keytool -import -alias "${RABBIT_GATEWAY_URL}"_client -file "${CLIENT_APP_CRT_NAME}".crt -keystore "${RABBIT_GATEWAY_CRT_NAME}"_trust_store.jks \ -noprompt -deststorepass "${CRT_STORAGES_PASSWORD}"; openssl s_client -showcerts -connect "${RABBIT_GATEWAY_URL}":"${RABBIT_GATEWAY_PORT}" -prexit 2>/dev/null | sed -n -e '/BEGIN\ CERTIFICATE/,/END\ CERTIFICATE/ p' \ | tee "${RABBIT_GATEWAY_URL}".cert \ && keytool -import -alias "${RABBIT_GATEWAY_URL}"_server -file "${RABBIT_GATEWAY_URL}".cert -keystore "${RABBIT_GATEWAY_CRT_NAME}"_trust_store.jks \ -noprompt -deststorepass "${CRT_STORAGES_PASSWORD}"; unset CLIENT_APP_CRT_NAME; unset CRT_STORAGES_PASSWORD; unset RABBIT_GATEWAY_CRT_NAME; unset RABBIT_GATEWAY_URL; unset RABBIT_GATEWAY_PORT; unset ROOT_CRT_NAME;Это создаст хранилища с сертификатами KeyStore и TrustStore: rabbit-gw-dev_key_store.p12 и rabbit-gw-dev_trust_store.jksКопирование хранилищ в образ DockerХранилища лежат в репозитории, в каталоге keystore, и копируются в контейнер – также в каталог keystore, расположенный в папке приложения.ADD app-repository/keystore/rabbit-gw-dev_key_store.p12 /app-in-container/keystore/rabbit-gw-dev_key_store.p12 ADD app-repository/keystore/rabbit-gw-dev_trust_store.jks /app-in-container/keystore/rabbit-gw-dev_trust_store.jks ENV SSL_KEYSTORE=/app-in-container/keystore/Через переменную SSL_KEYSTORE можно сослаться на каталог с хранилищами ключей, расположенный в контейнере, из настроек приложения.Включение TLS для RabbitMQ в Spring BootВыдержка из application.yml с настройками, отвечающими за TLS/SSL:spring: rabbitmq: # <-- host, port, username, password ssl: enabled: true keyStore: file:${SSL_KEYSTORE}${RABBIT_SSL_KEY_STORE} key-store-password: ${RABBIT_SSL_KEY_STORE_PASSWORD} trust-store: file:${SSL_KEYSTORE}${RABBIT_SSL_TRUST_STORE} trust-store-password: ${RABBIT_SSL_TRUST_STORE_PASSWORD} multirabbitmq: enabled: true connections: reserve-gateway: # <-- host, port, username, password ssl: enabled: ${spring.rabbitmq.ssl.enabled} keyStore: ${spring.rabbitmq.ssl.keyStore} key-store-password: ${spring.rabbitmq.ssl.key-store-password} trust-store: ${spring.rabbitmq.ssl.trust-store} trust-store-password: ${spring.rabbitmq.ssl.trust-store-password}Дополнительно здесь используется Spring MultiRabbit Library для одновременного подключения к нескольким узлам RabbitMQ. Чтобы вручную СontainerFactory/RabbitTemplate для слушателей не создавать/настраивать.Ранее писал про обертку для Testcontainers, в которой тоже используется эта библиотека.Дополнительно – в документации RabbitMQ описано TLS подключение “голого” java client из кода, без использования Spring.Итог и дополнительные ссылкиВ целом – всё оказалось несложно (когда один раз проделаешь этот путь). Основная “проблема” – правильно создать KeyStore и TrustStore с сертификатами. Ну и базово понять разницу межу типами хранилищ KeyStore / TrustStore.Ссылки по теме (глубже в теорию):Java Secure Socket Extension (JSSE) Reference GuideThe Transport Layer Security (TLS) Protocol RFCИсходник в ТГ | на сайте#rabbitmq #ssl #tls #java #springboot