Google CloudSQLAdmin - 服务帐户没有存储桶所需的权限
Posted
技术标签:
【中文标题】Google CloudSQLAdmin - 服务帐户没有存储桶所需的权限【英文标题】:Google CloudSQLAdmin - The service account does not have the required permissions for the bucket 【发布时间】:2019-07-09 21:47:17 【问题描述】:我正在编写一个 python 函数,它使用服务帐户凭据调用 Google cloudSQLAdmin api 以将数据库导出到存储桶。
服务帐号已被授予项目所有者权限,并且存储桶已为项目所有者设置了权限。我们的项目已经启用了 sqlAdmin api。
Python 代码:
from google.oauth2 import service_account
from googleapiclient.discovery import build
import googleapiclient
import json
def main():
SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin', 'https://www.googleapis.com/auth/cloud-platform', 'https://www.googleapis.com/auth/devstorage.full_control']
SERVICE_ACCOUNT_FILE = './creds/service-account-credentials.json'
PROJECT = "[REDACTED]"
DB_INSTANCE = "[REDACTED]"
BUCKET_PATH = "gs://[REDACTED]/[REDACTED].sql"
DATABASES = [REDACTED]
BODY = # Database instance export request.
"exportContext": # Database instance export context. # Contains details about the export operation.
"kind": "sql#exportContext", # This is always sql#exportContext.
"fileType": "SQL", # The file type for the specified uri.
# SQL: The file contains SQL statements.
# CSV: The file contains CSV data.
"uri": BUCKET_PATH, # The path to the file in Google Cloud Storage where the export will be stored. The URI is in the form gs://bucketName/fileName. If the file already exists, the requests succeeds, but the operation fails. If fileType is SQL and the filename ends with .gz, the contents are compressed.
"databases": DATABASES,
,
credentials = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta4', credentials=credentials)
response = sqladmin.instances().export(project=PROJECT, instance=DB_INSTANCE, body=BODY).execute()
print(json.dumps(response, sort_keys=True, indent=4))
运行此代码会产生以下错误:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "[REDACTED]/main.py", line 47, in hello_pubsub
response = sqladmin.instances().export(project=PROJECT, instance=DB_INSTANCE, body=BODY).execute()
File "/usr/local/lib/python3.7/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/googleapiclient/http.py", line 851, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://www.googleapis.com/sql/v1beta4/projects/[REDACTED]/instances/[REDACTED]/export?alt=json returned "The service account does not have the required permissions for the bucket.">
我已在 2 个 GCP 项目中尝试过此操作,其中有多个具有不同权限的服务帐户。
相关问题: Access denied for service account (permission issue?) when importing a csv from cloud storage to cloud sql - 这个问题是由不正确的权限引起的,这里不应该是这种情况,因为该帐户具有项目所有者权限
【问题讨论】:
我终于想通了——谷歌实际上并没有在他们的文档中提到这一点,但每个 SQL 实例都有一个相应的服务帐户。它使用该服务帐户导出数据,因此您必须授予它访问目标容器的权限。 通过控制台(web gui)导出时,服务账号会自动添加到bucket权限中。如果之前不是这样导出的,需要自己添加帐号。 【参考方案1】:Google Cloud 使用identity and access management 系统管理资源:IAM。
每个 Cloud SQL 实例都使用相应的具有权限的服务帐号。要查找您的 Cloud SQL 服务帐号名称,请访问:
控制台 > SQL > 实例名称 > 服务帐户
使用此服务帐户名称,您可以grant access control permission for the bucket,从以下选项中进行选择:Storage Admin、Storage Object Admin、Storage Object Creator、Storage Object Viewer。
遵循最小权限原则,您只需添加:Storage Object Creator,即可导出至云端存储桶。
Detailed storage access roles descriptions are included in the documentation.
【讨论】:
这回答了我。值得那张漂亮的绿色支票。 其实要严格遵循“最小权限原则”,CloudSQL实例导出到GCS bucket只需要Storage Object Creator
(或legacyBucketWriter
)权限,相当于gcloud sql export sql
命令.见cloud.google.com/sql/docs/postgres/import-export/exporting
在授予桶访问服务帐户时我们应该使用哪个PRINCIPAL_TYPE
? (您提供的链接)【参考方案2】:
这些是对我有用的最小权限分配。
请注意,有 两个 相关的服务帐号。第一个是在配置 GCP Cloud SQL 实例时自动创建的服务帐号。此服务帐户的名称类似于p746284857472-d3jdkw@gcp-sa-cloud-sql.iam.gserviceaccount.com
。
第二个服务帐户是您自己创建的;让我们将此服务帐户称为cloud-sql-export
。我们还假设我们的 GCP 项目 ID 是 my_gcp_project_id
。
以下是权限:
创建一个将storage.admin
角色分配给 Cloud SQL 服务帐号的策略,并将此策略分配给您要将数据导出到的存储桶。这是 Terraform 代码:
data "google_iam_policy" "cloud_sql_bucket_admin"
binding
role = "roles/storage.admin"
members = [
"serviceAccount:p746284857472-d3jdkw@gcp-sa-cloud-sql.iam.gserviceaccount.com",
]
resource "google_storage_bucket_iam_policy" "mypolicy"
bucket = "mybucketname"
policy_data = data.google_iam_policy.cloud_sql_bucket_admin.policy_data
对于其他权限,我创建了一个角色并将该角色分配给自定义 cloud-sql-export
服务帐户:
resource "google_project_iam_custom_role" "cloudsql-export-bucket-role"
role_id = "cloudsqlExportBucketRole"
title = "Cloud SQL Export to Bucket Role"
description = "Export from Cloud SQL and write to buckets"
permissions = ["cloudsql.instances.get", "cloudsql.instances.export"]
resource "google_project_iam_member" "cloudsql_archive_role_bind"
project = "my_gcp_project_id"
role = "projects/my_gcp_project_id/roles/cloudsqlExportBucketRole"
member = "serviceAccount:cloud-sql-export@my_gcp_project_id.iam.gserviceaccount.com"
(这是对 Lucy Nunley 对原始问题的评论的扩展。)
【讨论】:
OP 没有说任何关于使用 terraform..?【参考方案3】:有点题外话,但应该提一下:错误信息
(gcloud.sql.import.csv) HTTPError 403:服务帐号没有存储桶所需的权限。
如果文件 *doesnt 存在于存储桶中或您使用了通配符(如 gcloud sql import csv fails with permissions error when import file contains wildcard 中所述),也会发生 因此,也许在花费数小时调试许可之前,首先仔细检查文件是否真的存在(在我的情况下,同时运行了一个清理计划,而我的测试文件被删除了......)。
【讨论】:
以上是关于Google CloudSQLAdmin - 服务帐户没有存储桶所需的权限的主要内容,如果未能解决你的问题,请参考以下文章
Google PlayGoogle Play 服务框架安装 ( 安装 Google Play 服务框架 | 安装 Google Play 服务 | 安装 Google Play 商店 )