gcloudコマンドで試すGCP Secret Manager


Secret Managerは、GCP上でパスワードやAPIキーなどの秘密情報を安全に管理するためのサービスです。2020年3月にGAしました。

似たカテゴリのサービスであるCloud Key Management Service(KMS)は、秘密情報そのものではなく、それらを暗号化・複合するための鍵を管理します。

以前はKMSと独自の暗号化・複合ソリューション、その他BerglasHashiCorp 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:[email protected] --role=roles/secretmanager.secretAccessor
Updated IAM policy for secret [test].
bindings:
- members:
  - serviceAccount:[email protected]
  role: roles/secretmanager.secretAccessor
etag: BwWqZxB39ss=
version: 1

# gcloud secretsコマンドでroles/appengine.appAdminを付与しようとするとエラーになります
$ gcloud secrets add-iam-policy-binding test --member=serviceAccount:[email protected] --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:[email protected]
  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: [[email protected]]

# 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 [[email protected]] 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としても、アプリケーション用のインテグレーション(ライブラリや環境変数管理)としても利用できそうなので随時追記します。

参考