Mutual Authentication in ActiveMQ Artemis cluster fails to get hostname from client IP address

134 Views Asked by At

I have set up an ActiveMQ Artemis cluster (version 2.27.1) to use mutual authentication. When the second node tries to connect to the first one, I get an error

WARN  [org.apache.activemq.artemis.core.server] AMQ222208: SSL handshake failed for client from /10.226.95.134:46882: java.security.cert.CertificateException: No subject alternative names matching IP address 10.226.95.134 found.

The hostname of the client is in the SAN of the certificate in the truststore. I can't figure out how to configure the acceptor to use the hostname instead of the IP address.

The broker.xml configuration is

<acceptor name="netty-master-acceptor01">
tcp://dev-artemis01:61617?sslEnabled=true;needClientAuth=true;verifyHost=true;keyStorePath=/keys/keystore.jks;keyStorePassword=123;trustStorePath=/keys/trusted_keystore.jks;trustStorePassword=password;protocols=CORE,AMQP
</acceptor>

...

<connector name="netty-master-connector02">
tcp://artemis02:61617?sslEnabled=true;keyStorePath=/keys/keystore.jks;keyStorePassword=123;trustStorePath=/keys/trusted_keystore.jks;trustStorePassword=password
</connector>

I ran openssl commands between artemis01 and artemis02 servers and they worked

openssl s_server -accept 3000 -key dev_artemis.key -cert dev-artemis.pem -CAfile dev-artemis.pem -state

openssl s_client -connect dev-artemis01:3000 -key dev_artemis.key -cert dev-artemis.pem -CAfile dev-artemis.pem -state

How can I configure the acceptor to use hostnames (which are in the SAN) instead of the raw IP addresses?

Edit:
This is what keytool shows in the certificate

keytool -list  -v -storepass 123 -keystore keystore-dev-artemisrr.jks
Keystore type: PKCS12
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: dev-artemisrr
Creation date: Jul 13, 2023
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=dev-artemisrr, OU=cfrm, O="Example Technologies, Inc.", L=Portsmouth, ST=New Hampshire, C=US
Issuer: CN=dev-artemisrr, OU=cfrm, O="Example Technologies, Inc.", L=Portsmouth, ST=New Hampshire, C=US
Serial number: 88da32c
Valid from: Thu Jul 13 15:55:28 EDT 2023 until: Sun Jul 12 15:55:28 EDT 2026
Certificate fingerprints:
     SHA1: 73:50:59:55:2B:18:F1:32:E2:DA:FA:C0:C1:C6:5A:F2:14:3F:91:D8
     SHA256: 09:36:4C:59:63:45:5B:72:59:54:2A:83:48:74:43:F0:63:D5:A3:42:DB:35:E5:C6:E5:33:D8:2B:A4:85:37:3A
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3

Extensions: 

#1: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
  DNSName: dev-artemisrr01-blue
  DNSName: dev-artemisrr02-blue
  DNSName: dev-artemisrr03-blue
  DNSName: dev-artemisrr01-green
  DNSName: dev-artemisrr02-green
  DNSName: dev-artemisrr03-green
]

#2: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: F8 7C 9C 65 AF FF 8F B6   BA 3E A0 26 46 C7 1C AA  ...e.....>.&F...
0010: F3 C9 43 9F                                        ..C.
]
]

*******************************************
*******************************************

I used the following script to create the certificate

#!/bin/bash
# Create Artemis Cluster Certificate.  

set -e

function createSAN()
{
    env=$1
    num_servers=$2
    server_type=$3
    alias_server_type="$server_type"0
    
    san="SAN="

    for ((i=0; i < $num_servers; i++)); 
    do
        san+="DNS:$env-$alias_server_type$((i+1))-blue,"
    done
    
    for ((i=0; i < $num_servers; i++)); 
    do
        san+="DNS:$env-$alias_server_type$((i+1))-green,"
    done

    # truncate the last comma
    san=${san%?}
    
    echo $san
}

function createCertificate()
{
    env=$1
    num_servers=$2
    server_type=$3

    echo -e "\nCreating $server_type certificate..."
    
    createSAN $env $num_servers $server_type
    
    # Create the certificate
    cn=$env-$server_type
    keytool -keystore keystore-$env-$server_type.jks -keyalg RSA -genkey -alias $env-$server_type -ext "$san" -dname "CN=$cn,OU=engineering,O=Ajax Technologies\, Inc.,L=Portsmouth,ST=New Hampshire,C=US" -validity 1095 -storepass $password -keypass $password
    
    # convert to pkcs12
    keytool -importkeystore -srckeystore keystore-$env-$server_type.jks -destkeystore keystore-$env-$server_type.p12 -deststoretype pkcs12 -deststorepass $password -srcstorepass $password
    
    # Extract the SSL certificate 
    openssl pkcs12 -nokeys -chain -in keystore-$env-$server_type.p12 -out $env-$server_type.crt -password pass:$password 
    
    # Extract the key
    openssl pkcs12 -nocerts -nodes -in keystore-$env-$server_type.p12 -out $env-$server_type.key -password pass:$password
    
    # Remove the bag attributes to be loaded into trusted keystore
    openssl x509 -in $env-$server_type.crt -out $env-$server_type.pem   
}

function createTrustedKeystore()
{
    # keytool -import -file C:\cacerts\firstCA.cert -alias firstCA -keystore myTrustStore
    for file in *.pem; do
        alias="$(basename "$file" | cut -d '.' -f1)"
        keytool -import -noprompt -file $alias.pem -alias $alias -keystore trusted_keystore.jks -storepass password
    done

}

rm -f *.jks *.p12 *.crt *.key

password=secret
createCertificate dev 3 artemis

password=password
createTrustedKeystore

I modified the configurations a little to remove some private information and uploaded the files in the etc folder to https://gist.github.com/milindrao/935f86f30a6f921da915ed44d17e4f1a

What's making this even more difficult to debug is that setting -Djavax.net.debug=all in the artemis.profile file is not spitting out any SSL logs in the artemis.log file. In fact, modifying the log4j2.properties file to add ssl logging won't even allow the artemis service to start.

logger.handshake.name=javax.net.ssl
logger.handshake.level=DEBUG
0

There are 0 best solutions below