Firebase Functionsで Secret Manager を利用する
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
Secret の値を確認
$ firebase functions:secrets:access SECRET_NAME
その他アクション
functions のコード更新
functions に runWith({ secrets: ['YOUR_SECRET']})
を追加
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 の値が読み込まれる。
Secret が埋め込まれた環境変数は、その functions が実行されている環境ではどこからでもアクセス可能。
("functions に受け渡す関数のスコープ内でしかアクセスできない" わけではない。)
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 になる。
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 });
});
deploy
.runWith()
を追加した functions を deploy
$ firebase deploy --only functions
エラーでた
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
権限 がないっぽい
エラー解決
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 管理者
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。
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。
MY_SECRET=mock_value