Autentikasi antarlayanan

Anda dapat menerapkan autentikasi antar-layanan menggunakan akun layanan di layanan gRPC. Halaman ini menunjukkan autentikasi layanan-ke-layanan dengan memandu Anda melalui contoh lengkap, termasuk cara mengonfigurasi Extensible Service Proxy (ESP) di layanan gRPC untuk mendukung permintaan yang diautentikasi dan cara memanggil layanan dari klien gRPC.

Agar layanan dapat melakukan panggilan yang diautentikasi ke Cloud Endpoints API, layanan yang memanggil harus memiliki akun layanan dan harus mengirim token autentikasi dalam panggilan. Pemanggil harus menggunakan token ID Google atau Token Web JSON (JWT) kustom yang ditandatangani hanya oleh akun layanan pemanggil. ESP memvalidasi bahwa klaim iss di JWT cocok dengan setelan issuer dalam konfigurasi layanan. ESP tidak memeriksa izin Identity and Access Management yang telah diberikan pada akun layanan.

Dalam contoh ini, Anda menyiapkan dan menggunakan bentuk autentikasi layanan-ke-layanan yang paling sederhana, di mana klien menggunakan akun layanannya Google Cloud untuk membuat JWT autentikasi. Pendekatan untuk metode autentikasi lainnya serupa, meskipun proses sisi klien untuk mendapatkan token autentikasi yang valid bergantung pada metode autentikasi yang digunakan.

Sebelum memulai

Panduan ini menggunakan contoh Bookstore yang digunakan dalam Tutorial kami.

  1. Clone repositori git tempat kode contoh gRPC dihosting:

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
    
  2. Ubah direktori kerja Anda:

    cd python-docs-samples/endpoints/bookstore-grpc/
    
  3. Ikuti petunjuk di Tutorial untuk menyiapkan project jika Anda belum memilikinya.

Dalam contoh ini, Anda menggunakan deployment ke Google Kubernetes Engine, meskipun penyiapan autentikasi sama untuk Compute Engine.

Dalam contoh, ada dua project Google Cloud Platform yang dirujuk:

  • Project produsen layanan, yaitu project yang memiliki layanan Cloud Endpoints untuk gRPC.
  • Project konsumen layanan, yaitu project yang memiliki klien gRPC.

Membuat akun layanan dan kunci konsumen

Untuk membuat akun layanan dan kunci untuk project konsumen:

  1. Di Google Cloud konsol, buka APIs & services.

    APIs & services

    Pastikan Anda berada di project konsumen.
  2. Di halaman Credentials, pada menu drop-down Create Credentials, pilih Service Account Key.
  3. Di halaman Create service account key, jika Anda memiliki akun layanan yang ingin digunakan, pilih akun tersebut. Jika tidak, di menu drop-down Akun layanan, pilih Akun layanan baru, lalu ketik nama akun.

    ID akun layanan yang sesuai akan dibuat untuk Anda. Catat ID-nya karena diperlukan di bagian berikutnya. Contoh:

    service-account-name@YOUR_PROJECT_ID.iam.gserviceaccount.com
    
  4. Klik menu drop-down Peran, lalu pilih peran berikut:

    • Akun Layanan > Service Account User
    • Service Accounts > Service Account Token Creator
  5. Pastikan jenis kunci JSON dipilih.

  6. Klik Buat. File kunci JSON akun layanan Anda didownload ke komputer lokal Anda. Catat lokasi dan pastikan disimpan dengan aman karena akan digunakan nanti untuk membuat token.

Mengonfigurasi autentikasi untuk layanan

Gunakan project produsen untuk semua langkah di bagian ini.

Menyiapkan autentikasi dalam konfigurasi gRPC API

Autentikasi untuk ESP dikonfigurasi di bagian authentication file YAML konfigurasi gRPC API Anda. Konfigurasi dengan autentikasi untuk layanan contoh ini ada di api_config_auth.yaml.

authentication:
  providers:
  - id: google_service_account
    # Replace SERVICE-ACCOUNT-ID with your service account's email address.
    issuer: SERVICE-ACCOUNT-ID
    jwks_uri: https://www.googleapis.com/robot/v1/metadata/x509/SERVICE-ACCOUNT-ID
  rules:
  # This auth rule will apply to all methods.
  - selector: "*"
    requirements:
      - provider_id: google_service_account

Bagian providers menentukan penyedia autentikasi yang ingin Anda gunakan - dalam hal ini, Anda ingin menggunakan akun layanan Google sebagai penyedia autentikasi. Bagian rules menentukan bahwa Anda memerlukan token dari penyedia ini untuk mengakses semua metode layanan Anda.

Di salinan file Anda sendiri dari repo yang di-clone:

  • Ubah MY_PROJECT_ID menjadi ID project produser Anda.
  • Ubah SERVICE-ACCOUNT-ID di bagian authentication (di nilai issuer dan jwks_uri) ke ID akun layanan konsumen yang Anda catat di bagian sebelumnya. Hal ini memberi tahu ESP bahwa Anda ingin memberikan akses ke layanan Anda kepada pengguna yang memberikan token valid dari akun layanan tertentu ini.
  • Secara opsional, tambahkan jwt_locations di bawah elemen providers. Anda dapat menggunakan nilai ini untuk menentukan lokasi JWT kustom. Lokasi JWT default adalah metadata Authorization (diawali dengan "Bearer ") dan metadata X-Goog-Iap-Jwt-Assertion.

Simpan file untuk langkah berikutnya.

Men-deploy konfigurasi dan layanan

Langkah-langkah ini sama seperti di Mulai menggunakan gRPC di GKE:

  1. Deploy konfigurasi layanan Anda ke Endpoints: Anda harus melakukannya meskipun Anda sudah melakukannya untuk tutorial, karena ini adalah konfigurasi yang berbeda. Catat nama layanan yang ditampilkan:

    gcloud endpoints services deploy api_descriptor.pb api_config_auth.yaml --project PRODUCER_PROJECT
    
  2. Buat cluster penampung dan autentikasi kubectl ke cluster, jika Anda belum melakukannya.

  3. Deploy API dan ESP contoh ke cluster. Jika Anda menggunakan project produsen dan konsumen yang terpisah, pastikan terlebih dahulu bahwa Anda telah menetapkan project yang sesuai dalam alat command line gcloud:

    gcloud config set project PRODUCER_PROJECT
    

Memanggil metode yang diautentikasi dari klien gRPC

Terakhir, di sisi klien, Anda dapat menggunakan kunci akun layanan untuk membuat token JWT, lalu menggunakan token tersebut untuk memanggil metode Bookstore yang diautentikasi. Pertama, instal persyaratan Python yang sesuai untuk membuat token dan menjalankan contoh klien. Pastikan Anda berada di folder python-docs-samples/endpoints/bookstore-grpc dari klien yang di-clone, lalu:

virtualenv bookstore-env
source bookstore-env/bin/activate
pip install -r requirements.txt

Buat token JWT

Dalam contoh ini, Bookstore menggunakan autentikasi layanan-ke-layanan di mana layanan panggilan diautentikasi murni oleh akun layanannya, sehingga pembuatan token yang sesuai untuk dikirim dengan permintaan kita menjadi sederhana. Perhatikan bahwa Anda juga dapat mewajibkan autentikasi layanan-ke-layanan yang lebih ketat, di mana token yang dihasilkan harus diautentikasi lebih lanjut oleh Google (menggunakan token ID Google).

Untuk contoh ini, skrip Python yang disediakan dapat membuat token dari file kunci JSON yang didownload sebelumnya, menggunakan ID pengguna dan email dummy.

#!/usr/bin/env python

# Copyright 2016 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Example of generating a JWT signed from a service account file."""

import argparse
import json
import time

import google.auth.crypt
import google.auth.jwt

"""Max lifetime of the token (one hour, in seconds)."""
MAX_TOKEN_LIFETIME_SECS = 3600


def generate_jwt(service_account_file, issuer, audiences):
    """Generates a signed JSON Web Token using a Google API Service Account."""
    with open(service_account_file) as fh:
        service_account_info = json.load(fh)

    signer = google.auth.crypt.RSASigner.from_string(
        service_account_info["private_key"], service_account_info["private_key_id"]
    )

    now = int(time.time())

    payload = {
        "iat": now,
        "exp": now + MAX_TOKEN_LIFETIME_SECS,
        # aud must match 'audience' in the security configuration in your
        # swagger spec. It can be any string.
        "aud": audiences,
        # iss must match 'issuer' in the security configuration in your
        # swagger spec. It can be any string.
        "iss": issuer,
        # sub and email are mapped to the user id and email respectively.
        "sub": issuer,
        "email": "user@example.com",
    }

    signed_jwt = google.auth.jwt.encode(signer, payload)
    return signed_jwt


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
    )
    parser.add_argument("--file", help="The path to your service account json file.")
    parser.add_argument("--issuer", default="", help="issuer")
    parser.add_argument("--audiences", default="", help="audiences")

    args = parser.parse_args()

    signed_jwt = generate_jwt(args.file, args.issuer, args.audiences)
    print(signed_jwt.decode("utf-8"))

Untuk membuat token menggunakan skrip:

  • Buat token JWT dan tetapkan ke variabel $JWT_TOKEN:

    JWT_TOKEN=$(python jwt_token_gen.py \
        --file=[SERVICE_ACCOUNT_FILE] \
        --audiences=[SERVICE_NAME] \
        --issuer=[SERVICE-ACCOUNT-ID])
    

    dengan:

    • [SERVICE_ACCOUNT_FILE] adalah file kunci JSON akun layanan konsumen yang didownload.
    • [SERVICE_NAME] adalah nama layanan Bookstore yang ditampilkan saat Anda men-deploy konfigurasi layanan yang diupdate ke Endpoints.
    • [SERVICE-ACCOUNT-ID] adalah ID akun layanan konsumen lengkap saat Anda membuat akun layanan.

Melakukan panggilan gRPC yang diautentikasi

Langkah terakhir ini menggunakan bookstore_client.py, yang merupakan klien yang sama yang digunakan dalam Tutorial. Untuk melakukan panggilan yang diautentikasi, klien meneruskan JWT sebagai metadata dengan panggilan metodenya.

def run(
    host, port, api_key, auth_token, timeout, use_tls, servername_override, ca_path

Untuk menjalankan contoh:

  1. Gunakan kubectl get services untuk mendapatkan alamat IP eksternal untuk Bookstore yang di-deploy:

    #kubectl get services
    NAME                 CLUSTER-IP      EXTERNAL-IP      PORT(S)           AGE
    echo                 10.11.246.240   104.196.186.92   80/TCP            10d
    endpoints            10.11.243.168   104.196.210.50   80/TCP,8090/TCP   10d
    esp-grpc-bookstore   10.11.254.34    104.196.60.37    80/TCP            1d
    kubernetes           10.11.240.1     <none>           443/TCP           10d
    

    Dalam hal ini, layanan esp-grpc-bookstore dan IP eksternalnya adalah 104.196.60.37.

  2. Tetapkan alamat IP ke variabel EXTERNAL_IP

    EXTERNAL_IP=104.196.60.37
    
  3. Mencantumkan semua rak dari layanan Bookstore:

    python bookstore_client.py --port=80 --host=$EXTERNAL_IP --auth_token=$JWT_TOKEN
    

    Layanan ini menampilkan semua rak di Toko Buku saat ini. Anda dapat memeriksanya dua kali dengan tidak memberikan token, atau dengan menentukan ID akun layanan yang salah saat membuat JWT. Perintah akan gagal.

Langkah berikutnya