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

ind*_*iel 10 python google-cloud-platform google-iam

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

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

Joh*_*ley 14

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

什么是Google Cloud凭据?

Google Cloud凭证是OAuth 2.0令牌。此令牌具有在最小Access Token和任选的Refresh Token,Client ID Token和支持等参数expiration,Service Account Email或Client Email等等。

Google Cloud API中的重要项目是Access Token。该令牌授权访问云。该令牌可用于程序(例如curl,软件(例如python)等)中,并且不需要SDK。的Access Token是在HTTP中使用Authorization报头。

什么是访问令牌?

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

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

这是一个JWT示例:

标头:

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "42ba1e234ac91ffca687a5b5b3d0ca2d7ce0fc0a"
}
Run Code Online (Sandbox Code Playgroud)

有效负载:

{
  "iss": "myservice@myproject.iam.gserviceaccount.com",
  "iat": 1493833746,
  "aud": "myservice.appspot.com",
  "exp": 1493837346,
  "sub": "myservice@myproject.iam.gserviceaccount.com"
}
Run Code Online (Sandbox Code Playgroud)

使用访问令牌:

启动虚拟机实例的示例。替换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
Run Code Online (Sandbox Code Playgroud)

Compute Engine服务帐户:

在这种情况下,达斯汀的答案是正确的,但是为了完整起见,我将提供一些其他信息。

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

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

from google.auth import compute_engine

cred = compute_engine.Credentials()
Run Code Online (Sandbox Code Playgroud)

服务帐户凭据:

在您了解所有凭证类型及其用例之前,这些凭证将用于除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)
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

使用该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)
Run Code Online (Sandbox Code Playgroud)


Zaa*_*Hai 6

尽管上面的答案很有用,但它遗漏了一个要点-从google.auth.default()或compute_engine.Credentials()没有令牌的凭证对象。回到最初的问题是什么是的替代方案gcloud auth print-access-token,我的回答是:

import google.auth
import google.auth.transport.requests
creds, projects = 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
Run Code Online (Sandbox Code Playgroud)

我使用的是官方的google-auth软件包和默认凭据,这将使您无论是在本地开发环境中还是在远程GCE / GKE应用程序中都可以使用。

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

  • 这对我有用,尽管我需要添加谷歌云范围才能进行刷新。因此,我将导入后的第一行更改为:“creds,project = google.auth.default(scopes = ['https://www.googleapis.com/auth/cloud-platform'])” (4认同)
  • 它将获取应用程序默认凭据 - 如果您在笔记本电脑上运行,这些通常是您的用户凭据。在 GAE 内部,它将是其服务帐户凭据等。 https://blog.doit-intl.com/google-auth-dispelling-the-magic-d3c114d39eef (3认同)

小智 5

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
Run Code Online (Sandbox Code Playgroud)


Hil*_*iao 5

在某些情况下,无法在需要 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

Run Code Online (Sandbox Code Playgroud)

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

curl https://example.googleapis.com/v1alpha1/projects/PROJECT_ID/locations -H "Authorization: Bearer ya29<REDACTED>"
Run Code Online (Sandbox Code Playgroud)

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

  • 兄弟,使用服务帐户 json 文件获取令牌的完美答案...... (2认同)