【问题标题】:Authorize Cloud SQL Admin API call from Cloud Function授权来自 Cloud Function 的 Cloud SQL Admin API 调用
【发布时间】:2020-12-13 05:53:08
【问题描述】:

我正在尝试构建小功能(后来部署到云功能)以将 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"))

【问题讨论】:

    标签: google-cloud-platform google-cloud-functions google-cloud-storage google-cloud-sql


    【解决方案1】:

    这看起来像 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"
    }
    

    【讨论】:

    • 我尝试使用 google-auth 包手动验证我的请求,并在 requirements.txt 上列出了 google-auth==1.20.1 但仍然没有运气并得到相同的错误。有什么我想念的吗?
    • 如果您设置了“授权”标头,您应该会收到不同的错误(或成功)。我会检查您的代码是否正确设置了标头,或者使用 Python 发现客户端来为您处理所有这些。
    • 不好意思问多了,我比较新,需要在google.auth.default()之前改project/project_id吗?以下是我设置从您那里复制的标头的方法:credentials, project = google.auth.default() headers = { 'Authorization': 'Bearer {}'.format(credentials.token), 'Content-Type': 'application/json' } print (headers) 当我在本地运行并安装了 gcloud sdk 时,它返回承载无,也许这就是我仍然未经身份验证的原因:{'Authorization': 'Bearer None', 'Content-Type': 'application/json'} 部署到云功能时的相同输出
    • @Chairul,在作为 App Engine 和 Cloud 功能的无服务服务中,无法访问或安装 Gcloud SDK,在云功能上使用 SQL 管理 API 的最佳方法是使用 Discovery client library 这个方法将使用与您功能关联的服务帐户
    • @Chairul - 我更新了我的示例以包含刷新令牌所需的缺失步骤。您可以在此处找到有关该库如何工作的更多说明:google-auth.readthedocs.io/en/latest/…
    猜你喜欢
    • 2022-09-28
    • 2021-04-26
    • 1970-01-01
    • 2021-03-18
    • 2018-12-28
    • 2020-11-13
    • 1970-01-01
    • 2018-08-13
    • 1970-01-01
    相关资源
    最近更新 更多