Skip to content

Commit c93c72e

Browse files
Add 1 day to validity period
1 parent a26bc1f commit c93c72e

File tree

2 files changed

+64
-138
lines changed

2 files changed

+64
-138
lines changed

src/snowflake/connector/crl.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ def _validate_chain(
313313
but some certificates can't be verified.
314314
"""
315315
# Check if start certificate is expired
316-
if not self._is_valid(start_cert):
316+
if not self._is_within_validity_dates(start_cert):
317317
logger.warning(
318318
"Start certificate is expired or not yet valid: %s", start_cert.subject
319319
)
@@ -326,6 +326,11 @@ def _validate_chain(
326326
if not self._is_ca_certificate(cert):
327327
logger.warning("Ignoring non-CA certificate: %s", cert)
328328
continue
329+
if not self._is_within_validity_dates(cert):
330+
logger.warning(
331+
"Ignoring certificate not within validity dates: %s", cert
332+
)
333+
continue
329334
subject_certificates[cert.subject].append(cert)
330335
currently_visited_subjects: set[x509.Name] = set()
331336

@@ -451,9 +456,8 @@ def _get_certificate_validity_dates(
451456
return not_valid_before, not_valid_after
452457

453458
@staticmethod
454-
def _is_valid(cert: x509.Certificate) -> bool:
459+
def _is_within_validity_dates(cert: x509.Certificate) -> bool:
455460
# Check if a certificate is currently valid (not expired and not before validity period).
456-
457461
not_valid_before, not_valid_after = (
458462
CRLValidator._get_certificate_validity_dates(cert)
459463
)
@@ -509,12 +513,12 @@ def _is_short_lived_certificate(cert: x509.Certificate) -> bool:
509513
validity period <= 7 days (604,800 seconds)
510514
"""
511515
issue_date, expiry_date = CRLValidator._get_certificate_validity_dates(cert)
512-
validity_period = expiry_date - issue_date
516+
validity_period = expiry_date - issue_date + timedelta(days=1)
513517

514518
march_15_2026 = datetime(2026, 3, 15, tzinfo=timezone.utc)
515519
if issue_date >= march_15_2026:
516-
return validity_period.total_seconds() <= 604800 # 7 days in seconds
517-
return validity_period.total_seconds() <= 864000 # 10 days in seconds
520+
return validity_period.days <= 7
521+
return validity_period.days <= 10
518522

519523
@staticmethod
520524
def _extract_crl_distribution_points(cert: x509.Certificate) -> list[str]:

test/unit/test_crl.py

Lines changed: 54 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -1864,49 +1864,49 @@ def test_crl_signature_verification_with_issuer_mismatch_warning(
18641864
(
18651865
# Issued on March 15, 2024, should use 10-day rule
18661866
datetime(2024, 3, 15, tzinfo=timezone.utc),
1867-
10,
1867+
9,
18681868
True,
18691869
),
18701870
(
18711871
# Issued on March 15, 2024, should use 10-day rule
18721872
datetime(2024, 3, 15, tzinfo=timezone.utc),
1873-
11,
1873+
10,
18741874
False,
18751875
),
18761876
(
18771877
# Issued on March 15, 2024, should use 10-day rule
18781878
datetime(2024, 3, 15),
1879-
10,
1879+
9,
18801880
True,
18811881
),
18821882
(
18831883
# Issued on March 15, 2024, should use 10-day rule
18841884
datetime(2024, 3, 15),
1885-
11,
1885+
10,
18861886
False,
18871887
),
18881888
(
18891889
# Issued on March 15, 2026, should use 7-day rule
18901890
datetime(2026, 3, 15, tzinfo=timezone.utc),
1891-
7,
1891+
6,
18921892
True,
18931893
),
18941894
(
18951895
# Issued on March 15, 2026, should use 7-day rule
18961896
datetime(2026, 3, 15, tzinfo=timezone.utc),
1897-
8,
1897+
7,
18981898
False,
18991899
),
19001900
(
19011901
# Issued on March 15, 2026, should use 7-day rule
19021902
datetime(2026, 3, 15),
1903-
7,
1903+
6,
19041904
True,
19051905
),
19061906
(
19071907
# Issued on March 15, 2026, should use 7-day rule
19081908
datetime(2026, 3, 15),
1909-
8,
1909+
7,
19101910
False,
19111911
),
19121912
],
@@ -1917,73 +1917,40 @@ def test_is_short_lived_certificate(cert_gen, issue_date, validity_days, expecte
19171917

19181918

19191919
def test_validate_certificate_signatures(cert_gen, session_manager):
1920-
"""Test that certificate validation fails with ERROR when signed by wrong key"""
1921-
# we will replace intermediate cert with one with a wrong signature
1922-
chain = cert_gen.create_simple_chain()
1920+
"""Test that certificate validation fails with ERROR when certificate is expired"""
1921+
name = x509.Name(
1922+
[
1923+
x509.NameAttribute(
1924+
NameOID.COMMON_NAME,
1925+
"Test Expired Certificate",
1926+
)
1927+
]
1928+
)
19231929
different_key = rsa.generate_private_key(
19241930
public_exponent=65537, key_size=2048, backend=default_backend()
19251931
)
1926-
different_cert = (
1932+
malsigned_cert = (
19271933
x509.CertificateBuilder()
1928-
.subject_name(chain.intermediate_cert.subject)
1929-
.issuer_name(chain.intermediate_cert.issuer)
1930-
.public_key(chain.intermediate_cert.public_key())
1934+
.subject_name(name)
1935+
.issuer_name(cert_gen.ca_certificate.subject)
1936+
.public_key(cert_gen.ca_certificate.public_key()) # does not matter
19311937
.serial_number(x509.random_serial_number())
1932-
.not_valid_before(datetime.now(timezone.utc))
1938+
.not_valid_before(datetime.now(timezone.utc) - timedelta(days=2))
19331939
.not_valid_after(datetime.now(timezone.utc) + timedelta(days=365))
19341940
.add_extension(
19351941
x509.BasicConstraints(ca=True, path_length=None),
19361942
critical=True,
19371943
)
1938-
.sign(different_key, hashes.SHA256(), backend=default_backend())
1944+
.sign(different_key, hashes.SHA256())
19391945
)
1940-
short_lived_different_cert = (
1941-
x509.CertificateBuilder()
1942-
.subject_name(chain.intermediate_cert.subject)
1943-
.issuer_name(chain.intermediate_cert.issuer)
1944-
.public_key(chain.intermediate_cert.public_key())
1945-
.serial_number(x509.random_serial_number())
1946-
.not_valid_before(datetime.now(timezone.utc))
1947-
.not_valid_after(datetime.now(timezone.utc) + timedelta(days=3))
1948-
.add_extension(
1949-
x509.BasicConstraints(ca=True, path_length=None),
1950-
critical=True,
1951-
)
1952-
.sign(different_key, hashes.SHA256(), backend=default_backend())
1953-
)
1954-
19551946
validator = CRLValidator(
19561947
session_manager,
19571948
cert_revocation_check_mode=CertRevocationCheckMode.ENABLED,
19581949
allow_certificates_without_crl_url=True,
1959-
trusted_certificates=[chain.root_cert],
1960-
)
1961-
1962-
# wrong signature - no path found = ERROR
1963-
assert (
1964-
validator._validate_chain(chain.leaf_cert, [different_cert, chain.root_cert])
1965-
== CRLValidationResult.ERROR
1966-
)
1967-
# wrong signature - short-lived - no path found = ERROR
1968-
assert (
1969-
validator._validate_chain(
1970-
chain.leaf_cert, [short_lived_different_cert, chain.root_cert]
1971-
)
1972-
== CRLValidationResult.ERROR
1973-
)
1974-
# wrong signature does not stop from searching of new path
1975-
assert (
1976-
validator._validate_chain(
1977-
chain.leaf_cert,
1978-
[
1979-
different_cert,
1980-
short_lived_different_cert,
1981-
chain.intermediate_cert,
1982-
chain.root_cert,
1983-
],
1984-
)
1985-
== CRLValidationResult.UNREVOKED
1950+
trusted_certificates=[cert_gen.ca_certificate],
19861951
)
1952+
# expired cert - no path found = ERROR
1953+
assert validator._validate_chain(malsigned_cert, []) == CRLValidationResult.ERROR
19871954

19881955

19891956
def test_validate_certificate_signatures_in_chain(cert_gen, session_manager):
@@ -2001,8 +1968,8 @@ def test_validate_certificate_signatures_in_chain(cert_gen, session_manager):
20011968
different_cert = (
20021969
x509.CertificateBuilder()
20031970
.subject_name(valid_cert.subject)
2004-
.issuer_name(cert_gen.ca_certificate.subject)
2005-
.public_key(cert_gen.ca_private_key.public_key())
1971+
.issuer_name(valid_cert.subject)
1972+
.public_key(valid_cert.public_key())
20061973
.serial_number(x509.random_serial_number())
20071974
.not_valid_before(datetime.now(timezone.utc))
20081975
.not_valid_after(datetime.now(timezone.utc) + timedelta(days=365))
@@ -2015,8 +1982,8 @@ def test_validate_certificate_signatures_in_chain(cert_gen, session_manager):
20151982
short_lived_different_cert = (
20161983
x509.CertificateBuilder()
20171984
.subject_name(valid_cert.subject)
2018-
.issuer_name(cert_gen.ca_certificate.subject)
2019-
.public_key(different_key.public_key())
1985+
.issuer_name(valid_cert.subject)
1986+
.public_key(valid_cert.public_key())
20201987
.serial_number(x509.random_serial_number())
20211988
.not_valid_before(datetime.now(timezone.utc))
20221989
.not_valid_after(datetime.now(timezone.utc) + timedelta(days=3))
@@ -2066,88 +2033,51 @@ def test_validate_certificate_signatures_in_chain(cert_gen, session_manager):
20662033

20672034
def test_validate_expired_certificates(cert_gen, session_manager):
20682035
"""Test that certificate validation fails with ERROR when certificate is expired"""
2069-
# We will replace intermediate cert with an expired one
2070-
chain = cert_gen.create_simple_chain()
2071-
2072-
# Create an expired certificate (expired 10 days ago)
2073-
expired_cert = (
2074-
x509.CertificateBuilder()
2075-
.subject_name(chain.intermediate_cert.subject)
2076-
.issuer_name(chain.intermediate_cert.issuer)
2077-
.public_key(chain.intermediate_cert.public_key())
2078-
.serial_number(x509.random_serial_number())
2079-
.not_valid_before(datetime.now(timezone.utc) - timedelta(days=365))
2080-
.not_valid_after(datetime.now(timezone.utc) - timedelta(days=10))
2081-
.add_extension(
2082-
x509.BasicConstraints(ca=True, path_length=None),
2083-
critical=True,
2084-
)
2085-
.sign(cert_gen.ca_private_key, hashes.SHA256(), backend=default_backend())
2036+
name = x509.Name(
2037+
[
2038+
x509.NameAttribute(
2039+
NameOID.COMMON_NAME,
2040+
"Test Expired Certificate",
2041+
)
2042+
]
20862043
)
2087-
2088-
# Create a short-lived expired certificate (expired 1 day ago)
2089-
short_lived_expired_cert = (
2044+
expired_cert = (
20902045
x509.CertificateBuilder()
2091-
.subject_name(chain.intermediate_cert.subject)
2092-
.issuer_name(chain.intermediate_cert.issuer)
2093-
.public_key(chain.intermediate_cert.public_key())
2046+
.subject_name(name)
2047+
.issuer_name(cert_gen.ca_certificate.subject)
2048+
.public_key(cert_gen.ca_certificate.public_key()) # does not matter
20942049
.serial_number(x509.random_serial_number())
2095-
.not_valid_before(datetime.now(timezone.utc) - timedelta(days=4))
2050+
.not_valid_before(datetime.now(timezone.utc) - timedelta(days=2))
20962051
.not_valid_after(datetime.now(timezone.utc) - timedelta(days=1))
20972052
.add_extension(
20982053
x509.BasicConstraints(ca=True, path_length=None),
20992054
critical=True,
21002055
)
2101-
.sign(cert_gen.ca_private_key, hashes.SHA256(), backend=default_backend())
2056+
.sign(cert_gen.ca_private_key, hashes.SHA256())
21022057
)
2103-
21042058
validator = CRLValidator(
21052059
session_manager,
21062060
cert_revocation_check_mode=CertRevocationCheckMode.ENABLED,
21072061
allow_certificates_without_crl_url=True,
2108-
trusted_certificates=[chain.root_cert],
2062+
trusted_certificates=[cert_gen.ca_certificate],
21092063
)
2110-
21112064
# expired cert - no path found = ERROR
2112-
assert (
2113-
validator._validate_chain(chain.leaf_cert, [expired_cert, chain.root_cert])
2114-
== CRLValidationResult.ERROR
2115-
)
2116-
# expired short-lived cert - no path found = ERROR
2117-
assert (
2118-
validator._validate_chain(
2119-
chain.leaf_cert, [short_lived_expired_cert, chain.root_cert]
2120-
)
2121-
== CRLValidationResult.ERROR
2122-
)
2123-
# expired cert does not stop from searching for a valid path
2124-
assert (
2125-
validator._validate_chain(
2126-
chain.leaf_cert,
2127-
[
2128-
expired_cert,
2129-
short_lived_expired_cert,
2130-
chain.intermediate_cert,
2131-
chain.root_cert,
2132-
],
2133-
)
2134-
== CRLValidationResult.UNREVOKED
2135-
)
2065+
assert validator._validate_chain(expired_cert, []) == CRLValidationResult.ERROR
21362066

21372067

21382068
def test_validate_expired_certificates_in_chain(cert_gen, session_manager):
21392069
"""Test that certificate validation fails with ERROR when certificate in chain is expired"""
2140-
# Create a certificate chain signed by the test CA: final_cert -> leafA -> A -> rootA -> CA
2070+
# Create a certificate chain signed by the test CA: final_cert -> leafA -> rootA -> CA
21412071
chain = cert_gen.create_cross_signed_chain()
21422072

2143-
valid_cert = chain.BsignA
2073+
valid_cert = chain.rootA
21442074

21452075
# Create an expired certificate with the same subject as valid_cert
21462076
expired_cert = (
21472077
x509.CertificateBuilder()
21482078
.subject_name(valid_cert.subject)
21492079
.issuer_name(cert_gen.ca_certificate.subject)
2150-
.public_key(cert_gen.ca_private_key.public_key())
2080+
.public_key(valid_cert.public_key())
21512081
.serial_number(x509.random_serial_number())
21522082
.not_valid_before(datetime.now(timezone.utc) - timedelta(days=365))
21532083
.not_valid_after(datetime.now(timezone.utc) - timedelta(days=10))
@@ -2163,7 +2093,7 @@ def test_validate_expired_certificates_in_chain(cert_gen, session_manager):
21632093
x509.CertificateBuilder()
21642094
.subject_name(valid_cert.subject)
21652095
.issuer_name(cert_gen.ca_certificate.subject)
2166-
.public_key(cert_gen.ca_private_key.public_key())
2096+
.public_key(valid_cert.public_key())
21672097
.serial_number(x509.random_serial_number())
21682098
.not_valid_before(datetime.now(timezone.utc) - timedelta(days=4))
21692099
.not_valid_after(datetime.now(timezone.utc) - timedelta(days=1))
@@ -2183,15 +2113,13 @@ def test_validate_expired_certificates_in_chain(cert_gen, session_manager):
21832113

21842114
# expired cert - no path found = ERROR
21852115
assert (
2186-
validator._validate_chain(
2187-
chain.final_cert, [chain.leafA, expired_cert, chain.rootB]
2188-
)
2116+
validator._validate_chain(chain.final_cert, [chain.leafA, expired_cert])
21892117
== CRLValidationResult.ERROR
21902118
)
21912119
# expired short-lived cert - no path found = ERROR
21922120
assert (
21932121
validator._validate_chain(
2194-
chain.final_cert, [chain.leafA, short_lived_expired_cert, chain.rootB]
2122+
chain.final_cert, [chain.leafA, short_lived_expired_cert]
21952123
)
21962124
== CRLValidationResult.ERROR
21972125
)
@@ -2204,7 +2132,6 @@ def test_validate_expired_certificates_in_chain(cert_gen, session_manager):
22042132
expired_cert,
22052133
short_lived_expired_cert,
22062134
valid_cert,
2207-
chain.rootB,
22082135
],
22092136
)
22102137
== CRLValidationResult.UNREVOKED
@@ -2240,13 +2167,8 @@ def test_trusted_certificates_helpers(cert_gen):
22402167
(timedelta(days=-365), timedelta(seconds=1), True),
22412168
],
22422169
)
2243-
def test_is_valid_certificate(timedelta_before, timedelta_after, expected_result):
2244-
"""Test the _is_valid function for certificate validity checks
2245-
2246-
timedelta_before: offset from now to calculate not_valid_before (negative = past)
2247-
timedelta_after: offset from now to calculate not_valid_after (positive = future)
2248-
expected_result: expected result of _is_valid()
2249-
"""
2170+
def test_is_within_validity_dates(timedelta_before, timedelta_after, expected_result):
2171+
"""Test the _is_within_validity_dates function for certificate validity checks"""
22502172
key = rsa.generate_private_key(
22512173
public_exponent=65537, key_size=2048, backend=default_backend()
22522174
)
@@ -2267,7 +2189,7 @@ def test_is_valid_certificate(timedelta_before, timedelta_after, expected_result
22672189
.sign(key, hashes.SHA256(), backend=default_backend())
22682190
)
22692191

2270-
assert CRLValidator._is_valid(cert) is expected_result
2192+
assert CRLValidator._is_within_validity_dates(cert) is expected_result
22712193

22722194

22732195
def test_verify_against_idp_extension_no_extension(cert_gen):

0 commit comments

Comments
 (0)