Skip to content

Commit 4e87066

Browse files
authored
SNOW-1821505 Introduce disableOCSPChecks config option (#1253)
1 parent 369574d commit 4e87066

11 files changed

+157
-11
lines changed

connection.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -787,7 +787,7 @@ func buildSnowflakeConn(ctx context.Context, config Config) (*snowflakeConn, err
787787
}
788788
var st http.RoundTripper = SnowflakeTransport
789789
if sc.cfg.Transporter == nil {
790-
if sc.cfg.InsecureMode {
790+
if sc.cfg.DisableOCSPChecks || sc.cfg.InsecureMode {
791791
// no revocation check with OCSP. Think twice when you want to enable this option.
792792
st = snowflakeInsecureTransport
793793
} else {

connection_configuration.go

+3
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,10 @@ func handleSingleParam(cfg *Config, key string, value interface{}) error {
133133
return err
134134
}
135135
err = determineAuthenticatorType(cfg, v)
136+
case "disableocspchecks":
137+
cfg.DisableOCSPChecks, err = parseBool(value)
136138
case "insecuremode":
139+
logInsecureModeDeprecationInfo()
137140
cfg.InsecureMode, err = parseBool(value)
138141
case "ocspfailopen":
139142
var vv ConfigBool

connection_configuration_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ func TestLoadConnectionConfigForOAuth(t *testing.T) {
9494
assertEqualF(t, cfg.Authenticator, AuthTypeOAuth)
9595
assertEqualF(t, cfg.Token, "token_value")
9696
assertEqualF(t, cfg.Port, 443)
97+
assertEqualE(t, cfg.DisableOCSPChecks, true)
9798
}
9899

99100
func TestReadTokenValueWithTokenFilePath(t *testing.T) {
@@ -110,6 +111,7 @@ func TestReadTokenValueWithTokenFilePath(t *testing.T) {
110111
assertNilF(t, err, "The error should not occur")
111112
assertEqualF(t, cfg.Authenticator, AuthTypeOAuth)
112113
assertEqualF(t, cfg.Token, "mock_token123456")
114+
assertEqualE(t, cfg.InsecureMode, true)
113115
}
114116

115117
func TestLoadConnectionConfigWitNonExistingDSN(t *testing.T) {

doc.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,12 @@ The following connection parameters are supported:
106106
107107
- application: Identifies your application to Snowflake Support.
108108
109-
- insecureMode: false by default. Set to true to bypass the Online
109+
- disableOCSPChecks: false by default. Set to true to bypass the Online
110110
Certificate Status Protocol (OCSP) certificate revocation check.
111111
IMPORTANT: Change the default value for testing or emergency situations only.
112112
113+
- insecureMode: deprecated. Use disableOCSPChecks instead.
114+
113115
- token: a token that can be used to authenticate. Should be used in conjunction with the "oauth" authenticator.
114116
115117
- client_session_keep_alive: Set to true have a heartbeat in the background every hour to keep the connection alive

driver_test.go

+16
Original file line numberDiff line numberDiff line change
@@ -1791,6 +1791,22 @@ func TestOpenWithTransport(t *testing.T) {
17911791
t.Fatal("transport did not receive any requests")
17921792
}
17931793

1794+
// Test that transport override also works in OCSP checks disabled.
1795+
countingTransport.requests = 0
1796+
config.DisableOCSPChecks = true
1797+
db, err = driver.OpenWithConfig(context.Background(), *config)
1798+
if err != nil {
1799+
t.Fatalf("failed to open with config. config: %v, err: %v", config, err)
1800+
}
1801+
conn = db.(*snowflakeConn)
1802+
if conn.rest.Client.Transport != transport {
1803+
t.Fatal("transport doesn't match")
1804+
}
1805+
db.Close()
1806+
if countingTransport.requests == 0 {
1807+
t.Fatal("transport did not receive any requests")
1808+
}
1809+
17941810
// Test that transport override also works in insecure mode
17951811
countingTransport.requests = 0
17961812
config.InsecureMode = true

dsn.go

+27-3
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@ type Config struct {
7979
ExternalBrowserTimeout time.Duration // Timeout for external browser login
8080
MaxRetryCount int // Specifies how many times non-periodic HTTP request can be retried
8181

82-
Application string // application name.
82+
Application string // application name.
83+
DisableOCSPChecks bool // driver doesn't check certificate revocation status
84+
// Deprecated: InsecureMode use DisableOCSPChecks instead
8385
InsecureMode bool // driver doesn't check certificate revocation status
8486
OCSPFailOpen OCSPFailOpenMode // OCSP Fail Open
8587

@@ -126,7 +128,7 @@ func (c *Config) Validate() error {
126128

127129
// ocspMode returns the OCSP mode in string INSECURE, FAIL_OPEN, FAIL_CLOSED
128130
func (c *Config) ocspMode() string {
129-
if c.InsecureMode {
131+
if c.DisableOCSPChecks || c.InsecureMode {
130132
return ocspModeInsecure
131133
} else if c.OCSPFailOpen == ocspFailOpenNotSet || c.OCSPFailOpen == OCSPFailOpenTrue {
132134
// by default or set to true
@@ -241,6 +243,9 @@ func DSN(cfg *Config) (dsn string, err error) {
241243
if cfg.InsecureMode {
242244
params.Add("insecureMode", strconv.FormatBool(cfg.InsecureMode))
243245
}
246+
if cfg.DisableOCSPChecks {
247+
params.Add("disableOCSPChecks", strconv.FormatBool(cfg.DisableOCSPChecks))
248+
}
244249
if cfg.Tracing != "" {
245250
params.Add("tracing", cfg.Tracing)
246251
}
@@ -637,7 +642,14 @@ func parseParams(cfg *Config, posQuestion int, dsn string) (err error) {
637642
// parseDSNParams parses the DSN "query string". Values must be url.QueryEscape'ed
638643
func parseDSNParams(cfg *Config, params string) (err error) {
639644
logger.Infof("Query String: %v\n", params)
640-
for _, v := range strings.Split(params, "&") {
645+
paramsSlice := strings.Split(params, "&")
646+
insecureModeIdx := findByPrefix(paramsSlice, "insecureMode")
647+
disableOCSPChecksIdx := findByPrefix(paramsSlice, "disableOCSPChecks")
648+
if insecureModeIdx > -1 && disableOCSPChecksIdx > -1 {
649+
logger.Warn("duplicated insecureMode and disableOCSPChecks. disableOCSPChecks takes precedence")
650+
paramsSlice = append(paramsSlice[:insecureModeIdx-1], paramsSlice[insecureModeIdx+1:]...)
651+
}
652+
for _, v := range paramsSlice {
641653
param := strings.SplitN(v, "=", 2)
642654
if len(param) != 2 {
643655
continue
@@ -715,12 +727,20 @@ func parseDSNParams(cfg *Config, params string) (err error) {
715727
return err
716728
}
717729
case "insecureMode":
730+
logInsecureModeDeprecationInfo()
718731
var vv bool
719732
vv, err = strconv.ParseBool(value)
720733
if err != nil {
721734
return
722735
}
723736
cfg.InsecureMode = vv
737+
case "disableOCSPChecks":
738+
var vv bool
739+
vv, err = strconv.ParseBool(value)
740+
if err != nil {
741+
return
742+
}
743+
cfg.DisableOCSPChecks = vv
724744
case "ocspFailOpen":
725745
var vv bool
726746
vv, err = strconv.ParseBool(value)
@@ -839,6 +859,10 @@ func parseDSNParams(cfg *Config, params string) (err error) {
839859
return
840860
}
841861

862+
func logInsecureModeDeprecationInfo() {
863+
logger.Warn("insecureMode is deprecated. Use disableOCSPChecks instead.")
864+
}
865+
842866
func parseTimeout(value string) (time.Duration, error) {
843867
var vv int64
844868
var err error

dsn_test.go

+81
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,58 @@ func TestParseDSN(t *testing.T) {
540540
ocspMode: ocspModeInsecure,
541541
err: nil,
542542
},
543+
{
544+
dsn: "u:p@a?database=d&schema=s&role=r&application=aa&authenticator=snowflake&disableOCSPChecks=true&passcode=pp&passcodeInPassword=true",
545+
config: &Config{
546+
Account: "a", User: "u", Password: "p",
547+
Protocol: "https", Host: "a.snowflakecomputing.com", Port: 443,
548+
Database: "d", Schema: "s", Role: "r", Authenticator: AuthTypeSnowflake, Application: "aa",
549+
DisableOCSPChecks: true, Passcode: "pp", PasscodeInPassword: true,
550+
OCSPFailOpen: OCSPFailOpenTrue,
551+
ValidateDefaultParameters: ConfigBoolTrue,
552+
ClientTimeout: defaultClientTimeout,
553+
JWTClientTimeout: defaultJWTClientTimeout,
554+
ExternalBrowserTimeout: defaultExternalBrowserTimeout,
555+
IncludeRetryReason: ConfigBoolTrue,
556+
},
557+
ocspMode: ocspModeInsecure,
558+
err: nil,
559+
},
560+
{
561+
dsn: "u:p@a?database=d&schema=s&role=r&application=aa&authenticator=snowflake&disableOCSPChecks=true&passcode=pp&passcodeInPassword=true",
562+
config: &Config{
563+
Account: "a", User: "u", Password: "p",
564+
Protocol: "https", Host: "a.snowflakecomputing.com", Port: 443,
565+
Database: "d", Schema: "s", Role: "r", Authenticator: AuthTypeSnowflake, Application: "aa",
566+
InsecureMode: false, DisableOCSPChecks: true, Passcode: "pp", PasscodeInPassword: true,
567+
OCSPFailOpen: OCSPFailOpenTrue,
568+
ValidateDefaultParameters: ConfigBoolTrue,
569+
ClientTimeout: defaultClientTimeout,
570+
JWTClientTimeout: defaultJWTClientTimeout,
571+
ExternalBrowserTimeout: defaultExternalBrowserTimeout,
572+
IncludeRetryReason: ConfigBoolTrue,
573+
},
574+
ocspMode: ocspModeInsecure,
575+
err: nil,
576+
},
577+
// disableOCSPChecks should take precedence over insecureMode
578+
{
579+
dsn: "u:p@a?database=d&schema=s&role=r&application=aa&authenticator=snowflake&disableOCSPChecks=false&insecureMode=true&passcode=pp&passcodeInPassword=true",
580+
config: &Config{
581+
Account: "a", User: "u", Password: "p",
582+
Protocol: "https", Host: "a.snowflakecomputing.com", Port: 443,
583+
Database: "d", Schema: "s", Role: "r", Authenticator: AuthTypeSnowflake, Application: "aa",
584+
DisableOCSPChecks: false, Passcode: "pp", PasscodeInPassword: true,
585+
OCSPFailOpen: OCSPFailOpenTrue,
586+
ValidateDefaultParameters: ConfigBoolTrue,
587+
ClientTimeout: defaultClientTimeout,
588+
JWTClientTimeout: defaultJWTClientTimeout,
589+
ExternalBrowserTimeout: defaultExternalBrowserTimeout,
590+
IncludeRetryReason: ConfigBoolTrue,
591+
},
592+
ocspMode: ocspModeFailOpen,
593+
err: nil,
594+
},
543595
{
544596
// schema should be ignored as no value is specified.
545597
dsn: "u:p@a?database=d&schema",
@@ -1412,6 +1464,35 @@ func TestDSN(t *testing.T) {
14121464
},
14131465
dsn: "u:[email protected]:443?insecureMode=true&ocspFailOpen=true&validateDefaultParameters=true",
14141466
},
1467+
{
1468+
cfg: &Config{
1469+
User: "u",
1470+
Password: "p",
1471+
Account: "a",
1472+
DisableOCSPChecks: true,
1473+
},
1474+
dsn: "u:[email protected]:443?disableOCSPChecks=true&ocspFailOpen=true&validateDefaultParameters=true",
1475+
},
1476+
{
1477+
cfg: &Config{
1478+
User: "u",
1479+
Password: "p",
1480+
Account: "a",
1481+
InsecureMode: true,
1482+
DisableOCSPChecks: false,
1483+
},
1484+
dsn: "u:[email protected]:443?insecureMode=true&ocspFailOpen=true&validateDefaultParameters=true",
1485+
},
1486+
{
1487+
cfg: &Config{
1488+
User: "u",
1489+
Password: "p",
1490+
Account: "a",
1491+
InsecureMode: false,
1492+
DisableOCSPChecks: true,
1493+
},
1494+
dsn: "u:[email protected]:443?disableOCSPChecks=true&ocspFailOpen=true&validateDefaultParameters=true",
1495+
},
14151496
{
14161497
cfg: &Config{
14171498
User: "u",

ocsp.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -723,11 +723,7 @@ func canEarlyExitForOCSP(results []*ocspStatus, chainSize int) *ocspStatus {
723723
}
724724
}
725725
if len(msg) > 0 {
726-
logger.Warnf(
727-
"WARNING!!! Using fail-open to connect. Driver is connecting to an "+
728-
"HTTPS endpoint without OCSP based Certificate Revocation checking "+
729-
"as it could not obtain a valid OCSP Response to use from the CA OCSP "+
730-
"responder. Detail: %v", msg[1:])
726+
logger.Debugf("OCSP responder didn't respond correctly. Assuming certificate is not revoked. Detail: %v", msg[1:])
731727
}
732728
return nil
733729
}

test_data/connections.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ port = '443'
2020
authenticator = 'oauth'
2121
testNot = 'problematicParameter'
2222
token = 'token_value'
23+
disableOCSPChecks = true
2324

2425
[aws-oauth-file]
2526
account = 'snowdriverswarsaw.us-west-2.aws'
@@ -43,4 +44,5 @@ database = 'test_default_db'
4344
schema = 'test_default_go'
4445
protocol = 'https'
4546
authenticator = 'oauth'
46-
token_file_path = './test_data/snowflake/session/token'
47+
token_file_path = './test_data/snowflake/session/token'
48+
insecureMode = true

util.go

+9
Original file line numberDiff line numberDiff line change
@@ -339,3 +339,12 @@ func withLowerKeys[T any](in map[string]T) map[string]T {
339339
}
340340
return out
341341
}
342+
343+
func findByPrefix(in []string, prefix string) int {
344+
for i, v := range in {
345+
if strings.HasPrefix(v, prefix) {
346+
return i
347+
}
348+
}
349+
return -1
350+
}

util_test.go

+11
Original file line numberDiff line numberDiff line change
@@ -409,3 +409,14 @@ func TestWithLowerKeys(t *testing.T) {
409409
assertEqualE(t, lowerM["abc"], "def")
410410
assertEqualE(t, lowerM["ghi"], "KLM")
411411
}
412+
413+
func TestFindByPrefix(t *testing.T) {
414+
nonEmpty := []string{"aaa", "bbb", "ccc"}
415+
assertEqualE(t, findByPrefix(nonEmpty, "a"), 0)
416+
assertEqualE(t, findByPrefix(nonEmpty, "aa"), 0)
417+
assertEqualE(t, findByPrefix(nonEmpty, "aaa"), 0)
418+
assertEqualE(t, findByPrefix(nonEmpty, "bb"), 1)
419+
assertEqualE(t, findByPrefix(nonEmpty, "ccc"), 2)
420+
assertEqualE(t, findByPrefix(nonEmpty, "dd"), -1)
421+
assertEqualE(t, findByPrefix([]string{}, "dd"), -1)
422+
}

0 commit comments

Comments
 (0)