Cloud Functionsで機密情報の管理にSecret Managerを利用する
最近GCPのCloud Functionsを利用するようになり、Cloud Functionsで利用するAPIキーなどの 機密情報を環境変数に入れようとしたのですが、公式のドキュメントに以下の記載がありました。
弊社ではCloud KMSも利用していますが統合がないという事なので、今年の3月にGAになったSecret Managerを利用してみたいと思います。
Secret Managerとは
シークレット管理Secret ManagerとはパスワードやAPIキーなどの機密情報を集中管理する為のサービスです。
登録した機密情報をアプリケーション側で取得する際には作成したシークレット名とバージョンを指定すると復号化された状態で返却されます。
暗号化/復号化はSecret Manager側が行ってくれるためにCloud KMSよりも手軽に利用できます。
IAMで作成したシークレット毎に権限を設定できるのできめ細かなアクセス制御が可能です。
サービスアカウントの作成
今回はシークレット単位で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に張り付けてください。
// 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
最新の情報をお届けします
- facebookでフォロー
- Twitterでフォロー
- Feedlyでフォロー