24
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

FirebaseAdvent Calendar 2020

Day 10

Cloud Functions for Firebase + Secret Manager でシークレット情報を扱う

Last updated at Posted at 2020-12-09

この記事は Firebase Advent Calendar 2020 10日目の記事です。

先日 Cloud Functions for Firebase + Cloud KMS でシークレット情報を扱う という記事を書きました。
今回は、今年 GA になった Secret Manager を使ってみたいと思います。

はじめに

サービスを開発し始めると、外部サービスのシークレットキーや認証用のID/PASSWORDなど、秘匿しなければいけない情報を扱いたいケースが多々あります。
これらの情報はソース管理するべきではない情報であるため、環境変数等を利用して対応するケースも多いかと思います。
Cloud Functions for Firebase にも 環境変数 はありますが、シークレット情報を直接扱うことには適していません。

また、先日記載した Cloud KMS を使う方法には、いくつか難点がありました。

  • Cloud KMS は鍵の管理のため、暗号化/復号化処理を自分で実装しないといけないこと。
  • 鍵のローテーションに応じて古いバージョンを廃止する場合、再度暗号化が必要なこと。

Secret Manager では、この辺を含めて自動でやってくれる範囲が広く、エンジニアからするとより楽にシークレット情報を取り扱うことができます。

この記事では、Secret Manger を使ってシークレット情報を Cloud Functions for Firebase から取り扱う方法を記載します。

Secret Manager について

Secret Manager とは、GCP で提供されているサービスの一つで、シークレット情報を管理するための安全で便利なストレージシステムです。
Cloud Functionsのドキュメント によると、シークレット情報の取り扱いのベストプラクティスとして Secret Manager が紹介されています。

対象読者

  • Cloud Functions for Firebase を利用したことがある方
  • GCP の扱いに少しでも慣れている方
    GCP コンソール の細かい操作方法は省略している箇所がありますので、GCPを触ったことない方は分かりにくいかもしれません。

Secret Manager の設定

お試しで実践される方は、新規GCPプロジェクトを作成して頂ければと思います。

APIの有効化

Secret Manager を使うためには、API を有効化する必要があります。
GCP コンソール → APIとサービス より、Secret Manager API を有効化します。

Secret Manager API の有効化

シークレットの作成

実際にシークレットを作成してみましょう。
GCP コンソール → セキュリティ → シークレットマネージャー よりシークレットを作成します。
シクレットの作成

以下を入力して、シークレットを作成 しましょう。

  • シークレットの名前
  • シークレットの値 (ファイルを直接インポートすることも可能です。)
  • リージョン (必要に応じてリージョンを設定してください。)

シークレットの作成

ステータスが 有効 になっていれば完了です。
シークレットのステータス

Cloud Functions for Firebase で復号化処理の作成

必要なモジュールのインストール

Functions 用の環境がない方は、firebase init 等で事前に環境を生成してください。
Secret Manager を扱うために必要なモジュールをインストールします。

npm i @google-cloud/secret-manager

Secret Manager の情報を環境変数に設定します。

// プロジェクトIDはシークレットを作成したGCPのプロジェクトIDを設定します。
$ firebase functions:config:set project.id="YOUR_PROJECT_ID"

// シークレットの作成の際に入力した名前を設定します。
$ firebase functions:config:set secret.name="secret-sample"

// 作成したシークレットのバージョンを設定します。
$ firebase functions:config:set secret.version="1"

設定した内容を確認します。

$ firebase functions:config:get
{
  "secret": {
    "name": "secret-sample",
    "version": "1"
  },
  "project": {
    "id": "YOUR_PROJECT_ID"
  }
}

実際の処理を書いていきましょう。
今回も HTTP トリガーとします。

Node.js
import * as functions from 'firebase-functions';
import { SecretManagerServiceClient } from '@google-cloud/secret-manager';

export const helloWorld = functions
    .region("asia-northeast1")
    .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
Error: could not handle the request

Functions のログをみてみると以下のようにエラーが出ているのが確認できます。
Cloud KMS の時と同様に、IAM で権限が必要なようです。

Error: 7 PERMISSION_DENIED: Permission 'secretmanager.versions.access' denied for resource 'projects/YOUR_PROJECT_ID/secrets/secret-sample/versions/1'

権限の確認と設定

Functions を実行しているサービスアカウントの確認

GCPコンソール → Cloud Functions → helloWorld → 詳細タブ を開きます。
サービスアカウントが記載されています。
YOUR_PROJECT_ID@appspot.gserviceaccount.com というサービスアカウントで実行されていることがわかります。

サービスアカウントの確認

権限の設定

上記で確認したサービスアカウントに、権限を設定します。
GCP コンソール → セキュリティ → シークレットマネージャー より、作成したシークレットにチェックを入れ、メンバーを追加します。
メンバーの追加

以下を設定し、保存します。

  • 新しいメンバーに Functions を実行しているサービスアカウント を入力する
  • ロールに Secret Manager のシークレットアクセサー を設定する

ロールの設定

シークレット情報へのアクセスの確認

権限設定ができたので、再度確認してみましょう。

// 動作確認
$ curl https://asia-northeast1-YOUR_PROJECT_ID.cloudfunctions.net/helloWorld
Hello World : some secret value

できました!

まとめ

Secret Manager を利用して、Cloud Functions for Firebase からシークレット情報にアクセスする一例を書きました。
実際に運用する際には、まだまだ留意する点があるとは思いますが、Cloud KMS よりも簡単に扱えるのが感じられるかと思います。

24
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?