Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 31 additions & 14 deletions src/snowflake/connector/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def _get_private_bytes_from_file(
# add the new client type to the server to support these features.
"internal_application_name": (CLIENT_NAME, (type(None), str)),
"internal_application_version": (CLIENT_VERSION, (type(None), str)),
"insecure_mode": (False, bool), # Error security fix requirement
"disable_ocsp_checks": (False, bool),
"ocsp_fail_open": (True, bool), # fail open on ocsp issues, default true
"inject_client_pause": (0, int), # snowflake internal
"session_parameters": (None, (type(None), dict)), # snowflake session parameters
Expand Down Expand Up @@ -327,8 +327,10 @@ class SnowflakeConnection:
Use connect(..) to get the object.

Attributes:
insecure_mode: Whether or not the connection is in insecure mode. Insecure mode means that the connection
validates the TLS certificate but doesn't check revocation status.
insecure_mode (deprecated): Whether or not the connection is in OCSP disabled mode. It means that the connection
validates the TLS certificate but doesn't check revocation status with OCSP provider.
disable_ocsp_checks: Whether or not the connection is in OCSP disabled mode. It means that the connection
validates the TLS certificate but doesn't check revocation status with OCSP provider.
ocsp_fail_open: Whether or not the connection is in fail open mode. Fail open mode decides if TLS certificates
continue to be validated. Revoked certificates are blocked. Any other exceptions are disregarded.
session_id: The session ID of the connection.
Expand Down Expand Up @@ -438,6 +440,23 @@ def __init__(
elif "streamlit" in sys.modules:
kwargs["application"] = "streamlit"

if "insecure_mode" in kwargs:
logger.warning(
"The 'insecure_mode' connection property is deprecated. "
"Please use 'disable_ocsp_checks' instead"
)

if (
"disable_ocsp_checks" in kwargs
and kwargs["disable_ocsp_checks"] != kwargs["insecure_mode"]
):
logger.warning(
"The values for 'disable_ocsp_checks' and 'insecure_mode' differ. "
"Using the value of 'disable_ocsp_checks."
)
else:
self._disable_ocsp_checks = kwargs["insecure_mode"]

self.converter = None
self.query_context_cache: QueryContextCache | None = None
self.query_context_cache_size = 5
Expand Down Expand Up @@ -470,8 +489,8 @@ def __init__(
atexit.register(self._close_at_exit)

@property
def insecure_mode(self) -> bool:
return self._insecure_mode
def disable_ocsp_checks(self) -> bool:
return self._disable_ocsp_checks

@property
def ocsp_fail_open(self) -> bool:
Expand All @@ -480,8 +499,8 @@ def ocsp_fail_open(self) -> bool:
def _ocsp_mode(self) -> OCSPMode:
"""OCSP mode. INSEC
URE, FAIL_OPEN or FAIL_CLOSED."""
if self.insecure_mode:
return OCSPMode.INSECURE
if self.disable_ocsp_checks:
return OCSPMode.DISABLE_OCSP_CHECKS
elif self.ocsp_fail_open:
return OCSPMode.FAIL_OPEN
else:
Expand Down Expand Up @@ -1288,7 +1307,7 @@ def __config(self, **kwargs):
)

if self.ocsp_fail_open:
logger.info(
logger.debug(
"This connection is in OCSP Fail Open Mode. "
"TLS Certificates would be checked for validity "
"and revocation status. Any other Certificate "
Expand All @@ -1297,12 +1316,10 @@ def __config(self, **kwargs):
"connectivity."
)

if self.insecure_mode:
logger.info(
"THIS CONNECTION IS IN INSECURE MODE. IT "
"MEANS THE CERTIFICATE WILL BE VALIDATED BUT THE "
"CERTIFICATE REVOCATION STATUS WILL NOT BE "
"CHECKED."
if self.disable_ocsp_checks:
logger.debug(
"This connection runs with disabled OCSP checks. "
"Revocation status of the certificate will not be checked against OCSP Responder."
)

def cmd_query(
Expand Down
4 changes: 2 additions & 2 deletions src/snowflake/connector/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,12 +354,12 @@ class OCSPMode(Enum):
FAIL_OPEN: A response indicating a revoked certificate results in a failed connection. A response with any
other certificate errors or statuses allows the connection to occur, but denotes the message in the logs
at the WARNING level with the relevant details in JSON format.
INSECURE: The connection will occur anyway.
DISABLE_OCSP_CHECKS: The OCSP check will not happen. If the certificate is valid then connection will occur.
"""

FAIL_CLOSED = "FAIL_CLOSED"
FAIL_OPEN = "FAIL_OPEN"
INSECURE = "INSECURE"
DISABLE_OCSP_CHECKS = "DISABLE_OCSP_CHECKS"


@unique
Expand Down
12 changes: 6 additions & 6 deletions src/snowflake/connector/ocsp_snowflake.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ def __init__(self) -> None:
self.cache_enabled = False
self.cache_hit = False
self.fail_open = False
self.insecure_mode = False
self.disable_ocsp_checks = False

def set_event_sub_type(self, event_sub_type: str) -> None:
"""
Expand Down Expand Up @@ -380,8 +380,8 @@ def set_cache_hit(self, cache_hit) -> None:
def set_fail_open(self, fail_open) -> None:
self.fail_open = fail_open

def set_insecure_mode(self, insecure_mode) -> None:
self.insecure_mode = insecure_mode
def set_disable_ocsp_checks(self, disable_ocsp_checks) -> None:
self.disable_ocsp_checks = disable_ocsp_checks

def generate_telemetry_data(
self, event_type: str, urgent: bool = False
Expand All @@ -396,7 +396,7 @@ def generate_telemetry_data(
TelemetryField.KEY_OOB_OCSP_REQUEST_BASE64.value: self.ocsp_req,
TelemetryField.KEY_OOB_OCSP_RESPONDER_URL.value: self.ocsp_url,
TelemetryField.KEY_OOB_ERROR_MESSAGE.value: self.error_msg,
TelemetryField.KEY_OOB_INSECURE_MODE.value: self.insecure_mode,
TelemetryField.KEY_OOB_DISABLE_OCSP_CHECKS.value: self.disable_ocsp_checks,
TelemetryField.KEY_OOB_FAIL_OPEN.value: self.fail_open,
TelemetryField.KEY_OOB_CACHE_ENABLED.value: self.cache_enabled,
TelemetryField.KEY_OOB_CACHE_HIT.value: self.cache_hit,
Expand Down Expand Up @@ -1091,7 +1091,7 @@ def validate_certfile(self, cert_filename, no_exception: bool = False):
cert_map = {}
telemetry_data = OCSPTelemetryData()
telemetry_data.set_cache_enabled(self.OCSP_CACHE_SERVER.CACHE_SERVER_ENABLED)
telemetry_data.set_insecure_mode(False)
telemetry_data.set_disable_ocsp_checks(False)
telemetry_data.set_sfc_peer_host(cert_filename)
telemetry_data.set_fail_open(self.is_enabled_fail_open())
try:
Expand Down Expand Up @@ -1137,7 +1137,7 @@ def validate(

telemetry_data = OCSPTelemetryData()
telemetry_data.set_cache_enabled(self.OCSP_CACHE_SERVER.CACHE_SERVER_ENABLED)
telemetry_data.set_insecure_mode(False)
telemetry_data.set_disable_ocsp_checks(False)
telemetry_data.set_sfc_peer_host(hostname)
telemetry_data.set_fail_open(self.is_enabled_fail_open())

Expand Down
10 changes: 4 additions & 6 deletions src/snowflake/connector/ssl_wrap_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def ssl_wrap_socket_with_ocsp(*args: Any, **kwargs: Any) -> WrappedSocket:
FEATURE_OCSP_MODE.name,
FEATURE_OCSP_RESPONSE_CACHE_FILE_NAME,
)
if FEATURE_OCSP_MODE != OCSPMode.INSECURE:
if FEATURE_OCSP_MODE != OCSPMode.DISABLE_OCSP_CHECKS:
from .ocsp_asn1crypto import SnowflakeOCSPAsn1Crypto as SFOCSP

v = SFOCSP(
Expand All @@ -98,11 +98,9 @@ def ssl_wrap_socket_with_ocsp(*args: Any, **kwargs: Any) -> WrappedSocket:
errno=ER_OCSP_RESPONSE_CERT_STATUS_REVOKED,
)
else:
log.info(
"THIS CONNECTION IS IN INSECURE "
"MODE. IT MEANS THE CERTIFICATE WILL BE "
"VALIDATED BUT THE CERTIFICATE REVOCATION "
"STATUS WILL NOT BE CHECKED."
log.debug(
"This connection does not perform OCSP checks. "
"Revocation status of the certificate will not be checked against OCSP Responder."
)

return ret
Expand Down
2 changes: 1 addition & 1 deletion src/snowflake/connector/telemetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class TelemetryField(Enum):
KEY_OOB_CERT_ID = "certId"
KEY_OOB_OCSP_REQUEST_BASE64 = "ocspRequestBase64"
KEY_OOB_OCSP_RESPONDER_URL = "ocspResponderURL"
KEY_OOB_INSECURE_MODE = "insecureMode"
KEY_OOB_DISABLE_OCSP_CHECKS = "disableOcspChecks"
KEY_OOB_FAIL_OPEN = "failOpen"
KEY_OOB_CACHE_ENABLED = "cacheEnabled"
KEY_OOB_CACHE_HIT = "cacheHit"
Expand Down
73 changes: 70 additions & 3 deletions test/integ/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ def test_bogus(db_parameters):
host=db_parameters["host"],
port=db_parameters["port"],
login_timeout=5,
insecure_mode=True,
disable_ocsp_checks=True,
)

with pytest.raises(DatabaseError):
Expand Down Expand Up @@ -1357,19 +1357,86 @@ def test_server_session_keep_alive(conn_cnx):


@pytest.mark.skipolddriver
def test_ocsp_mode_insecure(conn_cnx, is_public_test, caplog):
def test_ocsp_mode_disable_ocsp_checks(conn_cnx, is_public_test, caplog):
caplog.set_level(logging.DEBUG, "snowflake.connector.ocsp_snowflake")
with conn_cnx(insecure_mode=True) as conn, conn.cursor() as cur:
with conn_cnx(disable_ocsp_checks=True) as conn, conn.cursor() as cur:
assert cur.execute("select 1").fetchall() == [(1,)]
assert "snowflake.connector.ocsp_snowflake" not in caplog.text
assert "This connection does not perform OCSP checks." in caplog.text
caplog.clear()

with conn_cnx() as conn, conn.cursor() as cur:
assert cur.execute("select 1").fetchall() == [(1,)]
if is_public_test:
assert "snowflake.connector.ocsp_snowflake" in caplog.text
assert "This connection does not perform OCSP checks." not in caplog.text
else:
assert "snowflake.connector.ocsp_snowflake" not in caplog.text
assert "This connection does not perform OCSP checks." not in caplog.text


@pytest.mark.skipolddriver
def test_ocsp_mode_insecure_mode(conn_cnx, is_public_test, caplog):
caplog.set_level(logging.DEBUG, "snowflake.connector.ocsp_snowflake")
with conn_cnx(insecure_mode=True) as conn, conn.cursor() as cur:
assert cur.execute("select 1").fetchall() == [(1,)]
assert "snowflake.connector.ocsp_snowflake" not in caplog.text
assert "The 'insecure_mode' connection property is deprecated." in caplog.text
assert "This connection does not perform OCSP checks." in caplog.text


@pytest.mark.skipolddriver
def test_ocsp_mode_insecure_mode_and_disable_ocsp_checks_match(
conn_cnx, is_public_test, caplog
):
caplog.set_level(logging.DEBUG, "snowflake.connector.ocsp_snowflake")
with conn_cnx(
insecure_mode=True, disable_ocsp_checks=True
) as conn, conn.cursor() as cur:
assert cur.execute("select 1").fetchall() == [(1,)]
assert "snowflake.connector.ocsp_snowflake" not in caplog.text
assert "The 'insecure_mode' connection property is deprecated." in caplog.text
assert (
"The values for 'disable_ocsp_checks' and 'insecure_mode' differ. "
"Using the value of 'disable_ocsp_checks."
) not in caplog.text
assert "This connection does not perform OCSP checks." in caplog.text


@pytest.mark.skipolddriver
def test_ocsp_mode_insecure_mode_and_disable_ocsp_checks_mismatch_ocsp_disabled(
conn_cnx, is_public_test, caplog
):
caplog.set_level(logging.DEBUG, "snowflake.connector.ocsp_snowflake")
with conn_cnx(
insecure_mode=False, disable_ocsp_checks=True
) as conn, conn.cursor() as cur:
assert cur.execute("select 1").fetchall() == [(1,)]
assert "snowflake.connector.ocsp_snowflake" not in caplog.text
assert "The 'insecure_mode' connection property is deprecated." in caplog.text
assert (
"The values for 'disable_ocsp_checks' and 'insecure_mode' differ. "
"Using the value of 'disable_ocsp_checks."
) in caplog.text
assert "This connection does not perform OCSP checks." in caplog.text


@pytest.mark.skipolddriver
def test_ocsp_mode_insecure_mode_and_disable_ocsp_checks_mismatch_ocsp_enabled(
conn_cnx, is_public_test, caplog
):
caplog.set_level(logging.DEBUG, "snowflake.connector.ocsp_snowflake")
with conn_cnx(
insecure_mode=True, disable_ocsp_checks=False
) as conn, conn.cursor() as cur:
assert cur.execute("select 1").fetchall() == [(1,)]
assert "snowflake.connector.ocsp_snowflake" in caplog.text
assert "The 'insecure_mode' connection property is deprecated." in caplog.text
assert (
"The values for 'disable_ocsp_checks' and 'insecure_mode' differ. "
"Using the value of 'disable_ocsp_checks."
) in caplog.text
assert "This connection does not perform OCSP checks." not in caplog.text


@pytest.mark.skipolddriver
Expand Down
Loading