我的情况如下:
Google帐户A在BigQuery中有一些数据。
Google帐户B管理帐户A的BigQuery数据,并且还获得了帐户A的云平台项目的编辑权限。
帐户B在Google云端硬盘中有一张工作表,其中包含一些很酷的参考数据。帐户B登录到BQ Web控制台,并在此工作表支持的帐户A的BQ项目中创建一个表。
一切都很好。帐户B可以在来自网络用户界面的帐户A的BQ数据中成功查询并加入此表。
问题:
Google帐户A还有一个服务帐户,该帐户是Google帐户A的云平台项目的编辑器。此服务帐户使用python google-cloud API管理和查询BQ中的数据。当此服务帐户尝试查询由帐户B的GDrive工作表支持的参考表时,作业将失败并显示以下错误:
Scanner scanner = new Scanner(System.in);
System.out.print("Team name: ");
String teamName = scanner.nextLine();
System.out.print("Player 1: ");
String player1 = scanner.nextLine();
System.out.print("Player 2: ");
String player2 = scanner.nextLine();
System.out.print("Player 3: ");
String player3 = scanner.nextLine();
System.out.print("Player 4: ");
String player4 = scanner.nextLine();
Team team = new Team(teamName, player1, player2, player3, player4, comp1, comp2);
我可以说,这实际上是一个身份验证问题。如何为帐户A的服务帐户提供对帐户B的GDrive的适当访问权限,以便它可以访问该参考表?
奖励积分: GDrive工作表支持的表与本机BQ表之间是否存在性能差异?
答案 0 :(得分:3)
虽然Orbit的回答帮助我找到了解决问题的方法,但还有一些事情你需要考虑。因此,我想为问题添加详细的解决方案。如果Orbit的基本解决方案不起作用,则需要此解决方案,特别是如果您使用G Suite并且您的政策不允许使用域外的帐户共享工作表/文档。在这种情况下,您无法直接与服务帐户共享文档/表格。
开始之前:
user@company.com
有权访问该表。将所需的范围添加到您的服务帐户的OAuth客户端(您可能需要让G Suite管理员为您执行此操作):
https://www.googleapis.com/auth/bigquery
https://www.googleapis.com/auth/drive
如果委派的用户可以在BigQuery UI中访问基于驱动器的表,那么您的服务帐户现在也应该能够代表委派的用户访问它。
这是一个适合我的完整代码段:
#!/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()
请注意,我无法直接设置委派,需要使用creds = creds.create_delegated(delegated_user)
和http = creds.authorize(httplib2.Http())
创建HTTP客户端。然后,授权的HTTP客户端可以用作BigQuery客户端的HTTP客户端:client = bigquery.Client(http=http)
。
另请注意,服务帐户不需要在项目设置中分配任何预定义角色,即,您不必将其设置为bigquery用户甚至是项目所有者。我想它主要通过委托来获取访问权。
答案 1 :(得分:2)
对于那些尝试通过Airflow或Google Cloud Composer做到这一点的人,您需要完成两个主要步骤。
将对电子表格的视图访问权限授予project_name@developer.gserviceaccount.com
。该帐户应该与您用来访问Google BigQuery的服务帐户相同。可以在Sheets GUI中或以编程方式完成。
然后,您将能够查询引用Google表格的外部表。
答案 2 :(得分:1)
您应该能够通过以下步骤实现此目的:
首先使用与服务帐户关联的电子邮件/“服务帐户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()
答案 3 :(得分:0)
只需从 Evan Kaeding 答案中添加步骤即可。您可以在Airflow UI菜单“管理员”->“连接”->选择连接中找到气流连接。就我而言,我还需要在气流连接中添加服务帐户的密钥文件路径或密钥文件JSON