Skip to content

Commit 87a7c23

Browse files
authored
fix: Allow unencrypted Snowflake key (#5097)
Signed-off-by: Nick Venenga <nick@venenga.com>
1 parent 244da16 commit 87a7c23

File tree

2 files changed

+78
-3
lines changed

2 files changed

+78
-3
lines changed

sdk/python/feast/infra/utils/snowflake/snowflake_utils.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -513,22 +513,26 @@ def chunk_helper(lst: pd.DataFrame, n: int) -> Iterator[Tuple[int, pd.DataFrame]
513513

514514

515515
def parse_private_key_path(
516-
private_key_passphrase: str,
516+
private_key_passphrase: Optional[str] = None,
517517
key_path: Optional[str] = None,
518518
private_key_content: Optional[bytes] = None,
519519
) -> bytes:
520520
"""Returns snowflake pkb by parsing and reading either from key path or private_key_content as byte string."""
521521
if private_key_content:
522522
p_key = serialization.load_pem_private_key(
523523
private_key_content,
524-
password=private_key_passphrase.encode(),
524+
password=private_key_passphrase.encode()
525+
if private_key_passphrase is not None
526+
else None,
525527
backend=default_backend(),
526528
)
527529
elif key_path:
528530
with open(key_path, "rb") as key:
529531
p_key = serialization.load_pem_private_key(
530532
key.read(),
531-
password=private_key_passphrase.encode(),
533+
password=private_key_passphrase.encode()
534+
if private_key_passphrase is not None
535+
else None,
532536
backend=default_backend(),
533537
)
534538
else:
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import tempfile
2+
from typing import Optional
3+
4+
import pytest
5+
from cryptography.hazmat.primitives import serialization
6+
from cryptography.hazmat.primitives.asymmetric import rsa
7+
8+
from feast.infra.utils.snowflake.snowflake_utils import parse_private_key_path
9+
10+
PRIVATE_KEY_PASSPHRASE = "test"
11+
12+
13+
def _pem_private_key(passphrase: Optional[str]):
14+
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
15+
return private_key.private_bytes(
16+
encoding=serialization.Encoding.PEM,
17+
format=serialization.PrivateFormat.TraditionalOpenSSL,
18+
encryption_algorithm=(
19+
serialization.BestAvailableEncryption(passphrase.encode())
20+
if passphrase
21+
else serialization.NoEncryption()
22+
),
23+
)
24+
25+
26+
@pytest.fixture
27+
def unencrypted_private_key():
28+
return _pem_private_key(None)
29+
30+
31+
@pytest.fixture
32+
def encrypted_private_key():
33+
return _pem_private_key(PRIVATE_KEY_PASSPHRASE)
34+
35+
36+
def test_parse_private_key_path_key_content_unencrypted(unencrypted_private_key):
37+
parse_private_key_path(
38+
None,
39+
None,
40+
unencrypted_private_key,
41+
)
42+
43+
44+
def test_parse_private_key_path_key_content_encrypted(encrypted_private_key):
45+
parse_private_key_path(
46+
PRIVATE_KEY_PASSPHRASE,
47+
None,
48+
encrypted_private_key,
49+
)
50+
51+
52+
def test_parse_private_key_path_key_path_unencrypted(unencrypted_private_key):
53+
with tempfile.NamedTemporaryFile(mode="wb") as f:
54+
f.write(unencrypted_private_key)
55+
f.flush()
56+
parse_private_key_path(
57+
None,
58+
f.name,
59+
None,
60+
)
61+
62+
63+
def test_parse_private_key_path_key_path_encrypted(encrypted_private_key):
64+
with tempfile.NamedTemporaryFile(mode="wb") as f:
65+
f.write(encrypted_private_key)
66+
f.flush()
67+
parse_private_key_path(
68+
PRIVATE_KEY_PASSPHRASE,
69+
f.name,
70+
None,
71+
)

0 commit comments

Comments
 (0)