我正在尝试创建到Cloud SQL数据库的TLS连接,但是在尝试准备一条语句时遇到以下错误:
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")
答案 0 :(得分:3)
我缺少的主要关键是我使用的Go版本已有几个月的历史,并且不包含特定的修复程序,并且我未指定与Cloud SQL实例关联的主机名。我在任何地方都找不到这个问题的答案,而是自己通过逐步执行TLS握手代码来找出问题所在和原因,从而找到了解决方案。
2018年9月之前发布的Go版本不会正确验证Cloud SQL在TLS服务器证书中使用的主机名。 Cloud SQL主机名包含一个':'字符,该字符导致该主机名和服务器证书被视为无效。该问题已解决。
使用TLS连接到Cloud SQL实例的正确方法是遵循以下步骤:
更新您的Go,以便进行更改以允许验证服务器证书中的Cloud SQL主机名。
使用Cloud SQL控制台创建客户端证书。
创建TLS连接,如下所示:
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")