Я пытаюсь получить доступ к экземпляру 6.x ES с помощью клиента REST высокого уровня 6.7.2.
Доступ к этому экземпляру ES предоставляется мне через имя хоста (https://****.azureedge.net), имя пользователя и пароль.
Мое приложение Spring Boot без проблем получает данные из той же ES, когда оно запускается из моей среды разработки (IDE), но выдает исключение SSLHandshakeException, как только я пытаюсь запустить его из контейнера Docker (с моей машины разработки или кластера K8s в облаке). ).
Контейнер сделан с базовым образом: FROM debian:stretch-slim
& OpenJDK 11.0.2
с необходимыми модулями Spring Boot.
Я добился некоторого прогресса в отладке с -Djavax.net.debug=all
. Оказывается, что во время работы в образе докера происходит всего несколько первых шагов обычного SSL-квитирования:
Produced ClientHello handshake message
WRITE: TLS13 handshake, length = 2352
Raw write
Raw read (0000: 15 03 03 00 02 02 28 ......( )
READ: TLSv1.2 alert, length = 2
Received alert message (
"Alert": {
"level" : "fatal",
"description": "handshake_failure"
}
)
, за которым следует SSLHandshakeException:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at org.elasticsearch.client.RestClient$SyncResponseListener.get(RestClient.java:938)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:227)
at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1764)
at org.elasticsearch.client.RestHighLevelClient.performRequest(RestHighLevelClient.java:1749)
at org.elasticsearch.client.RestHighLevelClient.performRequestAndParseEntity(RestHighLevelClient.java:1708)
at org.elasticsearch.client.SecurityClient.getSslCertificates(SecurityClient.java:508)
....
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at java.base/sun.security.ssl.Alert.createSSLException(Unknown Source)
at java.base/sun.security.ssl.Alert.createSSLException(Unknown Source)
at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source)
at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Unknown Source)
at java.base/sun.security.ssl.TransportContext.dispatch(Unknown Source)
at java.base/sun.security.ssl.SSLTransport.decode(Unknown Source)
at java.base/sun.security.ssl.SSLEngineImpl.decode(Unknown Source)
at java.base/sun.security.ssl.SSLEngineImpl.readRecord(Unknown Source)
at java.base/sun.security.ssl.SSLEngineImpl.unwrap(Unknown Source)
at java.base/sun.security.ssl.SSLEngineImpl.unwrap(Unknown Source)
at java.base/javax.net.ssl.SSLEngine.unwrap(Unknown Source)
at org.apache.http.nio.reactor.ssl.SSLIOSession.doUnwrap(SSLIOSession.java:271)
at org.apache.http.nio.reactor.ssl.SSLIOSession.doHandshake(SSLIOSession.java:316)
at org.apache.http.nio.reactor.ssl.SSLIOSession.isAppInputReady(SSLIOSession.java:509)
at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:120)
at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:162)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:337)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:276)
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:591)
При запуске из моего локального окружения рукопожатие выглядит непрерывно:
Produced ClientHello handshake message
WRITE: TLS13 handshake, length = 460
Raw write
Raw read
READ: TLSv1.2 handshake, length = 155
Consuming ServerHello
ServerHello
Negotiated protocol version: TLSv1.3
Session initialized: Session(1560119025211|TLS_AES_256_GCM_SHA384)
WRITE: TLS13 change_cipher_spec, length = 1
Raw write
Raw read
READ: TLSv1.2 change_cipher_spec, length = 1
Consuming ChangeCipherSpec message
Raw read
READ: TLSv1.2 application_data, length = 27
...
Raw read
READ: TLSv1.2 application_data, length = 8469
Consuming server Certificate handshake message
... // here is the list of 3 certificates with "SHA256withRSA", "SHA256withRSA", "SHA1withRSA" signature algorithms
Found trusted certificate ⇢ SHA1withRSA
...
Работая локально, я заметил CN=Microsoft IT TLS CA 2, OU=Microsoft IT, O=Microsoft Corporation, L=Redmond, ST=Washington, C=US
, а также CN=Baltimore CyberTrust Root, OU=CyberTrust, O=Baltimore, C=IE
как эмитентов, возможно, это важно, но я предполагаю, что это ожидается с учетом адреса хоста ES (Azure).
В заключение я хотел подчеркнуть, что мне не нужно было делать ничего особенного, чтобы сделать эту работу в моей macOS Java 11.0.2 среде разработки.
Я уже пытался следовать, но это ничего не изменило:
- Изменение базового образа Docker со «тонкого» на несжатый вариант
- Использование OpenJDK 11.0.1 или 11.0.2
- Добавлен сертификат от хоста в TrustStore, который JVM использует во время выполнения. (Я проверил в контейнере Docker, что действительно есть еще один сертификат, но учитывая, когда сбой рукопожатия происходит, я думаю, что это не имеет значения)
- попытался принудительно применить приложение с помощью: "-Dcom.sun.net.ssl.enableECC = false", "-Djdk.tls.client.protocols = TLSv1.3", "-Dhttps.protocols = TLSv1.3", не помогло
Интересно: завиток из образа Docker с BasicAuth «общается» с тем же URL-адресом без проблем (рукопожатие завершено) и небольшой запрос возвращает результаты. Я предполагаю, что curl и JVM используют разные источники доверенных CA внутри Docker, разные алгоритмы для квитирования связи и т. Д.
Заранее спасибо за любую помощь