【Secret Manager】シークレットごとに読めるサービスアカウントを絞る方法

【Secret Manager】シークレットごとに読めるサービスアカウントを絞る方法 GCP

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 で指定します。

参考

この記事を書いた人

渋谷で働くよわよわエンジニア。TypeScript(Next.js/Node.js)/Golang/AWS/Flutterなど
LINE API Expert(2023/1~)

tokkuをフォローする
オススメ記事
在宅ワークが多くなって、デスクの配線周りに困っている方は、拡張デスクの導入がおすすめです。Windows/MacOS/Linuxの複数の機器をスッキリとデスク周りに収める事ができました!リモートからサーバーメンテを行うインフラエンジニアは必見です!
GCP
シェアする
tokkuをフォローする

コメント

タイトルとURLをコピーしました