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 商店 )

无法验证服务器身份calendar.google

怎样彻底删除google服务

无法登陆与google服务器通信出现问题三星账户

打开游戏的时候提示没有google play 服务怎么办?

手机最近老是出现google play服务出错,怎么处理