Skip to content

Commit

Permalink
SNOW-1821504: [JDBC] Initialal OCSP deprecation plan steps (#2008)
Browse files Browse the repository at this point in the history
  • Loading branch information
sfc-gh-ext-simba-vb authored Jan 11, 2025
1 parent dcac111 commit 895b098
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 15 deletions.
8 changes: 4 additions & 4 deletions src/main/java/net/snowflake/client/core/HttpUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -345,9 +345,9 @@ public static CloseableHttpClient buildHttpClient(
}

TrustManager[] trustManagers = null;
if (key != null && key.getOcspMode() != OCSPMode.INSECURE) {
// A custom TrustManager is required only if insecureMode is disabled,
// which is by default in the production. insecureMode can be enabled
if (key != null && key.getOcspMode() != OCSPMode.DISABLE_OCSP_CHECKS) {
// A custom TrustManager is required only if disableOCSPChecks is disabled,
// which is by default in the production. disableOCSPChecks can be enabled
// 1) OCSP service is down for reasons, 2) PowerMock test that doesn't
// care OCSP checks.
// OCSP FailOpen is ON by default
Expand Down Expand Up @@ -742,7 +742,7 @@ public static String executeRequest(
HttpClientSettingsKey ocspAndProxyKey,
ExecTimeTelemetryData execTimeData)
throws SnowflakeSQLException, IOException {
boolean ocspEnabled = !(ocspAndProxyKey.getOcspMode().equals(OCSPMode.INSECURE));
boolean ocspEnabled = !(ocspAndProxyKey.getOcspMode().equals(OCSPMode.DISABLE_OCSP_CHECKS));
logger.debug("Executing request with OCSP enabled: {}", ocspEnabled);
execTimeData.setOCSPStatus(ocspEnabled);
return executeRequestInternal(
Expand Down
11 changes: 9 additions & 2 deletions src/main/java/net/snowflake/client/core/OCSPMode.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,15 @@ public enum OCSPMode {
*/
FAIL_OPEN(1),

/** Insure mode. No OCSP check is made. */
INSECURE(2);
/**
* @deprecated Use {@link #DISABLE_OCSP_CHECKS} for clarity. This configuration option is used to
* disable OCSP verification. Insure mode. No OCSP check is made.
*/
@Deprecated
INSECURE(2),

/** Disable OCSP checks. It's used to disable OCSP verification. */
DISABLE_OCSP_CHECKS(3);

private final int value;

Expand Down
22 changes: 20 additions & 2 deletions src/main/java/net/snowflake/client/core/SFBaseSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -712,14 +712,32 @@ public void unsetInvalidProxyHostAndPort() {
* Get OCSP mode
*
* @return {@link OCSPMode}
* @throws SnowflakeSQLException
*/
public OCSPMode getOCSPMode() {
public OCSPMode getOCSPMode() throws SnowflakeSQLException {
OCSPMode ret;

Boolean disableOCSPChecks =
(Boolean) connectionPropertiesMap.get(SFSessionProperty.DISABLE_OCSP_CHECKS);
Boolean insecureMode = (Boolean) connectionPropertiesMap.get(SFSessionProperty.INSECURE_MODE);
if (insecureMode != null && insecureMode) {
logger.warn(
"The 'insecureMode' connection property is deprecated. Please use 'disableOCSPChecks' instead.");
}

if ((disableOCSPChecks != null && insecureMode != null)
&& (disableOCSPChecks != insecureMode)) {
logger.error(
"The values for 'disableOCSPChecks' and 'insecureMode' must be identical. "
+ "Please unset insecureMode.");
throw new SnowflakeSQLException(
ErrorCode.DISABLEOCSP_INSECUREMODE_VALUE_MISMATCH,
"The values for 'disableOCSPChecks' and 'insecureMode' " + "must be identical.");
}
if ((disableOCSPChecks != null && disableOCSPChecks)
|| (insecureMode != null && insecureMode)) {
// skip OCSP checks
ret = OCSPMode.INSECURE;
ret = OCSPMode.DISABLE_OCSP_CHECKS;
} else if (!connectionPropertiesMap.containsKey(SFSessionProperty.OCSP_FAIL_OPEN)
|| (boolean) connectionPropertiesMap.get(SFSessionProperty.OCSP_FAIL_OPEN)) {
// fail open (by default, not set)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,13 @@ public enum SFSessionProperty {
APP_ID("appId", false, String.class),
APP_VERSION("appVersion", false, String.class),
OCSP_FAIL_OPEN("ocspFailOpen", false, Boolean.class),
/**
* @deprecated Use {@link #DISABLE_OCSP_CHECKS} for clarity. This configuration option is used to
* disable OCSP verification.
*/
@Deprecated
INSECURE_MODE("insecureMode", false, Boolean.class),
DISABLE_OCSP_CHECKS("disableOCSPChecks", false, Boolean.class),
QUERY_TIMEOUT("queryTimeout", false, Integer.class),
STRINGS_QUOTED("stringsQuotedForColumnDef", false, Boolean.class),
APPLICATION("application", false, String.class),
Expand Down
10 changes: 4 additions & 6 deletions src/main/java/net/snowflake/client/core/SFTrustManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -841,10 +841,8 @@ private void executeRevocationStatusChecks(
}

private String generateFailOpenLog(String logData) {
return "WARNING!!! Using fail-open to connect. Driver is connecting to an "
+ "HTTPS endpoint without OCSP based Certificate Revocation checking "
+ "as it could not obtain a valid OCSP Response to use from the CA OCSP "
+ "responder. Details: \n"
return "OCSP responder didn't respond correctly. Assuming certificate is "
+ "not revoked. Details: "
+ logData;
}

Expand Down Expand Up @@ -981,7 +979,7 @@ private void executeOneRevocationStatusCheck(
ocspLog = telemetryData.generateTelemetry(SF_OCSP_EVENT_TYPE_VALIDATION_ERROR, error);
if (isOCSPFailOpen()) {
// Log includes fail-open warning.
logger.error(generateFailOpenLog(ocspLog), false);
logger.debug(generateFailOpenLog(ocspLog), false);
} else {
// still not success, raise an error.
logger.debug(ocspLog, false);
Expand Down Expand Up @@ -1163,7 +1161,7 @@ private OCSPResp fetchOcspResponse(
new DecorrelatedJitterBackoff(sleepTime, MAX_SLEEPING_TIME_IN_MILLISECONDS);
boolean success = false;

final int maxRetryCounter = isOCSPFailOpen() ? 1 : 3;
final int maxRetryCounter = isOCSPFailOpen() ? 1 : 2;
Exception savedEx = null;
CloseableHttpClient httpClient =
ocspCacheServerClient.computeIfAbsent(
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/net/snowflake/client/jdbc/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ public enum ErrorCode {
INVALID_OKTA_USERNAME(200060, SqlState.CONNECTION_EXCEPTION),
GCP_SERVICE_ERROR(200061, SqlState.SYSTEM_ERROR),
AUTHENTICATOR_REQUEST_TIMEOUT(200062, SqlState.CONNECTION_EXCEPTION),
INVALID_STRUCT_DATA(200063, SqlState.DATA_EXCEPTION);
INVALID_STRUCT_DATA(200063, SqlState.DATA_EXCEPTION),
DISABLEOCSP_INSECUREMODE_VALUE_MISMATCH(200064, SqlState.INVALID_PARAMETER_VALUE);

public static final String errorMessageResource = "net.snowflake.client.jdbc.jdbc_error_messages";

Expand Down
26 changes: 26 additions & 0 deletions src/test/java/net/snowflake/client/jdbc/ConnectionLatestIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

Expand Down Expand Up @@ -1636,4 +1637,29 @@ public void shouldFailOnSslExceptionWithLinkToTroubleShootingGuide() throws Inte
"https://docs.snowflake.com/en/user-guide/client-connectivity-troubleshooting/overview"));
}
}

/**
* Test production connectivity with disableOCSPChecksMode enabled. This test applies to driver
* versions after 3.21.0
*/
@Test
public void testDisableOCSPChecksMode() throws SQLException {

String deploymentUrl = "jdbc:snowflake://sfcsupport.snowflakecomputing.com";
Properties properties = new Properties();

properties.put("user", "fakeuser");
properties.put("password", "fakepwd");
properties.put("account", "fakeaccount");
properties.put("disableOCSPChecks", true);
SQLException thrown =
assertThrows(
SQLException.class,
() -> {
DriverManager.getConnection(deploymentUrl, properties);
});

assertThat(
thrown.getErrorCode(), anyOf(is(INVALID_CONNECTION_INFO_CODE), is(BAD_REQUEST_GS_CODE)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* Copyright (c) 2025 Snowflake Computing Inc. All right reserved.
*/
package net.snowflake.client.jdbc;

import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import net.snowflake.client.category.TestTags;
import net.snowflake.client.core.SFTrustManager;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

/** Tests for connection with DisableOCSPchecks and insecuremode settings. */
@Tag(TestTags.CONNECTION)
public class ConnectionWithDisableOCSPModeLatestIT extends BaseJDBCTest {
public static final int INVALID_CONNECTION_INFO_CODE = 390100;
private static final int DISABLE_OCSP_INSECURE_MODE_MISMATCH = 200064;
public static final int BAD_REQUEST_GS_CODE = 390400;

@BeforeEach
public void setUp() {
SFTrustManager.deleteCache();
}

@AfterEach
public void tearDown() {
SFTrustManager.cleanTestSystemParameters();
}

/**
* Test connectivity with disableOCSPChecksMode and insecure mode enabled. This test applies to
* driver versions after 3.21.0
*/
@Test
public void testDisableOCSPChecksModeAndInsecureModeSet() throws SQLException {

boolean disableOCSPChecks = true;
boolean insecureMode = true;
assertThat(
returnErrorCodeFromConnection(disableOCSPChecks, insecureMode),
anyOf(is(INVALID_CONNECTION_INFO_CODE), is(BAD_REQUEST_GS_CODE)));
}

/**
* Test production connectivity with only disableOCSPChecksMode enabled. This test applies to
* driver versions after 3.21.0
*/
@Test
public void testDisableOCSPChecksModeSet() throws SQLException {
boolean disableOCSPChecks = true;
assertThat(
returnErrorCodeFromConnection(disableOCSPChecks, null),
anyOf(is(INVALID_CONNECTION_INFO_CODE), is(BAD_REQUEST_GS_CODE)));
}

/**
* Test production connectivity with only insecureMode enabled. This test applies to driver
* versions after 3.21.0
*/
@Test
public void testInsecureModeSet() throws SQLException {
boolean insecureMode = true;
assertThat(
returnErrorCodeFromConnection(null, insecureMode),
anyOf(is(INVALID_CONNECTION_INFO_CODE), is(BAD_REQUEST_GS_CODE)));
}

/**
* Test production connectivity with disableOCSPChecksMode enabled AND insecureMode disabled. This
* test applies to driver versions after 3.21.0
*/
@Test
public void testDisableOCSPChecksModeAndInsecureModeMismatched() throws SQLException {
boolean disableOCSPChecks = true;
boolean insecureMode = false;
assertThat(
returnErrorCodeFromConnection(disableOCSPChecks, insecureMode),
anyOf(is(DISABLE_OCSP_INSECURE_MODE_MISMATCH)));
}

/**
* Helper method to return error code from connection.
*
* @param disableOSCPChecks
* @param isInsecureMode
* @return SF Error code
* @throws SQLException
*/
public int returnErrorCodeFromConnection(Boolean disableOSCPChecks, Boolean isInsecureMode)
throws SQLException {
String deploymentUrl = "jdbc:snowflake://sfcsupport.snowflakecomputing.com";
Properties properties = new Properties();

properties.put("user", "fakeuser");
properties.put("password", "fakepwd");
properties.put("account", "fakeaccount");
if (disableOSCPChecks != null) {
properties.put("disableOCSPChecks", disableOSCPChecks);
}
if (isInsecureMode != null) {
properties.put("insecureMode", isInsecureMode);
}

SQLException thrown =
assertThrows(
SQLException.class,
() -> {
DriverManager.getConnection(deploymentUrl, properties);
});

return (thrown.getErrorCode());
}
}

0 comments on commit 895b098

Please sign in to comment.