【问题标题】:Creating VMs from Instance Template on Cloud Function via API call通过 API 调用从 Cloud Function 上的实例模板创建 VM
【发布时间】:2019-12-02 19:44:49
【问题描述】:

我编写的代码似乎是我需要的,但是它不起作用并且我收到 401 错误(身份验证)我已经尝试了所有方法:1. 服务帐户权限 2. 创建密钥 id 和密钥(不知道如何使用这些来获取访问令牌) 3. 基本上,过去 2 天都尝试了所有方法。

import requests
from google.oauth2 import service_account


METADATA_URL = 'http://metadata.google.internal/computeMetadata/v1/'
METADATA_HEADERS = {'Metadata-Flavor': 'Google'}
SERVICE_ACCOUNT = [NAME-OF-SERVICE-ACCOUNT-USED-WITH-CLOUD-FUNCTION-WHICH-HAS-COMPUTE-ADMIN-PRIVILEGES]


def get_access_token():
    url = '{}instance/service-accounts/{}/token'.format(
        METADATA_URL, SERVICE_ACCOUNT)

    # Request an access token from the metadata server.
    r = requests.get(url, headers=METADATA_HEADERS)
    r.raise_for_status()

    # Extract the access token from the response.
    access_token = r.json()['access_token']

    return access_token

def start_vms(request):
    request_json = request.get_json(silent=True)
    request_args = request.args

    if request_json and 'number_of_instances_to_create' in request_json:
            number_of_instances_to_create = request_json['number_of_instances_to_create']
    elif request_args and 'number_of_instances_to_create' in request_args:
        number_of_instances_to_create = request_args['number_of_instances_to_create']
    else:
        number_of_instances_to_create = 0
    access_token = get_access_token()
    address = "https://www.googleapis.com/compute/v1/projects/[MY-PROJECT]/zones/europe-west2-b/instances?sourceInstanceTemplate=https://www.googleapis.com/compute/v1/projects/[MY-PROJECT]/global/instanceTemplates/[MY-INSTANCE-TEMPLATE]"
    headers = {'token': '{}'.format(access_token)}
    for i in range(1,number_of_instances_to_create):
        data = {'name': 'my-instance-{}'.format(i)}
        r = requests.post(address, data=data, headers=headers)
        r.raise_for_status()
        print("my-instance-{} created".format(i))

有什么建议/指导吗?如果有人能告诉我如何使用秘密 ID 和密钥获取访问令牌。另外,我不太确定 OAuth2.0 是否会起作用,因为我本质上是想打开这些机器,它们会进行一些处理然后自毁。因此,无需用户参与即可允许访问。如果 OAuth2.0 是错误的方法,我还能使用什么?

我尝试使用 gcloud,但不推荐子处理 gcloud 命令。

【问题讨论】:

    标签: python google-cloud-platform oauth-2.0 google-cloud-functions google-compute-engine


    【解决方案1】:

    我做了类似的事情,虽然我使用了 Node 10 Firebase Functions 运行时,但应该非常相似。

    我同意 OAuth 不是正确的解决方案,因为不涉及任何用户。

    您需要使用的是“应用程序默认凭据”,它基于云功能的默认服务帐户可用的权限,该帐户将在此处标记为“App Engine 默认服务帐户”:
    @987654321 @

    (对于我的项目,该服务帐户已经拥有启动和停止 GCE 实例所需的权限,但对于其他 API,我已手动授予它权限。)

    ADC 用于服务器到服务器的 API 调用。为了使用它,我只使用范围调用了 google.auth.getClient(属于 Google APIs Auth Library),即。 “https://www.googleapis.com/auth/cloud-platform”。

    这个 API 非常通用,因为它可以返回您需要的任何凭据,所以当我在云函数上运行时,它会返回一个“计算”对象,而当我在模拟器中运行时,它会给我一个“UserRefreshClient”对象。

    然后,我在对 compute.instances.insert() 和 compute.instances.stop() 的调用中包含该身份验证对象。

    这里是我用来测试我的代码的模板...

    {
      name: 'base',
      description: 'Temporary instance used for testing.',
      tags: { items: [ 'test' ] },
      machineType: `zones/${zone}/machineTypes/n1-standard-1`,
      disks: [
        {
          autoDelete: true, // you will want this!
          boot: true,
          type: 'PERSISTENT',
          initializeParams: {
            diskSizeGb: '10',
            sourceImage: "projects/ubuntu-os-cloud/global/images/ubuntu-minimal-1804-bionic-v20190628",
          }
        }
      ],
      networkInterfaces: [
        {
        network: `https://www.googleapis.com/compute/v1/projects/${projectId}/global/networks/default`,
        accessConfigs: [
            {
            name: 'External NAT',
            type: 'ONE_TO_ONE_NAT'
            }
          ]
        }
      ],
    }
    

    希望对您有所帮助。

    【讨论】:

    • 这让我有了一些思考。但是从启动实例的角度来看,目前有三种方式: 1. GUI 2. GCloud 3. API GUI 已经出局,因为它是一台机器+没有用户。 API 似乎已经过时了,因为它需要 OAuth2.0(再次没有用户进行身份验证)所以我只能使用 gcloud。 subprocess.call("gcloud compute create...", shell=True) 是最明智的方法还是您认为有更好的方法?
    • 基本使用CloudFunction,如何将代码指向服务账户? credentials = service_account.Credentials.from_service_account_info(service_account_info) 通常是 credentials = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
    • @daudnadeem 您写道,API 已经过时,因为它需要 OAuth,但不,我是说 API 使用 ADC 身份验证工作正常,而 ADC 身份验证比 OAuth 启动要简单得多。 (另外,我认为这是问题,所以我试图回答这个问题。)您不必将代码指向服务帐户 - 它会自动使用 Functions 的默认服务帐户 - 它真的很简单我在上面描述过。只要您在 GCP 上运行,这似乎是一个非常好的方法。
    • 您的回答包含的提示足以让我完成工作。干得好,先生。
    【解决方案2】:

    如果您收到 401 错误,则表示您使用的访问令牌已过期或无效。

    本指南将向您展示如何请求 OAuth 2.0 访问令牌并使用服务帐户进行 API 调用:https://developers.google.com/identity/protocols/OAuth2ServiceAccount

    提到的 .json 文件是您在服务帐户下的 IAM & Admin 中创建的私钥。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-05
      • 1970-01-01
      • 1970-01-01
      • 2017-05-23
      • 1970-01-01
      • 2021-09-26
      • 2021-01-15
      相关资源
      最近更新 更多