Google Cloud Functions引用服务账户JSON文件出现FileNotFoundError:跨GCP项目列出存储桶的问题咨询
解决Cloud Function中跨项目访问GCS存储桶的认证问题
你遇到的核心问题是:storage.Client.from_service_account_json()方法只能读取本地文件系统里的文件路径,没办法直接解析GCS的gs://格式URL,这就是触发FileNotFoundError的根本原因。下面给你几个可行的解决方案,按推荐程度排序:
方案1:使用Cloud Function默认服务账户(最推荐,无需管理密钥)
这是GCP官方首推的做法,不用手动处理密钥文件,只需给Cloud Function的默认服务账户赋予跨项目权限即可:
- 找到当前Cloud Function使用的服务账户(通常格式为
PROJECT_ID@appspot.gserviceaccount.com) - 切换到目标GCP项目,给这个服务账户添加
Storage Viewer角色(仅列桶需求)或匹配业务场景的更细粒度权限 - 修改代码,直接初始化客户端(若访问其他项目桶,需指定目标项目ID):
def explicit(argument): from google.cloud import storage # 自动使用Cloud Function默认服务账户完成认证 storage_client = storage.Client(project="TARGET_PROJECT_ID") buckets = list(storage_client.list_buckets()) print(buckets)
方案2:将密钥文件打包进Cloud Function部署包
如果必须使用自定义服务账户密钥,可以把JSON文件放到代码目录,部署时一起打包上传:
- 把
service_account.json下载到本地代码目录(和main.py同层级) - 修改代码中的路径为本地相对路径:
def explicit(argument): from google.cloud import storage # 使用本地相对路径,部署时会同步上传到Cloud Function的文件系统 storage_client = storage.Client.from_service_account_json( 'service_account.json') buckets = list(storage_client.list_buckets()) print(buckets) - 注意:务必不要把密钥文件提交到版本控制系统,避免泄露风险。
方案3:从Secret Manager拉取密钥内容(更安全的密钥管理方式)
如果不想把密钥打包进部署包,可以将密钥存储在Secret Manager中,运行时动态拉取:
- 将服务账户JSON文件上传到Secret Manager,创建新的Secret
- 给Cloud Function的服务账户添加
Secret Manager Secret Accessor角色 - 修改代码,先从Secret Manager读取密钥内容,再初始化客户端:
import json def explicit(argument): from google.cloud import storage from google.cloud import secretmanager # 从Secret Manager拉取密钥内容 secret_client = secretmanager.SecretManagerServiceClient() secret_name = "projects/YOUR_PROJECT/secrets/YOUR_SECRET_NAME/versions/latest" response = secret_client.access_secret_version(request={"name": secret_name}) secret_payload = response.payload.data.decode("UTF-8") # 用密钥内容初始化存储客户端 storage_client = storage.Client.from_service_account_info( json.loads(secret_payload)) buckets = list(storage_client.list_buckets()) print(buckets)
内容的提问来源于stack exchange,提问作者Martin Walczyński
相关产品推荐
相关产品推荐

