mirror of https://github.com/jackc/pgx.git
feat: add support for direct sslnegotiation
parent
04bcc0219d
commit
037e4cf9a2
|
@ -51,6 +51,8 @@ type Config struct {
|
||||||
KerberosSpn string
|
KerberosSpn string
|
||||||
Fallbacks []*FallbackConfig
|
Fallbacks []*FallbackConfig
|
||||||
|
|
||||||
|
Sslnegotiation string // sslnegotiation=postgres or sslnegotiation=direct
|
||||||
|
|
||||||
// ValidateConnect is called during a connection attempt after a successful authentication with the PostgreSQL server.
|
// ValidateConnect is called during a connection attempt after a successful authentication with the PostgreSQL server.
|
||||||
// It can be used to validate that the server is acceptable. If this returns an error the connection is closed and the next
|
// It can be used to validate that the server is acceptable. If this returns an error the connection is closed and the next
|
||||||
// fallback config is tried. This allows implementing high availability behavior such as libpq does with target_session_attrs.
|
// fallback config is tried. This allows implementing high availability behavior such as libpq does with target_session_attrs.
|
||||||
|
@ -318,6 +320,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con
|
||||||
"sslkey": {},
|
"sslkey": {},
|
||||||
"sslcert": {},
|
"sslcert": {},
|
||||||
"sslrootcert": {},
|
"sslrootcert": {},
|
||||||
|
"sslnegotiation": {},
|
||||||
"sslpassword": {},
|
"sslpassword": {},
|
||||||
"sslsni": {},
|
"sslsni": {},
|
||||||
"krbspn": {},
|
"krbspn": {},
|
||||||
|
@ -386,6 +389,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con
|
||||||
config.Port = fallbacks[0].Port
|
config.Port = fallbacks[0].Port
|
||||||
config.TLSConfig = fallbacks[0].TLSConfig
|
config.TLSConfig = fallbacks[0].TLSConfig
|
||||||
config.Fallbacks = fallbacks[1:]
|
config.Fallbacks = fallbacks[1:]
|
||||||
|
config.Sslnegotiation = settings["sslnegotiation"]
|
||||||
|
|
||||||
passfile, err := pgpassfile.ReadPassfile(settings["passfile"])
|
passfile, err := pgpassfile.ReadPassfile(settings["passfile"])
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -449,6 +453,7 @@ func parseEnvSettings() map[string]string {
|
||||||
"PGSSLSNI": "sslsni",
|
"PGSSLSNI": "sslsni",
|
||||||
"PGSSLROOTCERT": "sslrootcert",
|
"PGSSLROOTCERT": "sslrootcert",
|
||||||
"PGSSLPASSWORD": "sslpassword",
|
"PGSSLPASSWORD": "sslpassword",
|
||||||
|
"PGSSLNEGOTIATION": "sslnegotiation",
|
||||||
"PGTARGETSESSIONATTRS": "target_session_attrs",
|
"PGTARGETSESSIONATTRS": "target_session_attrs",
|
||||||
"PGSERVICE": "service",
|
"PGSERVICE": "service",
|
||||||
"PGSERVICEFILE": "servicefile",
|
"PGSERVICEFILE": "servicefile",
|
||||||
|
@ -646,6 +651,7 @@ func configTLS(settings map[string]string, thisHost string, parseConfigOptions P
|
||||||
sslkey := settings["sslkey"]
|
sslkey := settings["sslkey"]
|
||||||
sslpassword := settings["sslpassword"]
|
sslpassword := settings["sslpassword"]
|
||||||
sslsni := settings["sslsni"]
|
sslsni := settings["sslsni"]
|
||||||
|
sslnegotiation := settings["sslnegotiation"]
|
||||||
|
|
||||||
// Match libpq default behavior
|
// Match libpq default behavior
|
||||||
if sslmode == "" {
|
if sslmode == "" {
|
||||||
|
@ -657,6 +663,11 @@ func configTLS(settings map[string]string, thisHost string, parseConfigOptions P
|
||||||
|
|
||||||
tlsConfig := &tls.Config{}
|
tlsConfig := &tls.Config{}
|
||||||
|
|
||||||
|
if sslnegotiation == "direct" {
|
||||||
|
tlsConfig.NextProtos = []string{"postgresql"}
|
||||||
|
sslmode = "require"
|
||||||
|
}
|
||||||
|
|
||||||
if sslrootcert != "" {
|
if sslrootcert != "" {
|
||||||
var caCertPool *x509.CertPool
|
var caCertPool *x509.CertPool
|
||||||
|
|
||||||
|
|
|
@ -325,7 +325,15 @@ func connectOne(ctx context.Context, config *Config, connectConfig *connectOneCo
|
||||||
if connectConfig.tlsConfig != nil {
|
if connectConfig.tlsConfig != nil {
|
||||||
pgConn.contextWatcher = ctxwatch.NewContextWatcher(&DeadlineContextWatcherHandler{Conn: pgConn.conn})
|
pgConn.contextWatcher = ctxwatch.NewContextWatcher(&DeadlineContextWatcherHandler{Conn: pgConn.conn})
|
||||||
pgConn.contextWatcher.Watch(ctx)
|
pgConn.contextWatcher.Watch(ctx)
|
||||||
tlsConn, err := startTLS(pgConn.conn, connectConfig.tlsConfig)
|
var (
|
||||||
|
tlsConn net.Conn
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if config.Sslnegotiation == "direct" {
|
||||||
|
tlsConn = tls.Client(pgConn.conn, connectConfig.tlsConfig)
|
||||||
|
} else {
|
||||||
|
tlsConn, err = startTLS(pgConn.conn, connectConfig.tlsConfig)
|
||||||
|
}
|
||||||
pgConn.contextWatcher.Unwatch() // Always unwatch `netConn` after TLS.
|
pgConn.contextWatcher.Unwatch() // Always unwatch `netConn` after TLS.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pgConn.conn.Close()
|
pgConn.conn.Close()
|
||||||
|
|
Loading…
Reference in New Issue