Google Cloud の Secret Manager で、シークレット1つごとに「読めるサービスアカウント」を決める手順をまとめます。Secret Manager Secret Accessor ロールをプロジェクトに付けると、そのプロジェクトのシークレットが全部読めるようになります。ここでは、ロールをシークレット単位で付け、別のシークレットは読めないことまで確かめます。前提は Google Cloud CLI(gcloud)が使える環境で、操作するアカウントにシークレットの Secret Manager Admin(roles/secretmanager.admin)があることです。
ロールを付ける場所で読める範囲が変わる
Secret Manager の読み取りに使うロールは roles/secretmanager.secretAccessor(Secret Manager Secret Accessor)です。中身は secretmanager.versions.access の権限で、シークレットの値を取り出せます。
このロールはシークレット・プロジェクト・フォルダ・組織のどこにでも付けられ、付けた場所で読める範囲が決まります。
| 付ける場所 | 読める範囲 |
|---|---|
| シークレット | そのシークレットだけ |
| プロジェクト | プロジェクト内の全シークレット |
| フォルダ | フォルダ内の全プロジェクトの全シークレット |
| 組織 | 組織内の全プロジェクトの全シークレット |
利用者やテナントごとにシークレットを分けていて、アプリごとに読めるものを絞りたいなら、シークレットに付けます。なお roles/owner は secretmanager.versions.access を含みますが、roles/editor と roles/viewer は含みません。
シークレット単位で読み取りを許可する
1. シークレットを作る
例として、2つのシークレット tenant-a-token と tenant-b-token を作ります。
printf "token-for-a" | gcloud secrets create tenant-a-token --data-file=-
printf "token-for-b" | gcloud secrets create tenant-b-token --data-file=-
--data-file=- で標準入力から値を読みます。echo を使うと末尾に改行が入るので、printf を使います。
2. サービスアカウントにシークレットのロールを付ける
app-a@PROJECT_ID.iam.gserviceaccount.com に tenant-a-token だけを読ませます。
gcloud secrets add-iam-policy-binding tenant-a-token \
--member="serviceAccount:app-a@PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
--member は serviceAccount:・user:・group: のどれかを頭に付けたメールアドレスで指定します。gcloud secrets add-iam-policy-binding は既存のバインディングに追記します。REST API の setIamPolicy を直接呼ぶとポリシー全体が置き換わるので、既存の付与を消さないよう注意してください。
3. 付いたことを確かめる
gcloud secrets get-iam-policy tenant-a-token
bindings に次のような項目があれば付いています。
bindings:
- members:
- serviceAccount:app-a@PROJECT_ID.iam.gserviceaccount.com
role: roles/secretmanager.secretAccessor
4. Cloud Run から読む場合
Cloud Run でシークレットを使うときは、サービスの実行に使うサービスアカウント(サービス ID)に上のロールを付けたうえで、デプロイ時にシークレットを指定します。
gcloud run deploy SERVICE --image IMAGE_URL \
--service-account=app-a@PROJECT_ID.iam.gserviceaccount.com \
--update-secrets=TENANT_TOKEN=tenant-a-token:latest
Cloud Run はデプロイ時に、サービス ID がそのシークレットを読めるかを確かめます。読めなければデプロイは通りません。環境変数で渡す値はインスタンスの起動時に1回だけ解決されるので、公式ドキュメントでは latest ではなくバージョン番号を固定することが推奨されています。値を差し替えたときに追従させたい場合は、ボリュームとしてマウントする方法があります。
動作を確かめる
サービスアカウントの権限で実際に読んでみます。自分のアカウントでサービスアカウントの権限を借りる(なりすます)には、そのサービスアカウントに対する Service Account Token Creator(roles/iam.serviceAccountTokenCreator)が必要です。また、プロジェクトで IAM Service Account Credentials API が有効になっている必要があります。
許可したシークレットは読めます。
gcloud secrets versions access latest --secret=tenant-a-token \
--impersonate-service-account=app-a@PROJECT_ID.iam.gserviceaccount.com
token-for-a
許可していない tenant-b-token を同じように読むと、secretmanager.versions.access の権限が無いというエラーで失敗します。
gcloud secrets versions access latest --secret=tenant-b-token \
--impersonate-service-account=app-a@PROJECT_ID.iam.gserviceaccount.com
ここで値が返ってきた場合は、シークレット以外の場所で同じロールが付いています。次の節で確かめます。
うまくいかないとき
許可していないシークレットまで読める
プロジェクト・フォルダ・組織のどこかに roles/secretmanager.secretAccessor か roles/owner が付いていると、シークレット単位の設定に関係なく全部読めます。上の階層で付けた許可は下の階層に引き継がれ、シークレット側の許可ポリシーでは打ち消せません。プロジェクトに付いているロールは次のコマンドで一覧できます。
gcloud projects get-iam-policy PROJECT_ID \
--flatten="bindings[].members" \
--filter="bindings.role:roles/secretmanager.secretAccessor" \
--format="table(bindings.members)"
ここに対象のサービスアカウントが出たら、プロジェクトの付与を外して、シークレットごとの付与に切り替えます。
gcloud projects remove-iam-policy-binding PROJECT_ID \
--member="serviceAccount:app-a@PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
シークレットの付与を取り消したい
シークレットに付けたロールは remove-iam-policy-binding で外します。
gcloud secrets remove-iam-policy-binding tenant-a-token \
--member="serviceAccount:app-a@PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
Compute Engine や GKE から読めない
Compute Engine のインスタンスや GKE のノードから Secret Manager を使うには、インスタンスやノードに cloud-platform の OAuth スコープが必要です。ロールを付けても読めない場合は、スコープを確かめてください。
なりすましの確認で失敗する
--impersonate-service-account を付けたコマンドがシークレット以前の段階で失敗するときは、自分のアカウントに Service Account Token Creator が付いているか、IAM Service Account Credentials API が有効かを確かめます。自分がプロジェクトのオーナーでも、このロールは別に付ける必要があります。
シークレットが多くて1つずつ付けるのが手間
IAM Conditions を使うと、リソース名の条件でまとめて許可できます。Secret Manager はリソースの名前・種類の属性と日時の属性に対応しており、たとえば「名前が特定の接頭辞で始まるシークレットだけ」といった条件を付けられます。add-iam-policy-binding の --condition で指定します。



コメント