notebook

都内でWEB系エンジニアやってます。

GCPのSecret Managerを使ってみる

この記事はGoogle Cloud Platform Advent Calendar 20203日目の記事です

AWSだとParameterStoreなどがあるがGCPだとなんなんだろうということで調べて使ってみた

Secret Manager

外部サービスのAPIキーやパスワードなどの秘匿情報を含むデータをGCP上で管理できるサービス

Secret Manager  |  Google Cloud

cloud.google.com

今回は実際にローカルの開発環境から使ってみる

データの登録

コマンドラインから登録する

$ echo 'hoge fuga' | gcloud secrets create my-secret --data-file=-

標準入力から入力する方法以外にもいろいろある

$ echo -n $TOGGL_API_TOKEN | gcloud secrets create 'toggl/token' --data-file=-
ERROR: (gcloud.secrets.create) INVALID_ARGUMENT: Resource ID [toggl/token] is not in a valid format.

AWSのパラメータストアのノリで/区切りがいけるかなと試してみたがだめだった

/ は使えない模様

$ echo -n $TOGGL_API_TOKEN | gcloud secrets create 'toggl-token' --data-file=-
Created version [1] of the secret [toggl-token].

取得

$ gcloud secrets versions access latest --secret='my-secret'
hoge fuga

更新

$ echo -n 'hoge fuga piyo' | gcloud secrets versions add my-secret --data-file=-

値が変わっていることが確認できる

$ gcloud secrets versions access latest --secret='my-secret'
hoge fuga piyo

Rubyの実装で試してみる

CloudRunからキーを参照して使う予定だったのでいったんローカルでサーバを起動して動作させられるか試す

事前にサービスアカウントを作成してSecret Manager のシークレット アクセサーのロールを追加しておく

  • app.rb
require "google/cloud/secret_manager"
require "sinatra"

post "/" do
  client = Google::Cloud::SecretManager.secret_manager_service
  key = client.secret_version_path project: project_id, secret: 'my-secret', secret_version: 'latest'
  res = client.access_secret_version name: key
  p 'secret ======'
  p res.payload
  p res.payload.data
end
  • サーバの起動
$ ruby app.rb
  • アクセス
$ curl http://127.0.0.1:8080

適当にアクセスしてログを見る

  • ログ
"secret ======"
<Google::Cloud::SecretManager::V1::SecretPayload: data: "hoge fuga piyo">
"hoge fuga piyo"

gcloudコマンドでは意識しなかったがsecretが保存されているパスを指定する必要がある

サンプルでいうと

projects/#{project_id}/secrets/{secret_name}/versions/latest

project_idが必要

GOOGLE_APPLICATION_CREDENTIALSにサービスアカウントのキーを置いておけばそのあたりよしなにやってくれるのかと思っていたらそんなことはなく

PermissionDeniedで怒られた

 2020-10-30 10:40:12 - Google::Cloud::PermissionDeniedError - 7:Secret Manager API has not been used in project 111111111111 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/secretmanager.googleapis.com/overview?project=111111111111 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.. debug_error_string:{"created":"@1604054412.050131516","description":"Error received from peer ipv4:172.217.27.74:443","file":"src/core/lib/surface/call.cc","file_line":1062,"grpc_message":"Secret Manager API has not been used in project 111111111111 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/secretmanager.googleapis.com/overview?project=111111111111 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.","grpc_status":7}:
        /usr/local/bundle/gems/google-cloud-secret_manager-v1-0.5.0/lib/google/cloud/secret_manager/v1/secret_manager_service/client.rb:826:in `rescue in access_secret_version'
        /usr/local/bundle/gems/google-cloud-secret_manager-v1-0.5.0/lib/google/cloud/secret_manager/v1/secret_manager_service/client.rb:792:in `access_secret_version'
        ./app.rb:21:in `block in <main>'

プロジェクトIDがないと別のプロジェクト的なものと解釈されてAPI有効にしろ!などと言われるっぽい(該当プロジェクトでは有効にしている)

ここで出てくるPROJECT_NUMBER的なもの(111111111111)はどのプロジェクトなのかは探せなかったので不明

結構詰まったが最終的にはGitHubでコード検索して実装方法を探して解決した

過去のバージョンの値を取得する

ここのバージョンを指定することで過去の値も取ることができる

  • ログ
"projects/sampleproject-0000000/secrets/my-secret/versions/1"
<Google::Cloud::SecretManager::V1::SecretPayload: data: "hoge fuga">
"hoge fuga"

あまり過去のバージョンのキーを指定するケースが思い浮かばないがそういうこともできる

おわり

簡単に使用できた

各種言語のクライアントライブラリもあるので導入は簡単にできそう

実際に使っていくと管理対象が増えてきたときにどうやって管理するのかが心配ではある

AWSのパラメータストアだと/区切りでパスを指定できて特定のパスまでの情報を一括で取得できたりしてよくできているなと思った

一方GCPだとそうではなさそうなので命名規則でなんとかするくらいしか思い浮かばず

そもそも用途がーみたいな話もありそうだなと思いつつ、どのような運用が良いのか答えが出ていないので詳しい方にアドバイスとかもらえたら嬉しい