如何使用 Python 以编程方式获取 GCP Bearer 令牌

2025-03-24 09:14:00
admin
原创
14
摘要:问题描述:gcloud auth print-access-token给了我一个 Bearer 令牌,我稍后可以使用;但是,这是一个 shell 命令。我如何通过 Google Cloud Python API 以编程方式获取一个? 我看到了之前使用oauth2client的示例,但oauth2client现...

问题描述:

gcloud auth print-access-token给了我一个 Bearer 令牌,我稍后可以使用;但是,这是一个 shell 命令。我如何通过 Google Cloud Python API 以编程方式获取一个?

我看到了之前使用oauth2client的示例,但oauth2client现在已弃用。如何使用google.auth和oauthlib来实现这一点?


解决方案 1:

虽然标记为正确的答案(截至 2023-09-10)非常有帮助,但它忽略了一个重要点 - 从google.auth.default()或获取的凭据对象compute_engine.Credentials()将不包含令牌。所以回到最初的问题,即 的编程替代方案是什么gcloud auth print-access-token,我的答案是:

import google.auth
import google.auth.transport.requests
creds, project = google.auth.default()

# creds.valid is False, and creds.token is None
# Need to refresh credentials to populate those

auth_req = google.auth.transport.requests.Request()
creds.refresh(auth_req)

# Now you can use creds.token

我正在使用官方的 google-auth 包和默认凭据,这将帮助您在本地开发和远程 GCE/GKE 应用中运行。

遗憾的是,这没有正确的记录,我不得不阅读 google-auth代码来弄清楚如何获取令牌。

解决方案 2:

答案取决于您的环境以及您想要如何创建/获取凭证。

什么是 Google Cloud Credentials?

Google Cloud 凭据是 OAuth 2.0 令牌。此令牌至少包含一个Access Token,可选包含一个Refresh Token、,Client ID Token以及支持参数,例如expirationService Account EmailClient Email等。

Google Cloud API 中最重要的项目是Access Token。此令牌用于授权访问云。此令牌可用于 等程序curl、 等软件python,并且不需要 SDK。Access Token用于 HTTPAuthorization标头中。

什么是访问令牌?

访问令牌是 Google 生成的不透明值,源自签名的 JWT(更准确地说是 JWS)。JWT 由标头和声明(有效负载)Json 结构组成。这两个 Json 结构使用服务帐户的私钥进行签名。这些值经过 base64 编码并连接起来以创建访问密钥。

访问令牌的格式为:base64(header) + '.' + base64(payload) + '.' + base64(signature)

以下是 JWT 的示例:

标头:

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "42ba1e234ac91ffca687a5b5b3d0ca2d7ce0fc0a"
}

有效载荷:

{
  "iss": "myservice@myproject.iam.gserviceaccount.com",
  "iat": 1493833746,
  "aud": "myservice.appspot.com",
  "exp": 1493837346,
  "sub": "myservice@myproject.iam.gserviceaccount.com"
}

使用访问令牌:

启动虚拟机实例的示例。替换 PROJECT_ID、ZONE 和 INSTANCE_NAME。此示例适用于 Windows。

curl -v -X GET -H "Authorization: Bearer <access_token_here>" ^
https://www.googleapis.com/compute/v1/projects/%PROJECT_ID%/zones/%ZONE%/instances/%INSTANCE_NAME%/start

Compute Engine 服务帐号:

对于这个案例来说,达斯汀的回答是正确的,但是为了完整性,我将添加一些额外的信息。

这些凭据由 GCP 自动为您创建,并从 VM 实例元数据中获取。权限由Cloud API access scopesGoogle 控制台控制。

但是,这些凭据有一些限制。要修改凭据,您必须先停止 VM 实例。此外,并非所有权限(角色)都受支持。

from google.auth import compute_engine

cred = compute_engine.Credentials()

服务帐户凭证:

在您了解所有类型的凭据及其用例之前,这些是您将用于除gcloud和 之外的所有操作的凭据gsutil。了解这些凭据将使编写程序时使用 Google Cloud 变得更加简单。从 Google 服务帐户 Json 文件获取凭据很容易。唯一需要注意的是,凭据会过期(通常为 60 分钟),需要刷新或重新创建。

gcloud auth print-access-token不推荐。服务帐户凭据是 Google 推荐的方法。

这些凭证由控制台、gcloud 或通过程序/API 创建。权限由 IAM 分配给凭证,并在 Compute Engine、App Engine、Firestore、Kubernetes 等以及 Google Cloud 之外的其他环境中运行。这些凭证从 Google Cloud 下载并存储在 Json 文件中。注意scopes参数。这定义了授予结果凭证对象的权限。

SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin']
SERVICE_ACCOUNT_FILE = 'service-account-credentials.json'

from google.oauth2 import service_account

cred = service_account.Credentials.from_service_account_file(
            SERVICE_ACCOUNT_FILE, scopes=SCOPES)

Google OAuth 2.0 凭证:

这些凭据源自完整的 OAuth 2.0 流程。这些凭据是在启动浏览器访问 Google 帐户以授权访问时生成的。此过程要复杂得多,需要大量代码来实现,并且需要内置 Web 服务器来回调授权。

此方法提供了额外的功能,例如能够在浏览器中运行所有内容,例如您可以创建云存储文件浏览器,但请注意您了解安全隐患。此方法是用于支持 Google 登录等的技术。我喜欢使用此方法在允许在网站上发布之前对用户进行身份验证等。正确授权的 OAuth 2.0 身份和范围的可能性是无穷无尽的。

示例代码使用google_auth_oauthlib

from google_auth_oauthlib.flow import InstalledAppFlow

flow = InstalledAppFlow.from_client_secrets_file(
    'client_secrets.json',
    scopes=scope)

cred = flow.run_local_server(
    host='localhost',
    port=8088,
    authorization_prompt_message='Please visit this URL: {url}',
    success_message='The auth flow is complete; you may close this window.',
    open_browser=True)

使用该库的示例代码requests_oauthlib

from requests_oauthlib import OAuth2Session

gcp = OAuth2Session(
        app.config['gcp_client_id'],
        scope=scope,
        redirect_uri=redirect_uri)

# print('Requesting authorization url:', authorization_base_url)

authorization_url, state = gcp.authorization_url(
                        authorization_base_url,
                        access_type="offline",
                        prompt="consent",
                        include_granted_scopes='true')

session['oauth_state'] = state

return redirect(authorization_url)


# Next section of code after the browser approves the request

token = gcp.fetch_token(
            token_url,
            client_secret=app.config['gcp_client_secret'],
            authorization_response=request.url)

解决方案 3:

在某些情况下,无法在服务器或容器上设置环境变量,同时需要 Bearer 访问令牌来调用 Google 云 API。我提出以下方法来解决此类问题:

# pip3 install google-auth
# pip3 install requests

import google.auth
import google.auth.transport.requests
from google.oauth2 import service_account

credentials = service_account.Credentials.from_service_account_file('/home/user/secrets/hil-test.json', scopes=['https://www.googleapis.com/auth/cloud-platform'])
auth_req = google.auth.transport.requests.Request()
credentials.refresh(auth_req)
credentials.token

最后一行将打印用于调用 Google 云 API 的访问令牌。ya29<REDACTED>将以下 curl 命令替换为来自 python 的打印令牌以进行测试:

curl https://example.googleapis.com/v1alpha1/projects/PROJECT_ID/locations -H "Authorization: Bearer ya29<REDACTED>"

执行 python 获取令牌,然后在 BASH 中使用 curl 调用 API 可能毫无意义。目的是演示如何获取令牌来调用 Google Cloud Alpha API,该 API 可能没有任何 Python 客户端库,但有 REST API。然后开发人员可以使用Python 请求HTTP 库来调用 API。

解决方案 4:

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


# getting the credentials and project details for gcp project
credentials, your_project_id = google.auth.default(scopes=["https://www.googleapis.com/auth/cloud-platform"])

#getting request object
auth_req = google.auth.transport.requests.Request()

print(credentials.valid) # prints False
credentials.refresh(auth_req) #refresh token
#cehck for valid credentials
print(credentials.valid)  # prints True
print(credentials.token) # prints token

解决方案 5:

官方文档代码示例

我遵循了 Cloud Functions 的官方文档,它适用于任何 GCP API:

auth_req = google.auth.transport.requests.Request()
id_token = google.oauth2.id_token.fetch_id_token(
    auth_req,
     # This is an OAuth authorisation scope that you must pass
     # depending on the API.
     # You can see an example of the need for this scope here: https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/insert#authorization-scopes
    "https://www.googleapis.com/auth/bigquery"
)

现在,您可以在标题id_token中使用Authorisation

headers = {'Authorization': f'Bearer {id_token}'}

解决方案 6:

这可能不是推荐的方式,但对于我的应用程序中的 Rest API 来说,这是一种获取令牌的简单方法。

from subprocess import PIPE, Popen


def cmdline(command):
    process = Popen(
        args=command,
        stdout=PIPE,
        shell=True
    )
    return process.communicate()[0]


token = cmdline("gcloud auth application-default print-access-token")
print("Token:"+token)

解决方案 7:

当我寻找一种无需创建服务帐户即可使用 Python SDK 的方法时,我找到了一种方法。我想要一种在本地开发可在云中运行的脚本的方法。我能够通过使用 gcloud 命令的工件来实现这一点:

export GOOGLE_APPLICATION_CREDENTIALS=~/.config/gcloud/legacy_credentials/<me>/adc.json

解决方案 8:

结合这篇文章和 Google Cloud 文档中的建议,我编写了一个返回令牌的辅助函数。如果可能,它会生成一个令牌;如果不可能,它会从环境中获取令牌,然后检查令牌是否有效。

import google
import os
import requests

GOOGLE_APPLICATION_CREDENTIALS = "GOOGLE_APPLICATION_CREDENTIALS"
GCS_OAUTH_TOKEN = "GCS_OAUTH_TOKEN"
SCOPE = "https://www.googleapis.com/auth/cloud-platform"
URL = "https://www.googleapis.com/oauth2/v1/tokeninfo"
PAYLOAD = "access_token={}"
HEADERS = {"content-type": "application/x-www-form-urlencoded"}
OK = "OK"


def get_gcs_token():
    """
    Returns gcs access token.
    Ideally, this function generates a new token, requries that GOOGLE_APPLICATION_CREDENTIALS be set in the environment
    (os.environ).
    Alternatively, environment variable GCS_OAUTH_TOKEN could be set if a token already exists
    """
    if GOOGLE_APPLICATION_CREDENTIALS in os.environ:
        # getting the credentials and project details for gcp project
        credentials, your_project_id = google.auth.default(scopes=[SCOPE])

        # getting request object
        auth_req = google.auth.transport.requests.Request()
        credentials.refresh(auth_req)  # refresh token
        token = credentials.token
    elif GCS_OAUTH_TOKEN in os.environ:
        token = os.environ[GCS_OAUTH_TOKEN]
    else:
        raise ValueError(
            f"""Could not generate gcs token because {GOOGLE_APPLICATION_CREDENTIALS} is not set in the environment.
Alternatively, environment variable {GCS_OAUTH_TOKEN} could be set if a token already exists, but it was not"""
        )

    r = requests.post(URL, data=PAYLOAD.format(token), headers=HEADERS)
    if not r.reason == OK:
        raise ValueError(
            f"Could not verify token {token}

Response from server:
{r.text}"
        )
    if not r.json()["expires_in"] > 0:
        raise ValueError(f"token {token} expired")
    return token
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1857  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1423  
  PLM(产品生命周期管理)项目管理软件旨在管理产品从概念到退役的整个生命周期,整合流程、数据和人员,提升企业效率与创新能力。对企业而言,投资PLM项目管理软件是重大决策,衡量其投资回报率(ROI)至关重要,能助企业判断投资是否值得,为后续决策提供依据。明确PLM项目管理软件的成本构成在衡量投资回报率之前,必须清晰了解P...
plm办公软件   8  
  在项目管理领域,PLM(产品生命周期管理)系统的应用日益广泛。它贯穿产品从概念设计到退役的整个生命周期,对企业的产品创新、成本控制和市场竞争力提升起着关键作用。然而,在项目推进过程中,需求变更难以避免。有效的需求变更管理至关重要,它关乎项目能否按时、按质量交付,以及成本是否可控。本文将深入探讨PLM系统需求变更管理的5...
plm系统功能介绍   10  
  医疗器械唯一标识(UDI)追溯体系的建立,是医疗器械行业合规管理的关键举措。它不仅有助于提升医疗器械全生命周期的管理效率,保障患者安全,还能满足监管部门对医疗器械质量和安全追溯的严格要求。产品生命周期管理(PLM)系统作为一种集成化的管理平台,能够为医疗器械UDI追溯提供强大的支撑。通过其核心模块的协同运作,可实现医疗...
国内plm系统排名   10  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用