0

我可以在 Google Cloud Shell 中不成功使用密钥文件的情况下创建 SecretManagerServiceClient:

from google.cloud import secretmanager
from google.oauth2 import service_account
from google.auth.exceptions import DefaultCredentialsError
import logging
import sys
import os


def list_secrets(client, project_id):
    """
    Retrieve all secrets associated with a project
    :param project_id: the alpha-numeric name of the project
    :return: a generator of Secrets
    """
    try:
        secret_list = client.list_secrets(request={"parent": "projects/{}".format(project_id)})
    except Exception as e:
        sys.exit("Did not successfully retrieve secret list.")
    return secret_list


def set_env_secrets(client, secret_ids, label=None):
    """
    Sets secrets retrieved from Google Secret Manager in the runtime environment
    of the Python process
    :param secret_ids: a generator of Secrets
    :param label: Secrets with this label will be set in the environment
    """
    for s in secret_ids:
        # we only want secrets with matching labels (or all of them if label wasn't specified)
        if not label or label in s.labels:
            version = client.access_secret_version(request={'name': '{}/versions/latest'.format(s.name)})
            payload_str = version.payload.data.decode("UTF-8")
            os.environ[s.name.split('/')[-1]] = payload_str


if __name__ == "__main__":
    client = secretmanager.SecretManagerServiceClient() 
    secrets = list_secrets(client, "myprojectid-123456")
    set_env_secrets(client, secrets)
    print(os.getenv("DATA_DB_HOST"))

但是,当我在 Google Cloud Run 中使用类似的代码作为容器入口点的基础时,尝试使用默认服务帐户的凭据检索客户端失败并出现

File "entry_point.py", line 27, in get_client
    client = secretmanager.SecretManagerServiceClient()
  File "/usr/local/lib/python3.6/site-packages/google/cloud/secretmanager_v1/services/secret_manager_service/client.py", line 274, in __init__
    client_info=client_info,
  File "/usr/local/lib/python3.6/site-packages/google/cloud/secretmanager_v1/services/secret_manager_service/transports/grpc.py", line 162, in __init__
    scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id
  File "/usr/local/lib/python3.6/site-packages/google/auth/_default.py", line 340, in default
    credentials, project_id = checker()
  File "/usr/local/lib/python3.6/site-packages/google/auth/_default.py", line 186, in _get_explicit_environ_credentials
    os.environ[environment_vars.CREDENTIALS]
  File "/usr/local/lib/python3.6/site-packages/google/auth/_default.py", line 97, in load_credentials_from_file
    "File {} was not found.".format(filename)
google.auth.exceptions.DefaultCredentialsError: File  was not found.

默认服务帐户具有 Editor 和 Secret Manager Admin 角色(感谢 @DanielOcando 的评论)。为什么这里描述的 ADC 库没有获取默认服务帐户的权限并使用它们来实例化客户端?

更新 1

@guillaumeblaquiere 询问了依赖关系。该容器使用 Python 3.6.12 和以下库构建:

Django==2.1.15
django-admin-rangefilter==0.3.7
django-extensions==2.1.2
django-ipware==1.1.6
pytz==2017.3
psycopg2==2.7.3.2
waitress==1.4.1
geoip2==2.6
gunicorn==19.9.0
social-auth-app-django==3.1.0
semver==2.8.1
sentry-sdk==0.6.9
google-api-core==1.23.0
google-auth==1.23.0
google-cloud-secret-manager==2.0.0

我创建了一个自定义服务帐户,向其中添加了 Editor 和 Secret Manager Admin 角色,然后使用控制台使用该帐户部署了一个新修订版,但出现了同样的错误。

更新 2

认为匹配 Cloud Shell 中的 CPython 版本就可以解决问题,我使用 Python 3.7 重建了图像。没运气。

更新 3

采取不同的策略,我将 Service Account Token Creator 角色添加到项目的默认服务帐户中,并创建了一个 terraform 文件并将其配置为服务帐户模拟。gcloud auth application-default login在调用 terraform 之前,我还在 shell 中运行。

provider "google" {
  alias   = "tokengen"
} 

data "google_client_config" "default" {
  provider = google.tokengen
} 

data "google_service_account_access_token" "sa" {
  provider               = "google.tokengen"
  target_service_account = "XXXXXXXXXXXX-compute@developer.gserviceaccount.com"
  lifetime               = "600s"
  scopes = [
    "https://www.googleapis.com/auth/cloud-platform",
  ] 
} 

provider "google" {
  project   = "myprojectid-123456"
  region    = "us-central1"
  zone      = "us-central1-f"
  #impersonate_service_account = "XXXXXXXXXXXX-compute@developer.gserviceaccount.com
}


resource "google_cloud_run_service" "default" {
  name     = "myprojectid-123456"
  location = "us-central1"
  
  template {
    spec { 
      containers {
        image = "us.gcr.io/myprojectid-123456/testimage"
      } 
    } 
  } 
  traffic {
    percent         = 100
    latest_revision = true
  }
}

这确实可以创建服务,但是当端点尝试实例化 SecretManagerServiceClient 时,同样会导致相同的错误。

4

0 回答 0