Skip to content

feat: allow vault secret lookup by name in _id options#591

Merged
burmecia merged 2 commits intosupabase:mainfrom
wenerme:feat/vault-name-fallback
Mar 31, 2026
Merged

feat: allow vault secret lookup by name in _id options#591
burmecia merged 2 commits intosupabase:mainfrom
wenerme:feat/vault-name-fallback

Conversation

@wenerme
Copy link
Copy Markdown
Contributor

@wenerme wenerme commented Mar 26, 2026

Summary

  • Change get_vault_secret() to fall back to get_vault_secret_by_name() when the input is not a valid UUID
  • All FDW *_id options (conn_string_id, api_key_id, bearer_token_id, sa_key_id, etc.) now accept either a vault secret UUID or a human-readable name
  • Existing UUID-based usage is completely unaffected

Motivation

Currently, to reference a vault secret you must use the UUID returned by vault.create_secret():

CREATE SERVER mysql_server
  FOREIGN DATA WRAPPER mysql_wrapper
  OPTIONS (conn_string_id 'a1b2c3d4-e5f6-7890-abcd-ef1234567890');

UUIDs are hard to remember and make DDL less readable. With this change, you can use the human-readable name:

SELECT vault.create_secret('mysql://...', 'mysql_prod');

CREATE SERVER mysql_server
  FOREIGN DATA WRAPPER mysql_wrapper
  OPTIONS (conn_string_id 'mysql_prod');

How it works

get_vault_secret() tries Uuid::try_parse() first:

  • Valid UUID → lookup by id or key_id (existing behavior, unchanged)
  • Not a valid UUID → fall back to get_vault_secret_by_name() (lookup by name)

Since vault secret names are human-readable labels that cannot be valid UUID format, there is no ambiguity.

Scope

Only one file changed: supabase-wrappers/src/utils.rs (1 function, ~10 lines changed). All native and Wasm FDWs that call get_vault_secret() automatically benefit without any code changes.

Test plan

Existing UUID-based vault lookups are already covered by FDW integration tests. The name fallback uses the existing get_vault_secret_by_name() function which is already tested through Stripe FDW's api_key_name option. No new test infrastructure is needed since this is a simple routing change based on Uuid::try_parse().

Change `get_vault_secret()` to fall back to name-based lookup when
the input is not a valid UUID.

This allows all FDW `*_id` options (e.g. `conn_string_id`,
`api_key_id`, `bearer_token_id`) to accept either a vault secret
UUID or a human-readable name, making configuration easier:

```sql
-- Before: only UUID worked
OPTIONS (conn_string_id 'a1b2c3d4-e5f6-...')

-- Now: name also works
OPTIONS (conn_string_id 'my_mysql_prod')
```

Since vault secret names are human-readable labels that cannot be
valid UUIDs, there is no ambiguity. Existing UUID-based usage is
completely unaffected.
@wenerme
Copy link
Copy Markdown
Contributor Author

wenerme commented Mar 29, 2026

@coderabbitai review

@burmecia burmecia added the core label Mar 30, 2026
@burmecia
Copy link
Copy Markdown
Member

There is already a get_vault_secret_by_name() function, should we use that instead?

@wenerme
Copy link
Copy Markdown
Contributor Author

wenerme commented Mar 30, 2026

Good point! Yes, get_vault_secret_by_name() already exists and works well — this PR actually calls it as the fallback:

Err(_) => get_vault_secret_by_name(secret_id),

The motivation for putting the auto-detection in get_vault_secret() rather than adding explicit _name options to each FDW:

  1. Zero per-FDW changes: All 15+ FDWs (native + Wasm) that already call get_vault_secret() automatically support name-based lookup without any code changes
  2. No new options: Users don't need to learn conn_string_name, api_key_name, sa_key_name, etc. — the existing _id options just work with both UUID and name
  3. No ambiguity: Vault secret names are human-readable labels (e.g. "my_mysql_prod") that can never pass Uuid::try_parse(), so UUID lookups are unaffected

The alternative would be adding a _name option to each FDW individually (like Stripe's api_key_name), but that requires touching every FDW and doubling the number of vault-related options.

Happy to take a different approach if you prefer keeping get_vault_secret() strictly UUID-only though — for example, we could add a new helper like get_vault_secret_by_id_or_name() to keep the original function unchanged.

Copy link
Copy Markdown
Member

@burmecia burmecia left a comment

Choose a reason for hiding this comment

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

Thanks for the PR!

@burmecia burmecia merged commit 90184a4 into supabase:main Mar 31, 2026
7 checks passed
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.

2 participants