Closed10

Firebase Functionsで Secret Manager を利用する

nbstshnbstsh

Secret を設定

以下コマンドを実行して、プロンプトに従い値を設定すればOK

$ firebase functions:secrets:set SECRET_NAME

実行するとこんな感じになる↓

$ firebase functions:secrets:set MY_SECRET       
? Enter a value for MY_SECRET [input is hidden] 
✔  Created a new secret version projects/${PROJECT_ID}/secrets/MY_SECRET/versions/1
nbstshnbstsh

Secret の値を確認

$ firebase functions:secrets:access SECRET_NAME

https://cloud.google.com/secret-manager/docs/access-control

その他アクション

https://firebase.google.com/docs/functions/config-env#managing_secrets

nbstshnbstsh

functions のコード更新

functions に runWith({ secrets: ['YOUR_SECRET']}) を追加

index.ts
export const mySecret = functions
  .region('asia-northeast1')
+  .runWith({
+    secrets: ['MY_SECRET'],
+  })
  .https.onRequest((request, res) => {
    res.send({ MY_SECRET: process.env.MY_SECRET });
  });

これでこの functions が実行される時のみ、環境変数に secret の値が読み込まれる。

nbstshnbstsh

Secret が埋め込まれた環境変数は、その functions が実行されている環境ではどこからでもアクセス可能。
("functions に受け渡す関数のスコープ内でしかアクセスできない" わけではない。)

index.ts
const secretVal = process.env.MY_SECRET;

export const secretFn = functions
  .region('asia-northeast1')
  .runWith({
    secrets: ['MY_SECRET'],
  })
  .https.onRequest((request, res) => {
    res.send({ MY_SECRET: secretVal });
  });

このように functions の onRequest に渡している関数の外側でも問題なく動作する。

もちろんこのような場合でも、runWith({ secrets: ['MY_SECRET'] }) を指定しない限り MY_SECRET は環境変数に埋め込まれない。

例えば、以下のsecretFn2 を deploy して実行した場合、 process.env.MY_SECRET に Secret の値は埋め込まれないため secretVal は undefined になる。

index.ts
const secretVal = process.env.MY_SECRET;

const secretFn = functions
  .region('asia-northeast1')
  .runWith({
    secrets: ['MY_SECRET'],
  })
  .https.onRequest((request, res) => {
    res.send({ MY_SECRET: secretVal });
  });

const secretFn2 = functions
  .region('asia-northeast1')
  .https.onRequest((request, res) => {
    res.send({ MY_SECRET: secretVal });
  });
nbstshnbstsh

deploy

.runWith() を追加した functions を deploy

$ firebase deploy --only functions
nbstshnbstsh

エラーでた

deploy しようとしたところ以下のようなエラー出た...

i  functions: ensurin ${PROJECT_ID}@appspot.gserviceaccount.com access to secret MY_SECRET.

Error: HTTP Error: 403, Permission 'secretmanager.secrets.setIamPolicy' denied for resource 'projects/${PROJECT_ID}/secrets/MY_SECRET' (or it may not exist).

secretmanager.secrets.setIamPolicy権限 がないっぽい

nbstshnbstsh

エラー解決

fiirebase tools を利用する際に認証している "プリンシパル" (個人の google account 等) に SecretManager 閲覧者 role を付与して解決。

原因

deploy する際に firebase tools でログインしているアカウントに secretmanager.secrets.setIamPolicy 権限 がない

対応

secretmanager.secrets.setIamPolicy 権限を含む role =>Secret Manager 管理者 role を付与してあげればOK。
(secretmanager.secrets.setIamPolicy 権限を含む role は Secret Manager 管理者 のみ)

参考

Secret Manager 関連の role 一覧

  • SecretManager 閲覧者
  • Secret Manager のシークレット バージョンの追加
  • Secret Manager のシークレット バージョンのマネージャー
  • Secret Manager のシークレット アクセサー
  • Secret Manager 管理者

https://cloud.google.com/secret-manager/docs/access-control

nbstshnbstsh

Secret の更新 (functions の re-deploy)

Secret を更新した場合、その Secret にアクセスする functions は再度 deploy する必要がある。

functions で利用中の Secret に対して、firebase functions:secrets:set SECRET_NAME を実行し Secret の値を更新すると、その Secret を利用している functions を再 deploy するかプロンプトで尋ねられる。

こんな感じ↓

$ firebase functions:secrets:set MY_SECRET       
? Enter a value for MY_SECRET [hidden]
✔  Created a new secret version projects/${PROJECT_ID}/secrets/MY_SECRET/versions/2
i  1 functions are using stale version of secret MY_SECRET:
        secretFn(asia-northeast1)
? Do you want to re-deploy the functions and destroy the stale version of
 secret MY_SECRET? (Y/n) 

プロンプトに従い deploy すればOK。

nbstshnbstsh

Emulator で Secret Manager の値を mock

Similar to Cloud Functions emulator support for environment variables, you can override secrets values by setting up a .secret.local file. This makes it easy for you to test your functions locally, especially if you don't have access to the secret value.

.secret.local file を作成して、そこに mock したい Secret の値を記せばOK。

.secret.local
MY_SECRET=mock_value

https://firebase.google.com/docs/functions/config-env#secrets_and_credentials_in_the_emulator

このスクラップは2022/06/16にクローズされました