使用mysql-client从Alpine Docker映像内部通过SSL连接到Amazon RDS。 并validation证书
我有一个数据库托pipe在亚马逊RDS(欧洲西部2区)。
我试图从一个Docker容器中连接到它。 我的中级证书是rds-ca-2015-eu-west-2.pem
。
Ubuntu工作正常:
docker run --rm -v "$PWD/rds-ca-2015-eu-west-2.pem:/ca.pem:ro,cached" ubuntu sh -c '\ apt-get update > /dev/null \ && apt-get install -y mysql-client > /dev/null \ && mysql \ -h MYDATABASE.eu-west-2.rds.amazonaws.com \ -P 3306 \ -u MYUSERNAME \ -pMYPASSWORD \ --ssl-mode=VERIFY_IDENTITY \ --ssl-ca=/ca.pem \ -e "SELECT NOW();"'
输出:
mysql: [Warning] Using a password on the command line interface can be insecure. NOW() 2017-08-31 13:03:05
但阿尔卑斯的行为有所不同:
docker run --rm -v "$PWD/rds-ca-2015-eu-west-2.pem:/ca.pem:ro,cached" alpine sh -c '\ apk update > /dev/null \ && apk add mysql-client > /dev/null \ && mysql \ -h MYDATABASE.eu-west-2.rds.amazonaws.com \ -P 3306 \ -u MYUSERNAME \ -pMYPASSWORD \ --ssl-verify-server-cert \ --ssl-ca=/ca.pem \ -e "SELECT NOW();"'
输出:
ERROR 2026 (HY000): SSL connection error: error:14007086:SSL routines:CONNECT_CR_CERT:certificate verify failed
这里发生了什么? 我如何debugging? 如何使证书validation成功?
不可否认,我对Alpine的MySQL调用与Ubuntu的调用略有不同。 Alpine的MySQL客户端较旧,使用--ssl-verify-server-cert
而不是--ssl-mode=VERIFY_IDENTITY
。 这不是问题的根源; 我已经成功地使用了--ssl-verify-server-cert
连接到macOS上的RDS。
我听说MySQL客户端可以用两种不同的SSL实现来构build:
- yaSSL – 不支持证书链或
--ssl-capath
- OpenSSL的
当然,如果apk
提供的MySQL客户端不支持证书链,那就可以解释它。 或者,如果Alpine带有较less的根证书或中间证书。
我尝试了以下。 它没有帮助。
apk add ca-certificates && update-ca-certificates
这不是一个networking问题。 如果closures证书validation(即删除--ssl-ca
和--ssl-verify-server-cert
),并使用encryption( --ssl
):Alpine成功连接到RDS。
所以这纯粹是一个authenticationvalidation问题。
关于debugging,很高兴知道:
- mysql-client(而不是它的SSL实现) 尝试什么?
- 它信任哪些根证书?
- 它咨询了哪些中间证书?
如果证书链不受支持,也许有办法抓住整个链,并将其连接成一个证书 ?
我声称rds-ca-2015-root.pem
是一个可信任的用于证书中间证书rds-ca-2015-eu-west-2.pem
。
我想,也许我可以结合证书:
cat rds-ca-2015-eu-west-2.pem rds-ca-2015-root.pem > chained-cert.pem
我试图使用chained-cert.pem
作为我的中间证书。 这没有奏效。 也许我误解了一些东西。
我认为也许这将是有用的抢证书,以便我可以尝试直接validation它,而不是通过MySQL客户端。
openssl s_client -connect MYDATABASE.eu-west-2.rds.amazonaws.com:3306 -showcerts
可悲的是,这导致:
7428:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-64.50.6/src/ssl/s23_clnt.c:618:
因为MySQL:3306在启动SSL会话之前首先使用明文协议。
我试图获取证书的另一种方法是利用mysql-connector-java
的会话处理; 它理解协议,并在适当的时候交给SSL。
我在sun.security.x509.X509CertImpl#verify(PublicKey var1, String var2)
放置了一个断点,尝试查看二进制证书。
有各种各样的字节数组看起来很像DER编码的证书,所以我试图通过base64编码将它们转换成PEM,用-----BEGIN|END CERTIFICATE-----
围绕它们,并限制列使用fold -w 64 cert.pem
。
这没有奏效。 我所生产的每件东西都没有错, 当我试图用opensslparsing或validation它们时,它们都遇到了Expecting: TRUSTED CERTIFICATE
。
诚然,这是一个远射。