Amazon の商品ページなどのスクレイピング API を作ろうと Google Cloud を使い始めて早くも 5ヶ月経ってしまいました(笑)。もちろん掛かりっきりになっているわけではありませんが、それにしてもクラウドサービスって難しいですね。特にセキュリティ関連がややこしくて、今回も本番用を立ち上げようとした Cloud Run の Python アプリから Secret Manager にアクセスできずに解決までひと月くらい掛かってしまいました。
01サービスアカウントをチェックせよ
今回うまくいかなかったケースは、Cloud Run の Python アプリから WordPress に JSON データを送る際に送り先の URL と認証用の API トークンを Secret Manager に保存して Python から呼び出そうとしたのですがこれがエラーになるというものです。
結論から言いますと、Cloud Run から Secret Manager にアクセスするサービスアカウントは明示的に指定しない限りデフォルトのサービスアカウントなることを知らなかったからであり、デプロイのために作成したカスタムサービスアカウントに 「Secret Manager のシークレットアクセサー」ロールを与えているのにエラーになっておかしい、おかしいと悩んでいたということです。
今回のケースで言えば、Cloud Run に対して権限を持っているサービスアカウントがそのまま Secret Manager に対してアクセス権限を持っているわけではないということになります。セキュリティのためとはいえ、ややこしい。
で、もう少し詳しく書きますが、まずはこれまでの履歴は次の記事からたどれます。
02Secret Manager シークレットアクセサーロールの与え方
Cloud Run から Secret Manager にアクセスできない場合に確認すべき箇所は2つです。
Cloud Run 実行用サービスアカウントの確認
まず、サービスアカウントの確認です。
コンソールからデプロイした Cloud Run のサービスを確認します。

Cloud Run の該当サービスを選択し、鉛筆アイコンの「新しいリビジョンの編集とデプロイ」をクリックします。

セキュリティタブをクリックしますとサービスアカウントのプルダウンがありますのでそこで既存のサービスアカウントを選ぶか新しく作成して「デプロイ」ボタンをクリックします。そうしますと新しいリビジョンが作成されます。つまり、このサービスアカウントはリビジョンごとに設定する必要があるということになります。
「新しいサービスアカウントの作成」に進んだ場合は次のように進みます。

サービスアカウント名を入力して先に進みますと、そのページで Secret Manager のシークレットアクセサーロールを付与することが出来ます。デプロイすれば新しいリビジョンが作成されます。
gcloud で作業する場合は、サービスアカウント名を指定して新規にデプロイします。
gcloud run deploy サービス名 \
--image=イメージのURL \
--service-account=サービスアカウントのメールアドレス \
--region=リージョン名
これで上記のセキュリティタブで表示されるサービスアカウントとして設定されます。ただし、シークレットアクセサーロールは付与されませんので次項目の作業が必要になります。
なお、このサービスアカウント設定はリビジョンごとに指定できます。つまり、リビジョンごとに確認する必要があるということになります。
Secret Manager シークレットアクセサーロールを与える
2つ目はそのサービスアカウントに Secret Manager シークレットアクセサーロール(roles/secretmanager.secretAccessor)を与えます。
コンソールで行う場合は、ナビゲーションメニューから IAM と管理 > IAM と進みます。

該当するサービスアカウントの鉛筆アイコンをクリックします。これはすでにロールが与えられている画面です。

「別のロールを追加」をクリックし、「Secret Manager のシークレットアクセサー」を選択して保存します。
gcloud から行う場合は次のようにします。
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:SERVICE_ACCOUNT_EMAIL" \
--role="roles/secretmanager.secretAccessor"
03まとめ
Google Cloud ではサービスアカウントとロールを正しく理解していないとトラブルが発生しやすいですし、セキュリティ上好ましくないということになります。
正しくは上のリンクなどを読んでいただいたほうがいいですが、考え方としては、Google Cloud の各サービスは API で通信するようになっており、利用するためには各サービス専用のサービスアカウントに限定されたロールを与える必要があるということだと思います。
ちなみに Cloud Run に Python アプリをデプロイし Secret Manager とシークレットのやり取りするだけで次のようなサービスアカウントが作成されます。

ナビゲーションメニューから IAM の管理 > IAM と進み、右上の「Google 提供のロール付与を含める」にチェックを入れますと自動的に作成されるサービスアカウントと付与されたロールがみられます。