如何使用Go创建到Cloud SQL数据库的TLS连接?

时间:2018-12-12 22:31:32

标签: mysql ssl go google-cloud-platform google-cloud-sql

我正在尝试创建到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")

1 个答案:

答案 0 :(得分:3)

我缺少的主要关键是我使用的Go版本已有几个月的历史,并且不包含特定的修复程序,并且我未指定与Cloud SQL实例关联的主机名。我在任何地方都找不到这个问题的答案,而是自己通过逐步执行TLS握手代码来找出问题所在和原因,从而找到了解决方案。

2018年9月之前发布的Go版本不会正确验证Cloud SQL在TLS服务器证书中使用的主机名。 Cloud SQL主机名包含一个':'字符,该字符导致该主机名和服务器证书被视为无效。该问题已解决。

使用TLS连接到Cloud SQL实例的正确方法是遵循以下步骤:

  1. 更新您的Go,以便进行更改以允许验证服务器证书中的Cloud SQL主机名。

  2. 使用Cloud SQL控制台创建客户端证书。

  3. 创建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")