App Identity Python API 개요

App Identity API를 사용하면 애플리케이션이 자신의 애플리케이션 ID(다른 명칭은 프로젝트 ID)를 알릴 수 있습니다. App Engine 애플리케이션은 ID를 사용하여 다른 App Engine 앱, Google API, 타사 애플리케이션과 서비스에 자신의 ID를 어설션할 수 있습니다. URL 또는 이메일 주소를 생성하거나 런타임 결정을 내릴 때도 애플리케이션 ID를 사용할 수 있습니다.

애플리케이션 ID 가져오기

애플리케이션 ID는 app_identity.get_application_id() 메소드를 사용하여 찾을 수 있습니다. WSGI 또는 CGI 환경이 API로 처리되는 일부 구현 세부정보를 노출합니다.

애플리케이션 호스트 이름 가져오기

기본적으로 App Engine 앱은 http://<your_app_id>.appspot.com 형식의 URL에서 제공되며, 여기서 앱 ID는 호스트 이름의 일부입니다. 앱이 커스텀 도메인에서 제공되는 경우 전체 호스트 이름 구성요소를 검색해야 할 수 있습니다. app_identity.get_default_version_hostname() 메소드를 사용하여 이 작업을 수행할 수 있습니다.

다른 App Engine 앱에 ID 어설션

App Engine 앱에 요청을 보내는 App Engine 앱의 ID를 확인하려면 X-Appengine-Inbound-Appid 요청 헤더를 사용합니다. 이 헤더는 URLFetch 서비스를 통해 요청에 추가되며 사용자가 수정할 수 없으므로 이 헤더가 있으면 요청하는 애플리케이션의 ID라고 신뢰할 수 있습니다.

이 헤더를 요청에 추가하려면 요청을 보내는 앱에서 URLFetch 서비스가 리디렉션을 따르지 않도록 지시해야 합니다. 즉, fetch follow_redirects 매개변수를 False로 설정해야 합니다. 그러면 App Engine이 자동으로 헤더를 HTTP 응답에 추가합니다.

애플리케이션 핸들러에서 X-Appengine-Inbound-Appid 헤더를 읽고 요청을 보낼 수 있는 ID 목록과 비교하여 수신 ID를 확인할 수 있습니다.

다음 스니펫에서는 허용되는 앱 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을 제공하는 서비스의 경우 이 계정 액세스 권한을 부여하여 애플리케이션 액세스 권한을 부여할 수 있습니다.

제3자 서비스에 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 버킷 이름 가져오기

애플리케이션마다 무료 저장용량 5GB 및 무료 I/O 작업 할당량이 포함된 기본 Cloud Storage 버킷이 있습니다. 이 버킷의 최대 저장용량은 5GB이며, 앱에서 결제를 사용 설정하고 추가 저장용량을 결제하여 유료 버킷으로 설정하면 저장용량을 늘릴 수 있습니다.

기본 버킷의 이름을 가져오려면 App Identity API를 사용하면 됩니다. google.appengine.api.app_identity.app_identity.get_default_gcs_bucket_name을 호출하세요.

이 페이지가 도움이 되었나요? 평가를 부탁드립니다.

다음에 대한 의견 보내기...

App Engine standard environment for Python 2