クラウド同上

Secret Managerを使ってみる@Cloud Functions編

Author
furuya3
Lv:9 Exp:7165

2018年11月入社 システム開発本部所属です。

2020年3月にGoogle CloudでSecret ManagerがGAになりました。AWSでは「AWS Secrets Manager」として既におなじみの機能ですが、これをうまく利用するとパスワードや秘密鍵などの機密情報を扱うのがとても楽になります。

この記事ではSecret Managerを使うメリットと、Cloud FunctionsからSecret Managerに登録したシークレットを利用する方法の例を紹介します。以前にCloud KMSの鍵で暗号化した情報をCloud Functionsで利用する方法を紹介しましたが、それと比べてどのくらい楽になるのかを見ていただければと思います。

Cloud KMSで暗号化された情報を使ってみる@Cloud Functions編

速攻理解!Secret Managerで機密データ管理

Secret ManagerはAPIキーやパスワードなどの機密データを集中管理するためのサービスです。このサービスにパスワードなどの情報をバージョン付シークレットとして登録しておき、他のシステムから「シークレット名、バージョン」を指定して呼び出すことで利用します。

■ Secret Manager

Mailgunなど、Google Cloud外のサービスを利用する際にはID/passwordなどの認証情報を使わざるを得ない状況が発生します。これまでだと、Cloud KMSで作成した鍵などを使用して、個別に認証情報を暗号化/復号化する方法が一般的でした。

これの何が面倒かというと、実際にやられたことがある方にはわかっていただけると思うのですが・・・

・Cloud KMSの鍵で暗号化/復号化する仕組みは自分で作らないといけない
・認証情報をローテーションする度に暗号化をしないといけない
 → メンテナンスが面倒。システムが増えると・・・

・暗号化した認証情報を個別に管理しないといけない
 → 使われているのかどうかわからない認証情報が溜まっていく。
   けど、どこかで使われているかもしれないから消せない。
   認証情報をローテーションしたいけど、どこで使われているかわからない。

みたいな面倒事が発生します。
Secret Manager には下記機能があるので、これらの大部分を解決してくれます。

・シークレット(認証情報)の集中管理ができる
・暗号化/復号化はSecret Manager側でやってくれる
・IAMでシークレット毎に利用権限の設定が可能
・Audit Logでシークレットの利用履歴を確認できる
・シークレットのバージョン管理が可能

もう一つ便利なところとして、Secret ManagerはGoogle CloudのサービスですのでCloud IAMで利用権限を設定することができます。具体的にはプロジェクトレベルもしくはシークレットのレベルでIAMロールを設定することが可能です。
シークレットレベルでIAMロールを設定すると、「アカウントAにはシークレットα の使用を許可するがアカウントBには許可しない」など細かく指定することができます。

ただ、Secret Managerには残念なところもあり、GAにはなりましたが2020年4月現在で東京リージョン(asia-northeast1)と大阪リージョン(asia-northeast2)ではまだ使うことができません。対応が待たれるところです。
※東京リージョンと大阪リージョンでも使えるようになりました!

また、IAM Conditions にも未対応です。こちらも対応すれば、特定の曜日時刻でのみシークレットを使えたり、特定のIPアドレスからのみシークレットの利用を許可する事ができたりしそうなので、対応さえしてくれればもっと利用の幅が広がりそうです。

■ Cloud IAM Conditions の概要

でもお高いんでしょ?

Secret Managerは無料のサービスではないので、利用した量に応じて課金が発生します。具体的には

  ・シークレットの個数(バージョン)
  ・シークレットを呼び出した回数

に比例して月額料金が決まります。

■ Secret Managerの料金

2020年4月現在の料金は下記のようになっています。

ざっくりですが、下記条件で2つのバージョンを持つシークレットを1ヶ月利用した場合の料金を算出すると$0.15になります。シークレットを個別管理する手間を考えると、十分利用の検討に値するのではないでしょうか。

 ・Secret Managerは単一リージョンで利用する
 ・有効なシークレットはバージョン1と2の2つ ・・・ $0.06 × 2
 ・呼び出し回数は 100回/day ≒ 月間3000回 ・・・ $0.03

シークレットを作成してみる

では実際にSecret Managerにシークレットを登録してみましょう。
下記ステップで作業を行います。今回はシークレット単位でIAMロールを設定し、次項でCloud Functionsからこのシークレットを取得してみます。

1.シークレットを利用できるサービスアカウントを作成する
2.シークレットを作成する
3.サービスアカウントにシークレットを利用できるロールを設定する

シークレットを利用できるサービスアカウントを作成する

Cloud Functionsにセットするサービスアカウントを作成します。

サービスアカウントの権限は何も設定せず、続行してください。

完了でサービスアカウントの作成を終了します。

シークレットを作成する

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

WEBコンソールの「セキュリティ」→「シークレットマネージャー」を開きます。

プロジェクトでSecret Manager APIが有効になっていない場合はこの画面に遷移します。APIを有効にしてください。

「シークレットを作成」を開きます。

テスト用のシークレットを作成します。
・名前 : sample
・シークレットの値 : hogehoge
・リージョン : asia-east1

サービスアカウントにシークレットを利用できるロールを設定する

Secret Managerに登録したシークレットを利用するには、サービスアカウントに
「roles/secretmanager.secretAccessor」(Secret Manager のシークレット アクセサー)
のIAMロールが必要になります。

■ Access control

作成したシークレットの情報パネルを開きます。

「メンバーを追加」から作成したサービスアカウントを追加し、「Secret Manager のシークレット アクセサー」のIAMロールを設定します。

Cloud Functionsからシークレットを使ってみる

ではCloud Functionsからシークレットを取得してみましょう。以下、Pythonとクライアントライブラリを使って取得する例になります。関数はSecret Managerからシークレットを取得できたら内容をログに出力して終了します。

概要

構成
サービスアカウントは前項で作成したものを指定します。

構成 パラメータ
名前 secret-sample
トリガー HTTP
ランタイム Python 3.7
実行する関数 main
サービスアカウント test-secretmanager@sample-project.iam.gserviceaccount.com
※前項で作成したサービスアカウント

環境変数
シークレットの情報を設定します。

名前
PROJECT_ID シークレットを設定したSecret ManagerがあるプロジェクトID
SECRET_NAME シークレットの名前
SECRET_VERSION シークレットのバージョン

Cloud Functions作成用ファイル

試される場合はenv.yamlとgcloudコマンドのオプションをご利用の環境に合わせて変更してください

main.py

import os
from google.cloud import secretmanager

# 環境変数読み込み
project_id = os.environ.get('PROJECT_ID')
secret_name = os.environ.get('SECRET_NAME')
secret_ver = os.environ.get('SECRET_VERSION')

def get_secret_text(project_id, secret_name, secret_ver):
    '''
    プロジェクトID、シークレット名、シークレットのバージョンを指定して
    Secret Manager から情報を取得する
    '''
    client = secretmanager.SecretManagerServiceClient()
    name = client.secret_version_path(project_id, secret_name, secret_ver)
    response = client.access_secret_version(name)

    return(response.payload.data.decode('UTF-8'))

def main(request):
    '''
    メイン関数
    '''
    plain_secret = get_secret_text(project_id, secret_name, secret_ver)

    print(plain_secret)

requirements.txt

google-cloud-secret-manager

env.yaml

PROJECT_ID: sample-project
SECRET_NAME: sample
SECRET_VERSION: '1'

Cloud Shellを起動し、フォルダを作成してその配下に上記ファイルを配置します。
そのフォルダから下記gcloudコマンドを実行してCloud Functionsの関数を作成します。

gcloud functions deploy secret-sample \
 --entry-point main \
 --env-vars-file env.yaml \
 --runtime python37 \
 --trigger-http \
 --allow-unauthenticated \
 --service-account=test-secretmanager@sample-project.iam.gserviceaccount.com

テスト

関数ができたらテスト実行してみましょう。Secret Managerからシークレットを取得できていれば、ログに表示されているはずです。

おわりに

Secret Managerおよび登録したシークレットをCloud Functionsから利用する方法の一例を紹介いたしました。とても便利なサービスなので、Cloud KMS等で作成した鍵を利用してパスワードを暗号化/復号化されたことがある方には、是非とも一度Secret Managerを試してみていただきたいと思います。

本番環境で利用する際は運用についていろいろな考慮が必要になるかと思いますが、Cloudのよいところは気軽に始められるところです。使ってみないとわからないことも多々ございますので、まずは最小構成で試してみていただき、ご利用の環境にあった構成を見つけていただければと思います。マネージドサービスとして提供されている機能をうまく使い倒し、運用の負荷をどんどん減らしていきましょう。

クラウドエースでは、Google Cloud Platformのご利用について様々な技術支援を行っております。何かお困りのことがございましたらぜひご相談ください!