Secret Managerは、GCP上でパスワードやAPIキーなどの秘密情報を安全に管理するためのサービスです。2020年3月にGAしました。
似たカテゴリのサービスであるCloud Key Management Service(KMS)は、秘密情報そのものではなく、それらを暗号化・複合するための鍵を管理します。
以前はKMSと独自の暗号化・複合ソリューション、その他BerglasやHashiCorp Vaultを利用していたケースの一部もSercert Manager単独で賄えるはずです。
概念
SecretとVersionという単位を理解する必要があります。
Secretは各プロジェクトのグローバルに作成されます。Secretに対しては削除、Versionの追加、ラベルの付与などの操作が可能です。
SecretはVersionを持ちます。個々のVersionは秘密情報や有効、無効、削除済みのステータスを持ちます。
たとえば、「Service AのパスワードをSecret Managerで管理し、アプリケーションから利用したい」とします。これを実現するには、service-a-password
という名前でSecretを作成し、パスワードを指定してVersionを作成します。このパスワードをアプリケーションから利用する際は、service-a-password
SecretのVersion 1を指定してSecret Managerから取得します。
パスワードをローテーションする際は、service-a-password
SecretにVersionを追加します。
GCPのコンソールから確認するとつぎのようになります。
コマンド概要
gcloudコマンドではSecretと、locationsとversionsに対する操作が可能です。[]は適当に読み替えてください。
# GCPプロジェクト内ではじめて利用する場合はAPIを有効化します
$ gcloud services enable --project [PROJECT_ID] secretmanager.googleapis.com
$ gcloud secrets
ERROR: (gcloud.secrets) Command name argument expected.
Available groups for gcloud secrets:
locations Manage locations of users' secrets.
versions Manage secret versions.
Available commands for gcloud secrets:
add-iam-policy-binding Add IAM policy binding to a secret.
create Create a new secret.
delete Delete a secret.
describe Describe a secret's metadata.
get-iam-policy Get the IAM policy for the secret.
list List all secret names.
remove-iam-policy-binding Remove IAM policy binding for a secret.
set-iam-policy Set the IAM policy binding for a secret.
update Update a secret's metadata.
...
$ gcloud secrets locations
ERROR: (gcloud.secrets.locations) Command name argument expected.
Available commands for gcloud secrets locations:
describe Describe a location.
list List all available locations.
...
$ gcloud secrets versions
ERROR: (gcloud.secrets.versions) Command name argument expected.
Available commands for gcloud secrets versions:
access Access a secret version's data.
add Create a new version of an existing secret.
describe Describe metadata about the secret version.
destroy Destroy a secret version's metadata and secret
data.
disable Disable the version of the provided secret.
enable Enable the version of the provided secret.
list List all versions for a secret.
...
listは利用可能なロケーションのリストです。
$ gcloud secrets locations list
NAME LOCATION
asia-east1 Taiwan
asia-southeast1 Singapore
australia-southeast1 Sydney
europe-north1 Finland
europe-west1 Belgium
europe-west4 Netherlands
us-central1 Iowa
us-east1 South Carolina
us-east4 Northern Virginia
us-west1 Oregon
us-west2 Los Angeles
gcloudコマンドからSecretを作成するときは、--locations
オプションで指定します。指定しない場合はGCPがよしなに選択します。後から変更できません。
準備
gcloudコマンドで挙動を確認するにあたり、つぎのコマンドで権限を付与します。
$ gcloud projects add-iam-policy-binding [PROJECT_ID] --member="serviceAccount:[SERVICE_ACCOUNT]" --role="roles/secretmanager.admin"
利用できるロールはつぎの3つです。
- roles/secretmanager.admin
- roles/secretmanager.secretAccessor
- roles/secretmanager.viewer
今回はSecret自体を作成する必要があるため、roles/secretmanager.admin
を付与しています。
Secret・Versionの作成・変更
test
という名前のSecretを作成し、秘密情報を保存する方法を見ていきます。
$ gcloud secrets create test
Created secret [test].
$ gcloud secrets list
NAME CREATED REPLICATION_POLICY LOCATIONS
test 2020-07-14T12:44:01 automatic
# Secret自体を消そうとすると、含むVersionも一緒に消します。
$ gcloud secrets delete test
You are about to destroy the secret [test] and its [0] version(s).
This action cannot be reversed.
Do you want to continue (Y/n)? n
ERROR: (gcloud.beta.secrets.delete) Aborted by user.
$ gcloud beta secrets describe test
createTime: '2020-07-14T12:44:01.379968Z'
name: projects/xxxxxxxxxxxx/secrets/test
replication:
automatic: {}
# Secret自体にできる操作はラベル関連です
$ gcloud secrets update test -h
Usage: gcloud secrets update SECRET [optional flags]
optional flags may be --clear-labels | --help | --remove-labels |
--update-labels
For detailed information on this command and its flags, run:
gcloud secrets update --help
# testtestという秘密情報でVersionを追加します
$ echo "test test" > secret.txt
$ gcloud secrets versions add test --data-file ./secret.txt
Created version [1] of the secret [test].
$ gcloud secrets versions list test
NAME STATE CREATED DESTROYED
1 enabled 2020-07-14T13:16:36 -
# describeはデータを確認するものではありません
$ gcloud secrets versions describe 1 --secret test
createTime: '2020-07-14T13:16:36.616572Z'
name: projects/xxxxxxxxxxxx/secrets/test/versions/1
state: ENABLED
# Versionのデータを読むのは'access'です
$ gcloud secrets versions access 1 --secret test
test test
# Version毎に無効にできます
$ gcloud secrets versions disable 1 --secret test
Disabled version [1] of the secret [test].
$ gcloud secrets versions list test
NAME STATE CREATED DESTROYED
1 disabled 2020-07-14T13:16:36 -
# 無効にしたVersionにアクセスするとエラーになります
$ gcloud secrets versions access 1 --secret test
ERROR: (gcloud.secrets.versions.access) FAILED_PRECONDITION: Secret Version [projects/xxxxxxxxxxxx/secrets/test/versions/1] is in DISABLED state.
# Versionを削除する前にdisableすることが推奨されています
$ gcloud secrets versions destroy 1 --secret test
You are about to destroy version [1] of the secret [test]. This action
cannot be reversed.
Do you want to continue (Y/n)? Y
Destroyed version [1] of the secret [test].
# 削除したVersionにアクセスしてもエラーになりますが、状態は区別されています
$ gcloud secrets versions access 1 --secret test
ERROR: (gcloud.secrets.versions.access) FAILED_PRECONDITION: Secret Version [projects/xxxxxxxxxxxx/secrets/test/versions/1] is in DESTROYED state.
$ gcloud secrets versions list test
NAME STATE CREATED DESTROYED
1 destroyed 2020-07-14T13:16:36 2020-07-14T13:27:25
# Versionを増やします
$ gcloud secrets versions add test --data-file ./secret.txt
Created version [2] of the secret [test].
$ gcloud secrets versions list test
NAME STATE CREATED DESTROYED
2 enabled 2020-07-14T13:28:46 -
1 destroyed 2020-07-14T13:16:36 2020-07-14T13:27:25
Secretの権限管理
test
Secretにアクセスできるサービスを設定します。system-a
というService AccountをもつサービスがこのSecretを利用するとしましょう。
# system-a Service Accountを用意します
$ gcloud iam service-accounts create system-a
Created service account [system-a].
# gcloud secretsコマンドで、system-aにSecret Manager関連のポリシーをバインディングできます
# roles/secretmanager.secretAccessor はデータアクセス専用です
$ gcloud secrets add-iam-policy-binding test --member=serviceAccount:system-a@yyyyyyyyyyyyy.iam.gserviceaccount.com --role=roles/secretmanager.secretAccessor
Updated IAM policy for secret [test].
bindings:
- members:
- serviceAccount:system-a@yyyyyyyyyyyyy.iam.gserviceaccount.com
role: roles/secretmanager.secretAccessor
etag: BwWqZxB39ss=
version: 1
# gcloud secretsコマンドでroles/appengine.appAdminを付与しようとするとエラーになります
$ gcloud secrets add-iam-policy-binding test --member=serviceAccount:system-a@yyyyyyyyyyyyy.iam.gserviceaccount.com --role=roles/appengine.appAdmin
ERROR: Policy modification failed. For a binding with condition, run "gcloud alpha iam policies lint-condition" to identify issues in condition.
ERROR: (gcloud.secrets.add-iam-policy-binding) INVALID_ARGUMENT: Role roles/appengine.appAdmin is not supported for this resource.
$ gcloud secrets get-iam-policy test
bindings:
- members:
- serviceAccount:system-a@yyyyyyyyyyyyy.iam.gserviceaccount.com
role: roles/secretmanager.secretAccessor
etag: BwWqZxB39ss=
version: 1
Secretの利用
system-a
というService Accountからアクセスしてみましょう。
今回はgcloudコマンドからアクセスしますが、コンピューティング系のサービスのService Accountを設定し、GCPクライアントライブラリからアクセスするのも要領は同じです。
# system-aのService Accountのクレデンシャルをローカルに…
$ gcloud auth activate-service-account --key-file system-a-service-account.json
Activated service account credentials for: [system-a@yyyyyyyyyyyyy.iam.gserviceaccount.com]
# test Secretのversion 2にアクセス
$ gcloud secrets versions access 2 --secret test
test test
# SecretのVersionにアクセスする以外の操作はエラーになります
$ gcloud secrets versions list test
ERROR: (gcloud.secrets.versions.list) PERMISSION_DENIED: Permission 'secretmanager.versions.list' denied for resource 'projects/yyyyyyyyyyyy/secrets/test' (or it may not exist).
$ gcloud secrets locations list
ERROR: (gcloud.secrets.locations.list) User [system-a@yyyyyyyyyyyy.iam.gserviceaccount.com] does not have permission to access project [yyyyyyyyyyyy] (or it may not exist): Permission 'secretmanager.locations.list' denied for resource 'projects/yyyyyyyyyyyy' (or it may not exist).
その他
BerglasはSecret Managerにも対応しているようです。
Secret管理用のCLIとしても、アプリケーション用のインテグレーション(ライブラリや環境変数管理)としても利用できそうなので随時追記します。