Подключение Spring Boot к AWS RDS MySQL - SSLHandshakeException: получено фатальное предупреждение: unknown_ca - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть приложение Spring Boot, из которого я пытаюсь подключиться к MySQL на AWS RDS.Однако у меня возникают проблемы со следующей ошибкой:

localhost-startStop-1, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca

После включения отладки для рукопожатия ssl я вижу, что для шага CertificateRequest Cert Authorities: пусты.Насколько я понимаю, это та часть, в которой клиент (приложение с весенней загрузкой) должен предоставить сертификат серверу (mysql db).

  • Certificate Request step - Сервер выдаст запрос сертификата от клиента.
  • Следующим шагом будет *** Certificate chain, то есть сертификат, который клиент отправляет на сервер.В этом случае для меня это отправка содержимого keyStore_cert.jks.

Что я думаю, проблема до сих пор: Сервер (MySQL DB) не знает об этомсертификат (мой keyStore_cert.jks), который отправляет клиент (мое приложение).Но у меня сложилось впечатление, что клиентские сертификаты не требуются, если вы не установите для пользователя REQUIRE X509.

Вопросы:

  • Есть личто-то еще, что я могу посмотреть, чтобы найти точную проблему?
  • Если выше проблемы, как я могу это исправить?Как я могу отключить проверку клиента?
  • Или как сохранить проверку клиента, но она работает?
  • Нужно ли что-нибудь добавить к keyStore_cert.jks / trustStore_cert.jks?


Это мои настройки и то, что я пробовал.

  • Версия RDS Engine: 5.7.22
  • mysql-connector-java v8.0.13
  • URL подключения: jdbc:mysql://<host>:<port>/<db_name>?useLegacyDatetimeCode=false&verifyServerCertificate=true&useSSL=true&requireSSL=true
  • для пользователя, которого я использую, я выполнил в БД следующее:
ALTER USER '<my_db_user>'@'%' require SSL;
GRANT USAGE ON <db_name>.* TO '<my_db_user>'@'%' REQUIRE SSL;
  • На основе документации AWS : я импортировал эти сертификаты (root ипромежуточный) в trustStore.Делать что-то: keytool -import -keystore trustStore_cert.jks -storepass <trustStore_password> -alias "awsrds-us-east1" -file rds-ca-2015-us-east-1.pem
  • Я использую наш собственный хранилище ключей.В это время ничего не было сделано с хранилищем ключей.
  • приложения trustStore и keyStore передаются в виде параметров JVM, как показано ниже:
-Djavax.net.ssl.keyStore=path/keyStore_cert.jks
-Djavax.net.ssl.keyStorePassword=<keyStore_password>
-Djavax.net.ssl.trustStore=path/trustStore_cert.jks
-Djavax.net.ssl.trustStorePassword=<trustStore_password>
  • Для конкретного пользователя, когдаЯ использую MySQL Workbench и в настройках соединения для Использую SSL Я указываю: Если доступно или Требуется .Он связывается с этим сообщением:
Host: <host>
Port: <port>
User: <user>
SSL: enabled with DHE-RSA-AES128-SHA
  • Однако, если я укажу, Требовать и проверять CA или Требовать и проверять личность это даетсообщение: SSL connection error: CA certificate is required if ssl-mode is VERIFY_CA or VERIFY_IDENTITY.Это имеет смысл, поскольку я ничего не указываю для файла CA.


Шаги для рукопожатия (некоторые журналы пропущены):

*** ClientHello, TLSv1.1 (seems okay)
***
*** ServerHello, TLSv1.1 (seems okay)
***
*** Certificate chain (has the root key)
chain [0] = [
[
  Version: V3
  Subject: C=US, ST=Washington, L=Seattle, O=Amazon.com, OU=RDS, CN=**<my_rds_name>abcd.us-east-1.rds.amazonaws.com**
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
...
...
chain [1] = [ (has the us-east-1 key)
[
  Version: V3
  Subject: CN=Amazon RDS us-east-1 CA, OU=Amazon RDS, O="Amazon Web Services, Inc.", L=Seattle, ST=Washington, C=US
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
...
...
***
Found trusted certificate:
[
[
  Version: V3
  Subject: CN=Amazon RDS us-east-1 CA, OU=Amazon RDS, O="Amazon Web Services, Inc.", L=Seattle, ST=Washington, C=US
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
...
...
*** CertificateRequest (the Authorities are empty)
Cert Types: RSA, DSS, ECDSA
Cert Authorities:
<Empty>
*** ServerHelloDone
matching alias: <my keyStoreAlias>
*** Certificate chain (seems entries from my own key Store)
chain [0] = [
[
  Version: V3
  Subject: CN=<the CN on my keyStore>, OU=Web Servers, O=Company , C=US
  Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11

***
*** ClientKeyExchange, RSA PreMasterSecret, TLSv1.1 (seems okay)

*** CertificateVerify (seem okay)
*** Finished
verify_data:  { 50, 89, 33, 202, 193, 158, 226, 114, 128, 50, 198, 250 }
***

1 Ответ

0 голосов
/ 26 апреля 2019

После работы со службой поддержки AWS RDS я получил объяснение, почему проблема и как ее исправить.

Просто для пояснения, эта проблема в основном представлена, только если вы передаете свое собственное хранилище ключей как часть аргументов JVM.Примерно так:

 -Djavax.net.ssl.keyStore=path/keyStore_cert.jks
 -Djavax.net.ssl.keyStorePassword=<keyStore_password>

RDS - это управляемая служба, и у них нет способа (в настоящее время) загрузить определенные клиентские сертификаты на сервер.Это означает, что они не могут передавать определенные сертификаты на уровне конфигурации БД.Обычно это было бы возможно, если бы вы включили собственный сервер MY SQL.В файле конфигурации для этого сервера вы можете указать сертификаты клиент / сервер.Таким образом, RDS не может проверить сертификат, предоставленный клиентом.

Если вы должны были передать хранилище ключей, в котором есть запись пары ключей (в качестве аргумента JVM или иным образом), во время рукопожатия SSL, этап аутентификации клиентапотерпит неудачуЭто ожидаемое поведение в базе данных.RDS не может ограничивать себя для проверки (или не проверки) файла, загруженного в поле клиента для клиента во время первоначального подключения.Поэтому, если хранилище ключей пропущено, сервер попытается сопоставить ключи сертификата с существующим файлом CA, а если он не совпадает, он не разрешит соединения.

Решение состоит в том, чтобы либо вообще не передавать хранилище ключейили передайте пустое хранилище ключей (то, которое не имеет пары ключей с только доверенной записью сертификата или просто пустое).

  1. , если вы решите не передавать хранилище ключей, тогдане указывайте эти свойства -Djavax.net.ssl.keyStore= & -Djavax.net.ssl.keyStorePassword=.И создайте URL-адрес соединения с БД следующим образом:
    -Ddb_jdbc_url=jdbc:mysql://<host>:<port>/<db_name>?useLegacyDatetimeCode=false&verifyServerCertificate=true&useSSL=true&requireSSL=true.Вам все еще нужно предоставить склад доверенных сертификатов.Подробнее см. Внизу.

  2. Передача черного хранилища ключей или (или передача доверенного хранилища в поле хранилища ключей) Вы можете передать все, что захотите, для хранилища ключей и для параметров JVM trustore.А для URL вы создаете его следующим образом:

    -Ddb_jdbc_url=jdbc:mysql://<host>:<port>/<db_name>?
    useLegacyDatetimeCode=false&verifyServerCertificate=true&useSSL=true&requireSSL=true
    &clientCertificateKeyStoreUrl=file:/user/documents/projects/trust-store-rds.jks
    &clientCertificateKeyStorePassword=<password>
    &clientCertificateKeyStoreType=JKS
    &trustCertificateKeyStoreUrl=file:/user/documents/projects/trust-store-rds.jks
    &trustCertificateKeyStorePassword=<password>
    &trustCertificateKeyStoreType=JKS

Обратите внимание, что для trustCertificateKeyStoreUrl и clientCertificateKeyStoreUrl я передаю один и тот же файл.

Обратите внимание, вам также необходимо настроить все предыдущие шаги:

  1. включить SSL для пользователя в БД.
CREATE USER 'my_user'@'%' IDENTIFIED BY 'my_password';
ALTER USER 'my_user'@'%' REQUIRE SSL;
GRANT USAGE ON *.* TO 'my_user'@'%' REQUIRE SSL ;

Вам необходимо импортировать корневые и региональные сертификаты AWS в хранилище доверенных сертификатов;Примерно так:
     keytool -import -keystore trust-store-rds.jks -storepass changeit -noprompt alias "aws-rds-root" -file rds-ca-2015-root.pem

     keytool -import -keystore trust-store-rds.jks -storepass changeit -noprompt -alias "aws-rds-us-east-1" -file rds-ca-2015-us-east-1.pem
Создайте URL, как указано выше.
...