diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 92fb2c6..9d47798 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -76,7 +76,7 @@ were args are one of the following:
| Query Argument | Description | Values |
|----------------|-------------|--------|
| use_prepared_statements | whether to use client-side query interpolation or server-side argument binding |
true = (default) use server-side bindings false = user client side interpolation |
-| tlsmode | the ssl policy for this connection | none (default) = don't use SSL for this connectionserver = server must support SSL, but skip verification (INSECURE!)server-strict = server must support SSLcustom = use custom TLS config (Need to generate certs with `resources/tests/genCerts.sh` in advance) |
+| tlsmode | the ssl policy for this connection | none = don't use SSL for this connectionprefer (default) = checks for SSL/TLS server support; if unsupported, SSL/TLS is not used for this connection. server = server must support SSL, but skip verification (INSECURE!)server-strict = server must support SSLcustom = use custom TLS config (Need to generate certs with `resources/tests/genCerts.sh` in advance) |
| locator | host and port of the Vertica connection | (default) localhost:5433 |
| user | Vertica user name | (default) dbadmin |
| password | Vertica password for the connecting user | (default) (empty) |
diff --git a/README.md b/README.md
index eb338ea..530c501 100644
--- a/README.md
+++ b/README.md
@@ -96,7 +96,7 @@ Currently supported query arguments are:
|----------------|-------------|--------|
| use_prepared_statements | Whether to use client-side query interpolation or server-side argument binding. | 1 = (default) use server-side bindings
0 = user client side interpolation **(LESS SECURE)** |
| connection_load_balance | Whether to enable connection load balancing on the client side. | 0 = (default) disable load balancing
1 = enable load balancing |
-| tlsmode | The ssl/tls policy for this connection. | 'none' (default) = don't use SSL/TLS for this connection'server' = server must support SSL/TLS, but skip verification **(INSECURE!)**'server-strict' = server must support SSL/TLS{customName} = use custom registered `tls.Config` (see "Using custom TLS config" section below) |
+| tlsmode | The ssl/tls policy for this connection. | 'none' = don't use SSL/TLS for this connection'prefer' (default) = checks for SSL/TLS server support; if unsupported, SSL/TLS is not used for this connection. 'server' = server must support SSL/TLS, but skip verification **(INSECURE!)**'server-strict' = server must support SSL/TLS{customName} = use custom registered `tls.Config` (see "Using custom TLS config" section below) |
| backup_server_node | A list of backup hosts for the client to try to connect if the primary host is unreachable. | a comma-seperated list of backup host-port pairs. E.g.
'host1:port1,host2:port2,host3:port3' |
| client_label | Sets a label for the connection on the server. This value appears in the `client_label` column of the SESSIONS system table. | (default) vertica-sql-go-{version}-{pid}-{timestamp} |
| autocommit | Controls whether the connection automatically commits transactions. | 1 = (default) on
0 = off|
diff --git a/connection.go b/connection.go
index 60b711f..ea1823f 100644
--- a/connection.go
+++ b/connection.go
@@ -58,6 +58,7 @@ var (
)
const (
+ tlsModePrefer = "prefer"
tlsModeServer = "server"
tlsModeServerStrict = "server-strict"
tlsModeNone = "none"
@@ -85,9 +86,9 @@ func (t *_tlsConfigs) get(name string) (*tls.Config, bool) {
var tlsConfigs = &_tlsConfigs{m: make(map[string]*tls.Config)}
// db, err := sql.Open("vertica", "user@tcp(localhost:3306)/test?tlsmode=custom")
-// reserved modes: 'server', 'server-strict' or 'none'
+// reserved modes: 'prefer', 'server', 'server-strict' or 'none'
func RegisterTLSConfig(name string, config *tls.Config) error {
- if name == tlsModeServer || name == tlsModeServerStrict || name == tlsModeNone {
+ if name == tlsModePrefer || name == tlsModeServer || name == tlsModeServerStrict || name == tlsModeNone {
return fmt.Errorf("config name '%s' is reserved therefore cannot be used", name)
}
return tlsConfigs.add(name, config)
@@ -665,6 +666,10 @@ func (v *connection) initializeSSL(sslFlag string) error {
}
if buf[0] == 'N' {
+ if sslFlag == tlsModePrefer {
+ connectionLogger.Info("SSL/TLS is not supported, proceeding with non-SSL connection in prefer mode")
+ return nil
+ }
return fmt.Errorf("SSL/TLS is not enabled on this server")
}
@@ -673,6 +678,9 @@ func (v *connection) initializeSSL(sslFlag string) error {
}
switch sslFlag {
+ case tlsModePrefer:
+ connectionLogger.Info("enabling SSL/TLS prefer mode")
+ v.conn = tls.Client(v.conn, &tls.Config{InsecureSkipVerify: true})
case tlsModeServer:
connectionLogger.Info("enabling SSL/TLS server mode")
v.conn = tls.Client(v.conn, &tls.Config{InsecureSkipVerify: true})
diff --git a/driver_test.go b/driver_test.go
index 4c77981..6cb544b 100644
--- a/driver_test.go
+++ b/driver_test.go
@@ -201,6 +201,10 @@ func TestTLSConfiguration(t *testing.T) {
switch *tlsMode {
case "none":
assertEqual(t, sslState, "None")
+ case "prefer":
+ if sslState != "None" && sslState != "Server" {
+ t.Fatalf("Expected ssl_state to be 'None' or 'Server', but got '%s'", sslState)
+ }
case "server", "server-strict":
assertEqual(t, sslState, "Server")
case "custom":
@@ -1227,7 +1231,7 @@ func TestClientOSHostnameProperty(t *testing.T) {
var verticaUserName = flag.String("user", "dbadmin", "the user name to connect to Vertica")
var verticaPassword = flag.String("password", os.Getenv("VERTICA_TEST_PASSWORD"), "Vertica password for this user")
var verticaHostPort = flag.String("locator", "localhost:5433", "Vertica's host and port")
-var tlsMode = flag.String("tlsmode", "none", "SSL/TLS mode (none, server, server-strict, custom)")
+var tlsMode = flag.String("tlsmode", "none", "SSL/TLS mode (none, prefer, server, server-strict, custom)")
var usePreparedStmts = flag.Bool("use_prepared_statements", true, "whether to use prepared statements for all queries/executes")
var oauthAccessToken = flag.String("oauth_access_token", os.Getenv("VERTICA_TEST_OAUTH_ACCESS_TOKEN"), "the OAuth Access Token to connect to Vertica")