web-dev-qa-db-ja.com

pythonを使用してプログラムでGCP Bearerトークンを取得する方法

gcloud auth print-access-tokenは、後で使用できるBearerトークンを提供します。ただし、これはシェルコマンドです。 Google Cloud Python API経由でプログラムで取得するにはどうすればよいですか?

前の例oauth2client を使用しているが、oauth2clientは非推奨になりました。 google.auth および oauthlib を使用してこれを行うにはどうすればよいですか?

10
indraniel

答えは、環境と資格情報の作成/取得方法によって異なります。

Google Cloud Credentialsとは?

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ヘッダーで使用されます。

アクセストークンとは

アクセストークンは、署名されたJWT、より正確にはJWSと呼ばれるものから派生した、Googleによって生成される不透明な値です。 JWTは、ヘッダーとクレーム(ペイロード)Json構造で構成されます。これら2つのJson構造は、サービスアカウントの秘密キーで署名されています。これらの値はbase64でエンコードおよび連結され、アクセスキーが作成されます。

アクセストークンの形式はbase64(header) + '.' + base64(payload) + '.' + base64(signature)です。

JWTの例を次に示します。

ヘッダ:

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

ペイロード:

_{
  "iss": "[email protected]",
  "iat": 1493833746,
  "aud": "myservice.appspot.com",
  "exp": 1493837346,
  "sub": "[email protected]"
}
_

アクセストークンの使用:

VMインスタンスを開始する例。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 Service Account:

ダスティンの答えはこの場合に正しいですが、完全性のためにいくつかの追加情報を含めます。

これらの認証情報はGCPによって自動的に作成され、VMインスタンスメタデータから取得されます。許可はGoogleコンソールの_Cloud API access scopes_によって制御されます。

ただし、これらの資格情報にはいくつかの制限があります。資格情報を変更するには、最初にVMインスタンスを停止する必要があります。さらに、すべての権限(ロール)がサポートされているわけではありません。

_from google.auth import compute_engine

cred = compute_engine.Credentials()
_

サービスアカウントの資格情報:

すべての種類の資格情報とその使用例を理解するまで、これらはgcloudgsutilを除くすべてに使用する資格情報です。これらの資格情報を理解すると、プログラムを作成するときに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 Credentials:

これらの資格情報は、完全なOAuth 2.0フローから取得されます。これらの資格情報は、アクセスを許可するためにGoogleアカウントにアクセスするためにブラウザーを起動するときに生成されます。承認のためのコールバック用の組み込みWebサーバーを実装し、必要とします。

このメソッドは、ブラウザーですべてを実行できるなどの追加機能を提供します。たとえば、クラウドストレージファイルブラウザーを作成できますが、セキュリティの意味を理解するよう注意してください。この方法は、Googleサインインなどをサポートするために使用される手法です。この方法を使用して、Webサイトなどへの投稿を許可する前にユーザーを認証します。正しく認証された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)
_
14
John Hanley

上記の答えは非常に有益ですが、1つの重要なポイントを見逃しています-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

公式のgoogle-authパッケージと デフォルトの認証情報 を使用しています。これにより、ローカルdevとリモートGCE/GKEアプリの両方で使用できます。

残念ながら、これは適切に文書化されておらず、トークンの取得方法を理解するためにgoogle-auth code を読む必要がありました。

6
Zaar Hai

サービスアカウントを作成せずにpython SDKを使用する方法を探しているときに、ここにいることに気づきました。クラウドで実行されるスクリプトをローカルで開発する方法が必要でした。これは、gcloudコマンドのアーティファクトを使用して:

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