Skip to content

Commit 691eac1

Browse files
fixup! SNOW-1902886: Validate account input
1 parent 0082672 commit 691eac1

File tree

3 files changed

+52
-27
lines changed

3 files changed

+52
-27
lines changed

src/snowflake/connector/connection.py

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,13 @@ def __init__(
669669
self._file_operation_parser = FileOperationParser(self)
670670
self._stream_downloader = StreamDownloader(self)
671671

672+
@staticmethod
673+
def _validate_account(account_str):
674+
if not is_valid_account_identifier(account_str):
675+
raise ValueError(
676+
"Invalid account identifier: only letters, digits, '_' and '-' allowed; no dots or slashes"
677+
)
678+
672679
# Deprecated
673680
@property
674681
def insecure_mode(self) -> bool:
@@ -1628,6 +1635,7 @@ def __config(self, **kwargs):
16281635
raise TypeError("auth_class must subclass AuthByPlugin")
16291636

16301637
if "account" in kwargs:
1638+
self._validate_account(kwargs["account"])
16311639
if "host" not in kwargs:
16321640
self._host = construct_hostname(kwargs.get("region"), self._account)
16331641

@@ -1748,20 +1756,8 @@ def __config(self, **kwargs):
17481756
ProgrammingError,
17491757
{"msg": "Account must be specified", "errno": ER_NO_ACCOUNT_NAME},
17501758
)
1751-
if self._account:
1752-
# Allow legacy formats like "acc.region" to continue parsing into simple account id
1753-
if "." in self._account:
1754-
self._account = parse_account(self._account)
1755-
if not is_valid_account_identifier(self._account):
1756-
Error.errorhandler_wrapper(
1757-
self,
1758-
None,
1759-
ProgrammingError,
1760-
{
1761-
"msg": "Invalid account identifier: only letters, digits, '_' and '-' allowed; no dots or slashes",
1762-
"errno": ER_INVALID_VALUE,
1763-
},
1764-
)
1759+
if self._account and "." in self._account:
1760+
self._account = parse_account(self._account)
17651761

17661762
if not isinstance(self._backoff_policy, Callable) or not isinstance(
17671763
self._backoff_policy(), Iterator

src/snowflake/connector/util_text.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,9 +265,11 @@ def is_valid_account_identifier(account: str) -> bool:
265265
"""
266266
if not isinstance(account, str) or not account:
267267
return False
268-
if "." in account or "/" in account or "\\" in account:
268+
269+
if "/" in account or "\\" in account:
269270
return False
270-
return bool(ACCOUNT_ID_VALIDATOR_RE.fullmatch(account))
271+
272+
return all(bool(ACCOUNT_ID_VALIDATOR_RE.fullmatch(p)) for p in account.split("."))
271273

272274

273275
def parse_account(account):

test/unit/test_parse_account.py

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import pytest
55

6+
from snowflake.connector import connect
67
from snowflake.connector.util_text import is_valid_account_identifier, parse_account
78

89

@@ -17,17 +18,43 @@ def test_parse_account_basic():
1718

1819

1920
@pytest.mark.parametrize(
20-
"value,expected",
21+
"value",
2122
[
22-
("abc", True),
23-
("ABC", True),
24-
("a_b-c1", True),
25-
("a.b", False),
26-
("a/b", False),
27-
("a\\b", False),
28-
("", False),
29-
("snowflakecomputing.com", False),
23+
"abc",
24+
"aaa.bbb.ccc",
25+
"aaa.bbb.ccc.ddd" "ABC",
26+
"a_b-c1",
27+
"account1",
28+
"my_account",
29+
"my-account",
30+
"account_123",
31+
"ACCOUNT_NAME",
3032
],
3133
)
32-
def test_is_valid_account_identifier(value, expected):
33-
assert is_valid_account_identifier(value) is expected
34+
def test_is_valid_account_identifier(value):
35+
assert is_valid_account_identifier(value) is True
36+
37+
38+
@pytest.mark.parametrize(
39+
"value",
40+
[
41+
"a/b",
42+
"a\\b",
43+
"",
44+
"aa.bb.ccc/dddd",
45+
"account@domain",
46+
"account name",
47+
"account\ttab",
48+
"account\nnewline",
49+
"account:port",
50+
"account;semicolon",
51+
"account'quote",
52+
'account"doublequote',
53+
],
54+
)
55+
def test_is_invalid_account_identifier(value):
56+
assert is_valid_account_identifier(value) is False
57+
with pytest.raises(ValueError) as err:
58+
connect(account=value, user="jdoe", password="***")
59+
60+
assert "Invalid account identifier" in str(err)

0 commit comments

Comments
 (0)