App Identity API untuk layanan paket lama

ID region

REGION_ID adalah kode singkat yang ditetapkan Google berdasarkan region yang Anda pilih saat membuat aplikasi. Kode ini tidak sesuai dengan negara atau provinsi, meskipun beberapa ID region mungkin tampak mirip dengan kode negara dan provinsi yang umum digunakan. Untuk aplikasi yang dibuat setelah Februari 2020, REGION_ID.r disertakan dalam URL App Engine. Untuk aplikasi lama yang dibuat sebelum tanggal tersebut, ID region bersifat opsional dalam URL.

Pelajari ID region lebih lanjut.

App Identity API memungkinkan aplikasi menemukan ID aplikasinya (juga disebut ID project). Dengan menggunakan ID ini, aplikasi App Engine dapat menegaskan identitasnya ke Aplikasi App Engine lainnya, Google API, serta aplikasi dan layanan pihak ketiga. ID aplikasi juga dapat digunakan untuk membuat URL atau alamat email, atau untuk membuat keputusan run-time.

Mendapatkan ID project

Project ID dapat ditemukan menggunakan metode app_identity.get_application_id(). Lingkungan WSGI atau CGI menampilkan beberapa detail implementasi, yang ditangani oleh API.

Mendapatkan nama host aplikasi

Secara default, aplikasi App Engine disalurkan dari URL dalam bentuk https://PROJECT_ID.REGION_ID.r.appspot.com, dengan ID project merupakan bagian dari nama host. Jika aplikasi disalurkan dari domain kustom, aplikasi tersebut mungkin perlu mengambil seluruh komponen nama host. Anda dapat melakukannya menggunakan metode app_identity.get_default_version_hostname().

Menyatakan identitas ke aplikasi App Engine lainnya

Jika ingin menentukan identitas aplikasi App Engine yang membuat permintaan ke aplikasi App Engine Anda, Anda dapat menggunakan header permintaan X-Appengine-Inbound-Appid. Header ini ditambahkan ke permintaan oleh layanan URLFetch dan tidak dapat diubah oleh pengguna, sehingga dengn aman menunjukkan project ID aplikasi yang melakukan permintaan, jika ada.

Persyaratan:

  • Hanya panggilan yang dilakukan ke domain appspot.com aplikasi Anda yang akan berisi header X-Appengine-Inbound-Appid. Panggilan ke domain kustom tidak berisi header.
  • Permintaan Anda harus ditetapkan agar tidak mengikuti pengalihan. Tetapkan urlfetch.fetch() follow_redirects parameter ke False.

Di pengendali aplikasi, Anda dapat memeriksa ID masuk dengan membaca header X-Appengine-Inbound-Appid dan membandingkannya dengan daftar ID yang diizinkan untuk membuat permintaan. Contoh:

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)

Menyatakan identitas ke Google API

Google API menggunakan protokol OAuth 2.0 untuk autentikasi dan otorisasi. App Identity API dapat membuat token OAuth yang dapat digunakan untuk menyatakan bahwa sumber permintaan adalah aplikasi itu sendiri. Metode get_access_token() menampilkan token akses untuk cakupan, atau daftar cakupan. Token ini kemudian dapat ditetapkan dalam header HTTP panggilan untuk mengidentifikasi aplikasi panggilan.

Contoh berikut menunjukkan cara menggunakan App Identity API untuk melakukan autentikasi ke Cloud Storage API dan mengambil serta mencantumkan semua bucket di project.
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)

Perlu diperhatikan bahwa identitas aplikasi direpresentasikan oleh nama akun layanan, yang biasanya adalah applicationid@. Anda bisa mendapatkan nilai yang tepat menggunakan metode get_service_account_name(). Untuk layanan yang menawarkan ACL, Anda dapat memberikan akses aplikasi dengan memberikan akses akun ini.

Menyatakan identitas ke layanan pihak ketiga

Token yang dibuat oleh get_access_token() hanya berfungsi pada layanan Google. Namun, Anda bisa menggunakan teknologi penandatanganan yang mendasarinya untuk menegaskan identitas aplikasi Anda ke layanan lain. Metode sign_blob() akan menandatangani byte menggunakan kunci pribadi yang unik untuk aplikasi Anda, dan metode get_public_certificates() akan menampilkan sertifikat yang dapat digunakan untuk memvalidasi tanda tangan.

Berikut adalah contoh yang menunjukkan cara menandatangani blob dan memvalidasi tanda tangannya:

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)

Mendapatkan nama Bucket Cloud Storage default

Setiap aplikasi dapat memiliki satu bucket Cloud Storage default, yang mencakup penyimpanan gratis 5 GB dan kuota gratis untuk operasi I/O.

Untuk mendapatkan nama bucket default, Anda dapat menggunakan App Identity API. Panggil google.appengine.api.app_identity.app_identity.get_default_gcs_bucket_name.