はじめに
App Store Connect API からiOSのダウンロード数を取得する実装で証明書を使用することになり、
functionsからApp Store Connectのprivate Keyをクラウド上の読み取れる場所に置く必要がありました。
そこで、GCPのSecret Managerを活用することになったため、Secret Managerとは何か、どんなメリットがあるのかなどをアウトプットします。
Secret Managerとは
- Secret ManagerはAPIキーやパスワードなどの機密データを集中管理するためのサービス。
- このサービスにパスワードなどの情報をバージョン付シークレットとして登録しておき、他のシステムから「シークレット名、バージョン」を指定して呼び出すことで利用します。
- また、IAMで作成したシークレット毎に権限を設定できるので、細かなアクセス制御が可能。
- Cloud Functionsのドキュメント によると、シークレット情報の取り扱いのベストプラクティスとして Secret Manager が紹介されています。
- AWSでいう「AWS Secrets Manager」と同機能
Cloud KMSとの比較
- これまでだとCloud KMS(Key Manegement System)で作成した鍵などを使用し、個別に認証情報を暗号化/復号化する方法が一般的だった。
- ただ、以下の点でCloud KMSは面倒でした。
・Cloud KMSの鍵で暗号化/復号化する仕組みは 「自分で」 作らないといけない
・認証情報をローテーションする度に暗号化をしないといけない
→ メンテナンスが面倒。システムが増えると・・・
・暗号化した認証情報を 「個別」 管理が必要
→ 使われているのかどうかわからない認証情報が溜まるが、どこかで使われているかもしれないから消せない。
一方、Secret Managerには下記機能があり、上記を解決できそうでした。
・シークレット(認証情報)の集中管理ができる
・暗号化/復号化はSecret Manager側でやってくれる
・GCPのサービスなのでIAMでシークレット毎に利用権限(ロール)の設定が可能
ex/ 「アカウントAにはシークレットα の使用を許可するがアカウントBには許可しない」など
・Audit Logでシークレットの利用履歴を確認できる
・シークレットのバージョン管理が可能
特に、暗号化/復号化はSecret Manager側が行ってくれる部分が、Cloud KMSよりも手軽に利用できそうでした!
料金
- Secret Managerは無料のサービスではなかった・・・
- 利用した量に応じて課金が発生します。具体的には
・シークレットの個数(バージョン)
・シークレットを呼び出した回数
に比例し、月額料金が決まります。
僕の場合、とりあえず
・1バージョン
・単一ロケーション
・1日1回のアクセス(呼び出し)
また、ローテーションは考えてないので、$0.06+$0.03/月なので、月10円ぐらいでした。
安い!
シークレットの作成手順
以下Secret Managerにシークレットを作成する手順。大きく3STEPになります。
- シークレットを利用できるサービスアカウントを作成
- シークレットを作成
- サービスアカウントにシークレットを利用できる権限ロールを設定
1/ シークレットを利用できるサービスアカウントを作成
下記スクショのように進めると、サービスアカウントを作成できる
ロールは不要
2/ シークレットを作成
Secret Managerにシークレットを登録します。
コンソールの「セキュリティ」→「Secret Manager」を開きます。
プロジェクトでSecret Manager APIが有効になっていない場合は、APIを有効にします。
「シークレットを作成」をクリック。
テスト用のシークレットを作成します。
-
名前
:sample -
シークレットの値
:auth-keyが入ったファイルをアップロード。すると、自動でシークレットの値が入ります。 -
レプリケーションポリシー
:このシークレットのロケーションを手動で管理する
をクリック- ロケーションが出てくるので、
asia-northeast1
を選択
- ロケーションが出てくるので、
-
暗号化
、有効期限
、通知
、ラベル
は、設定しない(何もしない)
3/ サービスアカウントにシークレットを利用できる権限ロールを設定
- シークレットを作成後、Secret Managerに登録したシークレットを利用するには、サービスアカウントに
Secret Manager のシークレットアクセサー
のIAMロールが必要になるので、ロールを追加します
Cloud Functionsからシークレットを使ってみる
まず、Secret Manager を扱うために必要なモジュールをインストールします。
- Functions 用の環境がない場合、上記の前に
firebase init
等で事前に環境を生成する。
$yarn add @google-cloud/secret-manager
or
$npm i @google-cloud/secret-manager
// index.js
import * as functions from 'firebase-functions';
import { SecretManagerServiceClient } from '@google-cloud/secret-manager';
const f = functions.region('asia-northeast1');
export const helloWorld = f.https.onRequest(async (request, response) => {
// 環境変数から設定した情報を取得
const projectId = functions.config().project.id;
const secretName = functions.config().secret.name;
const secretVersion = functions.config().secret.version;
const client = new SecretManagerServiceClient();
const name = client.secretVersionPath(projectId, secretName, secretVersion);
const [version] = await client.accessSecretVersion({
name: name,
});
const secretValue = version.payload?.data?.toString();
response.send(`Hello World` : ${secretValue}`);
});
動作確認
$ firebase deploy --only functions
$ curl https://asia-northeast1-YOUR_PROJECT_ID.cloudfunctions.net/helloWorld
> Hello World : some secret value
これで取得完了!