GitHub Actions工作流无法访问Google Cloud Storage Bucket问题求助
问题情况
我写了个Django测试用例test_retrieve_bucket,用来测Google Cloud Storage(GCS)存储桶的访问。本地跑测试全过,但在GitHub Actions里执行就失败,报缺少storage.buckets.get权限。
测试代码
from django.test import TestCase from google.cloud import storage from datetime import datetime from .models import Expense class DemoTest(TestCase): def setUp(self): self.expense = Expense.objects.create( invoice_number = "ABC", account_number = "123", customer_name = "XYZ", invoice_amount = 12.50, invoice_date = datetime.now() ) def test1(self): self.assertEqual(self.expense.invoice_number, "ABC") def test2(self): self.assertEqual(self.expense.account_number, "123") def test3(self): self.assertEqual(self.expense.customer_name, "XYZ") def test_retrieve_bucket(self): bucket_name = "test_bucket_8866" client = storage.Client() bucket = client.bucket(bucket_name) self.assertTrue(bucket.exists())
注:原代码缺少datetime和Expense模型的导入,本地能跑可能是环境隐含支持,但建议补上;另外原测试用return代替断言,Django测试框架不会识别这类逻辑,必须改成self.assertEqual这类官方断言方法。
报错信息
google.api_core.exceptions.Forbidden: 403 GET https://storage.googleapis.com/storage/v1/b/test_bucket_8866?fields=name&prettyPrint=false: test-service-account@tbi-finance.iam.gserviceaccount.com does not have storage.buckets.get access to the Google Cloud Storage bucket. Permission 'storage.buckets.get' denied on resource (or it may not exist).
已配置的GitHub Actions工作流
name: Django CI on: push: branches: [ "main" ] pull_request: branches: [ "main" ] jobs: build: runs-on: ubuntu-latest strategy: max-parallel: 4 matrix: python-version: [3.12.4] steps: - uses: actions/checkout@v4 - name: auth uses: google-github-actions/auth@v2.0.0 with: workload_identity_provider: 'projects/334572487877/locations/global/workloadIdentityPools/learn-github-actions-pool/providers/github-cdci' service_account: 'test-service-account@tbi-finance.iam.gserviceaccount.com' - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} - name: Install Dependencies run: | pip install pipenv && pipenv install --system - name: Run Tests run: | python manage.py test permissions: contents: 'read' id-token: 'write'
已完成的配置
- 通过Workload Identity Federation完成服务账号认证
- 给服务账号配置了Storage Object Admin权限
- 为工作负载身份池添加
WorkloadIdentityUser角色,执行命令:
gcloud iam service-accounts add-iam-policy-binding "test-service-account@tbi-finance.iam.gserviceaccount.com" \ --project="tbi-finance" \ --role="roles/iam.workloadIdentityUser" \ --member="principalSet://iam.googleapis.com/projects/334572487877/locations/global/workloadIdentityPools/learn-github-actions-pool/attribute.repository/duybtr/django_cdci"
排查与解决
关键问题
Storage Object Admin仅负责存储桶内对象的操作权限(如增删改查对象),不包含存储桶本身的读取权限——而bucket.exists()方法需要调用storage.buckets.get权限来确认桶是否存在,这就是报错的核心原因。
解决办法
给服务账号添加存储桶读取权限
给test-service-account@tbi-finance.iam.gserviceaccount.com添加Storage Bucket Viewer角色(该角色包含storage.buckets.get权限),执行以下命令二选一即可:# 方式一:给整个项目添加权限(适用于需要访问多个桶的场景) gcloud projects add-iam-policy-binding tbi-finance \ --member="serviceAccount:test-service-account@tbi-finance.iam.gserviceaccount.com" \ --role="roles/storage.bucketViewer" # 方式二:仅给目标桶添加权限(更安全,遵循最小权限原则) gcloud storage buckets add-iam-policy-binding gs://test_bucket_8866 \ --member="serviceAccount:test-service-account@tbi-finance.iam.gserviceaccount.com" \ --role="roles/storage.bucketViewer"验证权限是否生效
执行命令查看目标桶的IAM配置,确认服务账号已拥有对应权限:gcloud storage buckets get-iam-policy gs://test_bucket_8866修正测试代码的断言逻辑
原测试中test1、test2、test3用return语句,Django测试框架不会将其识别为断言验证,必须改成self.assertEqual()这类官方断言方法,否则这些测试等于未执行验证逻辑。确认GitHub Actions的认证状态
可在工作流中添加步骤打印认证信息,确保服务账号身份已正确获取:- name: Check Auth Status run: | gcloud auth list gcloud config get-value account
额外建议
如果测试仅需要操作存储桶内的对象,无需验证桶是否存在,可以直接去掉bucket.exists()的调用,这样就能避免对storage.buckets.get权限的依赖。另外本地测试能通过,大概率是因为本地使用的认证方式(如gcloud CLI登录)权限更宽泛,而GitHub Actions中使用的服务账号是最小权限配置,因此需要精准配置权限。
内容的提问来源于stack exchange,提问作者auco

