App Identity Python API 概要

App Identity API は、アプリケーションが自身のアプリケーション ID(「プロジェクト ID」とも呼ばれる)を見つけられるようにします。App Engine アプリケーションは ID を使用して、そのアプリケーションの識別情報を他の App Engine アプリ、Google API、サードパーティ製アプリケーションおよびサービスに表明します。アプリケーション ID は URL やメールアドレスの生成、ランタイムでの決定にも使用できます。

プロジェクト ID を取得する

プロジェクト ID は app_identity.get_application_id() メソッドで確認できます。WSGI または CGI 環境は、API によって処理される実装の詳細を公開しています。

アプリケーションのホスト名を取得する

デフォルトでは、App Engine アプリは URL から http://<your_app_id>.appspot.com という形式で提供され、アプリ ID はホスト名の一部となっています。 アプリがカスタム ドメインから提供される場合、ホスト名のコンポーネント全体を取得する必要があります。これは app_identity.get_default_version_hostname() メソッドを使用するとできます。

その他の App Engine アプリに ID を表明する

App Engine アプリにリクエストを行っている App Engine アプリの ID を特定するには、リクエスト ヘッダー X-Appengine-Inbound-Appid を使用します。このヘッダーは URLFetch サービスによりリクエストに追加され、ユーザーによる変更はできないため、リクエスト元のアプリケーション ID がある場合、その ID が安全に表示されます。

要件:

  • アプリの appspot.com ドメインへの呼び出しのみに X-Appengine-Inbound-Appid ヘッダーが含まれます。カスタム ドメインへの呼び出しにはヘッダーが含まれません。
  • リダイレクトに従わないようにリクエストを設定する必要があります。これを行うには、urlfetch.fetch() follow_redirects パラメータを False に設定します。

アプリケーション ハンドラでは、X-Appengine-Inbound-Appid ヘッダーを読み取り、リクエストを行うことを許可された ID のリストと比較することで受信 ID を確認できます。次に例を示します。

import webapp2

class MainPage(webapp2.RequestHandler):
    allowed_app_ids = [
        'other-app-id',
        'other-app-id-2'
    ]

    def get(self):
        incoming_app_id = self.request.headers.get(
            'X-Appengine-Inbound-Appid', None)

        if incoming_app_id not in self.allowed_app_ids:
            self.abort(403)

        self.response.write('This is a protected page.')

app = webapp2.WSGIApplication([
    ('/', MainPage)
], debug=True)

Google API に ID を表明する

Google API では、認証および承認に OAuth 2.0 プロトコルを使用しています。App Identity API は、リクエストのソースがアプリケーション自体であることを表明するために使用できる OAuth トークンを作成します。get_access_token() メソッドはスコープのアクセス トークン、またはスコープのリストを返します。その後、このトークンを呼び出しの HTTP ヘッダーに設定して、呼び出し元アプリケーションを特定できます。

次の例では、App Identity API を使用して Cloud Storage API に対する認証を行い、プロジェクトのすべてのバケットのリストを取得する方法を示します。
import json
import logging

from google.appengine.api import app_identity
from google.appengine.api import urlfetch
import webapp2

class MainPage(webapp2.RequestHandler):
    def get(self):
        auth_token, _ = app_identity.get_access_token(
            'https://www.googleapis.com/auth/cloud-platform')
        logging.info(
            'Using token {} to represent identity {}'.format(
                auth_token, app_identity.get_service_account_name()))

        response = urlfetch.fetch(
            'https://www.googleapis.com/storage/v1/b?project={}'.format(
                app_identity.get_application_id()),
            method=urlfetch.GET,
            headers={
                'Authorization': 'Bearer {}'.format(auth_token)
            }
        )

        if response.status_code != 200:
            raise Exception(
                'Call failed. Status code {}. Body {}'.format(
                    response.status_code, response.content))

        result = json.loads(response.content)
        self.response.headers['Content-Type'] = 'application/json'
        self.response.write(json.dumps(result, indent=2))

app = webapp2.WSGIApplication([
    ('/', MainPage)
], debug=True)

アプリケーションの ID はサービス アカウント名で表されることにご注意ください。通常は applicationid@appspot.gserviceaccount.com となります。get_service_account_name() メソッドを使用して正確な値を取得します。ACL を提供するサービスでは、このアカウントのアクセスを許可することでアプリケーションにアクセスを許可します。

サードパーティのサービスに ID を表明する

get_access_token() によって生成されたトークンは、Google サービスにのみ作用します。ただし、基盤となる署名テクノロジーを使用してアプリケーションの ID をその他のサービスに表明できます。sign_blob() メソッドはアプリケーション固有の秘密鍵を使用してバイトを署名し、get_public_certificates() メソッドは署名の検証に使用される証明書を返します。

次の例では、blob に署名し、その署名を確認しています。

import base64

from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Util.asn1 import DerSequence
from google.appengine.api import app_identity
import webapp2

def verify_signature(data, signature, x509_certificate):
    """Verifies a signature using the given x.509 public key certificate."""

    # PyCrypto 2.6 doesn't support x.509 certificates directly, so we'll need
    # to extract the public key from it manually.
    # This code is based on https://github.com/google/oauth2client/blob/master
    # /oauth2client/_pycrypto_crypt.py
    pem_lines = x509_certificate.replace(b' ', b'').split()
    cert_der = base64.urlsafe_b64decode(b''.join(pem_lines[1:-1]))
    cert_seq = DerSequence()
    cert_seq.decode(cert_der)
    tbs_seq = DerSequence()
    tbs_seq.decode(cert_seq[0])
    public_key = RSA.importKey(tbs_seq[6])

    signer = PKCS1_v1_5.new(public_key)
    digest = SHA256.new(data)

    return signer.verify(digest, signature)

def verify_signed_by_app(data, signature):
    """Checks the signature and data against all currently valid certificates
    for the application."""
    public_certificates = app_identity.get_public_certificates()

    for cert in public_certificates:
        if verify_signature(data, signature, cert.x509_certificate_pem):
            return True

    return False

class MainPage(webapp2.RequestHandler):
    def get(self):
        message = 'Hello, world!'
        signing_key_name, signature = app_identity.sign_blob(message)
        verified = verify_signed_by_app(message, signature)

        self.response.content_type = 'text/plain'
        self.response.write('Message: {}\n'.format(message))
        self.response.write(
            'Signature: {}\n'.format(base64.b64encode(signature)))
        self.response.write('Verified: {}\n'.format(verified))

app = webapp2.WSGIApplication([
    ('/', MainPage)
], debug=True)

デフォルトの Cloud Storage バケット名を取得する

各アプリケーションには 1 つのデフォルトの Cloud Storage バケットがあります。このバケットには無料のストレージ容量 5 GB と I/O オペレーションの無料の割り当てが含まれます。このバケットの最大ストレージ容量は 5GB ですが、アプリの課金を有効にして追加のストレージ分を支払い、支払済みのバケットにすることで増量できます。

デフォルトのバケットの名前を取得するには、App Identity API を使用して google.appengine.api.app_identity.app_identity.get_default_gcs_bucket_name を呼び出します。

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

Python 2 の App Engine スタンダード環境