【问题标题】:Accessing Google Sheets API from Google Compute Engine (python)从 Google Compute Engine (python) 访问 Google Sheets API
【发布时间】:2020-11-20 22:18:06
【问题描述】:

我正在尝试从 Compute Engine 实例中执行以下操作:

from googleapiclient.discovery import build

service = build('sheets', 'v4')
sheet = service.spreadsheets()
result = sheet.values().get(spreadsheetId=SPREADSHEET_ID, range=RANGE_NAME).execute()

根据这篇文章https://cloud.google.com/docs/authentication/production 以及 Cloud Console 中的这个页面

如果我在计算引擎中运行应用程序,我不需要显式传递 API 密钥。然而,我收到以下错误:

  googleapiclient.errors.HttpError: <HttpError 403 when requesting 
  https://sheets.googleapis.com/v4/spreadsheets/[...]?alt=json
  returned "Request had insufficient authentication scopes.".
  Details: "Request had insufficient authentication scopes.">

我错过了什么?我是否需要向我的实例服务帐户授予对 Sheets API 的访问权限?如果是这样,我该怎么做?我在云控制台中找不到任何有意义的东西。在Google Example 中,他们在创建凭据时明确传递范围SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly'],但我不知道如何在此处传递它们。

【问题讨论】:

    标签: python api google-sheets google-sheets-api gcloud


    【解决方案1】:

    我没有尝试过,但看到您的问题没有得到解答...

    使用 Google Apps 服务的一个问题是数据由指定的用户帐户(例如 you@company.com)访问,因此您需要使用其中一个枚举帐户制作表格public(这样任何东西都可以访问它;你可能不想这样做)。

    Cloud 和 Apps 之间存在分歧(是的,我知道 Google 营销中不再存在差异,但是......)而且,虽然云服务现在更喜欢 IAM,但其他​​ Google 服务仍然使用范围(不是 IAM) .因此,修改服务帐号的 IAM 权限将无济于事。

    你的范围是正确的。

    我认为(至少)有两种选择:

    • 将服务帐号添加到工作表的权限中;
    • 授予服务帐户委派身份验证 (link);

    所有服务帐户都有一个电子邮件地址....您应该(!?)能够将您的服务帐户的电子邮件地址添加到工作表中。

    你可以找到这个:

    gcloud iam service-accounts list --project=${PROJECT}

    gcloud projects get-iam-policy ${PROJECT}

    然后使用工作表的共享选项将电子邮件地址添加到工作表。

    201124 更新示例

    选择任何 Sheets(工作表)并从 URL 中获取其 ID。

    确认您能够在此处使用专门针对 Sheets v4 API GET 方法的(优秀的)APIs Explorer 访问它(使用您的用户凭据):

    https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/get

    创建一个 Google Cloud Platform 项目,启用工作表并创建一个服务帐户和一个密钥。

    注意因为表格不使用 IAM,我们不需要为服务帐户分配任何权限:

    PROJECT=[[YOUR-PROJECT-ID]]
    BILLING=$(gcloud alpha billing accounts list --format="value(name)")
    
    gcloud projects create ${PROJECT}
    gcloud beta billing projects link ${PROJECT} --billing-account=${BILLING}
    
    # Enable Sheets API
    gcloud services enable sheets.googleapis.com --project=${PROJECT}
    
    # Create Service Account & Key
    ROBOT="sheeter"
    
    gcloud iam service-accounts create ${ROBOT} \
    --project=${PROJECT}
    
    EMAIL=${ROBOT}@${PROJECT}.iam.gserviceaccount.com
    
    gcloud iam service-accounts keys create  ./${ROBOT}.json \
    --iam-account=${EMAIL} \
    --project=${PROJECT}
    
    # Use Application Default Credentials
    export GOOGLE_APPLICATION_CREDENTIALS=./${ROBOT}.json
    
    # Create Python virtualenv and add Google APIs SDK
    python3 -m venv venv
    source venv/bin/activate
    python3 -m pip install --upgrade google-api-python-client
    mkdir python
    cd python
    touch main.py
    

    使用以下来自 Google 的 example 的示例

    import google.auth
    
    from pprint import pprint
    
    from googleapiclient import discovery
    
    credentials, project = google.auth.default()
    
    service = discovery.build("sheets", "v4", credentials=credentials)
    
    spreadsheet_id = "[[SPREADSHEET_ID]]"
    
    ranges = []
    include_grid_data = False
    
    request = service.spreadsheets().get(spreadsheetId=spreadsheet_id,
                                         ranges=ranges,
                                         includeGridData=include_grid_data)
    response = request.execute()
    
    pprint(response)
    

    [[SPREADSHEET_ID]] 替换为您要使用的工作表的 ID

    尝试运行代码,它会403:

    python3 main.py
    

    ${EMAIL} 的值添加到工作表的共享权限

    再次运行代码,就成功了:

    {'properties': {'autoRecalc': 'ON_CHANGE',
                    'defaultFormat': {'backgroundColor': {'blue': 1,
                                                          'green': 1,
                                                          'red': 1},
                                      'backgroundColorStyle': {...
                 'properties': {'index': 1,
                                'sheetId': [[REDACTED]],
                                'sheetType': 'OBJECT',
                                'title': 'Chart'}}],
     'spreadsheetId': '[[SPREADSHEET_ID]]',
     'spreadsheetUrl': 'https://docs.google.com/spreadsheets/d/[[SPREADSHEET_ID]]/edit'}
    

    201124 使用 Compute Engine 更新

    创建 Compute Engine 实例时,您必须为其提供访问表格的范围:

    # Default Scopes
    SCOPES="https://www.googleapis.com/auth/devstorage.read_only,\
    https://www.googleapis.com/auth/logging.write,\
    https://www.googleapis.com/auth/monitoring.write,\
    https://www.googleapis.com/auth/servicecontrol,\
    https://www.googleapis.com/auth/service.management.readonly,\
    https://www.googleapis.com/auth/trace.append"
    
    # Add Sheets
    SCOPES="${SCOPES},https://www.googleapis.com/auth/spreadsheets.readonly"
    
    gcloud beta compute instances create sheeter \
    --project=${PROJECT} \
    --zone=${ZONE} \
    --machine-type=f1-micro \
    --image-family=debian-10 \
    --image-project=debian-cloud \
    --scopes=${SCOPES}
    

    您也可以在您选择的服务帐户下运行实例,例如:

    gcloud beta compute instances create sheeter \
    --project=${PROJECT} \
    --zone=${ZONE} \
    --machine-type=f1-micro \
    --image-family=debian-10 \
    --image-project=debian-cloud \
    --scopes=${SCOPES} \
    --service-account=${EMAIL}
    

    创建实例后,重复安装步骤。无需在实例上安装密钥,也无需在 GOOGLE_APPLICATION_CREDENTIALS 上安装,因为它们都是由 Compute Engine 提供的。

    检查实例运行的服务帐号:

    curl \
    --header "Metadata-Flavor: Google" \
    http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/
    

    应该让步,例如:

    ${PROJECT-NUM}-compute@developer.gserviceaccount.com/
    default/
    

    这是您的代码将在其下运行的服务帐户(在本例中为 Compute Engine 的默认帐户)。现在,运行代码。

    python3 main.py
    

    【讨论】:

    • 令人困惑的是,有权访问工作表的帐户与有权访问 API 的帐户之间的区别。我想要做的是避免明确指定可以访问 API 的帐户,因为我的程序已经在 Compute Engine 机器上作为该帐户运行。换句话说,我已经将服务帐户添加到工作表中,或者您可以假设工作表是公开的。
    • 对,但是,使用第一种方法,您无法避免将(计算引擎)服务帐户添加到工作表中,因为工作表只批准列出的帐户(或域范围内的委派)。您可以做的是为 Compute Engine 实例创建一个不同的服务帐户并添加它。代码仍将其作为默认值,但您可以将特定帐户添加到工作表(而不是项目的更广泛的 Compute Engine 帐户)。
    • 推论:您的代码以透明方式获取应用默认凭据(例如 Compute Engine 默认服务帐户)并将该帐户的身份提供给表格。 Sheets 会查看其授权列表,并需要查看列出的身份。有道理?我想我应该自己试试这个;-)
    • “您的代码透明地获取应用程序默认凭据”
    • 好的,我有一个工作样本给你...我会更新我的答案
    猜你喜欢
    • 2015-11-05
    • 2017-06-03
    • 1970-01-01
    • 1970-01-01
    • 2019-01-23
    • 1970-01-01
    • 2014-05-18
    • 2015-11-15
    • 1970-01-01
    相关资源
    最近更新 更多