グローバルナビゲーションへ

本文へ

フッターへ

お役立ち情報Blog



Cloud Functionsで機密情報の管理にSecret Managerを利用する

最近GCPのCloud Functionsを利用するようになり、Cloud Functionsで利用するAPIキーなどの 機密情報を環境変数に入れようとしたのですが、公式のドキュメントに以下の記載がありました。

シークレットの管理 環境変数は関数の構成に使用できますが、データベースの認証情報や API キーなどの機密情報の格納には適しません。 このような機密性の高い値は、ソースコードや外部の環境変数以外の場所に保存する必要があります。 一部の実行環境やフレームワークでは、環境変数の内容がログに送信されることがあります。 YAML ファイル、デプロイ スクリプト、ソース管理に重要な認証情報は保存しないでください。 シークレットを保存する場合は、シークレット管理のベスト プラクティスを確認することをおすすめします。 Cloud KMS と Cloud Functions の固有の統合はありません。

弊社ではCloud KMSも利用していますが統合がないという事なので、今年の3月にGAになったSecret Managerを利用してみたいと思います。

Secret Managerとは

シークレット管理

Secret ManagerとはパスワードやAPIキーなどの機密情報を集中管理する為のサービスです。
登録した機密情報をアプリケーション側で取得する際には作成したシークレット名とバージョンを指定すると復号化された状態で返却されます。
暗号化/復号化はSecret Manager側が行ってくれるためにCloud KMSよりも手軽に利用できます。
IAMで作成したシークレット毎に権限を設定できるのできめ細かなアクセス制御が可能です。

Secret Mangerの料金表はこちら

サービスアカウントの作成

今回はシークレット単位でIAMロールを設定する想定なので、まずはシークレットを利用できるサービスアカウントを作成します。
後で作るCloud Functionsでこのサービスアカウントを利用することになります。

まずGCPコンソールにアクセスし「IAMと管理」⇒「サービスアカウント」をひらき、 「サービスアカウントを作成」をクリックします。

ここでは以下の情報を入力しました。

サービスアカウント名 secret-manager-test
サービスアカウントID 自動入力
サービスアカウントの説明 SecretManagerのテスト用

この状態で「作成」をクリックします。


「このサービスアカウントにプロジェクトへのアクセスを許可する」ではロール選択で適当なロールを選択します。
今回はとりあえず「Cloud Functionsサービスエージェント」を選択しました。
※ここでロールを選択しないとIAMにメンバーが出来なくてCloud Functionsのデプロイで失敗します。

「続行」をクリックします。


「ユーザーにこのサービスアカウントへのアクセスを許可」では何も設定せずに 「完了」をクリックします。

これで「secret-manager-test」のサービスアカウントが作成されました。

Secret Managerでシークレットの作成

次にSecret Managerにシークレットを登録します。

GCPコンソールで「セキュリティ」⇒「シークレット マネージャー」をクリックします。
初回は以下の画面が出ますので「有効にする」をクリックします。


この画面に遷移するので「シークレットを作成」をクリックします。


今回はテストなので以下の値を入れて「シークレットの作成」をクリックします。

名前 secret-test
シークレットの値 abcdefghijklmnopqrstuvwxyz
手動でリージョンを選択する チェックをつける
リージョン asia-northeast1を選択

これでシークレットが登録されました。

このシークレットを利用するにはサービスアカウントにSecret ManagerのシークレットアクセサーというIAMロールが必要になるので以下の画面で設定します。

  • 今回作成した「secret-test」を選択
  • 右側に「メンバーを追加」ボタンが表示されるのでクリック
  • 「新しいメンバー」に先ほど作成したサービスアカウントのメールアドレスを入力
  • 「ロール」で「シークレットマネージャ」の「Secret Manager のシークレット アクセサー」を選択
  • 「保存」をクリック

次にCloud Functionsの関数で利用する今作ったシークレットのリソースIDを控えておきます。 シークレットマネージャのシークレット一覧の「操作」の列にある黒丸三つをクリックすると「リソースIDをコピー」があるのでクリックしてリソースIDを控えておきます。

これで準備が整いました。

Cloud Functionsでの利用

実際にCloud Functionsで関数を作成していきます。

まずGCPコンソールにアクセスし「Cloud Functions」をひらき、 「関数を作成」をクリックします。
以下の設定をいれていきます。

基本エリア

関数名:secret-manager-test
リージョン:asia-northeast1

トリガー

トリガーのタイプ:Cloud Pub/Sub Cloud Pub/Sub
トピックを選択してください:secret-manager-test
※これはトピックを作成するで新たに作成しました

この状態で「保存」をクリック

変数、ネットワーク、詳細設定

  • 詳細
    • 割り当てられるメモリ:128MiB
    • タイムアウト:60
    • サービスアカウント:secret-manager-test
  • 環境変数
    • そのまま
  • 接続
    • そのまま

この状態で「次へ」をクリックします。

コードの画面ではランタイムは「Go 1.13」を選択し
エントリポイントは「HelloPubSub」のままにし、 以下のコードをfunction.goに張り付けてください。

 name :=”*****” の箇所には先ほど保存したシークレットのリソースIDを設定してください。

// Package p contains a Pub/Sub Cloud Function.
package p

import (
	"context"
	"fmt"
	"log"

	secretmanager "cloud.google.com/go/secretmanager/apiv1"
	secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
)

// PubSubMessage is the payload of a Pub/Sub event. Please refer to the docs for
// additional information regarding Pub/Sub events.
type PubSubMessage struct {
	Data []byte `json:"data"`
}

// HelloPubSub consumes a Pub/Sub message.
func HelloPubSub(ctx context.Context, m PubSubMessage) error {
	log.Println(string(m.Data))

	name := "*********ここにリソースIDを設定する***************"

	client, err := secretmanager.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("failed to create secretmanager client: %v", err)
	}

	// Build the request.
	req := &secretmanagerpb.AccessSecretVersionRequest{
		Name: name,
	}

	// Call the API.
	result, err := client.AccessSecretVersion(ctx, req)
	if err != nil {
		return fmt.Errorf("failed to access secret version: %v", err)
	}

	log.Println(string(result.Payload.Data))

	return nil
}

「デプロイ」をクリックしてしばらく待ちます。

デプロイが完了したら関数名「secret-manager-test」をクリックします。

「テスト」を選択して「関数をテストする」をクリックして見ましょう。

ログにシークレットに登録した値が表示されていれば成功です。

※もちろん本番運用の時は機密情報をログに出力しないようにしましょう! ※今回はあくまでサンプルなので作成したシークレット、サービスアカウント、IAMメンバーは削除しておきましょう。

これでCloud Functions関数内で安全に機密情報を扱えるようになりました。

まとめ

いかがだったでしょうか?実際にはリソースIDなどをCloud Functionsの環境変数にいれるなどして使うことになると思います。
プログラムのなかでリソースIDを渡すと機密情報を返す関数などを用意すればかなり便利になるのではないでしょうか?

この記事を書いた人

アーティス
アーティス
創造性を最大限に発揮するとともに、インターネットに代表されるITを活用し、みんなの生活が便利で、豊かで、楽しいものになるようなサービスやコンテンツを考え、創り出し提供しています。
この記事のカテゴリ

FOLLOW US

最新の情報をお届けします