如何验证服务帐户以对 GDrive 表支持的 BigQuery 表进行查询?

Kev*_*cka 3 google-sheets google-spreadsheet-api google-bigquery google-cloud-platform

我的情况如下:

Google 帐户 A 在 BigQuery 中有一些数据。

Google 帐户 B 管理帐户 A 的 BigQuery 数据,并且还获得了帐户 A 的 Cloud Platform 项目的编辑权限。

帐户 B 在 Google Drive 中有一个 Sheet,里面有一些很酷的参考数据。账户 B 登录到 BQ Web 控制台,并在此表支持的账户 A 的 BQ 项目中创建一个表。

一切都很好。账户 B 可以通过 Web UI 在账户 A 的 BQ 数据中成功查询并加入该表。

问题:

Google 帐户 A 也有一个服务帐户,它是 Google 帐户 A 的云平台项目的编辑器。此服务帐户使用 python google-cloud API 管理和查询 BQ 中的数据。当此服务帐户尝试查询由帐户 B 的 GDrive 表支持的引用表时,作业失败并显示以下错误:

Encountered an error while globbing file pattern.  JobID: "testing_gdrivesheet_query_job1"
Run Code Online (Sandbox Code Playgroud)

据我所知,这实际上是一个身份验证问题。我如何为账户 A 的服务账户授予对账户 B 的 GDrive 的适当访问权限,以便它可以访问该参考表?

加分点: 由 GDrive Sheet 支持的表与原生 BQ 表之间是否有任何性能差异?

Juv*_*uve 5

虽然 Orbit 的回答帮助我找到了该问题的解决方案,但您还需要考虑一些其他事项。因此,我喜欢添加我对问题的详细解决方案。如果 Orbit 的基本解决方案不起作用,尤其是当您使用G Suite并且您的政策不允许与域外帐户共享工作表/文档时,则需要此解决方案。在这种情况下,您无法直接与服务帐户共享文档/工作表。

在你开始之前:

  1. 在您的项目中创建或选择服务帐号
  2. 帐户设置中启用域范围委派 ( DwD ) 。如果不存在,则会为服务帐户生成 OAuth 客户端 ID。
  3. 确保被委托人user@company.com有权访问工作表。
  4. 将所需的范围添加到您的服务帐号的 OAuth 客户端(您可能需要让 G Suite 管理员为您执行此操作):

    • https://www.googleapis.com/auth/bigquery
    • https://www.googleapis.com/auth/drive

如果委派用户可以在 BigQuery 界面中访问基于驱动器的表,那么您的服务帐号现在也应该能够代表委派用户访问它。

这是一个对我有用的完整代码片段:

#!/usr/bin/env python

import httplib2
from google.cloud import bigquery
from oauth2client.service_account import ServiceAccountCredentials

scopes = [
    "https://www.googleapis.com/auth/drive",
    "https://www.googleapis.com/auth/bigquery",
]

delegated_user = "user@example.com"
project        = 'project-name'
table          = 'dataset-name.table-name'
query          = 'SELECT count(*) FROM [%s:%s]' % (project, table)

creds = ServiceAccountCredentials.from_json_keyfile_name('secret.json', scopes=scopes)
creds = creds.create_delegated(delegated_user)

http = creds.authorize(httplib2.Http())
client = bigquery.Client(http=http)

bq = client.run_sync_query(query)
bq.run()
print bq.fetch_data()
Run Code Online (Sandbox Code Playgroud)

请注意,我无法直接设置委托,需要使用creds = creds.create_delegated(delegated_user)和创建 HTTP 客户端http = creds.authorize(httplib2.Http())。然后,授权的 HTTP 客户端可以用作 BigQuery 客户端的 HTTP 客户端:client = bigquery.Client(http=http)

另请注意,服务帐户不需要在项目设置中分配任何预定义的角色,即您不必将其设为 bigquery 用户甚至项目所有者。我想它主要通过委托获得访问权限。


小智 4

您应该能够通过以下步骤来实现此目的:

首先共享带有与服务帐户关联的电子邮件/“服务帐户 ID”的工作表。

然后,如果您使用 bigquery 和驱动器范围创建客户端,您将能够访问工作表支持的表。(您可能需要在服务帐户上启用域范围委托)。

scopes = ['https://www.googleapis.com/auth/bigquery', 'https://www.googleapis.com/auth/drive']

credentials = ServiceAccountCredentials.from_json_keyfile_name(
'<path_to_json>', scopes=scopes)

# Instantiates a client
client = bigquery.Client(project = PROJECT, credentials = credentials)

bqQuery = client.run_sync_query(q)
bqQuery.run()
bqQuery.fetch_data()
Run Code Online (Sandbox Code Playgroud)