You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cloud Run部署Flask应用遇google.auth.DefaultCredentialsError问题排查

Cloud Run Flask应用使用Secret Manager存储ServiceAccount密钥认证失败问题解决

问题描述

在Cloud Run上托管Flask Web应用,将ServiceAccount密钥(JSON文件)存储到Secret Manager中,代码获取密钥payload后通过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>"命令可正常访问该密钥,怀疑是直接使用payload内容而非文件路径导致问题。

核心原因

GOOGLE_APPLICATION_CREDENTIALS环境变量要求的是ServiceAccount密钥文件的本地路径,而非密钥的JSON字符串内容。直接将JSON字符串赋值给该变量时,谷歌认证库会把这个字符串当作文件路径去读取,自然找不到对应文件,从而抛出错误。

解决方案

方法1:临时写入文件(快速验证方案)

将获取到的密钥内容写入临时文件,再将文件路径赋值给环境变量:

import tempfile
import os
from google.cloud import secretmanager

# 从Secret Manager获取密钥
def access_secret_version():
    client = secretmanager.SecretManagerServiceClient()
    # 替换为你的项目ID和Secret ID
    name = "projects/你的项目ID/secrets/你的Secret ID/versions/1"
    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():
    payload = access_secret_version()
    # 创建临时JSON文件存储密钥内容
    with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.json') as f:
        f.write(payload)
        temp_file_path = f.name
    
    os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = temp_file_path
    
    # 执行需要认证的操作...
    
    # 可选:操作完成后删除临时文件,Cloud Run实例销毁时会自动清理文件系统
    os.unlink(temp_file_path)

方法2:直接构建认证凭证(推荐方案)

跳过环境变量,直接用密钥内容构建ServiceAccount凭证,避免文件操作:

import json
from google.cloud import secretmanager
from google.oauth2 import service_account

# 从Secret Manager获取密钥
def access_secret_version():
    client = secretmanager.SecretManagerServiceClient()
    name = "projects/你的项目ID/secrets/你的Secret ID/versions/1"
    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():
    payload = access_secret_version()
    # 将JSON字符串解析为字典
    service_account_info = json.loads(payload)
    # 根据业务需求添加权限范围
    credentials = service_account.Credentials.from_service_account_info(
        service_account_info,
        scopes=["https://www.googleapis.com/auth/cloud-platform"]
    )
    
    # 在调用Google服务时直接传入凭证
    # 示例:初始化Cloud Storage客户端
    # from google.cloud import storage
    # storage_client = storage.Client(credentials=credentials)
    
    # 后续业务逻辑...

方法3:Cloud Run最佳实践(无需手动管理密钥)

Cloud Run支持直接为服务分配ServiceAccount,自动提供身份认证,无需在代码中处理密钥:

  • 登录GCP控制台,进入你的Cloud Run服务页面
  • 点击「编辑 & 部署新修订版本」,切换到「容器、变量和秘密」标签
  • 在「服务帐号」下拉框中选择一个拥有所需权限(如访问Secret Manager、目标GCP服务)的ServiceAccount
  • 完成部署后,应用会自动使用该身份进行认证,无需任何密钥相关代码

内容的提问来源于stack exchange,提问作者user20977191

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 03:05:47