App Engine Kullanıcıları hizmetinden Cloud Identity Platform'a taşıma (Modül 21)

1. Genel Bakış

Serverless Migration Station serisi codelab'ler (kendi hızınızda ilerleyebileceğiniz, uygulamalı eğitimler) ve ilgili videolar, Google Cloud sunucusuz geliştiricilerin öncelikle eski hizmetlerden uzaklaşarak bir veya daha fazla taşıma işlemi yapmalarına rehberlik ederek uygulamalarını modernleştirmelerine yardımcı olmayı amaçlar. Bu sayede uygulamalarınız daha taşınabilir hale gelir, daha fazla seçenek ve esneklik elde edersiniz. Böylece daha geniş bir Cloud ürün yelpazesiyle entegrasyon yapabilir, bu ürünlere erişebilir ve yeni dil sürümlerine daha kolay yükseltebilirsiniz. Başlangıçta öncelikle App Engine (standart ortam) geliştiricileri olmak üzere en eski Cloud kullanıcılarına odaklanılsa da bu seri, Cloud Functions ve Cloud Run gibi diğer sunucusuz platformları veya uygun olduğu durumlarda başka platformları da kapsayacak kadar geniştir.

Bu codelab'in amacı, Python 2 App Engine geliştiricilerine App Engine Users API/hizmetinden Cloud Identity Platform'a (GCIP) nasıl geçiş yapacaklarını göstermektir. Ayrıca, Datastore erişimi için App Engine NDB'den Cloud NDB'ye örtülü bir taşıma (öncelikle Taşıma Modülü 2'de ele alınır) ve Python 3'e yükseltme de vardır.

20. modülde, Kullanıcılar API'sinin kullanımını 1. modüldeki örnek uygulamaya ekleme konusu ele alınmaktadır. Bu modülde, tamamlanmış 20. modül uygulamasını alıp kullanımını Cloud Identity Platform'a taşıyacaksınız.

Bu demoda aşağıdaki işlemleri yapmayı öğreneceksiniz:

  • App Engine Users hizmetinin kullanımını Cloud Identity Platform ile değiştirme
  • App Engine NDB kullanımını Cloud NDB ile değiştirin (2. Modül'e de bakın).
  • Firebase Auth kullanarak farklı kimlik doğrulama kimlik sağlayıcıları ayarlama
  • Proje IAM bilgilerini almak için Cloud Resource Manager API'yi kullanma
  • Kullanıcı bilgilerini almak için Firebase Admin SDK'sını kullanma
  • Örnek uygulamayı Python 3'e taşıma

İhtiyacınız olanlar

Anket

Bu eğitimi nasıl kullanacaksınız?

Yalnızca okuyun Okuyun ve alıştırmaları tamamlayın

Python ile ilgili deneyiminizi nasıl değerlendirirsiniz?

Yeni başlayan Orta düzey Uzman

Google Cloud hizmetlerini kullanma deneyiminizi nasıl değerlendirirsiniz?

Başlangıç Orta İleri

2. Arka plan

App Engine Users hizmeti, App Engine uygulamaları tarafından kullanılmak üzere tasarlanmış bir kullanıcı kimlik doğrulama sistemidir. Kimlik sağlayıcı olarak Google ile Oturum Açma'yı sunar, uygulamalarda kullanılmak üzere kolay oturum açma ve kapatma bağlantıları sağlar ve yönetici kullanıcılar ile yalnızca yöneticilere yönelik işlevler kavramını destekler. Uygulama taşınabilirliğini iyileştirmek için Google Cloud, eski App Engine paketlenmiş hizmetlerinden Cloud bağımsız hizmetlerine geçiş yapmanızı önerir. Örneğin, Kullanıcılar hizmetinden Cloud Identity Platform'a geçiş yapabilirsiniz.

Identity Platform, Firebase Authentication'a dayanır ve çok öğeli kimlik doğrulama, OIDC ve SAML TOA desteği, çok kiracılı yapı, %99, 95 HDS gibi bir dizi kurumsal özellik ekler. Bu farklılıklar, Identity Platform ve Firebase Authentication ürün karşılaştırma sayfasında da vurgulanmaktadır. Her iki ürün de Users Service'in sunduğu işlevlerden çok daha fazla özelliğe sahiptir.

Bu 21. modül codelab'inde, uygulamanın kullanıcı kimlik doğrulamasını Users hizmetinden 20. modülde gösterilen işlevselliği en iyi şekilde yansıtan Identity Platform özelliklerine geçirme işlemi gösterilmektedir. 21. modülde, Datastore erişimi için App Engine NDB'den Cloud NDB'ye geçiş de ele alınmaktadır. Bu geçiş, 2. Modül'deki geçişle aynıdır.

20. modül kodu, Python 2 örnek uygulaması olarak "tanıtılsa" da kaynağın kendisi Python 2 ve 3 ile uyumludur ve 21. modülde Identity Platform'a (ve Cloud NDB'ye) geçiş yapıldıktan sonra da bu şekilde kalır. Identity Platform'a geçiş isteğe bağlı olduğundan Python 3'e yükseltirken Kullanıcılar hizmetini kullanmaya devam edebilirsiniz. Python 3 gibi 2. nesil çalışma zamanlarına yükseltirken paketlenmiş hizmetleri kullanmaya nasıl devam edeceğinizi öğrenmek için 17. modülün codelab'ini ve videoyu inceleyin.

Bu eğitimde aşağıdaki adımlar yer almaktadır:

  1. Kurulum/Ön Hazırlık
  2. Yapılandırmayı güncelleyin
  3. Uygulama kodunu değiştirme

3. Kurulum/Ön Hazırlık

Bu bölümde aşağıdakilerin nasıl yapılacağı açıklanmaktadır:

  1. Cloud projenizi ayarlama
  2. Temel örnek uygulamayı edinme
  3. Temel uygulamayı (yeniden) dağıtma ve doğrulama
  4. Yeni Google Cloud hizmetlerini/API'lerini etkinleştirme

Bu adımlar, bağımsız Cloud hizmetlerine taşınmaya hazır, çalışan bir kodla başlamanızı sağlar.

1. Proje oluşturma

20. Modül'deki codelab'i tamamladıysanız aynı projeyi (ve kodu) yeniden kullanın. Alternatif olarak, yepyeni bir proje oluşturun veya mevcut başka bir projeyi yeniden kullanın. Projenin etkin bir faturalandırma hesabına ve etkin bir App Engine uygulamasına sahip olduğundan emin olun. Proje kimliğinizi bulun ve bu codelab sırasında elinizin altında bulundurun. PROJ_ID değişkeniyle karşılaştığınızda proje kimliğinizi kullanın.

2. Temel örnek uygulamayı edinme

Ön koşullardan biri, çalışan bir 20. Modül App Engine uygulamasıdır. Bu nedenle, codelab'ini tamamlayın (önerilir; yukarıdaki bağlantı) veya depodaki 20. Modül kodunu kopyalayın. İster kendi verilerinizi ister bizim verilerimizi kullanın, işe buradan başlayacağız ("BAŞLANGIÇ"). Bu codelab, 21. modülün depo klasöründeki ("FINISH") koda benzeyen bir kodla sonuçlanan taşıma sürecinde size yol gösterir.

Module 20 repo klasörünü kopyalayın. Aşağıdaki çıkışa benzer görünmelidir ve 20. modül kod laboratuvarını yaptıysanız muhtemelen bir lib klasörü içerir:

$ ls
README.md               appengine_config.py     templates
app.yaml                main.py                 requirements.txt

3. Temel uygulamayı (yeniden) dağıtma ve doğrulama

Modül 20 uygulamasını dağıtmak için aşağıdaki adımları uygulayın:

  1. Varsa lib klasörünü silin ve pip install -t lib -r requirements.txt komutunu çalıştırarak klasörü yeniden doldurun. Hem Python 2 hem de 3 yüklüyse pip2 kullanmanız gerekebilir.
  2. gcloud komut satırı aracını yüklediğinizden, başlattığınızdan ve kullanımını incelediğinizden emin olun.
  3. Verilen her gcloud komutunda PROJ_ID değerini girmek istemiyorsanız önce gcloud config set project PROJ_ID ile Cloud projesini ayarlayın.
  4. Örnek uygulamayı gcloud app deploy ile dağıtma
  5. Uygulamanın hatasız bir şekilde beklendiği gibi çalıştığını doğrulayın. 20. modülün codelab'ini tamamladıysanız uygulama, en son ziyaretlerle birlikte üst kısımda kullanıcı giriş bilgilerini (kullanıcı e-postası, olası "yönetici rozeti" ve giriş/çıkış düğmesi) gösterir (aşağıda gösterilmiştir).

907e64c19ef964f8.png

Normal kullanıcı olarak oturum açıldığında kullanıcının e-posta adresi görüntülenir ve "Giriş" düğmesi "Çıkış" düğmesine dönüşür:

ad7b59916b69a035.png

Yönetici kullanıcı olarak oturum açıldığında kullanıcının e-posta adresi, yanında "(yönetici)" ifadesiyle birlikte gösterilir:

867bcb3334149e4.png

4. Yeni Google Cloud API'lerini/hizmetlerini etkinleştirme

Giriş

20. Modül uygulaması, ek kurulum gerektirmeyen paketlenmiş hizmetler olan App Engine NDB ve Users API'lerini kullanır. Ancak bağımsız Cloud hizmetleri ek kurulum gerektirir. Güncellenen uygulama hem Cloud Identity Platform'u hem de Cloud Datastore'u (Cloud NDB istemci kitaplığı aracılığıyla) kullanır. Ayrıca, App Engine yönetici kullanıcılarını belirlememiz için Cloud Resource Manager API'nin kullanılması gerekir.

Maliyet

  • App Engine ve Cloud Datastore'da "Daima Ücretsiz" katman kotaları vardır. Bu sınırların altında kaldığınız sürece bu eğitimi tamamlarken herhangi bir ücret ödemezsiniz. Daha fazla bilgi için App Engine fiyatlandırma sayfası ve Cloud Datastore fiyatlandırma sayfasına da göz atın.
  • Cloud Identity Platform'un kullanımı, aylık etkin kullanıcı sayısına (MAU) veya kimlik doğrulama işlemlerine göre faturalandırılır. Her kullanım modeli için "ücretsiz" sürüm mevcuttur. Daha fazla bilgi için fiyatlandırma sayfasına göz atın. Ayrıca, App Engine ve Cloud Datastore faturalandırma gerektirirken GCIP'nin tek başına kullanımı, enstrümansız günlük kotalarını aşmadığınız sürece faturalandırmanın etkinleştirilmesini gerektirmez. Bu nedenle, faturalandırma gerektiren Cloud API'lerinin/hizmetlerinin kullanılmadığı Cloud projelerinde bunu göz önünde bulundurun.
  • Cloud Resource Manager API'nin kullanımı, fiyatlandırma sayfasında belirtildiği gibi büyük ölçüde ücretsizdir.

Kullanıcılar, tercihlerine bağlı olarak Cloud API'leri Cloud Console'dan veya komut satırından (Cloud SDK'nın bir parçası olan gcloud komutu aracılığıyla) etkinleştirir. Cloud Datastore ve Cloud Resource Manager API'leriyle başlayalım.

Cloud Console'dan

Cloud Console'da API Yöneticisi'nin Kitaplık sayfasına (doğru proje için) gidin ve arama çubuğunu kullanarak bir API arayın. c7a740304e9d35b.png

Şu API'leri etkinleştirin:

Her API için Etkinleştir düğmesini ayrı ayrı bulun ve tıklayın. Faturalandırma bilgileri istenebilir. Örneğin, Resource Manager API'nin sayfasını aşağıda görebilirsiniz:

fc7bd8f4c49d12e5.png

Etkinleştirildikten sonra (genellikle birkaç saniye sonra) düğme Yönet olarak değişir:

8eca12d6cc7b45b0.png

Cloud Datastore'u da aynı şekilde etkinleştirin:

83811599b110e46b.png

Komut satırından

API'leri konsoldan etkinleştirmek görsel olarak bilgilendirici olsa da bazı kullanıcılar komut satırını tercih eder. Ayrıca, istediğiniz sayıda API'yi aynı anda etkinleştirebilirsiniz. Hem Cloud Datastore hem de Cloud Resource Manager API'lerini etkinleştirmek için bu komutu verin ve işlemin tamamlanmasını bekleyin.

$ gcloud services enable cloudresourcemanager.googleapis.com datastore.googleapis.com
Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.

Fatura bilgileri istenebilir.

Yukarıdaki komutta kullanılan her API'nin "URL'leri" API hizmet adları olarak adlandırılır ve her API'nin kitaplık sayfasının en altında bulunabilir. Kendi uygulamalarınız için diğer Cloud API'lerini etkinleştirmek istiyorsanız ilgili hizmet adlarını API sayfalarında bulabilirsiniz. Bu komut, etkinleştirebileceğiniz API'lerin tüm hizmet adlarını listeler:

gcloud services list --available --filter="name:googleapis.com".

İster Cloud Console'da ister komut satırında olsun, yukarıdaki adımları tamamladığınızda örneğimiz artık bu API'lere erişebilir. Sonraki adımlar, Cloud Identity Platform'u etkinleştirmek ve gerekli kod değişikliklerini yapmaktır.

Cloud Identity Platform'u etkinleştirme ve ayarlama (yalnızca Cloud Console)

Cloud Identity Platform, Google Cloud dışındaki bir kaynağa (ör. Firebase Authentication) bağlandığı veya bu kaynağa bağlı olduğu için bir Marketplace hizmetidir. Şu anda yalnızca Cloud Console'dan Marketplace hizmetlerini etkinleştirebilirsiniz. Aşağıdaki adımları uygulayın:

  1. Cloud Marketplace'teki Cloud Identity Platform sayfasına gidin ve Etkinleştir düğmesini tıklayın. İstenirse Firebase Authentication'dan yükseltme yapın. Bu işlem, Arka plan bölümünde daha önce açıklananlar gibi ek özellikleri etkinleştirir. Etkinleştir düğmesinin vurgulandığı Marketplace sayfası: 28475f1c9b29de69.png
  2. Identity Platform etkinleştirildikten sonra otomatik olarak Kimlik Sağlayıcılar sayfasına yönlendirilebilirsiniz. Aksi takdirde, bu kolay bağlantıyı kullanarak ilgili sayfaya gidebilirsiniz. fc2d92d42a5d1dd7.png
  3. Google Auth sağlayıcısını etkinleştirin. Hiç sağlayıcı ayarlanmadıysa Sağlayıcı ekle'yi tıklayın ve Google'ı seçin. Bu ekrana döndüğünüzde Google girişi etkinleştirilmiş olmalıdır. Bu eğiticide, App Engine Users hizmetini basit bir Google ile Oturum Açma hizmeti olarak yansıtmak için kullandığımız tek kimlik doğrulama sağlayıcı Google'dır. Kendi uygulamalarınızda ek kimlik doğrulama sağlayıcılarını etkinleştirebilirsiniz.
  4. Google'ı ve diğer istediğiniz kimlik doğrulama sağlayıcılarını seçip ayarladıktan sonra Uygulama Kurulumu Ayrıntıları'nı tıklayın ve açılan iletişim kutusunda, Web sekmesindeki config nesnesinde yer alan apiKey ve authDomain değerlerini kopyalayıp güvenli bir yere kaydedin. Neden tamamını kopyalamıyorsunuz? Bu iletişim kutusundaki snippet, sabit kodlanmış ve eski bir snippet'tir. Bu nedenle, en önemli kısımları kaydedip daha fazla eşzamanlı Firebase Auth kullanımıyla kodumuzda kullanmanız yeterlidir. Değerleri kopyalayıp güvenli bir yere kaydettikten sonra Kapat düğmesini tıklayarak gerekli tüm kurulumu tamamlayın. bbb09dcdd9be538e.png

4. Yapılandırmayı güncelleyin

Yapılandırmadaki güncellemeler, çeşitli yapılandırma dosyalarını değiştirmeyi ve App Engine'in eşdeğerini Cloud Identity Platform ekosisteminde oluşturmayı içerir.

appengine_config.py

  • Python 3'e yükseltiyorsanız appengine_config.py öğesini silin.
  • Identity Platform'a geçmeyi planlıyorsanız ancak Python 2'de kalacaksanız dosyayı silmeyin. Bunun yerine, Python 2 geri bağlantı noktası sırasında daha sonra güncelleyeceğiz.

requirements.txt

20. modülün requirements.txt dosyasında yalnızca Flask listeleniyordu. For Module 21, add the following packages:

requirements.txt içeriği artık şu şekilde görünmelidir:

flask
google-auth
google-cloud-ndb
google-cloud-resource-manager
firebase-admin

app.yaml

  • Python 3'e yükseltmek, app.yaml dosyasını basitleştirmek anlamına gelir. Çalışma zamanı yönergesi dışındaki her şeyi kaldırın ve bunu şu anda desteklenen bir Python 3 sürümüne ayarlayın. Örnekte şu anda 3.10 sürümü kullanılmaktadır.
  • Python 2'yi kullanmaya devam edecekseniz henüz herhangi bir işlem yapmayın.

ÖNCESİ:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

20. Modül örnek uygulamasında statik dosya işleyicileri yok. Uygulamalarınızda varsa bunları olduğu gibi bırakın. İsterseniz tüm komut dosyası işleyicilerinizi kaldırabilir veya app.yaml taşıma kılavuzunda açıklandığı gibi işleyicilerini auto olarak değiştirdiğiniz sürece referans olarak bırakabilirsiniz. Bu değişikliklerle birlikte, Python 3 için güncellenen app.yaml şu şekilde basitleştirildi:

SONRASI:

runtime: python310

Diğer yapılandırma güncellemeleri

Python 2'de kalmayı veya Python 3'e geçmeyi tercih etseniz de lib klasörünüz varsa bu klasörü silin.

5. Uygulama kodunu değiştirme

Bu bölümde, App Engine Users hizmetinin Cloud Identity Platform ile değiştirilmesiyle ilgili olarak ana uygulama dosyasında (main.py) yapılan güncellemeler yer almaktadır. Ana uygulamayı güncelledikten sonra web şablonunu güncelleyin, templates/index.html.

İçe aktarma işlemlerini ve başlatmayı güncelleme

İçe aktarma işlemlerini güncellemek ve uygulama kaynaklarını başlatmak için aşağıdaki adımları uygulayın:

  1. İçe aktarmalar için App Engine NDB'yi Cloud NDB ile değiştirin.
  2. Cloud NDB ile birlikte Cloud Resource Manager'ı da içe aktarın.
  3. Identity Platform, Firebase Auth'a dayalı olduğundan Firebase Admin SDK'sını içe aktarın.
  4. Cloud API'leri için bir API istemcisinin kullanılması gerekir. Bu nedenle, Flask'i başlatmanın hemen altında Cloud NDB için API istemcisini başlatın.

Cloud Resource Manager paketi burada içe aktarılırken, uygulama başlatma işleminin sonraki aşamalarında kullanacağız. Aşağıda, 20. modüldeki içe aktarma ve başlatma işlemlerinin yanı sıra yukarıdaki değişiklikler uygulandıktan sonra bölümlerin nasıl görüneceği açıklanmaktadır:

ÖNCESİ:

from flask import Flask, render_template, request
from google.appengine.api import users
from google.appengine.ext import ndb

app = Flask(__name__)

SONRASI:

from flask import Flask, render_template, request
from google.auth import default
from google.cloud import ndb, resourcemanager
from firebase_admin import auth, initialize_app

# initialize Flask and Cloud NDB API client
app = Flask(__name__)
ds_client = ndb.Client()

App Engine Admin kullanıcıları için destek

Uygulamaya, yönetici kullanıcıların tanınmasını destekleyen iki bileşen eklenmelidir:

  • _get_gae_admins() — Yönetici kullanıcıları toplar; bir kez çağrılır ve kaydedilir.
  • is_admin(): Oturum açan kullanıcının yönetici kullanıcı olup olmadığını kontrol eder. Her kullanıcı girişi yapıldığında çağrılır.

_get_gae_admins() hizmet işlevi, mevcut Cloud IAM izin politikası'nı getirmek için Resource Manager API'yi çağırır. İzin politikası, hangi ana hesaplara (insan kullanıcılar, hizmet hesapları vb.) hangi rollerin verileceğini tanımlar ve zorunlu kılar. Kurulum şunları içerir:

  • Bulut projesi kimliği getiriliyor (PROJ_ID)
  • Resource Manager API istemcisi oluşturma (rm_client)
  • App Engine Yönetici rolleri (_TARGETS) için (salt okunur) bir küme oluşturma

Resource Manager, Cloud projesi kimliğini gerektirir. Bu nedenle, google.auth.default() öğesini içe aktarın ve proje kimliğini almak için bu işlevi çağırın. Bu çağrıda, URL'ye benzeyen ancak OAuth2 izin kapsamı olan bir parametre bulunur. Uygulamalar bulutta (ör. Compute Engine sanal makinesinde veya App Engine uygulamasında) çalıştırıldığında geniş ayrıcalıklara sahip bir varsayılan hizmet hesabı sağlanır. En az ayrıcalık ilkesi doğrultusunda, kendi kullanıcı tarafından yönetilen hizmet hesaplarınızı oluşturmanızı öneririz.

API çağrıları için uygulamalarınızın kapsamını düzgün çalışmak için gereken minimum seviyeye daha da daraltmanız önerilir. Yapacağımız Resource Manager API çağrısı get_iam_policy() olup çalışması için aşağıdaki kapsamların birini gerektirir:

  • https://www.googleapis.com/auth/cloud-platform
  • https://www.googleapis.com/auth/cloud-platform.read-only
  • https://www.googleapis.com/auth/cloudplatformprojects
  • https://www.googleapis.com/auth/cloudplatformprojects.readonly

Örnek uygulamanın, izin politikasına yalnızca salt okuma erişimi gerekir. Politikayı değiştirmez ve projenin tamamına erişmesi gerekmez. Bu, uygulamanın gereken ilk üç izne ihtiyacı olmadığı anlamına gelir. Yalnızca sonuncusu gereklidir ve örnek uygulamada bu yöntem uygulanmaktadır.

İşlevin ana gövdesi, boş bir yönetici kullanıcıları grubu (admins) oluşturur, get_iam_policy() aracılığıyla allow_policy değerini getirir ve özellikle App Engine yönetici rollerini arayarak tüm bağlamaları arasında döngü oluşturur:

  • roles/viewer
  • roles/editor
  • roles/owner
  • roles/appengine.appAdmin

Bulunan her hedef rol için, bu role ait kullanıcıları derleyip genel yönetici kullanıcıları grubuna ekler. Bu işlem, bulunan ve bu App Engine örneğinin ömrü boyunca sabit (_ADMINS) olarak önbelleğe alınan tüm yönetici kullanıcıları döndürerek sona erer. Bu görüşme kısa süre içinde gösterilir.

Aşağıdaki _get_gae_admins() işlev tanımını, Cloud NDB API istemcisini oluşturmanın hemen altına (ds_client) main.py ekleyin:

def _get_gae_admins():
    'return set of App Engine admins'
    # setup constants for calling Cloud Resource Manager API
    _, PROJ_ID = default(  # Application Default Credentials and project ID
            ['https://www.googleapis.com/auth/cloudplatformprojects.readonly'])
    rm_client = resourcemanager.ProjectsClient()
    _TARGETS = frozenset((     # App Engine admin roles
            'roles/viewer',
            'roles/editor',
            'roles/owner',
            'roles/appengine.appAdmin',
    ))

    # collate users who are members of at least one GAE admin role (_TARGETS)
    admins = set()                      # set of all App Engine admins
    allow_policy = rm_client.get_iam_policy(resource='projects/%s' % PROJ_ID)
    for b in allow_policy.bindings:     # bindings in IAM allow-policy
        if b.role in _TARGETS:          # only look at GAE admin roles
            admins.update(user.split(':', 1).pop() for user in b.members)
    return admins

Kullanıcılar uygulamaya giriş yaptığında şunlar gerçekleşir:

  1. Kullanıcı Firebase'de oturum açtıktan sonra web şablonunda hızlı bir kontrol yapılır.
  2. Şablonda kimlik doğrulama durumu değiştiğinde, işleyicisi sonraki işlev olan is_admin() olan /is_admin'ye Ajax tarzı bir fetch() çağrısı yapılır.
  3. Firebase kimlik jetonu, POST gövdesinde is_admin() işlevine iletilir. Bu işlev, jetonu başlıklardan alır ve doğrulamak için Firebase Admin SDK'sını çağırır. Geçerli bir kullanıcıysa e-posta adresini ayıklayın ve yönetici kullanıcı olup olmadığını kontrol edin.
  4. Ardından, Boole sonucu şablona başarılı bir 200 olarak döndürülür.

_get_gae_admins() ifadesinden hemen sonra is_admin() ifadesini main.py ifadesine ekleyin:

@app.route('/is_admin', methods=['POST'])
def is_admin():
    'check if user (via their Firebase ID token) is GAE admin (POST) handler'
    id_token = request.headers.get('Authorization')
    email = auth.verify_id_token(id_token).get('email')
    return {'admin': email in _ADMINS}, 200

Kullanıcılar hizmetinde (özellikle is_current_user_admin() işlevi) sunulan işlevlerin kopyalanması için her iki işlevdeki kodun tamamı gereklidir. 21. modülde bir yedek çözüm uyguladığımızın aksine, 20. modüldeki bu işlev çağrısı tüm ağır işleri yaptı. Uygulama artık yalnızca App Engine hizmetine bağlı olmadığından uygulamalarınızı Cloud Run'a veya diğer hizmetlere taşıyabilirsiniz. Ayrıca, _TARGETS bölümünde istediğiniz rollere geçerek kendi uygulamalarınız için "yönetici kullanıcı" tanımını da değiştirebilirsiniz. Kullanıcılar Hizmeti ise App Engine yönetici rolleri için sabit kodlanmıştır.

Firebase Auth'ı başlatma ve App Engine yönetici kullanıcılarını önbelleğe alma

Firebase Auth'u, Flask uygulamasının başlatıldığı ve Cloud NDB API istemcisinin oluşturulduğu yere yakın bir yerde başlatabilirdik ancak tüm yönetici kodu tanımlanana kadar buna gerek yoktu. Şu anda bu noktadayız. Benzer şekilde, _get_gae_admins() tanımlandığına göre artık yönetici kullanıcıların listesini önbelleğe almak için bu işlevi çağırabilirsiniz.

Bu satırları is_admin() işlev gövdesinin hemen altına ekleyin:

# initialize Firebase and fetch set of App Engine admins
initialize_app()
_ADMINS = _get_gae_admins()

Veri modeli güncellemeleri sayfasını ziyaret edin.

Visit veri modeli değişmez. Datastore erişimi için Cloud NDB API istemci bağlam yöneticisinin (ds_client.context()) açıkça kullanılması gerekir. Kodda bu, Datastore çağrılarını Python with bloklarında hem store_visit() hem de fetch_visits() ile sarmalamanız gerektiği anlamına gelir. Bu güncelleme, 2. Modül ile aynıdır. Değişiklikleri aşağıdaki şekilde yapın:

ÖNCESİ:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)

def store_visit(remote_addr, user_agent):
    'create new Visit entity in Datastore'
    Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

def fetch_visits(limit):
    'get most recent visits'
    return Visit.query().order(-Visit.timestamp).fetch(limit)

SONRASI:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)

def store_visit(remote_addr, user_agent):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

def fetch_visits(limit):
    'get most recent visits'
    with ds_client.context():
        return Visit.query().order(-Visit.timestamp).fetch(limit)

Kullanıcı girişi mantığını web şablonuna taşıma

App Engine Users hizmeti sunucu tarafında çalışırken Firebase Auth ve Cloud Identity Platform ağırlıklı olarak istemci tarafında çalışır. Sonuç olarak, 20. Modül uygulamasındaki kullanıcı yönetimi kodunun büyük bir kısmı 21. Modül web şablonuna taşınır.

main.py içinde web bağlamı, şablona beş temel veri parçası iletir. Listelenen ilk dört veri, kullanıcı yönetimiyle bağlantılıdır ve kullanıcının oturum açıp açmamasına bağlı olarak değişir:

  • who: Oturum açılmışsa kullanıcının e-posta adresi, aksi takdirde user
  • admin: Oturum açan kullanıcı yöneticiyse (yönetici) rozeti
  • sign: Giriş veya Çıkış düğmesini gösterir.
  • link: Düğme tıklamasıyla oturum açma veya kapatma bağlantıları
  • visits: En son ziyaretler

ÖNCESİ:

@app.route('/')
def root():
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)

    # put together users context for web template
    user = users.get_current_user()
    context = {  # logged in
        'who':   user.nickname(),
        'admin': '(admin)' if users.is_current_user_admin() else '',
        'sign':  'Logout',
        'link':  '/_ah/logout?continue=%s://%s/' % (
                      request.environ['wsgi.url_scheme'],
                      request.environ['HTTP_HOST'],
                  ),  # alternative to users.create_logout_url()
    } if user else {  # not logged in
        'who':   'user',
        'admin': '',
        'sign':  'Login',
        'link':  users.create_login_url('/'),
    }

    # add visits to context and render template
    context['visits'] = visits  # display whether logged in or not
    return render_template('index.html', **context)

Tüm kullanıcı yönetimi web şablonuna taşınıyor. Bu nedenle, ana işleyiciyi 1. Modül uygulamasındaki haline geri getiren yalnızca ziyaretler kalıyor:

SONRASI:

@app.route('/')
def root():
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)
    return render_template('index.html', visits=visits)

Web şablonunu güncelleme

Önceki bölümdeki tüm güncellemeler şablonda nasıl görünüyor? Temel olarak kullanıcı yönetimi, uygulamadan şablonda çalışan Firebase Auth'a taşınıyor ve taşıdığımız tüm kodun bir kısmı JavaScript'e aktarılıyor. main.py'nın oldukça küçüldüğünü gördük. Bu nedenle, templates/index.html'da da benzer bir büyüme bekliyoruz.

ÖNCESİ:

<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
</head>
<body>
<p>
Welcome, {{ who }} <code>{{ admin }}</code>
<button id="logbtn">{{ sign }}</button>
</p><hr>

<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
    <li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>

<script>
document.getElementById("logbtn").onclick = () => {
    window.location.href = '{{ link }}';
};
</script>
</body>
</html>

Web şablonunun tamamını aşağıdaki içerikle değiştirin:

SONRASI:

<!doctype html>
<html>
<head>
<title>VisitMe Example</title>

<script type="module">
// import Firebase module attributes
import {
        initializeApp
} from "https://www.gstatic.com/firebasejs/9.10.0/firebase-app.js";
import {
        GoogleAuthProvider,
        getAuth,
        onAuthStateChanged,
        signInWithPopup,
        signOut
} from "https://www.gstatic.com/firebasejs/9.10.0/firebase-auth.js";

// Firebase config:
// 1a. Go to: console.cloud.google.com/customer-identity/providers
// 1b. May be prompted to enable GCIP and upgrade from Firebase
// 2. Click: "Application Setup Details" button
// 3. Copy: 'apiKey' and 'authDomain' from 'config' variable
var firebaseConfig = {
        apiKey: "YOUR_API_KEY",
        authDomain: "YOUR_AUTH_DOMAIN",
};

// initialize Firebase app & auth components
initializeApp(firebaseConfig);
var auth = getAuth();
var provider = new GoogleAuthProvider();
//provider.setCustomParameters({prompt: 'select_account'});

// define login and logout button functions
function login() {
    signInWithPopup(auth, provider);
};

function logout() {
    signOut(auth);
};

// check if admin & switch to logout button on login; reset everything on logout
onAuthStateChanged(auth, async (user) => {
    if (user && user != null) {
        var email = user.email;
        who.innerHTML = email;
        logbtn.onclick = logout;
        logbtn.innerHTML = "Logout";
        var idToken = await user.getIdToken();
        var rsp = await fetch("/is_admin", {
                method: "POST",
                headers: {Authorization: idToken}
        });
        var data = await rsp.json();
        if (data.admin) {
            admin.style.display = "inline";
        }
    } else {
        who.innerHTML = "user";
        admin.style.display = "none";
        logbtn.onclick = login;
        logbtn.innerHTML = "Login";
    }
});
</script>
</head>

<body>
<p>
Welcome, <span id="who"></span> <span id="admin"><code>(admin)</code></span>
<button id="logbtn"></button>
</p><hr>

<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
    <li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>

<script>
var who    = document.getElementById("who");
var admin  = document.getElementById("admin");
var logbtn = document.getElementById("logbtn");
</script>
</body>
</html>

Bu HTML gövdesinde birçok bileşen var. Bunları tek tek inceleyelim.

Firebase içe aktarma işlemleri

HTML belgesinin başlığında, sayfa başlığının ötesine geçtikten sonra gereken Firebase bileşenlerini içe aktarın. Firebase bileşenleri artık verimlilik için birden fazla modüle ayrılıyor. Firebase'i başlatma kodu ana Firebase uygulama modülünden içe aktarılırken Firebase kimlik doğrulamasını, kimlik doğrulama sağlayıcısı olarak Google'ı, oturum açma ve kapatmayı, kimlik doğrulama durumu değişikliği "geri çağırmayı" yöneten işlevler Firebase Auth modülünden içe aktarılır:

<!doctype html>
<html>
<head>
<title>VisitMe Example</title>

<script type="module">
// import Firebase module attributes
import {
        initializeApp
} from "https://www.gstatic.com/firebasejs/9.10.0/firebase-app.js";
import {
        GoogleAuthProvider,
        getAuth,
        onAuthStateChanged,
        signInWithPopup,
        signOut
} from "https://www.gstatic.com/firebasejs/9.10.0/firebase-auth.js";

Firebase yapılandırması

Bu eğitimin Identity Platform kurulumu bölümünde daha önce Application Setup Details (Uygulama Kurulumu Ayrıntıları) iletişim kutusundan apiKey ve authDomain değerlerini kaydetmiştiniz. Bu değerleri, sonraki bölümdeki firebaseConfig değişkenine ekleyin. Yorumlarda daha ayrıntılı talimatların bağlantısı verilmiştir:

// Firebase config:
// 1a. Go to: console.cloud.google.com/customer-identity/providers
// 1b. May be prompted to enable GCIP and upgrade from Firebase
// 2. Click: "Application Setup Details" button
// 3. Copy: 'apiKey' and 'authDomain' from 'config' variable
var firebaseConfig = {
        apiKey: "YOUR_API_KEY",
        authDomain: "YOUR_AUTH_DOMAIN",
};

Firebase başlatma

Bir sonraki bölümde, Firebase bu yapılandırma bilgileriyle başlatılır.

// initialize Firebase app & auth components
initializeApp(firebaseConfig);
var auth = getAuth();
var provider = new GoogleAuthProvider();
//provider.setCustomParameters({prompt: 'select_account'});

Bu, Google'ı kimlik doğrulama sağlayıcısı olarak kullanma özelliğini ayarlar ve tarayıcı oturumunuzda yalnızca bir Google Hesabı kayıtlı olsa bile hesap seçicinin gösterilmesi için yorum satırı olarak devre dışı bırakılmış bir seçenek sunar. Başka bir deyişle, birden fazla hesabınız olduğunda bu "hesap seçici" ile karşılaşmanız beklenir: a38369389b7c4c7e.png Ancak oturumda yalnızca bir kullanıcı varsa giriş işlemi, kullanıcı etkileşimi olmadan otomatik olarak tamamlanır. (Pop-up gösterilip kaybolur.) Özel parametre satırındaki yorum işaretini kaldırarak hesap seçici iletişim kutusunun bir kullanıcı için gösterilmesini (uygulamaya hemen giriş yapmak yerine) zorlayabilirsiniz. Etkinleştirilirse tek kullanıcılı girişlerde bile hesap seçici gösterilir: b75624cb68d94557.png

Giriş ve çıkış işlevleri

Sonraki kod satırları, giriş veya çıkış düğmesi tıklamalarıyla ilgili işlevleri oluşturur:

// define login and logout button functions
function login() {
    signInWithPopup(auth, provider);
};

function logout() {
    signOut(auth);
};

Oturum açma ve kapatma işlemleri

Bu <script> blokundaki son ana bölüm, her kimlik doğrulama değişikliği (oturum açma veya kapatma) için çağrılan işlevdir.

// check if admin & switch to logout button on login; reset everything on logout
onAuthStateChanged(auth, async (user) => {
    if (user && user != null) {
        var email = user.email;
        who.innerHTML = email;
        logbtn.onclick = logout;
        logbtn.innerHTML = "Logout";
        var idToken = await user.getIdToken();
        var rsp = await fetch("/is_admin", {
                method: "POST",
                headers: {Authorization: idToken}
        });
        var data = await rsp.json();
        if (data.admin) {
            admin.style.display = "inline";
        }
    } else {
        who.innerHTML = "user";
        admin.style.display = "none";
        logbtn.onclick = login;
        logbtn.innerHTML = "Login";
    }
});
</script>
</head>

20. modüldeki, "kullanıcı oturum açtı" şablon bağlamı mı yoksa "kullanıcı oturumu kapattı" bağlamı mı gönderileceğini belirleyen kod buraya taşınır. En üstteki koşul, kullanıcı başarılı bir şekilde giriş yaptığında true sonucunu verir ve aşağıdaki işlemler tetiklenir:

  1. Kullanıcının e-posta adresi gösterilecek şekilde ayarlanır.
  2. Giriş düğmesi Çıkış olarak değişir.
  3. (admin) yönetici kullanıcı rozetinin gösterilip gösterilmeyeceğini belirlemek için /is_admin ile Ajax tarzı bir çağrı yapılır.

Kullanıcı oturumu kapattığında, tüm kullanıcı bilgilerini sıfırlamak için else ifadesi yürütülür:

  1. Kullanıcı adı user olarak ayarlandı
  2. Yönetici rozetleri kaldırıldı
  3. Çıkış düğmesi tekrar Giriş olarak değiştirildi

Şablon değişkenleri

Başlık bölümü sona erdikten sonra, ana gövde gerekli şekilde değişen HTML öğeleriyle değiştirilen şablon değişkenleriyle başlar:

  1. Görünen kullanıcı adı
  2. (admin) yönetici rozeti (varsa)
  3. Giriş veya Çıkış düğmesi
<body>
<p>
Welcome, <span id="who"></span> <span id="admin"><code>(admin)</code></span>
<button id="logbtn"></button>
</p><hr>

En son ziyaretler ve HTML öğesi değişkenleri

En son ziyaret kodu değişmez ve son <script> bloğu, hemen yukarıda listelenen oturum açma ve oturum kapatma için değişen HTML öğelerinin değişkenlerini ayarlar:

<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
    <li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>

<script>
var who    = document.getElementById("who");
var admin  = document.getElementById("admin");
var logbtn = document.getElementById("logbtn");
</script>
</body>
</html>

Bu, App Engine NDB ve Users API'lerinden Cloud NDB ve Identity Platform'a geçişin yanı sıra Python 3'e yükseltme için uygulamada ve web şablonunda yapılması gereken değişiklikleri özetlemektedir. Yeni 21. Modül örnek uygulamanıza ulaştığınız için tebrik ederiz. Versiyonumuz, Module 21b repo folder içinde incelenebilir.

Bu codelab'in bir sonraki bölümü isteğe bağlıdır (*) ve yalnızca uygulamalarının Python 2'de kalması gereken kullanıcılar içindir. Bu bölümde, çalışan bir Python 2 Modülü 21 uygulamasına ulaşmak için gerekli adımlar açıklanmaktadır.

6. *Python 2 geri bağlantı noktası

Bu isteğe bağlı bölüm, Identity Platform'a geçiş yapan ancak Python 2 çalışma zamanında çalışmaya devam etmesi gereken geliştiriciler içindir. Bu sizin için önemli değilse bu bölümü atlayın.

21. Modül uygulamasının çalışan bir Python 2 sürümünü oluşturmak için aşağıdakilere ihtiyacınız vardır:

  1. Çalışma zamanı gereksinimleri: Python 2'yi destekleyen yapılandırma dosyaları ve Python 3 ile uyumsuzlukları önlemek için ana uygulamada yapılması gereken değişiklikler
  2. Küçük kitaplık değişikliği: Python 2, gerekli bazı özellikler Resource Manager istemci kitaplığına eklenmeden önce desteği sonlandırılmıştı. Bu nedenle, eksik işlevlere erişmek için alternatif bir yöntem kullanmanız gerekir.

Şimdi yapılandırmadan başlayarak bu adımları uygulayalım.

appengine_config.py dosyasını geri yükleme

Bu eğitimin önceki bölümlerinde, Python 3 App Engine çalışma zamanı tarafından kullanılmadığı için appengine_config.py öğesini silmeniz istenmişti. Python 2 için yalnızca korunması gerekmez, aynı zamanda appengine_config.py modülünün yerleşik üçüncü taraf kitaplıkların (yani grpcio ve setuptools) kullanımını destekleyecek şekilde güncellenmesi gerekir. Bu paketler, App Engine uygulamanız Cloud NDB ve Cloud Resource Manager gibi Cloud istemci kitaplıklarını her kullandığında gereklidir.

Bu paketleri kısa süre içinde app.yaml'ya ekleyeceksiniz ancak uygulamanızın bunlara erişebilmesi için setuptools'daki pkg_resources.working_set.add_entry() işlevinin çağrılması gerekir. Bu, lib klasörüne yüklenen kopyalanmış (kendiliğinden paketlenmiş veya satıcıdan alınmış) üçüncü taraf kitaplıkların yerleşik kitaplıklarla iletişim kurmasına olanak tanır.

Bu değişikliklerin geçerli olması için appengine_config.py dosyanızda aşağıdaki güncellemeleri uygulayın:

ÖNCESİ:

from google.appengine.ext import vendor

# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)

Bu kod tek başına setuptools ve grpcio kullanımını desteklemek için yeterli değildir. Birkaç satır daha eklemeniz gerekiyor. Bu nedenle, appengine_config.py dosyasını aşağıdaki gibi görünecek şekilde güncelleyin:

SONRASI:

import pkg_resources
from google.appengine.ext import vendor

# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
# Add libraries to pkg_resources working set to find the distribution.
pkg_resources.working_set.add_entry(PATH)

Cloud istemci kitaplıklarını desteklemek için gereken değişikliklerle ilgili daha fazla bilgiyi paketlenmiş hizmetleri taşıma belgelerinde bulabilirsiniz.

app.yaml

appengine_config.py'ya benzer şekilde, app.yaml dosyası Python 2'yi destekleyen bir dosyaya geri döndürülmelidir. Orijinal 20. modül app.yaml ile başlayalım:

ÖNCESİ:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

Daha önce belirtilen setuptools ve grpcio'ye ek olarak, Cloud Storage istemci kitaplığının kullanılmasını gerektiren bir bağımlılık (Identity Platform taşıma işlemiyle açıkça ilişkili değildir) vardır ve bu, ssl adlı başka bir yerleşik üçüncü taraf paketini gerektirir. libraries bölümüne üçünü de ekleyin. app.yaml için bu paketlerin mevcut "en yeni" sürümlerini seçin:

SONRASI:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

libraries:
- name: grpcio
  version: latest
- name: setuptools
  version: latest
- name: ssl
  version: latest

requirements.txt

21. modülde Python 3 requirements.txt'e Google Auth, Cloud NDB, Cloud Resource Manager ve Firebase Admin SDK'yı ekledik. Python 2'deki durum daha karmaşıktır:

ÖNCESİ:

flask

20. modülden requirements.txt başlayarak, 21. modül uygulamasının çalışması için aşağıdaki şekilde güncelleyin:

SONRASI:

grpcio==1.0.0
protobuf<3.18.0
six>=1.13.0
flask
google-gax<0.13.0
google-api-core==1.31.1
google-api-python-client<=1.11.0
google-auth<2.0dev
google-cloud-datastore==1.15.3
google-cloud-firestore==1.9.0
google-cloud-ndb
google-cloud-pubsub==1.7.0
firebase-admin

Bağımlılıklar değiştikçe paket ve sürüm numaraları depoda güncellenir ancak bu app.yaml, bu yazı yazıldığı sırada çalışan bir uygulama için yeterlidir.

Diğer yapılandırma güncellemeleri

Bu codelab'in önceki bölümlerinde lib klasörünü silmediyseniz şimdi silin. Yeni güncellenen requirements.txt ile bu gereksinimleri lib'e yüklemek için şu tanıdık komutu verin:

pip install -t lib -r requirements.txt  # or pip2

Geliştirme sisteminizde hem Python 2 hem de 3 yüklüyse pip yerine pip2 kullanmanız gerekebilir.

Uygulama kodunu değiştirme

Neyse ki gerekli değişikliklerin çoğu yapılandırma dosyalarında yapılıyor. Uygulama kodunda yapılması gereken tek değişiklik, API'ye erişmek için Resource Manager istemci kitaplığı yerine daha düşük düzeydeki Google API istemci kitaplığını kullanmak üzere küçük bir güncelleme yapmaktır. templates/index.html web şablonunda güncelleme yapılması gerekmez.

İçe aktarma işlemlerini ve başlatmayı güncelleme

Aşağıda gösterildiği gibi Resource Manager istemci kitaplığını (google.cloud.resourcemanager) Google API'leri istemci kitaplığıyla (googleapiclient.discovery) değiştirin:

ÖNCESİ:

from flask import Flask, render_template, request
from google.auth import default
from google.cloud import ndb, resourcemanager
from firebase_admin import auth, initialize_app

SONRASI:

from flask import Flask, render_template, request
from google.auth import default
from google.cloud import ndb
from googleapiclient import discovery
from firebase_admin import auth, initialize_app

App Engine Admin kullanıcıları için destek

Daha düşük düzeydeki istemci kitaplığının kullanılabilmesi için _get_gae_admins()'da birkaç değişiklik yapılması gerekir. Önce nelerin değiştiğini ele alalım, ardından güncelleme için gereken tüm kodu size verelim.

Python 2 kodu, google.auth.default()'dan döndürülen hem kimlik bilgilerinin hem de proje kimliğinin kullanılmasını gerektirir. Kimlik bilgileri Python 3'te kullanılmadığı için genel bir alt çizgi ( _ ) sahte değişkenine atanmıştır. Python 2 sürümü için gerekli olduğundan alt çizgiyi CREDS olarak değiştirin. Ayrıca, Resource Manager API istemcisi oluşturmak yerine API istemcisine benzer bir API hizmet uç noktası oluşturacaksınız. Bu nedenle, aynı değişken adını (rm_client) kullanmaya devam ediyoruz. Bir fark, hizmet uç noktası oluşturmak için kimlik bilgilerinin (CREDS) gerekmesidir.

Bu değişiklikler aşağıdaki kodda gösterilmektedir:

ÖNCESİ:

_, PROJ_ID = default(  # Application Default Credentials and project ID
        ['https://www.googleapis.com/auth/cloudplatformprojects.readonly'])
rm_client = resourcemanager.ProjectsClient()

SONRASI:

CREDS, PROJ_ID = default(  # Application Default Credentials and project ID
        ['https://www.googleapis.com/auth/cloud-platform'])
rm_client = discovery.build('cloudresourcemanager', 'v1', credentials=CREDS)

Diğer bir fark ise Resource Manager istemci kitaplığının noktalı özellik gösterimi kullanan allow-policy nesneleri döndürmesidir. Daha düşük düzeydeki istemci kitaplığı ise köşeli parantezlerin ( [ ]) kullanıldığı Python sözlüklerini döndürür. Örneğin, Resource Manager istemci kitaplığı için binding.role, daha düşük düzeydeki kitaplık için ise binding['role'] kullanılır. Ayrıca, eski kitaplıkta "underscore_separated" adlar ve API parametrelerini iletmek için biraz farklı bir yöntem kullanılırken, alt düzey kitaplık "CamelCased" adları tercih eder.

Bu kullanım farklılıkları aşağıda gösterilmiştir:

ÖNCESİ:

allow_policy = rm_client.get_iam_policy(resource='projects/%s' % PROJ_ID)
for b in allow_policy.bindings:     # bindings in IAM allow-policy
    if b.role in _TARGETS:          # only look at GAE admin roles
        admins.update(user.split(':', 1).pop() for user in b.members)

SONRASI:

allow_policy = rm_client.projects().getIamPolicy(resource=PROJ_ID).execute()
for b in allow_policy['bindings']:  # bindings in IAM allow-policy
    if b['role'] in _TARGETS:       # only look at GAE admin roles
        admins.update(user.split(':', 1).pop() for user in b['members'])

Tüm bu değişiklikleri bir araya getirerek Python 3 _get_gae_admins() işlevini eşdeğer Python 2 sürümüyle değiştirin:

def _get_gae_admins():
    'return set of App Engine admins'
    # setup constants for calling Cloud Resource Manager API
    CREDS, PROJ_ID = default(  # Application Default Credentials and project ID
            ['https://www.googleapis.com/auth/cloud-platform'])
    rm_client = discovery.build('cloudresourcemanager', 'v1', credentials=CREDS)
    _TARGETS = frozenset((     # App Engine admin roles
            'roles/viewer',
            'roles/editor',
            'roles/owner',
            'roles/appengine.appAdmin',
    ))

    # collate users who are members of at least one GAE admin role (_TARGETS)
    admins = set()                      # set of all App Engine admins
    allow_policy = rm_client.projects().getIamPolicy(resource=PROJ_ID).execute()
    for b in allow_policy['bindings']:  # bindings in IAM allow-policy
        if b['role'] in _TARGETS:       # only look at GAE admin roles
            admins.update(user.split(':', 1).pop() for user in b['members'])
    return admins

is_admin() işlevi, zaten güncellenmiş olan _get_gae_admins()'e dayandığı için herhangi bir güncelleme gerektirmez.

Python 3 Modülü 21 uygulamasını Python 2'ye geri aktarmak için gereken değişiklikler burada sona eriyor. Güncellenen 21. modül örnek uygulamanıza ulaştığınız için tebrik ederiz. Tüm kodu Module 21a repo folder içinde bulabilirsiniz.

7. Özet/Temizleme

Codelab'deki son adımlar, bu uygulamayı çalıştıran sorumluların (kullanıcılar veya hizmet hesapları) gerekli izinlere sahip olmasını sağlamak, ardından uygulamanızı amaçlandığı gibi çalıştığını ve değişikliklerin çıkışa yansıtıldığını doğrulamak için dağıtmaktır.

IAM izin politikasını okuma yetkisi

Daha önce, App Engine yönetici kullanıcısı olarak tanınmak için gereken dört rolü tanıtmıştık. Şimdi ise bilmeniz gereken beşinci bir rol var:

  • roles/viewer
  • roles/editor
  • roles/owner
  • roles/appengine.appAdmin
  • roles/resourcemanager.projectIamAdmin (IAM izin politikasına erişen asıl kullanıcılar için)

roles/resourcemanager.projectIamAdmin rolü, asıl kullanıcıların bir son kullanıcının App Engine yönetici rollerinden herhangi birinin üyesi olup olmadığını belirlemesini sağlar. roles/resourcemanager.projectIamAdmin üyesi olmadan, izin politikasını almak için Cloud Resource Manager API'ye yapılan çağrılar başarısız olur.

Uygulamanız, bu role otomatik olarak üyelik verilen App Engine'in varsayılan hizmet hesabı altında çalışacağı için burada herhangi bir açık işlem yapmanız gerekmez. Geliştirme aşamasında varsayılan hizmet hesabını kullansanız bile, uygulamanızın düzgün çalışması için gereken minimum izinlere sahip bir kullanıcı tarafından yönetilen hizmet hesabı oluşturup kullanmanızı önemle tavsiye ederiz. Bu tür bir hizmet hesabına üyelik vermek için aşağıdaki komutu çalıştırın:

$ gcloud projects add-iam-policy-binding PROJ_ID --member="serviceAccount:USR_MGD_SVC_ACCT@PROJ_ID.iam.gserviceaccount.com" --role=roles/resourcemanager.projectIamAdmin

PROJ_ID, Cloud projesi kimliği, USR_MGD_SVC_ACCT@PROJ_ID.iam.gserviceaccount.com ise uygulamanız için oluşturduğunuz kullanıcı tarafından yönetilen hizmet hesabıdır. Bu komut, projenizin güncellenmiş IAM politikasını verir. Burada, hizmet hesabının roles/resourcemanager.projectIamAdmin üyesi olduğunu doğrulayabilirsiniz. Daha fazla bilgi için referans belgelerine bakın. Tekrar belirtmek gerekirse bu codelab'de bu komutu vermeniz gerekmez ancak kendi uygulamalarınızı modernleştirirken referans olarak kullanmak üzere kaydedebilirsiniz.

Uygulamayı dağıtma ve doğrulama

Uygulamanızı standart gcloud app deploy komutuyla buluta yükleyin. Dağıtım tamamlandıktan sonra, kullanıcı yönetimi için App Engine Users hizmetini Cloud Identity Platform (ve Firebase Auth) ile başarıyla değiştirmiş olmanız dışında, 20. Modül uygulamasının neredeyse aynısı olan bir işlev görmeniz gerekir:

3a83ae745121d70.png

20. Modül'e kıyasla fark edeceğiniz bir değişiklik, Giriş'i tıkladığınızda yönlendirme yerine pop-up açılmasıdır. Bu durum, aşağıdaki ekran görüntülerinden bazılarında gösterilmiştir. Ancak 20. modülde olduğu gibi, tarayıcıya kaç Google Hesabı kaydedildiğine bağlı olarak davranış biraz farklılık gösterir.

Tarayıcıya kayıtlı kullanıcı yoksa veya henüz oturum açmamış tek bir kullanıcı varsa genel bir Google ile oturum açma pop-up'ı gösterilir:

8437f5f3d489a942.png

Tarayıcınıza tek bir kullanıcı kaydedilmişse ancak bu kullanıcı başka bir yerde oturum açarsa herhangi bir iletişim kutusu görünmez (veya iletişim kutusu açılıp hemen kapanır) ve uygulama oturum açılmış duruma geçer (kullanıcı e-postası ve Oturumu kapat düğmesi gösterilir).

Bazı geliştiriciler, tek bir kullanıcı için bile hesap seçici sağlamak isteyebilir:

b75624cb68d94557.png

Bunu uygulamak için web şablonundaki provider.setCustomParameters({prompt: 'select_account'}); satırının yorumunu daha önce açıklandığı şekilde kaldırın.

Birden fazla kullanıcı varsa hesap seçici iletişim kutusu açılır (aşağıya bakın). Henüz oturum açmadıysa kullanıcıya oturum açması istenir. Oturumunuz zaten açıksa pop-up kaybolur ve uygulama oturum açılmış duruma geçer.

c454455b6020d5e4.png

21. modülün oturum açma durumu, 20. modülün kullanıcı arayüzüyle aynı görünüme sahiptir:

49ebe4dcc1eff11f.png

Aynı durum, yönetici kullanıcı oturum açtığında da geçerlidir:

44302f35b39856eb.png

21. Modül'ün aksine, 20. Modül her zaman web şablonu içeriğinin mantığına uygulamadan (sunucu tarafı kodu) erişir. 20. Modül'ün bir kusuru, son kullanıcı uygulamaya ilk kez dokunduğunda bir ziyaretin, kullanıcı oturum açtığında ise başka bir ziyaretin kaydedilmesidir.

21. modülde giriş mantığı yalnızca web şablonunda (istemci tarafı kodu) gerçekleşir. Hangi içeriğin gösterileceğini belirlemek için sunucu tarafında gerekli bir gezi yoktur. Sunucuya yapılan tek çağrı, bir son kullanıcı oturum açtıktan sonra yönetici kullanıcıların kontrol edilmesidir. Bu, giriş ve çıkışların ek ziyaret olarak kaydedilmediği anlamına gelir. Bu nedenle, kullanıcı yönetimi işlemleri için en son ziyaretler listesi sabit kalır. Yukarıdaki ekran görüntülerinde, aynı dört ziyaretin birden fazla kullanıcı girişiyle gösterildiğine dikkat edin.

20. Modül'deki ekran görüntüleri, bu codelab'in başında "çift ziyaret hatası"nı gösterir. Her oturum açma veya kapatma işlemi için ayrı ziyaret günlükleri gösterilir. Kronolojik sıralamayı gösteren her ekran görüntüsünün en son ziyaret zaman damgalarını kontrol edin.

Temizleme

Genel

Şimdilik işiniz bittiyse faturalandırmayı önlemek için App Engine uygulamanızı devre dışı bırakmanızı öneririz. Ancak biraz daha test veya deneme yapmak isterseniz App Engine platformunda ücretsiz kota bulunur. Bu nedenle, kullanım katmanını aşmadığınız sürece sizden ücret alınmaz. Bu, işlem için geçerlidir ancak ilgili App Engine hizmetleri için de ücret alınabilir. Daha fazla bilgi için fiyatlandırma sayfasını inceleyin. Bu taşıma işlemine başka Cloud hizmetleri de dahilse bunlar ayrı olarak faturalandırılır. Her iki durumda da varsa aşağıdaki "Bu codelab'e özel" bölümüne bakın.

Tam açıklama yapmak gerekirse App Engine gibi bir Google Cloud sunucusuz bilgi işlem platformuna dağıtım yapıldığında küçük derleme ve depolama maliyetleri oluşur. Cloud Build ve Cloud Storage'ın kendi ücretsiz kotaları vardır. Bu görüntünün depolanması, kotanın bir kısmını kullanır. Ancak, böyle bir ücretsiz katmanın olmadığı bir bölgede yaşıyor olabilirsiniz. Bu nedenle, olası maliyetleri en aza indirmek için depolama alanı kullanımınıza dikkat edin. İncelemeniz gereken belirli Cloud Storage "klasörleri" şunlardır:

  • console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/images
  • console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com
  • Yukarıdaki depolama bağlantıları PROJECT_ID ve LOCınıza bağlıdır. Örneğin, uygulamanız ABD'de barındırılıyorsa "us" olur.

Öte yandan, bu uygulamaya veya ilgili diğer taşıma codelab'lerine devam etmeyecekseniz ve her şeyi tamamen silmek istiyorsanız projenizi kapatın.

Bu codelab'e özel

Aşağıda listelenen hizmetler bu codelab'e özeldir. Daha fazla bilgi için her ürünün belgelerine bakın:

Sonraki adımlar

Bu eğitimin yanı sıra eski paketlenmiş hizmetlerden geçişe odaklanan diğer taşıma modüllerini de inceleyebilirsiniz:

  • 2. Modül: App Engine ndb'den Cloud NDB'ye taşıma
  • 7-9. modüller: App Engine görev sırasından (push görevleri) Cloud Tasks'e geçiş
  • 12-13. modüller: App Engine Memcache'ten Cloud Memorystore'a geçiş
  • 15-16. Modüller: App Engine Blobstore'dan Cloud Storage'a geçiş
  • 18-19. Modüller: App Engine görev sırasından (çekme görevleri) Cloud Pub/Sub'a geçiş

App Engine artık Google Cloud'daki tek sunucusuz platform değil. Küçük bir App Engine uygulamanız veya sınırlı işlevselliğe sahip bir uygulamanız varsa ve bunu bağımsız bir mikro hizmete dönüştürmek istiyorsanız ya da tek bir uygulamayı birden fazla yeniden kullanılabilir bileşene ayırmak istiyorsanız Cloud Functions'a geçmeyi düşünebilirsiniz. Container mimarisine alma, özellikle CI/CD (sürekli entegrasyon/sürekli teslim veya dağıtım) ardışık düzeninden oluşuyorsa uygulama geliştirme iş akışınızın bir parçası haline geldiyse Cloud Run'a geçmeyi düşünebilirsiniz. Bu senaryolar aşağıdaki modüllerde ele alınır:

  • App Engine'den Cloud Functions'a geçiş: 11. Modül'e bakın.
  • App Engine'den Cloud Run'a taşıma: Uygulamanızı Docker ile container mimarisine almak için 4. Modül'e, container'lar, Docker bilgisi veya Dockerfile olmadan yapmak için 5. Modül'e bakın.

Başka bir sunucusuz platforma geçmek isteğe bağlıdır. Herhangi bir değişiklik yapmadan önce uygulamalarınız ve kullanım alanlarınız için en iyi seçenekleri göz önünde bulundurmanızı öneririz.

Bir sonraki geçiş modülünüz hangisi olursa olsun, tüm Serverless Migration Station içeriklerine (codelab'ler, videolar, kaynak kodu [varsa]) açık kaynaklı depodan erişebilirsiniz. Depodaki README, hangi taşımaların dikkate alınması gerektiği ve ilgili "sıra" hakkında da rehberlik sağlar.

8. Ek kaynaklar

Bu veya ilgili taşıma modüllerini daha ayrıntılı olarak inceleyen geliştiriciler için ek kaynakları aşağıda bulabilirsiniz. Aşağıda bu içerikle ilgili geri bildirimde bulunabilir, kod bağlantılarını ve faydalı bulabileceğiniz çeşitli dokümanları inceleyebilirsiniz.

Codelab'lerle ilgili sorunlar/geri bildirimler

Bu codelab ile ilgili sorun bulursanız lütfen göndermeden önce sorununuzu arayın. Arama yapma ve yeni sorunlar oluşturma bağlantıları:

Taşıma kaynakları

20. Modül (BAŞLANGIÇ) ve 21. Modül (BİTİŞ) ile ilgili depo klasörlerinin bağlantılarını aşağıdaki tabloda bulabilirsiniz.

Codelab

Python 2

Python 3

20. Modül

code

(yok)

21. Modül (bu codelab)

code

code

Online referanslar

Bu eğitimle ilgili kaynakları aşağıda bulabilirsiniz:

Cloud Identity Platform ve Cloud Marketplace

Cloud Resource Manager, Cloud IAM, Firebase Admin SDK

App Engine kullanıcıları, App Engine NDB, Cloud NDB, Cloud Datastore

Diğer taşıma modülü referansları

App Engine'e taşıma

App Engine platformu

Google Cloud SDK

Diğer Cloud bilgileri

Videolar

Lisans

Bu çalışma, Creative Commons Attribution 2.0 Genel Amaçlı Lisans ile lisans altına alınmıştır.