问题描述
我正在尝试创建到Cloud SQL数据库的TLS连接,但是在尝试准备一条语句时遇到以下错误:
I'm trying to create a TLS connection to a Cloud SQL database but I'm getting the following error when trying to prepare a statement:
x509: cannot validate certificate for <cloud sql instance ip>
because it doesn't contain any IP SANs
这是我的设置代码:
rootCertPool := x509.NewCertPool()
pem, err := ioutil.ReadFile("/path/server-ca.pem")
if err != nil {
log.Fatal(err)
}
if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
log.Fatal("Failed to append PEM.")
}
clientCert := make([]tls.Certificate, 0, 1)
certs, err := tls.LoadX509KeyPair("/path/client-cert.pem",
"/path/client-key.pem")
if err != nil {
log.Fatal(err)
}
clientCert = append(clientCert, certs)
mysql.RegisterTLSConfig("custom", &tls.Config{
RootCAs: rootCertPool,
Certificates: clientCert,
})
db, err := sql.Open("mysql",
"<user>:<password>@tcp(<cloud sql ip>:3306)/<db_name>?tls=custom")
推荐答案
我缺少的关键是我使用的Go版本已有几个月的历史,并且没有特定的修复程序,并且我未指定主机名与我的Cloud SQL实例相关联.我在任何地方都找不到这个问题的答案,而是自己通过逐步执行TLS握手代码来找出问题所在和原因,从而找到了解决方案.
They key things I was missing was that the version of Go I was using was several months old and did not contain a specific fix and I did not specify the hostname associated with my Cloud SQL instance. I could not find an answer for this problem anywhere and found the solution myself by stepping through the TLS handshake code to see what went wrong and why.
2018年9月之前发布的Go版本不会正确验证Cloud SQL在TLS服务器证书中使用的主机名.Cloud SQL主机名包含一个':'字符,该字符导致该主机名和服务器证书被视为无效.该问题已解决.
Versions of Go released before September 2018 would not correctly validate the hostnames that Cloud SQL uses in the TLS server certificate. Cloud SQL hostnames contain a ':' character and that caused the hostname and therefore the server certificate to be considered invalid. That has been fixed.
使用TLS连接到Cloud SQL实例的正确方法是遵循以下步骤:
The correct way to connect to a Cloud SQL instance using TLS is to follow these steps:
-
更新您的Go,以便进行更改以允许验证服务器证书中的Cloud SQL主机名.
Update your Go so that you have the change that allows validation of Cloud SQL hostnames that are in the server certificate.
使用Cloud SQL控制台创建客户端证书.
Create client certificates using the Cloud SQL console.
按如下所示创建TLS连接:
Create the TLS connection as follows:
import (
"crypto/tls"
"crypto/x509"
"database/sql"
"github.com/go-sql-driver/mysql"
"io/ioutil"
)
rootCertPool := x509.NewCertPool()
pem, err := ioutil.ReadFile("/path/server-ca.pem")
if err != nil {
log.Fatal(err)
}
if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
log.Fatal("Failed to append PEM.")
}
clientCert := make([]tls.Certificate, 0, 1)
certs, err := tls.LoadX509KeyPair("/path/client-cert.pem",
"/path/client-key.pem")
if err != nil {
log.Fatal(err)
}
clientCert = append(clientCert, certs)
mysql.RegisterTLSConfig("custom", &tls.Config{
RootCAs: rootCertPool,
Certificates: clientCert,
ServerName: "<gcp-project-id>:<cloud-sql-instance>", // hostname
})
db, err := sql.Open("mysql",
"<user>:<password>@tcp(<cloud sql ip>:3306)/<db_name>?tls=custom")
这篇关于如何使用Go创建到Cloud SQL数据库的TLS连接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!