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

时间:2016-11-02 22:51:26

标签: google-sheets google-bigquery google-cloud-platform google-spreadsheet-api

我的情况如下:

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表之间是否存在性能差异?

4 个答案:

答案 0 :(得分:3)

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

开始之前:

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

    • https://www.googleapis.com/auth/bigquery
    • https://www.googleapis.com/auth/drive
  5. 如果委派的用户可以在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做到这一点的人,您需要完成两个主要步骤。

  1. 将对电子表格的视图访问权限授予project_name@developer.gserviceaccount.com。该帐户应该与您用来访问Google BigQuery的服务帐户相同。可以在Sheets GUI中或以编程方式完成。

  2. 将以下范围添加到Airflow中的Google Cloud Connection: airflow scope

然后,您将能够查询引用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

add json keyfile

基于此引用https://cloud.google.com/composer/docs/how-to/managing/connections#creating_a_connection_to_another_project