- GitHub Actionsのワークフローを利用しているプロジェクトで、GCPのSecret Managerを使って環境変数を一元管理したいと思いました。しかし、GCPのSecret Managerから秘密情報を取得する際に「403 Permission Denied」エラーに遭遇しました。
- けっこう悩んだ末わかったのは、GCPの仕様として、自前で用意したサービスアカウントへSecret Managerへのアクセス権限を付与しても無効かもということでした。解決策として、デフォルトのサービスアカウントへ、自前のサービスアカウントを紐付けることで問題が解消しました。
Google Cloudの認証の仕組み
今回は、GitHub Actionsの設定ファイル(Yaml)で、認証用JSONファイルを読み込むことでGoogle認証を行い、Secret Managerへ環境変数を適用する仕組みにしました。
# 省略...
- id: 'auth'
name: 'Authenticate to Google Cloud'
uses: 'google-github-actions/auth@v1'
with:
credentials_json: '${{ secrets.GCLOUD_CREDENTIAL }}'
# 省略...
- name: Configure dotenv file
# load envs from github secrets
run: |
cat << EOF > .env
# 省略(環境変数の定義)...
EOF
- name: Run a new version of secrets
run: |
gcloud secrets versions add ${{ secrets.GCLOUD_SECRET_LABEL }} --data-file .env
そして認証ファイルで認証する自前のサービスアカウントには、PythonでGcloudのAPIを使うための権限(Secret Manager周りや、コンテナ管理のためのArtifact Registry周り、CloudStorageなど)を付与しておきました。
ちなみにPythonコードでは、ENVファイルの中身がGCPのSecret Managerから取得されます(下記、payload変数を作る箇所)
# 省略...
def get_google_secret_payload(secret_label, version) -> str | None:
try:
_, project_id = google.auth.default()
except google.auth.exceptions.DefaultCredentialsError:
project_id = None
if project_id is None:
return None
# 省略...
client = secretmanager.SecretManagerServiceClient()
gcloud_secret_name = (
f"projects/{project_id}/secrets/{secret_label}/versions/{version}"
)
payload = client.access_secret_version(name=gcloud_secret_name).payload.data.decode(
"UTF-8"
)
return payload
# 省略...
問題の原因
これを動かした結果、エラー「google.api_core.exceptions.PermissionDenied: 403 Permission 'secretmanager.versions.access' denied for resource 'projects/***project/secrets/env_file/versions/latest' (or it may not exist)."」が発生して、Secret Managerから秘密情報を取得できず、、Secret Manager周りの権限を管理者権限にしても、同じでした。
その原因は、コードが動くCloudRun環境(今回私はCloudRunへのデプロイを行いました)がデフォルトで別のサービスアカウント(サービスアカウント「***-compute@developer.gserviceaccount.com」)を使用して認証するようになっているようであり、そのアカウントがSecret Managerへの適切なアクセス権限を持っていなかったためです。
解決策
デフォルトのサービスアカウントに「Secret Managerのシークレットアクセサー」ロールを付与し、
さらに自前のサービスアカウントにデフォルトのサービスアカウントユーザーへのアクセス権限を付与。
これにより、デフォルトのサービスアカウントを介してカスタムサービスアカウントの権限でSecret Managerにアクセスすることが可能になりました。バンザイ