Loading...

2023-11-28(火) 15:00

🗄️ SupabaseのVaultを使ってシークレットを保存、使用する

Supabase
SupabaseのVaultを使ってシークレット(APIキー、環境変数など)を保存し、Database Function内で使用する方法を解説します。

目次

前提と注意事項

  • Supabase アカウントを作成済みであること
  • Supabase のプロジェクトを作成済みであること
  • Supabase Vault は記事公開時点でまだベータ版です。

この記事では以下の公式ドキュメントを参考にします。

Vault

Managing secrets in Postgres.

supabase.com

この記事のゴール

Supabase の Vault にシークレットを保存し、Database Function 内で使用できるようになることをゴールとします。

Vault にシークレットを保存する

Supabase Vault のページは、以下のように Supabase の Web 管理画面のサイドメニューにある「Project Settings」(歯車アイコン)ページからアクセスできます。 Vault のページを開くと、以下のようにAdd new secretという緑色のボタンがあるので、これをクリックします。

Vaultにシークレットを新規保存する

Add new secretをクリックすると、以下のようなダイアログが開きます。
ここに保存したいシークレットの情報を入力します。

Vaultにシークレットを新規保存するダイアログ

入力項目は以下です。

  • Name: シークレットの名前(Databas Function などで利用する時にこの名前を使用します。)
  • Description: シークレットの説明
  • Secret value: シークレットの値
  • Select a key to encrypt your secret with: シークレットを暗号化するためのキーを選択する項目です。ここでは、新しくキーを作成するためにCreate a new Encryption Key のままにします。
  • Name of encryption key: 新しく作成するキーの名前です。ここではencryption-anon-keyという名前にします。

上記を入力したら、Add secretをクリックして保存します。 保存できると以下のように一覧に表示されます。

Supabase Vault一覧

以上で Vault へのシークレットの保存は完了です。次に Vault に保存したシークレットを実際に Database Function 内で使用する方法を解説します。

Database Function で Vault に保存したシークレットを使用する

ここでは、例えば Database Function の中からあるサービスに HTTP POST リクエストを送るときにそのサービスの API キーを使用する場合を想定し、以下のような Database Function を作成します。

Database Function内でVaultに保存したシークレットを使用する
create or replace function public.http_post_function()
 returns jsonb
 language plpgsql
 security definer
 set search_path to 'public', 'extensions', 'vault'
as $function$
declare
  vault_anon_key text;
  function_url text := 'https://xxxxxxxxxx/functions/v1/myfunction';
begin
  -- anon key をVaultから取得し、vault_anon_keyに格納する
  select decrypted_secret
  into vault_anon_key
  from vault.decrypted_secrets
  where name = 'anon_key';
 
  -- HTTP POSTリクエストのAuthorization Headerの中でvault_anon_keyを使用する
  select
      from net.http_post(
          url:= function_url,
          headers:=('{"Content-Type": "application/json", "Authorization": "Bearer ' || vault_anon_key || '"}')::jsonb,
          body:='{"record": {"username": "from database function", "email": "[email protected]"}}'::jsonb
      ) as request_id;
 
end;
$function$;
 

ハイライトした部分がポイントになります。上記のように、vault.decrypted_secretsからシークレットの名前(上記だとanon_key)を指定して取得しています。(11行目-15行目)。
あとは取得したシークレットを格納したvault_anon_keyを、必要なところで使用することができます。(21行目)

まとめ

Database Function の中で何かしらのサービスにアクセスするために使用したいシークレットがある場合などに Vault を活用できます。 Vault を使用することで、シークレットを Database Function のソースコードに直接書く必要がなくなりますし、不注意によってシークレットを公開してしまうリスクを減らすことができます。