CORE-742: switch Snowflake CI auth from password to private key#2224
CORE-742: switch Snowflake CI auth from password to private key#2224
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:
|
|
Warning Rate limit exceeded
To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe PR changes YAML inline serialization to explicitly serialize Python ChangesYAML Serialization and Snowflake Profile
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 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 unit tests (beta)
Comment |
|
👋 @devin-ai-integration[bot] |
…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
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.<<: *snowflakeanchor used by the innerelementaryprofile inherits the newprivate_keyfield automatically.Companion PR (must merge together):
elementary-data/dbt-data-reliability— 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/dbt-data-reliabilityPR 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. Both the outerelementary_testsprofile and the innerelementaryprofile (which inherits via<<: *snowflake) are correctly updated.Link to Devin session: https://app.devin.ai/sessions/c6321f52b3274f499dd305e96c8ed73b
Requested by: @haritamar
Summary by CodeRabbit
New Features
Bug Fixes