从 Google Compute Engine (python) 访问 Google 工作表 API

Accessing Google Sheets API from Google Compute Engine (python)

我正在尝试从 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.">

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

我没试过这个,但看到你的问题没有答案...

使用 Google Apps 服务的一个问题是数据由命名用户帐户(例如 you@company.com)访问,因此您需要使用枚举帐户之一 使 sheet public (这样任何人都可以访问它;你可能不想这样做)。

云和应用程序之间存在差异(是的,我知道 Google 营销中不再存在差异,但是......)并且,虽然云服务现在更喜欢 IAM,但另一个 Google 服务仍然使用作用域(不是 IAM)。因此,修改服务帐户的 IAM 权限无济于事。

你的范围是正确的。

我认为有(至少)2个选项:

  • 将服务帐户添加到 sheet 的权限;
  • 授予服务帐户委托授权 (link);

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

你可以找到这个:

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

gcloud projects get-iam-policy ${PROJECT}

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

201124 更新示例

选择任何 Sheets (sheet) 并从 URL.

中获取其 ID

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

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

创建一个 Google 云平台项目,启用 sheets 并创建一个服务帐户和一个密钥。

NOTE Because Sheets does not use IAM, we don't need to assign any permissions to the Service Account:

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]] 替换为您要使用的 Sheet 的 ID

试试 运行 代码,它将 403:

python3 main.py

${EMAIL} 的值添加到 Sheet 的共享权限

运行再写一遍代码,就成功了:

{'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 实例时,您必须赋予它访问 Sheets:

的范围
# 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