授权来自Cloud Function的Cloud SQL Admin API调用

问题描述

我正在尝试构建小功能(以后将其部署到云功能)以将BAK文件还原到云sql。此功能将由cron触发。 在阅读有关授权此API的文档时,我有点迷失:https://cloud.google.com/sql/docs/sqlserver/import-export/importing#importing_data_from_a_bak_file_in

已经创建了具有以下角色的服务帐户:Cloud sql Admin,Storage Admin,Storage Object Admin,Storage Object Viewer,并在创建Cloud Function时从下拉菜单中选择了该服务帐户,但不起作用。

在阅读以下内容后,还尝试生成API密钥:https://cloud.google.com/sql/docs/sqlserver/admin-api/how-tos/authorizing

所以我的POST网址变成这样:

https://www.googleapis.com/sql/v1beta4/projects/project-id/instances/instance-id/import?key=generatedAPIKey

但仍然出现错误

  "error": {
    "code": 401,"message": "Request is missing required authentication credential. Expected OAuth 2 access token,login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.","errors": [
      {
        "message": "Login required.","domain": "global","reason": "required","location": "Authorization","locationType": "header"
      }
    ],"status": "UNAUTHENTICATED"
  }
}

我需要为此使用Oauth 2吗?这是我在Cloud Function中的代码

import http.client
import mimetypes

def restore_bak(request):
    conn = http.client.HTTPSConnection("www.googleapis.com")
    payload = "{\r\n \"importContext\":\r\n   {\r\n      \"fileType\": \"BAK\",\r\n      \"uri\": \"gs://{bucket_name}/{backup_name}.bak\",\r\n      \"database\": \"{database_name}\"\r\n    }\r\n}\r\n"
    headers = {
      'Content-Type': 'application/json'
    }
    conn.request("POST","/sql/v1beta4/projects/{project_id}/instances/{instance_name}/import",payload,headers)
    res = conn.getresponse()
    data = res.read()
    print(data.decode("utf-8"))
    return(data.decode("utf-8"))

解决方法

这看起来像python,所以我建议使用Discovery Client Library for Python。该库为SQL Admin API提供了方便的包装器:

# Construct the service object for the interacting with the Cloud SQL Admin API.
service = discovery.build('sqladmin','v1beta4',http=http)

req = service.instances().list(project="PROJECT_ID")
resp = req.execute()
print json.dumps(resp,indent=2)

默认情况下,该库使用“ Application Default Credentials (ADC)”策略从环境中获取凭据。

您还可以通过创建oauth2令牌并将其设置为请求中的标头来手动验证请求(例如,如果要使用asyncio)。最简单的方法是使用google-auth程序包获取ADC并将其设置为标头:

import google.auth
import google.auth.transport.requests

credentials,project_id = google.auth.default()
credentials.refresh(google.auth.transport.requests.Request())
headers = {
    "Authorization": "Bearer {}".format(credentials.token),"Content-Type": "application/json"
}