Elasticsearch and Microsoft Windows Enterprise Certificate Authority

I'm at a bit of a loss here. I'm attempting to secure the Elastic Stack with certs generated by our organization’s Microsoft Enterprise Certificate Authority. Elasticsearch will happily start, but when I attempt to generate a token for Kibana, I get this error. I currently have a single node:

user@elastic01:~$ sudo /usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token  -f --scope kibana

13:07:52.145 [main] WARN  org.elasticsearch.common.ssl.DiagnosticTrustManager - failed to establish trust with server at [10.141.22.26]; the server provided a certificate with subject name [CN=instance], fingerprint [c79c82d819e87ddecc94fe51234e518d31a76f19], keyUsage [digitalSignature, keyEncipherment] and extendedKeyUsage [serverAuth]; the session uses cipher suite [TLS_AES_256_GCM_SHA384] and protocol [TLSv1.3]; the certificate does not have any subject alternative names; the certificate is issued by [CN=Organization Name,DC=Organization,DC=org] but the server did not provide a copy of the issuing certificate in the certificate chain; the issuing certificate with fingerprint […] is trusted in this ssl context ([xpack.security.http.ssl (with trust configuration: PEM-trust{/etc/elasticsearch/certs/ORG_Root.pem})])
java.security.cert.CertificateException: No subject alternative names present
        at sun.security.util.HostnameChecker.matchIP(HostnameChecker.java:142) ~[?:?]
        at sun.security.util.HostnameChecker.match(HostnameChecker.java:101) ~[?:?]
        at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:452) ~[?:?]
        at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:426) ~[?:?]
        at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:238) ~[?:?]
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:132) ~[?:?]
        at org.elasticsearch.common.ssl.DiagnosticTrustManager.checkServerTrusted(DiagnosticTrustManager.java:82) ~[?:?]
        at sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1335) ~[?:?]
        at sun.security.ssl.CertificateMessage$T13CertificateConsumer.onConsumeCertificate(CertificateMessage.java:1226) ~[?:?]
        at sun.security.ssl.CertificateMessage$T13CertificateConsumer.consume(CertificateMessage.java:1169) ~[?:?]
        at sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396) ~[?:?]
        at sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:480) ~[?:?]
        at sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:458) ~[?:?]
        at sun.security.ssl.TransportContext.dispatch(TransportContext.java:201) ~[?:?]
        at sun.security.ssl.SSLTransport.decode(SSLTransport.java:172) ~[?:?]
        at sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1500) ~[?:?]
        at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1415) ~[?:?]
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:450) ~[?:?]
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:421) ~[?:?]
        at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:578) ~[?:?]
        at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:183) ~[?:?]
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:142) ~[?:?]
        at org.elasticsearch.xpack.core.common.socket.SocketAccess.lambda$doPrivileged$0(SocketAccess.java:42) ~[?:?]
        at java.security.AccessController.doPrivileged(AccessController.java:569) [?:?]
        at org.elasticsearch.xpack.core.common.socket.SocketAccess.doPrivileged(SocketAccess.java:41) [x-pack-core-8.3.2.jar:8.3.2]
        at org.elasticsearch.xpack.core.security.CommandLineHttpClient.execute(CommandLineHttpClient.java:178) [x-pack-core-8.3.2.jar:8.3.2]
        at org.elasticsearch.xpack.core.security.CommandLineHttpClient.execute(CommandLineHttpClient.java:112) [x-pack-core-8.3.2.jar:8.3.2]
        at org.elasticsearch.xpack.security.tool.BaseRunAsSuperuserCommand.checkClusterHealthWithRetries(BaseRunAsSuperuserCommand.java:214) [x-pack-security-8.3.2.jar:8.3.2]
        at org.elasticsearch.xpack.security.tool.BaseRunAsSuperuserCommand.execute(BaseRunAsSuperuserCommand.java:127) [x-pack-security-8.3.2.jar:8.3.2]
        at org.elasticsearch.common.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:54) [elasticsearch-8.3.2.jar:8.3.2]
        at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:85) [elasticsearch-cli-8.3.2.jar:8.3.2]
        at org.elasticsearch.cli.Command.main(Command.java:50) [elasticsearch-cli-8.3.2.jar:8.3.2]
        at org.elasticsearch.launcher.CliToolLauncher.main(CliToolLauncher.java:64) [cli-launcher-8.3.2.jar:8.3.2]

ERROR: Failed to determine the health of the cluster.

The OS is ubuntu 20.04.4 running elasticsearch 8.3.2.

Here are the steps I have taken:

-Generate .CSR with

sudo /usr/share/elasticsearch/bin/elasticsearch-certutil csr

-Input .CSR into the Certificate Authority to generate a .CER
-move certs to /etc/elasticsearch/certs
-add root CA to both the system CA store and the Java cert keystore

Here is the relevant certificate configuration of elasticsearch.yml:

# Enable encryption for HTTP API client connections, such as Kibana, Logstash, and Agents
xpack.security.http.ssl:
  enabled: true
  certificate: certs/elastic01.cer
  key: certs/elastic01.key
  certificate_authorities: certs/ORG_Root.pem

# Enable encryption and mutual authentication between cluster nodes
xpack.security.transport.ssl:
  enabled: true
  verification_mode: certificate
  certificate: certs/elastic01.cer
  key: certs/elastic01.key
  certificate_authorities: certs/ORG_Root.pem

I've tried searching and I'm not finding anything similar to what I'm doing and I’m also not sure what I’m missing here. Let me know if there’s any more information I should provide.

Your HTTP cert is issued to CN=instance and no subject alternative names (SANs). Therefore it does not match the actual hostname and won't pass the hostname verification. You can either:

  • Regenerate the certification to have correct SANs
  • Or skip hostname verification with ./bin/elasticsearch-create-enrollment-token -f --scope kibana -E xpack.security.http.ssl.verification_mode=certificate

Ah! Thank you for responding. I goofed the CSR. I haven't had the time to revisit this, but I will try to this week and see if I can make more progress with this insight.