我有ActiveMQ Artemis集群,具有共享存储的活动备份模式,版本2.17.0。SSL用于此群集。
我从Kafka集群中获取了密钥库/信任库文件,该文件与双向TLS完全兼容。我用阿尔忒弥斯重复使用这些文件,它也非常好用。但是,当我在URL字符串中启用needClientAuth=true
时,问题就出现了。
以下是文档说明:
needClientAuth
此属性仅适用于
acceptor
。它告诉连接到此接收器的客户端需要双向SSL。有效值为true
或false
。默认值为false
。
因此,如果我想实现双向TLS,我必须使用此选项。然后,服务器和客户端都必须有自己的密钥库/信任库对。在我的情况下,服务器和客户端都是相同的。
当我在接收器URL字符串中有needClientAuth=true
时,我使用Artemis CLI连接到Artemis集群,这就是我在CLI输出中得到的:
Connection failed::Failed to create session factory
这就是阿尔忒弥斯实例所说的:
WARN [org.apache.activemq.artemis.core.server] AMQ222208: SSL handshake failed for client from /123.123.123.123:36788: javax.net.ssl.SSLHandshakeException: Empty client certificate chain.
正如我所说,提到的密钥库/信任库与Kafka配合良好,没有问题。但是,它不适用于ActiveMQ Artemis。如果我从acceptor
URL字符串中删除needClientAuth=true
,那么一切都很好。
以下是我如何生成密钥库/信任库:
# Generate private key and CSR
openssl req -new -newkey rsa:2048 -nodes -days 365 -subj '/CN=something.com/OU=XXX/O=Company/L=City/ST=City/C=XX' -keyout private.key -out mycsr.csr
# Upload CSR to magic website, get back CA and signed certificate.
# ...
# Since CA is chain, and you cannot import chain into keystore/truststore, split into multiple files: ca1.cer and ca2.cer.
# ...
# Create truststore.jks
keytool -importcert -noprompt -alias ca1 -file ca1.cer -keystore truststore.jks
keytool -importcert -noprompt -alias ca2 -file ca2.cer -keystore truststore.jks
# Because it's impossible to create JKS keystore out of private key, first generate PKCS12 keystore:
openssl pkcs12 -inkey private.key -in certificate.cer -export -out keystore.p12
# Now convert PKCS12 keystore to JKS keystore:
keytool -importkeystore -srckeystore keystore.p12 -srcstoretype pkcs12 -destkeystore keystore.jks -deststoretype jks
# Since above command added only a private key, we also need to add an issued certificate:
keytool -importcert -noprompt -alias certificate -file certificate.cer -keystore keystore.jks
# Some client's (in Kafka) does not work if CA is not added to keystore, so add it:
keytool -importcert -noprompt -alias ca1 -file ca1.cer -keystore keystore.jks
keytool -importcert -noprompt -alias ca2 -file ca2.cer -keystore keystore.jks
# End up with the following files:
keystore.jks
truststore.jks
---------
ca.cer
certificate.cer
private.key
接受方URL(带needClientAuth=true
(:
tcp://server.com:1234?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;amqpMinLargeMessageSize=102400;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE;useEpoll=true;amqpCredits=1000;amqpLowCredits=300;amqpDuplicateDetection=true;sslEnabled=true;needClientAuth=true;keyStorePath=/opt/ssl/keystore.jks;keyStorePassword=123;trustStorePath=/opt/ssl/truststore.jks;trustStorePassword=123
当使用ActiveMQ Artemis CLI进行连接时,我会传递以下URL:
tcp://server.com:1234?sslEnabled=true;keyStorePath=/opt/ssl/truststore.jks;keyStorePassword=123;trustStorePath=/opt/ssl/truststore.jks;trustStorePassword=123
我缺少什么
经纪人和客户都需要拥有自己的证书。您似乎只创建了一个证书,并在代理和客户端上使用它。
例如,代理需要在其密钥库中有自己的证书,该证书将呈现给客户端,并且客户端在其信任库中也有该证书。然后,客户端需要在其密钥库中拥有自己的证书,并将其呈现给代理,代理拥有的证书是其信任库。
据我所知,你没有这么做。看看ActiveMQ Artemis附带的ssl-enabled-dual-authentication
示例。它包含使用自签名证书运行所需的所有keytool
命令。一旦你用简单的自签名证书启动并运行了它,你就可以使用证书颁发机构签名的证书了。
值得注意的是,如果您使用由证书颁发机构签名的证书,您只需将CA的根证书导入到代理和客户端上的JVM信任库中,就不需要破坏任何单独的信任库。客户端和代理将隐含地信任由您的CA签名的证书。
最后,您在ActiveMQ Artemis CLI中使用的URL看起来不正确,因为keyStorePath
正在引用信任库/opt/ssl/truststore.jks
。