pgx tls 连接抛出有效证书的客户端证书无效错误

我正在尝试使用 pgx 与 postgres 10 db 建立 TLS 连接。


我的连接字符串类似于:"host='my-host.com' port='5432' dbname='my-db' user='my-db-user' sslmode='verify-full' sslcert='/path/to/db_user.crt' sslkey='/path/to/db_user.key' sslrootcert='/path/to/ca_roots.pem'"


当我psql在命令行上直接运行它时,它可以工作,因此证书和密钥文件必须有效。db_user.crt并且db_user.key都是 PEM 文件。(命令行也适用于sslmode='verify-full',因此 rootcert 也应该没问题)


但是当我pgx用那个连接字符串初始化一个池时,它失败了:


FATAL:连接需要有效的客户端证书(SQLSTATE 28000)


去期待 PEM 以外的东西吗?还是应该使用 pgx 初始化 ssl 证书和密钥对的不同方式?


代码

import (

    "context"

    "fmt"

    "os"


    "github.com/jackc/pgx/v4"

    "github.com/jackc/pgx/v4/pgxpool"

)


type mockLogger struct{}


func (ml *mockLogger) Log(ctx context.Context, level pgx.LogLevel, msg string, data map[string]interface{}) {

    fmt.Printf("[%s] %s : %+v\n", level.String(), msg, data)

}


func connect() error {

    connStr := "host='my-host.com' port='5432' dbname='my-db' user='my-db-user' sslmode='verify-full' sslcert='/path/to/db_user.crt' sslkey='/path/to/db_user.key' sslrootcert='/path/to/ca_roots.pem'"

    poolCfg, err := pgxpool.ParseConfig(connStr)

    if err != nil {

        return err

    }

    poolCfg.ConnConfig.Logger = &mockLogger{}

    poolCfg.ConnConfig.LogLevel = pgx.LogLevelTrace

    fmt.Printf("using connection string: \"%s\"\n", poolCfg.ConnString())


    connPool, err := pgxpool.ConnectConfig(context.TODO(), poolCfg)

    if err != nil {

        return err

    }


    connPool.Close()

    return nil

}


func main() {

    if err := connect(); err != nil {

        fmt.Printf("%+v\n", err)

        os.Exit(1)

    }

}



aluckdog
浏览 89回答 1
1回答

千万里不及你

概括事实证明,证书指向的证书sslcert需要包含完整的客户端证书链。当/path/to/db_user.crt包含客户端证书后跟客户端证书链时,pgx连接有效。而该psql命令在两种情况下都有效:什么时候sslcert只是没有链的叶客户端证书当sslcert包含客户端证书+链时不知道为什么 psql 在没有完整链的情况下很好,但它现在可以工作了。细节在后台,pgx 使用pgconn模块创建连接。反过来,这只是调用和文件tls.X509KeyPair的内容。sslcertsslkeypgconn/config.go :func configTLS(settings map[string]string, thisHost string, parseConfigOptions ParseConfigOptions) ([]*tls.Config, error) {    [...]    sslcert := settings["sslcert"]    sslkey := settings["sslkey"]    [...]    if sslcert != "" && sslkey != "" {        [...]        certfile, err := ioutil.ReadFile(sslcert)        if err != nil {            return nil, fmt.Errorf("unable to read cert: %w", err)        }        cert, err := tls.X509KeyPair(certfile, pemKey)        if err != nil {            return nil, fmt.Errorf("unable to load cert: %w", err)        }        tlsConfig.Certificates = []tls.Certificate{cert}
打开App,查看更多内容
随时随地看视频慕课网APP