CORE-742: switch Snowflake CI auth from password to private key#1001
CORE-742: switch Snowflake CI auth from password to private key#1001
Conversation
The 'snowflake' target in profiles.yml.j2 now uses key-pair authentication (private_key, with optional private_key_passphrase) instead of password. generate_profiles.py's _yaml_inline filter is updated to safely render multi-line strings (e.g. PEM private keys) as a double-quoted YAML scalar with escaped newlines, so the rendered profiles.yml stays parseable inline. The CI_WAREHOUSE_SECRETS GitHub Actions secret needs a coordinated update: - remove key 'snowflake_password' - add key 'snowflake_private_key' (PEM or base64-encoded DER) - optional 'snowflake_private_key_passphrase' for encrypted keys The CI service user's RSA_PUBLIC_KEY must also be configured in Snowflake. Co-Authored-By: Itamar Hartstein <haritamar@gmail.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe PR updates test profile generation: inline YAML rendering now emits double-quoted inline scalars for multi-line strings (escaping newlines); the Snowflake test profile template switches from password to private-key authentication (optionally including a passphrase). A README spacing tweak was also applied. ChangesTest profile generation and Snowflake auth
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
👋 @devin-ai-integration[bot] |
The prettier hook on master flags a missing blank line after the 'Elementary Tables' heading (pre-existing). Apply the auto-fix so that this PR's CI can pass. Co-Authored-By: Itamar Hartstein <haritamar@gmail.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@integration_tests/profiles/generate_profiles.py`:
- Around line 44-46: The helper _yaml_inline currently only applies
default_style='"' for multiline strings, causing single-line string secrets like
"true", "null", or "123" to be emitted unquoted and mis-parsed; change the
condition in _yaml_inline to treat any instance of str the same way (i.e., if
isinstance(value, str): use yaml.dump with default_flow_style=True and
default_style='"' and .strip()) so all string values are always quoted (keep
non-string return behavior unchanged).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: fc10e26b-037d-4021-8708-ef53de51e949
📒 Files selected for processing (2)
integration_tests/profiles/generate_profiles.pyintegration_tests/profiles/profiles.yml.j2
…back) Quoting only multi-line strings still allowed single-line string secrets like 'true', 'null', or '123' to be emitted unquoted and mis-parsed as booleans/None/integers when the rendered profiles.yml is loaded by dbt. Always quote string values for safety; non-string values (Undefined, dict, etc.) keep their previous behavior. Co-Authored-By: Itamar Hartstein <haritamar@gmail.com>
The previous change to always quote string values broke YAML type coercion for fields like redshift_port that come in as JSON strings but need to be rendered as bare YAML scalars so the dbt adapter parses them as integers. Revert to the original behavior: only multi-line strings (e.g. PEM private keys) are double-quoted with escaped newlines; single-line strings pass through unchanged so port/host/etc. continue to type-coerce correctly. Co-Authored-By: Itamar Hartstein <haritamar@gmail.com>
Summary
Migrates the Snowflake CI target in
integration_tests/profiles/profiles.yml.j2from password-based auth to key-pair authentication.password: …→private_key: …(with optionalprivate_key_passphrase)_yaml_inlineingenerate_profiles.pynow safely renders multi-line strings (e.g. PEM private keys) as a double-quoted YAML scalar with escaped newlines, so the renderedprofiles.ymlstays parseable when the secret is provided as a PEM string.Companion PR (must merge together):
elementary-data/elementary— see Linear ticket CORE-742.Required coordinated changes (outside this PR)
The
CI_WAREHOUSE_SECRETSGitHub Actions secret (a base64-encoded JSON blob, seegenerate_profiles.py) needs:snowflake_passwordsnowflake_private_key— Snowflake user's private key (PEM or base64-encoded DER). Multi-line PEM is supported.snowflake_private_key_passphrase— only if the key is encrypted.On Snowflake side:
ALTER USER <ci_user> SET RSA_PUBLIC_KEY = '<public_key_pem_without_headers>';generate_profiles.pyusesStrictUndefinedwhen secrets are loaded — so ifsnowflake_private_keyis missing from the secret blob, the Snowflake CI job will fail fast with a clear error rather than producing an unauthenticated profile.Review & Testing Checklist for Human
CI_WAREHOUSE_SECRETSin this repo's GitHub Actions secrets (addsnowflake_private_key, removesnowflake_password) before merging — otherwise the next Snowflake CI run will fail.RSA_PUBLIC_KEYon the Snowflake CI user.Test warehouse platformworkflow forwarehouse-type: snowflakefrom this branch and verifydbt debug -t snowflakeand the integration tests pass.elementary-data/elementaryPR is merged in lockstep so both repos' Snowflake CI stays green.Notes
Locally rendered the template with both PEM (multi-line) and base64 (single-line) inputs and confirmed the resulting YAML is parseable by
yaml.safe_load_alland containsprivate_key(and optionallyprivate_key_passphrase) on thesnowflaketarget with no leftoverpasswordfield.Link to Devin session: https://app.devin.ai/sessions/c6321f52b3274f499dd305e96c8ed73b
Requested by: @haritamar
Summary by CodeRabbit
New Features
Improvements
Documentation