2
0

SSL password - changes based on community feedback

This commit is contained in:
Eric McCormack
2022-07-08 14:24:59 -04:00
committed by Jack Christensen
parent 32ec44f726
commit c56b38c1f6
2 changed files with 16 additions and 13 deletions
+16 -11
View File
@@ -26,6 +26,7 @@ import (
type AfterConnectFunc func(ctx context.Context, pgconn *PgConn) error type AfterConnectFunc func(ctx context.Context, pgconn *PgConn) error
type ValidateConnectFunc func(ctx context.Context, pgconn *PgConn) error type ValidateConnectFunc func(ctx context.Context, pgconn *PgConn) error
type GetSSLPasswordFunc func(ctx context.Context) string
// Config is the settings used to establish a connection to a PostgreSQL server. It must be created by ParseConfig. A // Config is the settings used to establish a connection to a PostgreSQL server. It must be created by ParseConfig. A
// manually initialized Config will cause ConnectConfig to panic. // manually initialized Config will cause ConnectConfig to panic.
@@ -61,12 +62,14 @@ type Config struct {
// OnNotification is a callback function called when a notification from the LISTEN/NOTIFY system is received. // OnNotification is a callback function called when a notification from the LISTEN/NOTIFY system is received.
OnNotification NotificationHandler OnNotification NotificationHandler
// SslPasswordCallback is a callback function to handle Auth callback for SSL Password
SslPasswordCallback SslPasswordCallbackHandler
createdByParseConfig bool // Used to enforce created by ParseConfig rule. createdByParseConfig bool // Used to enforce created by ParseConfig rule.
} }
//Congig Options such as getsslpassword function
type ParseConfigOptions struct {
GetSSLPassword GetSSLPasswordFunc
}
// Copy returns a deep copy of the config that is safe to use and modify. // Copy returns a deep copy of the config that is safe to use and modify.
// The only exception is the TLSConfig field: // The only exception is the TLSConfig field:
// according to the tls.Config docs it must not be modified after creation. // according to the tls.Config docs it must not be modified after creation.
@@ -138,7 +141,8 @@ func NetworkAddress(host string, port uint16) (network, address string) {
// ParseConfig builds a *Config when sslpasswordcallback function is not provided // ParseConfig builds a *Config when sslpasswordcallback function is not provided
func ParseConfig(connString string) (*Config, error) { func ParseConfig(connString string) (*Config, error) {
return ParseConfigWithSslPasswordCallback(connString, nil) var parseConfigOptions ParseConfigOptions
return ParseConfigWithOptions(connString, parseConfigOptions)
} }
// ParseConfig builds a *Config with similar behavior to the PostgreSQL standard C library libpq. It uses the same // ParseConfig builds a *Config with similar behavior to the PostgreSQL standard C library libpq. It uses the same
@@ -204,7 +208,7 @@ func ParseConfig(connString string) (*Config, error) {
// which does not use TLS. This can lead to an unexpected unencrypted connection if the main TLS config is manually // which does not use TLS. This can lead to an unexpected unencrypted connection if the main TLS config is manually
// changed later but the unencrypted fallback is present. Ensure there are no stale fallbacks when manually setting // changed later but the unencrypted fallback is present. Ensure there are no stale fallbacks when manually setting
// TLCConfig. // TLCConfig.
// sslPasswordCallback function provide a callback function for sslpassword // ParseConfigOptions options for parse config
// //
// Other known differences with libpq: // Other known differences with libpq:
// //
@@ -218,7 +222,7 @@ func ParseConfig(connString string) (*Config, error) {
// servicefile // servicefile
// libpq only reads servicefile from the PGSERVICEFILE environment variable. ParseConfig accepts servicefile as a // libpq only reads servicefile from the PGSERVICEFILE environment variable. ParseConfig accepts servicefile as a
// part of the connection string. // part of the connection string.
func ParseConfigWithSslPasswordCallback(connString string, sslPasswordCallback SslPasswordCallbackHandler) (*Config, error) { func ParseConfigWithOptions(connString string, parseConfigOptions ParseConfigOptions) (*Config, error) {
defaultSettings := defaultSettings() defaultSettings := defaultSettings()
envSettings := parseEnvSettings() envSettings := parseEnvSettings()
@@ -338,7 +342,7 @@ func ParseConfigWithSslPasswordCallback(connString string, sslPasswordCallback S
tlsConfigs = append(tlsConfigs, nil) tlsConfigs = append(tlsConfigs, nil)
} else { } else {
var err error var err error
tlsConfigs, err = configTLS(settings, host, sslPasswordCallback) tlsConfigs, err = configTLS(settings, host, parseConfigOptions)
if err != nil { if err != nil {
return nil, &parseConfigError{connString: connString, msg: "failed to configure TLS", err: err} return nil, &parseConfigError{connString: connString, msg: "failed to configure TLS", err: err}
} }
@@ -605,7 +609,7 @@ func parseServiceSettings(servicefilePath, serviceName string) (map[string]strin
// configTLS uses libpq's TLS parameters to construct []*tls.Config. It is // configTLS uses libpq's TLS parameters to construct []*tls.Config. It is
// necessary to allow returning multiple TLS configs as sslmode "allow" and // necessary to allow returning multiple TLS configs as sslmode "allow" and
// "prefer" allow fallback. // "prefer" allow fallback.
func configTLS(settings map[string]string, thisHost string, sslPasswordCallback SslPasswordCallbackHandler) ([]*tls.Config, error) { func configTLS(settings map[string]string, thisHost string, parseConfigOptions ParseConfigOptions) ([]*tls.Config, error) {
host := thisHost host := thisHost
sslmode := settings["sslmode"] sslmode := settings["sslmode"]
sslrootcert := settings["sslrootcert"] sslrootcert := settings["sslrootcert"]
@@ -708,10 +712,11 @@ func configTLS(settings map[string]string, thisHost string, sslPasswordCallback
// If PEM is encrypted, attempt to decrypt using pass phrase // If PEM is encrypted, attempt to decrypt using pass phrase
if x509.IsEncryptedPEMBlock(block) { if x509.IsEncryptedPEMBlock(block) {
if sslpassword == "" { if sslpassword == "" {
if sslPasswordCallback == nil { if(parseConfigOptions.GetSSLPassword != nil){
return nil, fmt.Errorf("unable to find sslpassword: %w", err) sslpassword = parseConfigOptions.GetSSLPassword(context.Background())
}else{
return nil, fmt.Errorf("unable to find sslpassword")
} }
sslpassword = sslPasswordCallback()
} }
// Attempt decryption with pass phrase // Attempt decryption with pass phrase
// NOTE: only supports RSA (PKCS#1) // NOTE: only supports RSA (PKCS#1)
-2
View File
@@ -64,8 +64,6 @@ type NoticeHandler func(*PgConn, *Notice)
// notice event. // notice event.
type NotificationHandler func(*PgConn, *Notification) type NotificationHandler func(*PgConn, *Notification)
type SslPasswordCallbackHandler func() (string)
// Frontend used to receive messages from backend. // Frontend used to receive messages from backend.
type Frontend interface { type Frontend interface {
Receive() (pgproto3.BackendMessage, error) Receive() (pgproto3.BackendMessage, error)