Flask web app on Cloud Run - google.auth.exceptions.DefaultC



我在Cloud Run上托管一个Flask web应用程序。我还使用秘密管理器来存储服务帐户密钥。(我之前下载了一个带有密钥的JSON文件)

在我的代码中,我访问负载,然后使用os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = payload进行身份验证。当我部署应用程序并尝试访问该页面时,我得到一个内部服务错误。查看日志,我看到:

File "/usr/local/lib/python3.10/site-packages/google/auth/_default.py", line 121, in load_credentials_from_file
raise exceptions.DefaultCredentialsError(
google.auth.exceptions.DefaultCredentialsError: File {"

我可以通过:gcloud secrets versions access 1 --secret="<secret_id>"作为服务帐户通过gcloud访问秘密。

下面是我的Python代码:
# Grabbing keys from Secret Manager
def access_secret_version():
# Create the Secret Manager client.
client = secretmanager.SecretManagerServiceClient()
# Build the resource name of the secret version.
name = "projects/{project_id}/secrets/{secret_id}/versions/1"
# Access the secret version.
response = client.access_secret_version(request={"name": name})
payload = response.payload.data.decode("UTF-8")
return payload
@app.route('/page/page_two')
def some_random_func():
# New way
payload = access_secret_version() # <---- calling the payload

os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = payload

# Old way
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "service-account-keys.json"

从技术上讲,我不像以前那样访问JSON文件。payload变量存储整个键。这就是它不起作用的原因吗?

你的方法不正确。

当你在像Cloud run这样的Google计算服务上运行时,代码在计算服务的身份下运行。

在这种情况下,默认情况下,Cloud Run使用Compute Engine默认服务帐户,但是,最好为您的服务创建一个服务帐户,并在将其部署到Cloud Run时指定它(请参阅服务帐户)。

这个机制是"腿"之一。当你的代码在Google Cloud上运行时,指定环境变量(您也不需要创建密钥),Cloud Run服务从Metadata服务获取凭据:

import google.auth
credentials, project_id = google.auth.default()

参见google.authpackage

在代码中定义/设置环境变量是不好的做法。就其性质而言,环境变量应该由环境提供。用APPLICATION_DEFAULT_CREDENTIALS这样做意味着你的代码总是设置这个值,当它应该只在代码运行在Google Cloud时这样做。

为了完整起见,如果您需要从JSON字符串而不是从包含JSON字符串的文件中创建Credentials,您可以使用from_service_account_info(参见google.oauth2.service_account)