与 Google Cloud Postgres 的 SSL 连接

SSL connection to Google Cloud Postgres

我已将我的 postgres 数据库迁移到 Google Cloud SQL。

在未启用 SSL 的情况下,我可以毫无问题地进行连接。

但是我正在努力使 SSL 连接正常工作。

我正在使用 pgx 池驱动程序。

我已经下载了服务器、客户端和私钥 pem 文件。

我得到的错误信息是

failed to write startup message (x509: certificate signed by unknown authority)

    serverCert, err := ioutil.ReadFile("server-ca.pem")
    if err != nil {
        log.Fatal(err)
    }

    clientCert, err := ioutil.ReadFile("client-cert.pem")
    if err != nil {
        log.Fatal(err)
    }

    caCertPool := x509.NewCertPool()
    ok := caCertPool.AppendCertsFromPEM(serverCert)
    ok = caCertPool.AppendCertsFromPEM(clientCert)
    fmt.Println(ok)

    keypair, err := tls.LoadX509KeyPair("server-client-certs.pem", "client-key.pem")
    if err != nil {
        log.Fatal(err)
    }

    tlsConfig := &tls.Config{
        Certificates: []tls.Certificate{keypair},
        ServerName:   s.Host,
        ClientCAs:    caCertPool,
        ClientAuth:   tls.RequestClientCert,
        GetClientCertificate: func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
            return &keypair, nil
        },
    }

    connectionString := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s connect_timeout=%d sslmode=require",
        s.Host, s.Port, s.User, s.Password, s.Name, s.ConnectTimeout)

    connConfig, err := pgxpool.ParseConfig(connectionString)
    if connConfig != nil {
        connConfig.ConnConfig.TLSConfig = tlsConfig
    }

    var pool *pgxpool.Pool

    pool, err = pgxpool.ConnectConfig(context.Background(), connConfig)

您的 tls.Config 有很多问题,我建议您阅读 the docs 以了解每个字段的作用。

构建 CA 池:

CertPool 应该包含用于签署服务器证书的 CA 证书,这是 server-ca.pem。它不需要客户端证书。

指定 CA 池:

ClientCAs是服务端用来验证客户端证书的CA池,只在服务端使用。您需要在 RootCAs.

中指定您的 CA 池

这就是问题的原因,您的客户端正在尝试验证服务器证书但不知道其 CA。

其他领域:

ClientAuth 是服务器端字段,用于强制执行特定的客户端证书行为,在客户端设置时无效。

只要设置了

GetClientCertificate就不需要Certificates,你可以去掉它。

您还应该仔细检查您的客户端证书。您正在加载密钥对 server-client-certs.pem / client-key.pem。如果这些确实是客户端证书和密钥,那么你应该没问题。

假设您可以连接到数据库主机(在防火墙中列入白名单),您的证书都是正确的(服务器的 CA 证书、客户端证书和客户端密钥),此处列出的更正将使您能够连接。

完成所有这些之后,您的代码变为:

    caCertPool := x509.NewCertPool()
    ok := caCertPool.AppendCertsFromPEM(serverCert)
    fmt.Println(ok)

    keypair, err := tls.LoadX509KeyPair("server-client-certs.pem", "client-key.pem")
    if err != nil {
        log.Fatal(err)
    }

    tlsConfig := &tls.Config{
        Certificates: []tls.Certificate{keypair},
        ServerName:   s.Host,
        RootCAs:      caCertPool,
    }

最后说明:server-ca.pem 不是服务器证书,它是用于签署服务器证书的 CA 证书。客户端不会提前知道服务器证书,它会在 TLS 握手期间收到它。