繁体   English   中英

如何使用相互TLS / SSL加密从Java JDBC连接到SQL DB

[英]How to connect to SQL DB from Java JDBC with mutual TLS/SSL encryption

今天,云数据库非常流行,有时我们需要从便携式计算机或类似设备连接到一个数据库。 通常,有一个未加密连接的选项,但这不是很安全。 那么,如何连接到相互的TLS mysql服务器(如Google Cloud SQL)?

从mysql cli中,从Google Cloud Console下载服务器ca cert,客户端cert和密钥后,操作相当简单:

mysql -u <user-name> -h <server-ip> -p --ssl-ca=server-ca.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem

注意:对于Google Cloud,您也可以使用Cloud SQL代理,但我想在没有该代理的情况下进行连接

下面的Logstash 7和jvm 9+。

好的,我终于弄清楚了,将来自不同来源的信息拼凑在一起。 此解决方案已通过Google Cloud SQL和休眠测试,但也可以在其他设置中使用。

该解决方案需要使用Java密钥库(客户端证书/密钥)和信任库(服务器CA证书),并传递一些jdbc URL参数和JVM选项。

首先,让我们从server-ca.pem文件创建一个信任库:

keytool -importcert -alias gcpRoot -file server-ca.pem -keystore truststore.jks -storepass <chose a password and remember>

编辑:或将CA添加到jvms现有cacerts文件中(以确保其他https调用将起作用),将其重命名的cacerts复制到truststore.jks并运行:

OR: keytool -importcert -alias gcpRoot -file server-ca.pem -keystore truststore.jks -storepass changeit

其次,我们需要分两步将客户端证书和密钥导入密钥库文件(我使用SQL用户名作为别名,但我认为这并不重要)

openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem -out keystore.p12 -name "<keystore-alias>" -passout pass:<chose a password and remember>
keytool -importkeystore -alias <keystore-alias> -srckeystore keystore.p12  -srcstoretype pkcs12 -destkeystore keystore.jks -srcstorepass <insert same password here> -deststoretype JKS -deststorepass <password-for-output-jks-keystore>

接下来,我们需要修改jdbc连接URL(注意!某些IDE(如intelliJ)要求转义&并替换为&amp;

jdbc:mysql://<server-ip>/<db-name>?verifyServerCertificate=true&useSSL=true&requireSSL=true

最后,我们需要提供密钥库和信任库的位置和密码作为JVM参数:

-Djavax.net.ssl.trustStore="truststore.jks"
-Djavax.net.ssl.trustStorePassword="<password>"
-Djavax.net.ssl.keyStore="keystore.jks"
-Djavax.net.ssl.keyStorePassword="<password>"

更新:如果您在9或更高版本的jvm上运行(例如7+的logstash docker映像),则需要解决一些类加载问题,以使jdbc驱动程序均匀加载,并且您需要最新版本的mysql TLS的驱动程序。

首先,您显然必须将jdbc驱动程序的.jar文件放入<logstash-dir>/logstash-core/lib/jars/mysql-connector-java-8.0.17.jar (这将导致jar自动加载)。 而且我们还需要在输入配置中添加以下内容:

jdbc_driver_library => ""
jdbc_driver_class => "com.mysql.cj.jdbc.Driver"

由于某些原因,我仍然收到警告Loading class com.mysql.jdbc.Driver. This is deprecated. The new driver class is Loading class com.mysql.jdbc.Driver. This is deprecated. The new driver class is Loading class com.mysql.jdbc.Driver. This is deprecated. The new driver class is com.mysql.cj.jdbc.Driver',但尽管出现此警告,它仍可以工作。

虽然不是完全不是这个问题的答案,但我将添加此示例,说明如何与在kubernetes上部署的logstash jdbc插件一起使用,因为它并不完全简单明了,并且可能对类似系统有用。

该解决方案基于第一个解决方案,但是信任库必须基于jvm的完整cacerts

在输入定义中,将参数添加到jdbc URL:

input {
  jdbc {
    ...
    jdbc_connection_string => "jdbc:mysql://<server-ip>:3306/<db>?verifyServerCertificate=true&useSSL=true&requireSSL=true"
    jdbc_password => "${MYSQL_PASSWORD}"
    ...
  }
}

然后从信任库和密钥库以及mysql密码创建一个秘密:

kubectl create secret generic java-tls-creds --from-file=./keystore.jks --from-file=./truststore.jks
kubectl create secret generic mysql-password --from-literal='password=<password>'

然后,我们修改部署yaml以安装凭据,并添加LS_JAVA_OPTS指向它们:

apiVersion: apps/v1
kind: Deployment
... 
        env:
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-password
              key: password
        - name: LS_JAVA_OPTS
          value: -Djavax.net.ssl.keyStore=/java-tls-creds/keystore.jks -Djavax.net.ssl.keyStorePassword=<password> -Djavax.net.ssl.trustStore=/java-tls-creds/truststore.jks -Djavax.net.ssl.trustStorePassword=changeit
...
        volumeMounts:
        - name: java-tls-creds
          mountPath: "/java-tls-creds"
          readOnly: true
...
      volumes:
      - name: java-tls-creds
        secret:
          secretName: java-tls-creds

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM