Skip to content

CORE-742: switch Snowflake CI auth from password to private key#1001

Merged
haritamar merged 4 commits intomasterfrom
core-742-snowflake-private-key-auth
May 5, 2026
Merged

CORE-742: switch Snowflake CI auth from password to private key#1001
haritamar merged 4 commits intomasterfrom
core-742-snowflake-private-key-auth

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot commented May 5, 2026

Summary

Migrates the Snowflake CI target in integration_tests/profiles/profiles.yml.j2 from password-based auth to key-pair authentication.

  • password: …private_key: … (with optional private_key_passphrase)
  • _yaml_inline in generate_profiles.py now safely renders multi-line strings (e.g. PEM private keys) as a double-quoted YAML scalar with escaped newlines, so the rendered profiles.yml stays parseable when the secret is provided as a PEM string.
  • Single-line base64-encoded DER keys also continue to render correctly as plain scalars.

Companion PR (must merge together): elementary-data/elementary — see Linear ticket CORE-742.

Required coordinated changes (outside this PR)

The CI_WAREHOUSE_SECRETS GitHub Actions secret (a base64-encoded JSON blob, see generate_profiles.py) needs:

  • Remove key: snowflake_password
  • Add key: snowflake_private_key — Snowflake user's private key (PEM or base64-encoded DER). Multi-line PEM is supported.
  • Optional: snowflake_private_key_passphrase — only if the key is encrypted.

On Snowflake side:

  • Generate an RSA key pair for the CI service user.
  • ALTER USER <ci_user> SET RSA_PUBLIC_KEY = '<public_key_pem_without_headers>';
  • (Optional) you can keep the password set during transition and only remove it after this PR merges, so existing runs aren't broken.

generate_profiles.py uses StrictUndefined when secrets are loaded — so if snowflake_private_key is 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

  • Update CI_WAREHOUSE_SECRETS in this repo's GitHub Actions secrets (add snowflake_private_key, remove snowflake_password) before merging — otherwise the next Snowflake CI run will fail.
  • Configure the matching RSA_PUBLIC_KEY on the Snowflake CI user.
  • Trigger Test warehouse platform workflow for warehouse-type: snowflake from this branch and verify dbt debug -t snowflake and the integration tests pass.
  • Verify the companion elementary-data/elementary PR 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_all and contains private_key (and optionally private_key_passphrase) on the snowflake target with no leftover password field.

Link to Devin session: https://app.devin.ai/sessions/c6321f52b3274f499dd305e96c8ed73b
Requested by: @haritamar

Summary by CodeRabbit

  • New Features

    • Snowflake profiles now support private-key authentication with an optional passphrase
  • Improvements

    • Inline profile YAML now preserves multi-line strings by quoting and escaping newlines to keep profiles parseable
  • Documentation

    • Minor README spacing adjustment under "Elementary Tables"

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-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@linear
Copy link
Copy Markdown

linear Bot commented May 5, 2026

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5c12be45-bf8c-4464-9436-325f25cddd80

📥 Commits

Reviewing files that changed from the base of the PR and between f9fabdc and f6c5bd6.

📒 Files selected for processing (1)
  • integration_tests/profiles/generate_profiles.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • integration_tests/profiles/generate_profiles.py

📝 Walkthrough

Walkthrough

The 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.

Changes

Test profile generation and Snowflake auth

Layer / File(s) Summary
Data Shape / Doc
integration_tests/profiles/generate_profiles.py
_yaml_inline docstring updated to describe new multi-line string handling; Undefined still maps to ''.
Core Rendering
integration_tests/profiles/generate_profiles.py
_yaml_inline adds a str branch: multi-line strings (contain \n) are emitted via yaml.dump(..., default_flow_style=True, default_style='"'), producing double-quoted inline scalars with escaped newlines; other types unchanged.
Template Wiring
integration_tests/profiles/profiles.yml.j2
In snowflake_target(schema) macro, password was replaced with `private_key: {{ snowflake_private_key
Documentation / Cosmetic
README.md
Whitespace/spacing adjusted in the "Elementary Tables" section (blank line after "This includes:").

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 I nibble code by lantern light,
I curl newlines into quoted sight,
Snowflake keys tucked safe and neat,
Profiles hum and tests repeat,
A tiny hop — the build feels right.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the primary change: migrating Snowflake CI authentication from password to private key authentication, which is the main focus across updated configuration and utility files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch core-742-snowflake-private-key-auth

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

👋 @devin-ai-integration[bot]
Thank you for raising your pull request.
Please make sure to add tests and document all user-facing changes.
You can do this by editing the docs files in the elementary repository.

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>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 71fb19a and b694a92.

📒 Files selected for processing (2)
  • integration_tests/profiles/generate_profiles.py
  • integration_tests/profiles/profiles.yml.j2

Comment thread integration_tests/profiles/generate_profiles.py
devin-ai-integration Bot and others added 2 commits May 5, 2026 13:46
…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>
@haritamar haritamar merged commit 907e181 into master May 5, 2026
27 of 30 checks passed
@haritamar haritamar deleted the core-742-snowflake-private-key-auth branch May 5, 2026 15:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant