Skip to content

Commit a8539cb

Browse files
committed
deployment dev changes
1 parent e6c443b commit a8539cb

File tree

4 files changed

+362
-62
lines changed

4 files changed

+362
-62
lines changed

.github/workflows/snowpark-ci-cd.yml

Lines changed: 37 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -154,36 +154,20 @@ jobs:
154154
# Debug the Snowflake account format
155155
echo "Using Snowflake account: ${SNOWFLAKE_ACCOUNT}"
156156
157-
# Store private key from GitHub secrets
157+
# Store private key correctly from GitHub secrets
158158
echo "${{ secrets.SNOWFLAKE_PRIVATE_KEY }}" > ~/.snowflake/keys/rsa_key.p8
159159
chmod 600 ~/.snowflake/keys/rsa_key.p8
160160
161-
# Install cryptography for key handling
161+
# Install required packages
162162
pip install cryptography snowflake-connector-python
163163
164-
# Validate the key format
165-
python -c "
166-
from cryptography.hazmat.backends import default_backend
167-
from cryptography.hazmat.primitives import serialization
168-
try:
169-
with open('~/.snowflake/keys/rsa_key.p8', 'rb') as f:
170-
private_key = serialization.load_pem_private_key(
171-
f.read(),
172-
password=None,
173-
backend=default_backend()
174-
)
175-
print('Private key format is valid')
176-
except Exception as e:
177-
print(f'Error with private key format: {e}')
178-
# Don't exit with error yet
179-
"
180-
181-
# Create connection profile for the environment with key authentication
164+
# Create connection profile for the environment with direct key authentication
182165
cat > ~/.snowflake/connections.toml << EOF
183166
[dev]
184167
account = "$SNOWFLAKE_ACCOUNT"
185168
user = "$SNOWFLAKE_USER"
186-
private_key_path = "~/.snowflake/keys/rsa_key.p8"
169+
# Using direct path, no expansion needed in GitHub Actions
170+
private_key_path = "/home/runner/.snowflake/keys/rsa_key.p8"
187171
warehouse = "CO2_WH_DEV"
188172
role = "CO2_ROLE_DEV"
189173
database = "CO2_DB_DEV"
@@ -192,7 +176,8 @@ jobs:
192176
[prod]
193177
account = "$SNOWFLAKE_ACCOUNT"
194178
user = "$SNOWFLAKE_USER"
195-
private_key_path = "~/.snowflake/keys/rsa_key.p8"
179+
# Using direct path, no expansion needed in GitHub Actions
180+
private_key_path = "/home/runner/.snowflake/keys/rsa_key.p8"
196181
warehouse = "CO2_WH_PROD"
197182
role = "CO2_ROLE_PROD"
198183
database = "CO2_DB_PROD"
@@ -201,33 +186,43 @@ jobs:
201186
202187
chmod 600 ~/.snowflake/connections.toml
203188
204-
# Verify the connection file was created properly (without showing keys)
189+
# Verify the connection file was created properly
205190
echo "Connection file created with profiles:"
206191
grep -v private_key ~/.snowflake/connections.toml
207192
208-
# Test Snowflake connection with key authentication
209-
pip install snowflake-connector-python cryptography
193+
# Test the key can be read properly (without connecting)
210194
python -c "
211-
import snowflake.connector
212-
import os
213195
from cryptography.hazmat.backends import default_backend
214-
from cryptography.hazmat.primitives.asymmetric import rsa
215-
from cryptography.hazmat.primitives.asymmetric import padding
196+
from cryptography.hazmat.primitives import serialization
197+
import os
198+
199+
key_path = '/home/runner/.snowflake/keys/rsa_key.p8'
200+
print(f'Checking key at: {key_path}')
201+
print(f'Key exists: {os.path.exists(key_path)}')
202+
216203
try:
217-
with open(os.path.expanduser('~/.snowflake/keys/rsa_key.p8'), 'rb') as key:
218-
p_key = key.read()
219-
220-
conn = snowflake.connector.connect(
221-
user='$SNOWFLAKE_USER',
222-
account='$SNOWFLAKE_ACCOUNT',
223-
private_key=p_key,
224-
warehouse='CO2_WH_DEV',
225-
database='CO2_DB_DEV'
226-
)
227-
print('Connection successful!')
228-
conn.close()
204+
with open(key_path, 'rb') as f:
205+
key_data = f.read()
206+
print(f'Key length: {len(key_data)} bytes')
207+
print(f'Key starts with: {key_data[:30]}')
208+
209+
# Try to load the key to validate format
210+
p_key = serialization.load_pem_private_key(
211+
key_data,
212+
password=None,
213+
backend=default_backend()
214+
)
215+
print('Key loaded successfully!')
216+
217+
# Convert to DER format as required by Snowflake
218+
pkb = p_key.private_bytes(
219+
encoding=serialization.Encoding.DER,
220+
format=serialization.PrivateFormat.PKCS8,
221+
encryption_algorithm=serialization.NoEncryption()
222+
)
223+
print('Key converted to DER format successfully!')
229224
except Exception as e:
230-
print(f'Connection test failed: {e}')
225+
print(f'Error processing key: {e}')
231226
"
232227
233228
- name: Generate configuration and SQL files

scripts/check_snowflake_key_auth.py

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import os
2+
import sys
3+
import argparse
4+
import base64
5+
from pathlib import Path
6+
from cryptography.hazmat.backends import default_backend
7+
from cryptography.hazmat.primitives import serialization
8+
9+
def check_key_auth(key_path):
10+
"""
11+
Check if a private key file is valid for Snowflake authentication.
12+
13+
Args:
14+
key_path: Path to the private key file
15+
"""
16+
# Expand the path
17+
key_path = os.path.expanduser(key_path)
18+
19+
print(f"Checking private key at: {key_path}")
20+
21+
if not os.path.exists(key_path):
22+
print(f"❌ ERROR: File does not exist: {key_path}")
23+
return False
24+
25+
print(f"✓ File exists ({os.path.getsize(key_path)} bytes)")
26+
27+
try:
28+
# Read the file
29+
with open(key_path, "rb") as key_file:
30+
key_data = key_file.read()
31+
32+
print(f"✓ File read successfully")
33+
34+
# First 30 chars for debugging
35+
print(f"Key starts with: {key_data[:30]}")
36+
37+
# Check if it looks like a PEM file
38+
if not key_data.startswith(b"-----BEGIN"):
39+
print("❌ ERROR: File doesn't appear to be in PEM format")
40+
return False
41+
42+
print(f"✓ File appears to be in PEM format")
43+
44+
# Try to load the private key
45+
private_key = serialization.load_pem_private_key(
46+
key_data,
47+
password=None,
48+
backend=default_backend()
49+
)
50+
51+
print(f"✓ Key loaded successfully!")
52+
53+
# Convert to DER format required by Snowflake
54+
pkb = private_key.private_bytes(
55+
encoding=serialization.Encoding.DER,
56+
format=serialization.PrivateFormat.PKCS8,
57+
encryption_algorithm=serialization.NoEncryption()
58+
)
59+
60+
print(f"✓ Key converted to DER format successfully!")
61+
62+
# Create a sample connection code
63+
print("\nSample connection code:")
64+
print("-----------------------")
65+
print("import snowflake.connector")
66+
print("from cryptography.hazmat.backends import default_backend")
67+
print("from cryptography.hazmat.primitives import serialization")
68+
print("")
69+
print(f"# Read private key from {key_path}")
70+
print("with open(key_path, 'rb') as key_file:")
71+
print(" p_key = serialization.load_pem_private_key(")
72+
print(" key_file.read(),")
73+
print(" password=None,")
74+
print(" backend=default_backend()")
75+
print(" )")
76+
print("")
77+
print("# Convert to DER format")
78+
print("pkb = p_key.private_bytes(")
79+
print(" encoding=serialization.Encoding.DER,")
80+
print(" format=serialization.PrivateFormat.PKCS8,")
81+
print(" encryption_algorithm=serialization.NoEncryption()")
82+
print(")")
83+
print("")
84+
print("# Connect to Snowflake")
85+
print("conn = snowflake.connector.connect(")
86+
print(" user='YOUR_USERNAME',")
87+
print(" account='YOUR_ACCOUNT',")
88+
print(" private_key=pkb")
89+
print(")")
90+
91+
print("\n✅ The key appears to be valid for Snowflake key-pair authentication!")
92+
print(" Add it to your GitHub secrets or use it locally.")
93+
94+
return True
95+
except Exception as e:
96+
print(f"❌ ERROR: {str(e)}")
97+
return False
98+
99+
def format_key_for_github(key_path):
100+
"""
101+
Format a private key for GitHub secrets.
102+
103+
Args:
104+
key_path: Path to the private key file
105+
"""
106+
# Expand the path
107+
key_path = os.path.expanduser(key_path)
108+
109+
if not os.path.exists(key_path):
110+
print(f"❌ ERROR: File does not exist: {key_path}")
111+
return
112+
113+
try:
114+
# Read the file
115+
with open(key_path, "rb") as key_file:
116+
key_data = key_file.read()
117+
118+
# Format for GitHub secrets (keep newlines)
119+
formatted = key_data.decode('utf-8')
120+
121+
print("\nFormatted key for GitHub secrets:")
122+
print("--------------------------------")
123+
print(formatted)
124+
print("--------------------------------")
125+
print("\nAdd this entire text including BEGIN/END lines and all newlines to your GitHub secret.")
126+
except Exception as e:
127+
print(f"❌ ERROR: {str(e)}")
128+
129+
if __name__ == "__main__":
130+
parser = argparse.ArgumentParser(description="Check if a private key is valid for Snowflake authentication")
131+
parser.add_argument("--key-path", default="~/.snowflake/keys/rsa_key.p8", help="Path to the private key file")
132+
parser.add_argument("--format-for-github", action="store_true", help="Format the key for GitHub secrets")
133+
134+
args = parser.parse_args()
135+
136+
if args.format_for_github:
137+
format_key_for_github(args.key_path)
138+
else:
139+
check_key_auth(args.key_path)

scripts/setup_keypair_auth.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import os
2+
import sys
3+
import argparse
4+
from pathlib import Path
5+
from cryptography.hazmat.backends import default_backend
6+
from cryptography.hazmat.primitives.asymmetric import rsa
7+
from cryptography.hazmat.primitives import serialization
8+
9+
def setup_keypair_auth(username, account_name, key_dir="~/.snowflake/keys", key_size=2048):
10+
"""
11+
Set up key pair authentication for Snowflake.
12+
13+
Args:
14+
username: Snowflake username
15+
account_name: Snowflake account name
16+
key_dir: Directory to store keys
17+
key_size: Size of the RSA key
18+
"""
19+
# Expand the path
20+
key_dir = os.path.expanduser(key_dir)
21+
22+
# Create directory if it doesn't exist
23+
os.makedirs(key_dir, exist_ok=True)
24+
25+
print(f"Generating {key_size}-bit RSA key pair for Snowflake authentication...")
26+
27+
# Generate private key
28+
private_key = rsa.generate_private_key(
29+
public_exponent=65537,
30+
key_size=key_size,
31+
backend=default_backend()
32+
)
33+
34+
# Get public key
35+
public_key = private_key.public_key()
36+
37+
# Save private key
38+
private_key_path = os.path.join(key_dir, "rsa_key.p8")
39+
with open(private_key_path, "wb") as f:
40+
f.write(
41+
private_key.private_bytes(
42+
encoding=serialization.Encoding.PEM,
43+
format=serialization.PrivateFormat.PKCS8,
44+
encryption_algorithm=serialization.NoEncryption()
45+
)
46+
)
47+
48+
# Save public key
49+
public_key_path = os.path.join(key_dir, "rsa_key.pub")
50+
with open(public_key_path, "wb") as f:
51+
f.write(
52+
public_key.public_bytes(
53+
encoding=serialization.Encoding.PEM,
54+
format=serialization.PublicFormat.SubjectPublicKeyInfo
55+
)
56+
)
57+
58+
# Format public key for Snowflake SQL
59+
public_key_text = public_key.public_bytes(
60+
encoding=serialization.Encoding.PEM,
61+
format=serialization.PublicFormat.SubjectPublicKeyInfo
62+
).decode("utf-8")
63+
64+
# Remove header and footer
65+
clean_public_key = "".join(public_key_text.strip().split("\n")[1:-1])
66+
67+
# Create SQL script
68+
sql_path = os.path.join(key_dir, "register_key.sql")
69+
with open(sql_path, "w") as f:
70+
f.write(f"""-- Execute this SQL in Snowflake to register your public key
71+
ALTER USER {username} SET RSA_PUBLIC_KEY='-----BEGIN PUBLIC KEY-----\\n{clean_public_key}\\n-----END PUBLIC KEY-----';
72+
73+
-- Verify key registration
74+
DESC USER {username};
75+
""")
76+
77+
# Create a test script
78+
test_script_path = os.path.join(key_dir, "test_connection.py")
79+
with open(test_script_path, "w") as f:
80+
f.write(f"""import snowflake.connector
81+
from cryptography.hazmat.backends import default_backend
82+
from cryptography.hazmat.primitives import serialization
83+
84+
# Read private key
85+
with open(r"{private_key_path}", "rb") as key:
86+
p_key = serialization.load_pem_private_key(
87+
key.read(),
88+
password=None,
89+
backend=default_backend()
90+
)
91+
92+
# Convert to bytes for Snowflake
93+
pkb = p_key.private_bytes(
94+
encoding=serialization.Encoding.DER,
95+
format=serialization.PrivateFormat.PKCS8,
96+
encryption_algorithm=serialization.NoEncryption()
97+
)
98+
99+
# Connect to Snowflake with key
100+
conn = snowflake.connector.connect(
101+
user="{username}",
102+
account="{account_name}",
103+
private_key=pkb
104+
)
105+
106+
# Test the connection
107+
cur = conn.cursor()
108+
cur.execute("SELECT current_user(), current_role(), current_version()")
109+
print(cur.fetchone())
110+
cur.close()
111+
conn.close()
112+
print("Connection successful!")
113+
""")
114+
115+
print(f"\nKey pair generated successfully!")
116+
print(f"Private key: {private_key_path}")
117+
print(f"Public key: {public_key_path}")
118+
print(f"SQL script: {sql_path}")
119+
print(f"Test script: {test_script_path}")
120+
print("\nNEXT STEPS:")
121+
print(f"1. Execute the SQL script in Snowflake to register your public key")
122+
print(f"2. Run the test script to verify the key authentication works")
123+
print(f"3. Update your connections.toml file to use key authentication")
124+
125+
if __name__ == "__main__":
126+
parser = argparse.ArgumentParser(description="Set up key pair authentication for Snowflake")
127+
parser.add_argument("--username", required=True, help="Snowflake username")
128+
parser.add_argument("--account", required=True, help="Snowflake account name")
129+
parser.add_argument("--key-dir", default="~/.snowflake/keys", help="Directory to store keys")
130+
parser.add_argument("--key-size", type=int, default=2048, help="RSA key size (bits)")
131+
132+
args = parser.parse_args()
133+
134+
setup_keypair_auth(args.username, args.account, args.key_dir, args.key_size)

0 commit comments

Comments
 (0)