Skip to content

NO-SNOW: add Snowflake DSN connection-string parser to sf_core - #1336

Open
zeroshade wants to merge 2 commits into
snowflakedb:mainfrom
zeroshade:dsn-connection-string
Open

NO-SNOW: add Snowflake DSN connection-string parser to sf_core#1336
zeroshade wants to merge 2 commits into
snowflakedb:mainfrom
zeroshade:dsn-connection-string

Conversation

@zeroshade

Copy link
Copy Markdown
Contributor

This adds a Snowflake DSN connection-string parser to sf_core. A new config::dsn::parse_dsn decomposes user[:password]@account/db/schema-style connection strings — with an optional, case-insensitive snowflake:// prefix so the same string can be written as a full URL — into sf_core's canonical connection parameters, returning ParsedDsn { params, warnings }, and is re-exported from the config module. It supports the three documented DSN forms (.../db/schema, .../db, and host:port/db/schema?account=...). Only parameters sf_core actually recognizes are emitted; every other key (format-only options, region, OCSP toggles, unknown keys) is dropped and surfaced in warnings.

The motivation is to give the language wrappers (Go, ODBC, Python, JDBC) a single-string connect affordance without each reimplementing the DSN grammar. Centralizing the parse in the core keeps the connection-string vocabulary in one tested place and lets every wrapper share identical semantics.

The parser is a pure function that feeds the existing connection_set_options -> resolver::resolve pipeline, so alias resolution, host derivation, and validation are unchanged — it deliberately does not build hostnames or bypass the downstream is_allowed_account_char allow-list. It is hand-rolled with a single code path: the optional snowflake:// prefix is stripped rather than routed through url::Url, guaranteeing byte-for-byte identical results with or without the prefix. User, password, database, schema, and query values are URL-unescaped (%XX and +->space) while account and host are taken verbatim, matching the reference DSN behavior; host derivation from account remains the resolver's responsibility.

Risk is low: the change is an additive module with no edits to existing connection, auth, or validation logic. Because the input is an untrusted connection string, credential handling was given particular attention — error variants and warnings never echo a decoded value (only keys or static labels), the InvalidPort path is redacted so a mistyped user:secret cannot leak, ports are range-validated as u16, and an empty account= no longer satisfies the account requirement.

Testing: 25 unit tests cover the three forms, prefix parity and case-insensitivity, unescaping and +->space, every supported mapping (including the inverted CRL-cache booleans and certRevocationCheckMode), credential redaction, empty-account handling, and port validation; cargo test -p sf_core --lib config passes 380/380. The change was reviewed with roborev (security review passed; the default review's single finding — that requestTimeout should map to request_timeout — was verified against retry.rs as a name-based false positive, since query_timeout is sf_core's query-execution budget while request_timeout is the non-query HTTP retry budget that query execution deliberately ignores; documented and closed).

Not included here: an optional Connection::apply_dsn convenience / protobuf RPC for wrapper wiring, and defense-in-depth non-empty account validation in connection_config.

Add config::dsn::parse_dsn to decompose user[:password]@account/db/schema style connection strings (with an optional snowflake:// prefix) into canonical sf_core connection parameters. Only parameters sf_core recognizes are emitted; unsupported/unknown keys are collected as warnings. Re-exported from the config module.
The malformed-parameter warning previously echoed the raw query segment; a fat-fingered token/password passed as a segment without '=' could leak into warnings. Omit the segment content and only note that a malformed parameter was dropped. Updates the corresponding unit test.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant