1. Omówienie
Seria ćwiczeń z programowania dla bezserwerowych stacji migracji (samouczek, samouczków) i podobnych filmów ma pomóc deweloperom bezserwerowych Google Cloud w modernizacji aplikacji przez przeprowadzenie co najmniej 1 migracji, w wyniku rezygnacji ze starszych usług. W ten sposób Twoje aplikacje stają się bardziej przenośne, mają więcej opcji i elastyczność, co pozwala na integrację z szerszą gamą usług Cloud i uzyskiwanie do nich dostępu, a także łatwiejsze przejście na nowsze wersje językowe. Choć początkowo koncentrowaliśmy się na pierwszych użytkownikach Cloud, głównie deweloperów korzystających ze środowiska App Engine (środowisko standardowe), ta seria jest na tyle szeroka, aby uwzględnić inne platformy bezserwerowe, takie jak Cloud Functions i Cloud Run, oraz inne, w stosownych przypadkach.
Celem tego ćwiczenia w Codelabs jest pokazanie deweloperom aplikacji w języku Python 2 App Engine, jak przejść z interfejsu API/usługi użytkowników App Engine na Cloud Identity Platform (GCIP). Dostępna jest też migracja z App Engine NDB do Cloud NDB na potrzeby dostępu do Datastore (omówiona głównie w module migracji 2), a także przejście na Pythona 3.
W części 20 opisujemy, jak dodać sposób korzystania z interfejsu Users API do przykładowej aplikacji w module 1. W tym module ukończysz aplikację z modułu 20 i przeniesiesz jej wykorzystanie do Cloud Identity Platform.
Dowiesz się, jak:
- Zastąp użycie usługi App Engine Użytkownicy usługą Cloud Identity Platform.
- Zastąp korzystanie z App Engine NDB za pomocą Cloud NDB (zobacz też moduł 2).
- Skonfiguruj różnych dostawców tożsamości uwierzytelniania za pomocą Uwierzytelniania Firebase
- Uzyskiwanie informacji o uprawnieniach projektu przy użyciu interfejsu Cloud Resource Manager API
- Uzyskiwanie informacji o użytkownikach za pomocą pakietu Firebase Admin SDK
- Przenoszenie przykładowej aplikacji do języka Python 3
Czego potrzebujesz
- projekt Google Cloud Platform z aktywnym kontem rozliczeniowym GCP;
- Podstawowe umiejętności w języku Python
- praktyczna znajomość typowych poleceń w Linuksie
- Podstawowa wiedza o tworzeniu i wdrażaniu aplikacji App Engine.
- Przykładowa aplikacja działającego modułu 20 App Engine
Ankieta
Jak wykorzystasz ten samouczek?
Jak oceniasz swoje doświadczenia z językiem Python?
Jak oceniasz korzystanie z usług Google Cloud?
2. Tło
Usługa użytkowników App Engine to system uwierzytelniania użytkowników używany przez aplikacje App Engine. Udostępnia Logowanie przez Google jako dostawcę tożsamości, oferuje wygodne linki do logowania i wylogowywania się w aplikacjach oraz obsługuje koncepcję administratorów i funkcji dostępnych tylko dla administratorów. Aby zwiększyć przenośność aplikacji, Google Cloud zaleca przejście ze starszych pakietów App Engine na samodzielne usługi Cloud, na przykład z usługi Użytkownicy na Cloud Identity Platform.
Identity Platform jest oparty na Uwierzytelnianiu Firebase i dodaje wiele funkcji dla firm, w tym uwierzytelnianie wielopoziomowe, OIDC oraz Obsługa logowania jednokrotnego przez SAML, środowisko wielu najemców, gwarancja jakości usług na poziomie 99, 95% i inne funkcje. Różnice te są również wyróżnione na stronie porównania usług Identity Platform i Uwierzytelnianie Firebase. Obie usługi mają znacznie więcej funkcji niż usługa Użytkownicy.
W tym ćwiczeniu z programowania w module 21 pokazujemy, jak przejść z usługi Użytkownicy na funkcje Identity Platform dotyczące uwierzytelniania użytkowników aplikacji, które najlepiej odzwierciedlają funkcje omówione w module 20. Moduł 21 zawiera również migrację z App Engine NDB do Cloud NDB w celu uzyskania dostępu do Datastore, powtarzając migrację modułu 2.
Z kolei kod modułu 20 jest „reklamowany” jako przykładowa aplikacja w języku Python 2, samo źródło jest zgodne z językiem Python 2 i 3 i nie zmieni się nawet po migracji do Identity Platform (i Cloud NDB) w module 21. Możesz nadal korzystać z usługi Użytkownicy podczas uaktualniania do Pythona 3, ponieważ migracja do Identity Platform jest opcjonalna. Aby dowiedzieć się, jak dalej korzystać z pakietów usług przy jednoczesnym uaktualnieniu środowisk wykonawczych drugiej generacji, takich jak Python 3, zapoznaj się z ćwiczeniem z programowania poświęconym modułowi 17 i filmem.
W tym samouczku omawiamy następujące kroki:
- Konfiguracja/praca
- Aktualizacja konfiguracji
- Modyfikowanie kodu aplikacji
3. Konfiguracja/praca
W tej sekcji dowiesz się, jak:
- Konfigurowanie projektu Cloud
- Pobierz przykładową aplikację bazową
- (Ponowne) wdrażanie i weryfikowanie aplikacji bazowej
- Włącz nowe usługi i interfejsy API Google Cloud
Dzięki tym krokom zaczynasz od działającego kodu, który jest gotowy do migracji do samodzielnych usług Cloud.
1. Konfigurowanie projektu
Jeśli udało Ci się ukończyć Moduł 20 z programowania, wykorzystaj ponownie ten sam projekt (i kod). Możesz też utworzyć nowy projekt lub wykorzystać inny istniejący projekt. Sprawdź, czy projekt ma aktywne konto rozliczeniowe i włączoną aplikację App Engine. Znajdź identyfikator projektu i miej go pod ręką podczas tych ćwiczeń z programowania. Użyj go, gdy napotkasz zmienną PROJ_ID
.
2. Pobierz przykładową aplikację bazową
Jednym z warunków wstępnych jest działająca aplikacja z modułu 20 App Engine, więc wykonaj ćwiczenia z programowania (zalecane; link powyżej) lub skopiuj kod modułu 20 z repozytorium. Bez względu na to, czy używasz swoich czy naszych danych, od tego zaczniemy („START”). To ćwiczenie w Codelabs przeprowadzi Cię przez proces migracji, zakończy się kodem podobnym do tego, który znajduje się w folderze repozytorium modułu 21 („FINISH”).
- START: folder modułu 20 (Python 2)
- ZAKOŃCZ: Moduł 21 foldery ( Python 2 lub Python 3)
- Całe repozytorium (aby sklonować lub pobrać plik ZIP)
Skopiuj folder repozytorium modułu 20. Powinny one wyglądać jak poniższe dane wyjściowe. Jeśli ćwiczenie z programowania w module 20 zostało przez Ciebie wykonane, może zawierać folder lib
:
$ ls README.md appengine_config.py templates app.yaml main.py requirements.txt
3. (Ponowne) wdrażanie i weryfikowanie aplikacji bazowej
Aby wdrożyć aplikację modułu 20, wykonaj te czynności:
- Usuń folder
lib
(jeśli istnieje), a następnie uruchom poleceniepip install -t lib -r requirements.txt
, aby ponownie go wypełnić. Jeśli masz zainstalowany zarówno język Python 2, jak i Python 3, może być konieczne użycie metodypip2
. - Pamiętaj, aby zainstalować i zainicjować narzędzie wiersza poleceń
gcloud
, a także sprawdzić jego użycie. - Jeśli nie chcesz wpisywać danych
PROJ_ID
przy każdym wydanym poleceniugcloud
, ustaw najpierw projekt Google Cloud na wartośćgcloud config set project
PROJ_ID
. - Wdróż przykładową aplikację za pomocą:
gcloud app deploy
- Potwierdź, że aplikacja działa zgodnie z oczekiwaniami i nie zawiera błędów. Jeśli udało Ci się ukończyć Moduł 20, aplikacja wyświetla dane logowania użytkownika (adres e-mail, możliwe „plakietkę administratora” i przycisk logowania/wylogowania) u góry wraz z ostatnimi wizytami (jak pokazano poniżej).
Gdy logujesz się jako zwykły użytkownik, wyświetla się jego adres e-mail i jest wyświetlany komunikat „Zaloguj się” przycisk zmienia się na „Wyloguj się”. przycisk:
Gdy logujesz się jako administrator, adres e-mail użytkownika jest wyświetlany razem z ciągiem „(admin)”. obok niej:
4. Włącz nowe interfejsy API/usługi Google Cloud
Wprowadzenie
Aplikacja Module 20 korzysta z interfejsów App Engine NDB i Users API, usług dostępnych w pakiecie, które nie wymagają dodatkowej konfiguracji, ale samodzielne usługi Cloud już tak. Zaktualizowana aplikacja będzie korzystać zarówno z Cloud Identity Platform, jak i Cloud Datastore (za pomocą biblioteki klienta Cloud NDB). Musimy też określić administratorów App Engine, korzystając z interfejsu Cloud Resource Manager API.
Koszt
- App Engine i Cloud Datastore mają „Zawsze bezpłatne” poziomu. Jeśli będziesz go przekraczać, nie będziemy naliczać opłat za wykonanie tego samouczka. Więcej informacji znajdziesz też na stronie z cennikiem App Engine i na stronie z cennikiem Cloud Datastore.
- Opłaty za korzystanie z Cloud Identity Platform są naliczane w zależności od liczby aktywnych użytkowników miesięcznie lub liczby weryfikacji uwierzytelniania. jakaś wersja „bezpłatnej” jest dostępna dla każdego modelu wykorzystania. Więcej informacji znajdziesz na stronie z cennikiem. Co więcej, chociaż App Engine i Cloud Datastore wymagają płatności, samo korzystanie z GCIP nie wymaga włączenia płatności, o ile nie przekraczasz dziennych limitów bez instrumentów. Warto to rozważyć w przypadku projektów Cloud, które nie wymagają rozliczeń ani usług Cloud APIs.
- Korzystanie z interfejsu Cloud Resource Manager API jest w większości bezpłatne, zgodnie z cennikiem.
W zależności od preferencji użytkownicy włączają interfejsy Cloud APIs za pomocą konsoli Cloud lub wiersza poleceń (za pomocą polecenia gcloud
, które jest częścią pakietu SDK Cloud). Zacznijmy od interfejsów Cloud Datastore i Cloud Resource Manager API.
W konsoli Google Cloud
Otwórz stronę Biblioteki menedżera interfejsów API (odpowiedni projekt) w konsoli Cloud i wyszukaj interfejs API, korzystając z paska wyszukiwania.
Włącz te interfejsy API:
- Cloud Datastore
- Cloud Resource Manager (Menedżer zasobów Cloud)
Odszukaj i kliknij przycisk Włącz oddzielnie dla każdego interfejsu API. Może pojawić się prośba o podanie informacji rozliczeniowych. Oto przykładowa strona interfejsu Resource Manager API:
Po włączeniu przycisk zmienia się na Zarządzaj (zwykle po kilku sekundach):
Włącz Cloud Datastore w ten sam sposób:
Wiersz poleceń
Chociaż włączenie interfejsów API z poziomu konsoli jest dobrze ilustrowane, niektórzy wolą używać wiersza poleceń. Dodatkową zaletą jest to, że możesz włączyć dowolną liczbę interfejsów API jednocześnie. Uruchom to polecenie, by włączyć interfejsy Cloud Datastore i Cloud Resource Manager API oraz poczekać na zakończenie operacji, jak pokazano tutaj:
$ gcloud services enable cloudresourcemanager.googleapis.com datastore.googleapis.com Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.
Może pojawić się prośba o podanie informacji rozliczeniowych.
Kolumny „Adresy URL” każdego interfejsu API użytego w powyższym poleceniu są nazywane nazwami usług interfejsów API. Można je znaleźć u dołu strony biblioteki danego interfejsu API. Jeśli chcesz włączyć inne interfejsy Cloud API dla swoich aplikacji, ich nazwy usług znajdziesz na odpowiednich stronach interfejsów API. To polecenie wyświetla listę wszystkich nazw usług dla interfejsów API, które możesz włączyć:
gcloud services list
--available --filter="name:googleapis.com"
.
Po wykonaniu powyższych czynności zarówno w konsoli Cloud, jak i w wierszu poleceń, nasz przykład ma teraz dostęp do tych interfejsów API. Kolejne kroki to włączenie Cloud Identity Platform i wprowadzenie niezbędnych zmian w kodzie.
Włączanie i konfigurowanie Cloud Identity Platform (tylko w konsoli Cloud)
Cloud Identity Platform jest usługą Marketplace, ponieważ łączy się z zasobem spoza Google Cloud lub zależy od niego, na przykład z Uwierzytelnianiem Firebase. Obecnie usługi Marketplace możesz włączać tylko w konsoli Cloud. Wykonaj te czynności:
- Otwórz stronę Cloud Identity Platform w Cloud Marketplace i kliknij tam przycisk Włącz. Jeśli pojawi się taka prośba, przejdź na Uwierzytelnianie Firebase, aby odblokować dodatkowe funkcje, takie jak te opisane wcześniej w sekcji Kontekst. Oto strona Marketplace z zaznaczonym przyciskiem Włącz:
- Po włączeniu Identity Platform może nastąpić automatyczne przeniesienie na stronę Dostawcy tożsamości. Jeśli nie, kliknij ten wygodny link, aby przejść do strony.
- Włącz dostawcę uwierzytelniania Google. Jeśli nie masz skonfigurowanych żadnych dostawców, kliknij Add a Provider (Dodaj dostawcę) i wybierz Google (Google). Gdy wrócisz na ten ekran, wpis Google powinien być włączony. Google jest jedynym dostawcą uwierzytelniania używanym w tym samouczku, aby odzwierciedlić usługę Użytkownicy App Engine jako uproszczoną usługę logowania przez Google. We własnych aplikacjach możesz włączyć dodatkowych dostawców uwierzytelniania.
- Gdy wybierzesz i skonfigurujesz Google i innych dostawców uwierzytelniania, kliknij Application Setup Details (Szczegóły konfiguracji aplikacji), a następnie w oknie potwierdzenia skopiuj
apiKey
iauthDomain
z obiektuconfig
na karcie Sieć, zapisując oba w bezpiecznym miejscu. Może skopiujesz je wszystkie? Fragment tego okna jest zakodowany na stałe i opatrzony datą, dlatego wystarczy zapisać najważniejsze informacje i wykorzystać je w kodzie, jednocześnie korzystając z Uwierzytelniania Firebase. Po skopiowaniu wartości i zapisaniu ich w bezpiecznym miejscu kliknij przycisk Zamknij, aby dokończyć konfigurację.
4. Aktualizacja konfiguracji
Zmiany w konfiguracji obejmują zarówno zmianę różnych plików konfiguracji, jak i utworzenie odpowiednika App Engine, ale w ekosystemie Cloud Identity Platform.
appengine_config.py
- Jeśli przechodzisz na Pythona 3, usuń
appengine_config.py
- Jeśli planujesz modernizację w Identity Platform, ale pozostaw w języku Python 2, nie usuwaj pliku. Zamiast tego zaktualizujemy ją później podczas Backportu Pythona 2.
requirements.txt
W pliku requirements.txt
modułu 20 znajduje się tylko Flask. W module 21 dodaj te pakiety:
- Uwierzytelnianie Google
- Cloud NDB
- Cloud Resource Manager (Menedżer zasobów Cloud)
- Pakiet SDK Firebase Admin
Zawartość pola requirements.txt
powinna teraz wyglądać tak:
flask
google-auth
google-cloud-ndb
google-cloud-resource-manager
firebase-admin
app.yaml
- Przejście na Pythona 3 oznacza uproszczenie pliku
app.yaml
. Usuń wszystko oprócz dyrektywy środowiska wykonawczego i ustaw obsługiwaną wersję Pythona 3. W przykładzie jest obecnie używana wersja 3.10. - Jeśli korzystasz z Pythona 2, nie rób jeszcze żadnych czynności.
PRZED:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
Przykładowa aplikacja modułu 20 nie ma statycznych modułów obsługi plików. Jeśli Twoje aplikacje tak mają, pozostaw je bez zmian. W razie potrzeby możesz usunąć wszystkie moduły obsługi skryptów lub pozostawić je w celach informacyjnych, jeśli zmienisz ich nicki na auto
, zgodnie z opisem w przewodniku po migracji app.yaml
. Dzięki tym zmianom zaktualizowany app.yaml
dla Pythona 3 został uproszczony do:
PO:
runtime: python310
Inne aktualizacje konfiguracji
Niezależnie od tego, czy pozostaniesz w języku Python 2, czy przejdziesz do Pythona 3, usuń go, jeśli masz folder lib
.
5. Modyfikowanie kodu aplikacji
W tej sekcji omawiamy aktualizacje głównego pliku aplikacji main.py
, które zastępują użycie usługi Użytkownicy App Engine usługą Cloud Identity Platform. Po zaktualizowaniu głównej aplikacji zaktualizujesz szablon internetowy templates/index.html
.
Aktualizowanie importów i inicjowania
Aby zaktualizować importy i zainicjować zasoby aplikacji, wykonaj te czynności:
- Na potrzeby importów zastąp App Engine NDB danymi Cloud NDB.
- Oprócz Cloud NDB zaimportuj także usługę Cloud Resource Manager.
- Usługa Identity Platform jest oparta na Uwierzytelnianiu Firebase, więc zaimportuj pakiet SDK Firebase Admin.
- Interfejsy Cloud APIs wymagają użycia klienta API, więc zainicjuj go dla Cloud NDB tuż poniżej inicjowania Flask.
Podczas importowania pakietu Cloud Resource Manager w tym miejscu użyjemy go na późniejszym etapie podczas inicjowania aplikacji. Poniżej znajdziesz informacje o importach i inicjowaniu z Modułu 20 oraz o tym, jak powinny wyglądać poszczególne sekcje po wprowadzeniu powyższych zmian:
PRZED:
from flask import Flask, render_template, request
from google.appengine.api import users
from google.appengine.ext import ndb
app = Flask(__name__)
PO:
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()
Pomoc dla administratorów App Engine
Do aplikacji można dodać 2 komponenty, które obsługują rozpoznawanie administratorów:
_get_gae_admins()
– zbiera dane administratorów; wywołano raz i zapisanois_admin()
– sprawdza, czy zalogowany użytkownik jest administratorem. wywoływana przy każdym logowaniu użytkownika
Funkcja narzędziowa (_get_gae_admins()
) wywołuje interfejs Resource Manager API, aby pobrać bieżącą zasadę Cloud IAM allow-policy. Zasada allow-policy definiuje i egzekwuje, które role są przypisywane do poszczególnych podmiotów zabezpieczeń (użytkownicy, konta usługi itp.). Konfiguracja obejmuje:
- Pobieram identyfikator projektu Cloud (
PROJ_ID
) - Tworzę klienta interfejsu Resource Manager API (
rm_client
) - Tworzenie zestawu ról administratora App Engine (tylko do odczytu) (
_TARGETS
)
Menedżer zasobów wymaga identyfikatora projektu Cloud, więc zaimportuj plik google.auth.default()
i wywołaj tę funkcję, aby uzyskać identyfikator projektu. Zawiera ono parametr, który wygląda jak adres URL, ale jest zakresem uprawnień OAuth2. Podczas uruchamiania aplikacji w chmurze, na przykład na maszynie wirtualnej Compute Engine lub w aplikacji App Engine, udostępniane jest domyślne konto usługi z szerokimi uprawnieniami. Zgodnie ze sprawdzonymi metodami dotyczącymi jak najmniejszych uprawnień zalecamy utworzenie własnych kont usługi zarządzanych przez użytkowników.
W przypadku wywołań interfejsu API najlepiej jeszcze ograniczyć zakres aplikacji do minimalnego poziomu wymaganego do prawidłowego działania. Wywoływane przez nas wywołanie interfejsu Resource Manager API to get_iam_policy()
, które do działania wymaga jednego z tych zakresów:
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
Przykładowa aplikacja wymaga dostępu tylko do odczytu zasady allow-policy. Nie modyfikuje zasad ani nie potrzebuje dostępu do całego projektu. Oznacza to, że aplikacja nie potrzebuje żadnego z pierwszych 3 wymaganych uprawnień. Ostatni z nich to wszystko, czego potrzebujesz i tego właśnie wdrażamy w przykładowej aplikacji.
Główna treść funkcji tworzy pusty zbiór administratorów (admins
), pobiera allow_policy
za pomocą get_iam_policy()
i przewraca wszystkie jego powiązania w poszukiwaniu ról administratora App Engine:
roles/viewer
roles/editor
roles/owner
roles/appengine.appAdmin
W przypadku każdej znalezionej roli docelowej sprawdza, którzy użytkownicy należą do danej roli, przez dodanie ich do ogólnego zestawu administratorów. Zakończy się, gdy zostaną zwrócone dane wszystkich administratorów znalezionych i zapisanych w pamięci podręcznej w postaci wartości stałej (_ADMINS
) przez cały okres istnienia tej instancji App Engine. Wkrótce się z Tobą skontaktujemy.
Dodaj tę definicję funkcji _get_gae_admins()
do main.py
tuż poniżej tworzenia instancji klienta Cloud NDB API (ds_client
):
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
Gdy użytkownicy logują się w aplikacji:
- Gdy użytkownik zaloguje się w Firebase, przeprowadzana jest szybka weryfikacja na podstawie szablonu strony internetowej.
- Gdy stan uwierzytelniania w szablonie zmieni się, wywołanie
fetch()
w stylu Ajax zostanie wykonane do elementu/is_admin
, którego moduł obsługi jest następną funkcją (is_admin()
). - Token identyfikatora Firebase jest przekazywany w treści POST do kodu
is_admin()
, który pobiera go z nagłówków i wywołuje pakiet SDK Firebase Admin w celu jego weryfikacji. Jeśli adres e-mail jest prawidłowym użytkownikiem, wyodrębnij jego adres e-mail i sprawdź, czy należy do administratora. - Następnie wartość logiczna jest zwracana do szablonu z powodzeniem 200.
Dodaj is_admin()
do main.py
tuż po _get_gae_admins()
:
@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
Do odtworzenia funkcji dostępnych w usłudze Użytkownicy, a w szczególności z funkcji is_current_user_admin()
, wymagany jest cały kod z obu funkcji. To wywołanie funkcji w module 20 wykonało wszystkie najcięższe zadania, w przeciwieństwie do modułu 21, w którym wdrażamy rozwiązanie zastępcze. Dobra wiadomość jest taka, że aplikacja nie jest już zależna od usługi wyłącznie App Engine, co oznacza, że możesz przenieść swoje aplikacje do Cloud Run lub innych usług. Możesz też zmienić definicję „administratora” dla własnych aplikacji przez przełączenie na odpowiednie role w _TARGETS
, a usługa Użytkownicy jest na stałe zakodowana w przypadku ról administratora App Engine.
Inicjowanie administratorów App Engine korzystających z uwierzytelniania Firebase i pamięci podręcznej
Mogliśmy zainicjować Uwierzytelnianie Firebase u góry w pobliżu tego samego miejsca, w którym inicjowano aplikację Flask i utworzyłeś klienta Cloud NDB API. Nie było jednak potrzebne do zdefiniowania całego kodu administratora, czyli właśnie teraz. Podobnie, gdy zdefiniowano już pole _get_gae_admins()
, wywołaj je, aby zapisać w pamięci podręcznej listę administratorów.
Dodaj te wiersze tuż pod treścią funkcji is_admin()
:
# initialize Firebase and fetch set of App Engine admins
initialize_app()
_ADMINS = _get_gae_admins()
Aktualizacje modelu danych wizyt
Model danych Visit
się nie zmienia. Dostęp do Datastore wymaga jawnego użycia menedżera kontekstu klienta Cloud NDB API (ds_client.context()
). W kodzie oznacza to opakowanie wywołań Datastore zarówno w store_visit()
, jak i fetch_visits()
wewnątrz bloków Pythona with
. Ta aktualizacja jest taka sama jak w module 2. Wprowadź zmiany w następujący sposób:
PRZED:
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)
PO:
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)
Przenieś logikę logowania użytkownika do szablonu internetowego
Usługa użytkowników App Engine działa po stronie serwera, a Uwierzytelnianie Firebase i Cloud Identity Platform działają głównie po stronie klienta. W rezultacie duża część kodu zarządzania użytkownikami z aplikacji Moduł 20 jest przenoszona do szablonu internetowego modułu 21.
W main.py
kontekst internetowy przekazuje do szablonu 5 zasadniczych danych. Cztery pierwsze z nich są powiązane z zarządzaniem użytkownikami i różnią się w zależności od tego, czy użytkownik jest zalogowany:
who
– adres e-mail użytkownika, który jest zalogowany, lub użytkownik, jeśli jest zalogowany;admin
– plakietka (administrator), jeśli zalogowany użytkownik jest administratoremsign
– pokaż przycisk Zaloguj się lub Wyloguj sięlink
– linki umożliwiające zalogowanie się i wylogowanie po kliknięciu przyciskuvisits
– ostatnie wizyty
PRZED:
@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)
Wszystkie elementy zarządzania użytkownikami zostaną przeniesione do szablonu internetowego, więc pozostało nam tylko wizyty, przywracając główny moduł obsługi do stanu z aplikacji w module 1:
PO:
@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)
Zaktualizuj szablon internetowy
Jak wyglądają w szablonie wszystkie aktualizacje z poprzedniej sekcji? Głównie przenieśliśmy zarządzanie użytkownikami z aplikacji do uwierzytelniania Firebase działającego w szablonie i częściowo przenosimy cały kod do JavaScriptu. main.py
znacznie zmalało – spodziewaj się podobnego wzrostu w kategorii templates/index.html
.
PRZED:
<!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>
Zastąp cały szablon internetowy poniższą treścią:
PO:
<!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>
Treść HTML składa się z wielu komponentów, więc omówimy je po kolei.
Importy Firebase
Nie wychodząc z nagłówka dokumentu HTML, zaimportuj potrzebne komponenty Firebase za tytułem strony. Aby zwiększyć wydajność, komponenty Firebase są teraz podzielone na wiele modułów. Kod inicjujący Firebase jest importowany z głównego modułu aplikacji Firebase, a funkcje zarządzające uwierzytelnianiem Firebase, Google jako dostawca uwierzytelniania, logowanie i wylogowywanie oraz zmiana stanu uwierzytelniania „wywołanie zwrotne” zostaną zaimportowane z modułu Uwierzytelniania Firebase:
<!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";
Konfiguracja Firebase
Wcześniej podczas konfigurowania Identity Platform w tym samouczku zapisano apiKey
i authDomain
w oknie Szczegóły konfiguracji aplikacji. Dodaj te wartości do zmiennej firebaseConfig
w następnej sekcji. Link do szczegółowych instrukcji znajdziesz w komentarzach:
// 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",
};
Inicjalizacja Firebase
W następnej sekcji zainicjujesz Firebase, korzystając z tych informacji o konfiguracji.
// initialize Firebase app & auth components
initializeApp(firebaseConfig);
var auth = getAuth();
var provider = new GoogleAuthProvider();
//provider.setCustomParameters({prompt: 'select_account'});
Pozwala to używać Google jako dostawcy uwierzytelniania i udostępnia opcję bez komentarza, która umożliwia wyświetlenie selektora kont, nawet jeśli w sesji przeglądarki jest zarejestrowane tylko jedno konto Google. Innymi słowy, jeśli masz kilka kont, zobaczysz selektor kont zgodnie z oczekiwaniami: Jeśli jednak w sesji będzie tylko jeden użytkownik, proces logowania zakończy się automatycznie bez interakcji ze strony użytkownika. (Pojawi się wyskakujące okienko, po czym znika). Możesz wymusić wyświetlanie okna selektora kont u jednego użytkownika (zamiast od razu logować się w aplikacji), usuwając komentarz do wiersza parametru niestandardowego. Jeśli ta opcja jest włączona, nawet logowanie pojedynczego użytkownika powoduje wyświetlenie selektora kont:
Funkcje logowania i wylogowywania
Następne wiersze kodu tworzą funkcje kliknięć przycisku logowania lub wylogowania:
// define login and logout button functions
function login() {
signInWithPopup(auth, provider);
};
function logout() {
signOut(auth);
};
Działania związane z logowaniem i wylogowywaniem się
Ostatnia główna sekcja tego bloku <script>
to funkcja, która jest wywoływana przy każdej zmianie uwierzytelniania (zalogowaniu się lub wylogowaniu).
// 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>
Kod w module 20 określający, czy należy wysłać „zalogowania użytkownika” kontekst szablonu a „użytkownik wylogowany” kontekst został przeniesiony w tym miejscu. Wartość warunkowa na górze powoduje wyświetlenie wyniku true
, jeśli użytkownik się zalogował, co powoduje wykonanie tych działań:
- Adres e-mail użytkownika jest skonfigurowany do wyświetlania.
- Przycisk Zaloguj zmieni się w Wyloguj.
- Wywołanie
/is_admin
w stylu Ajax pozwala określić, czy należy wyświetlać plakietkę administratora(admin)
.
Gdy użytkownik się wyloguje, wykonywana jest klauzula else
, aby zresetować wszystkie informacje o użytkowniku:
- Nazwa użytkownika ustawiona na user
- Usunięto plakietkę administratora
- Przycisk Wyloguj się zmienił się z powrotem na Login
Zmienne szablonu
Po zakończeniu sekcji nagłówka główna treść zaczyna się od zmiennych szablonu, które są zastępowane elementami HTML, które zmieniają się zależnie od potrzeb:
- Wyświetlana nazwa użytkownika
- Plakietka administratora
(admin)
(jeśli jest potrzebna) - Przycisk Zaloguj się lub Wyloguj się
<body>
<p>
Welcome, <span id="who"></span> <span id="admin"><code>(admin)</code></span>
<button id="logbtn"></button>
</p><hr>
Najnowsze wizyty i zmienne elementów HTML
Kod ostatniej wizyty nie zmienia się, a końcowy blok <script>
ustawia zmienne dla elementów HTML, które zmieniają się w przypadku wymienionego powyżej sposobu logowania i wylogowywania:
<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>
To już koniec zmian, które trzeba wprowadzić w aplikacji i szablonie internetowym, aby przejść z interfejsów App Engine NDB i Users API na Cloud NDB i Identity Platform, a także przejść na Pythona 3. Gratulujemy udostępnienia nowej, przykładowej aplikacji w module 21. Nasza wersja jest dostępna do przejrzenia w folderze repozytorium modułu 21b.
Następna część ćwiczenia w Codelabs jest opcjonalna * i tylko dla użytkowników, których aplikacje muszą pozostać w języku Python 2. Prowadzą Cię one przez czynności niezbędne do znalezienia działającej aplikacji modułu Python 21.
6. *Backport Pythona 2
Ta opcjonalna sekcja jest przeznaczona dla deweloperów przeprowadzających migrację z Identity Platform, ale którzy muszą nadal korzystać ze środowiska wykonawczego Pythona 2. Jeśli ten problem Cię nie dotyczy, pomiń tę sekcję.
Aby utworzyć działającą wersję aplikacji Moduł 21 w języku Python 2, potrzebujesz:
- Wymagania dotyczące środowiska wykonawczego: pliki konfiguracji, które obsługują Pythona 2, oraz zmiany w głównej aplikacji, które pozwalają uniknąć niezgodności z Pythonem 3
- Drobna zmiana w bibliotece: język Python 2 został wycofany, zanim do biblioteki klienta Menedżera zasobów zostały dodane niektóre wymagane funkcje. W związku z tym potrzebujesz innego sposobu na dostęp do tej brakującej funkcji.
Zacznijmy od konfiguracji.
Przywróć appengine_config.py
Na początku tego samouczka poinstruowaliśmy Cię, by usunąć plik appengine_config.py
, ponieważ nie jest on używany przez środowisko wykonawcze App Engine w języku Python 3. W przypadku Pythona 2 nie tylko należy ją zachować. Trzeba też zaktualizować Moduł 20 appengine_config.py
, aby obsługiwał korzystanie z wbudowanych bibliotek zewnętrznych (grpcio
i setuptools
). Te pakiety są wymagane zawsze, gdy aplikacja App Engine używa bibliotek klienta Cloud, takich jak Cloud NDB czy Cloud Resource Manager.
Za chwilę dodasz te pakiety do usługi app.yaml
, ale aby aplikacja mogła uzyskać do nich dostęp, musi zostać wywołana funkcja pkg_resources.working_set.add_entry()
z usługi setuptools
. Dzięki temu skopiowane (dodane do siebie lub dostarczone przez dostawcę) biblioteki innych firm zainstalowane w folderze lib
będą mogły komunikować się z wbudowanymi bibliotekami.
Aby wprowadzić te zmiany, wprowadź w pliku appengine_config.py
te aktualizacje:
PRZED:
from google.appengine.ext import vendor
# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
Ten kod nie wystarczy do korzystania z elementów setuptools
i grpcio
. Potrzebnych jest jeszcze kilka wierszy, więc zaktualizuj appengine_config.py
, aby wyglądał tak:
PO:
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)
Więcej informacji o zmianach wymaganych do obsługi bibliotek klienta Cloud znajdziesz w dokumentacji migracji pakietów usług.
app.yaml
Podobnie jak w przypadku appengine_config.py
plik app.yaml
musi zostać przywrócony do wersji, która obsługuje język Python 2. Zacznijmy od oryginalnego modułu 20 app.yaml
:
PRZED:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
Oprócz wspomnianych wcześniej rozwiązań setuptools
i grpcio
istnieje zależność (niezwiązana bezpośrednio z migracją Identity Platform) wymagająca użycia biblioteki klienta Cloud Storage oraz która wymaga innego wbudowanego pakietu innych firm: ssl
. Dodaj wszystkie trzy w nowej sekcji libraries
, wybierając „najnowsze” dostępnych wersji tych pakietów do usługi app.yaml
:
PO:
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
W module 21 dodaliśmy do Pythona 3 requirements.txt
Google Auth, Cloud NDB, Cloud Resource Manager i Firebase Admin SDK. Sytuacja w języku Python 2 jest bardziej złożona:
- Interfejs Resource Manager API zapewnia funkcję allow-policy wymaganą w przykładowej aplikacji. Ta funkcja nie była jeszcze dostępna w ostatecznej wersji Pythona 2 w bibliotece klienta Cloud Resource Manager. (Jest dostępny tylko w wersji Pythona 3).
- W związku z tym wymagany jest alternatywny sposób dostępu do tej funkcji z poziomu interfejsu API. Rozwiązaniem jest używanie biblioteki klienta interfejsów API Google niższego poziomu do komunikacji z interfejsem API. Aby przełączyć się na tę bibliotekę klienta, zastąp
google-cloud-resource-manager
pakietemgoogle-api-python-client
niższego poziomu. - Ponieważ Python 2 został wycofany, graf zależności obsługujący moduł 21 wymaga zablokowania niektórych pakietów w określonych wersjach. Niektóre pakiety muszą być wywoływane, nawet jeśli nie zostały określone w zasadzie
app.yaml
w języku Python 3.
PRZED:
flask
Począwszy od modułu 20 requirements.txt
, zaktualizuj go do następującego fragmentu w przypadku działającego modułu 21:
PO:
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
Numery pakietu i wersji będą aktualizowane w repozytorium w miarę zmiany zależności, ale w momencie tworzenia tego tekstu app.yaml
wystarczy w przypadku działającej aplikacji.
Inne aktualizacje konfiguracji
Jeśli folder lib
nie został usunięty z wcześniejszej części tego ćwiczenia z programowania, zrób to teraz. W przypadku zaktualizowanej wersji requirements.txt
uruchom to znane polecenie, aby zainstalować te wymagania w systemie lib
:
pip install -t lib -r requirements.txt # or pip2
Jeśli w Twoim systemie programistycznym masz zainstalowany język Python 2 i 3, może być konieczne użycie pip2
zamiast pip
.
Modyfikowanie kodu aplikacji
Na szczęście większość wymaganych zmian znajduje się w plikach konfiguracji. Jedyną wymaganą zmianą w kodzie aplikacji jest drobna aktualizacja umożliwiająca korzystanie z biblioteki klienta interfejsu API Google niższego poziomu zamiast biblioteki klienta Menedżera zasobów do uzyskiwania dostępu do interfejsu API. Szablon internetowy templates/index.html
nie wymaga aktualizacji.
Importowanie i inicjowanie aktualizacji
Zastąp bibliotekę klienta Menedżera zasobów (google.cloud.resourcemanager
) biblioteką klienta interfejsów API Google (googleapiclient.discovery
), jak pokazano poniżej:
PRZED:
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
PO:
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
Pomoc dla administratorów App Engine
Aby umożliwić korzystanie z biblioteki klienta niższego poziomu, trzeba wprowadzić w _get_gae_admins()
kilka zmian. Omówmy najpierw, co się zmienia, a potem przekażę Ci cały kod do zaktualizowania.
Kod Pythona 2 wymaga użycia zarówno danych logowania, jak i identyfikatora projektu zwróconego z narzędzia google.auth.default()
. Dane logowania nie są używane w Pythonie 3, więc zostały przypisane do ogólnej zmiennej podkreślenia ( _
). Jest ono wymagane w przypadku wersji Pythona 2, dlatego zmień podkreślenie na CREDS
. Poza tym zamiast tworzyć klienta interfejsu Resource Manager API, utworzysz punkt końcowy usługi interfejsu API podobnie jak w przypadku klienta API, więc zachowamy tę samą nazwę zmiennej (rm_client
). Jedna z różnic polega na tym, że utworzenie instancji punktu końcowego usługi wymaga danych logowania (CREDS
).
Te zmiany znajdują odzwierciedlenie w poniższym kodzie:
PRZED:
_, PROJ_ID = default( # Application Default Credentials and project ID
['https://www.googleapis.com/auth/cloudplatformprojects.readonly'])
rm_client = resourcemanager.ProjectsClient()
PO:
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)
Inna różnica polega na tym, że biblioteka klienta Menedżera zasobów zwraca obiekty zasady allow-policy, które używają notacji atrybutów kropkowanych, a biblioteka klienta niższego poziomu zwraca słowniki Pythona, w których używane są nawiasy kwadratowe ( [ ]
). Na przykład użyj binding.role
w przypadku biblioteki klienta Menedżera zasobów, a nie binding['role']
w przypadku biblioteki niższego poziomu. W pierwszym przypadku użyto również argumentu „podkreślenie_oddzielone”. zamiast nazw z bibliotek niższego poziomu preferujących format „CamelCased” oraz nieco inny sposób przekazywania parametrów interfejsu API.
Poniżej przedstawiono różnice w wykorzystaniu:
PRZED:
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)
PO:
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'])
Po połączeniu wszystkich tych zmian zastąp zmienną _get_gae_admins()
w języku Python 3 tą równoważną wersją języka Python 2:
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
Funkcja is_admin()
nie wymaga żadnych aktualizacji, ponieważ opiera się na metodzie _get_gae_admins()
, która została już zaktualizowana.
To już koniec zmian wymaganych do przeniesienia aplikacji z modułu 21 w języku Python 3 do Pythona 2. Gratulujemy udostępnienia zaktualizowanej przykładowej aplikacji modułu 21. Cały kod znajdziesz w folderze repozytorium modułu 21a.
7. Podsumowanie/Czyszczenie
Ostatnim krokiem w Codelabs jest zapewnienie podmiotów zabezpieczeń (użytkowników lub kont usługi) uruchamiających tę aplikację, które mają do tego odpowiednie uprawnienia. Następnie wdróż aplikację, aby sprawdzić, czy działa prawidłowo, a zmiany zostały uwzględnione w danych wyjściowych.
Możliwość odczytu zasady zezwolenia na uprawnienia
Omówiliśmy już 4 role wymagane do zostania administratorem App Engine, ale musisz się zapoznać z piątą:
roles/viewer
roles/editor
roles/owner
roles/appengine.appAdmin
roles/resourcemanager.projectIamAdmin
(w przypadku podmiotów zabezpieczeń uzyskujących dostęp do zezwalającej zasady uprawnień)
Rola roles/resourcemanager.projectIamAdmin
umożliwia podmiotom zabezpieczeń określenie, czy użytkownik jest członkiem dowolnej z ról administratora App Engine. Jeśli nie masz członkostwa w zasadzie roles/resourcemanager.projectIamAdmin
, wywołania interfejsu API Cloud Resource Manager w celu pobrania zasady allow-policy zakończą się niepowodzeniem.
Nie musisz podejmować żadnych działań, ponieważ Twoja aplikacja będzie działać z domyślnym kontem usługi App Engine, które automatycznie otrzymuje członkostwo w tej roli. Nawet jeśli na etapie programowania używasz domyślnego konta usługi, zdecydowanie zalecamy utworzenie i korzystanie z konta usługi zarządzanego przez użytkownika z minimalnymi uprawnieniami wymaganymi do prawidłowego działania aplikacji. Aby przyznać członkostwo takiemu kontu usługi, uruchom to polecenie:
$ 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
to identyfikator projektu Cloud, a USR_MGD_SVC_ACCT@PROJ_ID.iam.gserviceaccount.com
to zarządzane przez użytkownika konto usługi, które tworzysz dla swojej aplikacji. To polecenie wyświetla zaktualizowane zasady uprawnień w projekcie, w których możesz sprawdzić, czy konto usługi ma członkostwo w środowisku roles/resourcemanager.projectIamAdmin
. Więcej informacji znajdziesz w dokumentacji referencyjnej. Nie musisz uruchamiać tego polecenia w tym ćwiczeniu z programowania, ale możesz je zapisać jako materiał referencyjny do modernizacji swoich aplikacji.
Wdróż i zweryfikuj aplikację
Prześlij aplikację do chmury za pomocą standardowego polecenia gcloud app deploy
. Po wdrożeniu usługi powinny być widoczne prawie takie same jak w aplikacji z modułu 20, z wyjątkiem tego, że na potrzeby zarządzania użytkownikami zastąpiono usługę użytkowników App Engine usługą Cloud Identity Platform (i Uwierzytelnianiem Firebase).
Jedną z różnic w porównaniu z Modułem 20 jest to, że kliknięcie przycisku logowania powoduje wyświetlenie wyskakującego okienka, a nie przekierowania. Pokazuje to niektóre z poniższych zrzutów ekranu. Podobnie jak w przypadku Modułu 20, działanie różni się nieco w zależności od tego, ile kont Google zostało zarejestrowanych w przeglądarce.
Jeśli nie ma żadnego użytkownika zarejestrowanego w przeglądarce lub użytkownik, który jeszcze się nie zalogował, pojawi się ogólne wyskakujące okienko Logowanie przez Google:
Jeśli 1 użytkownik jest zarejestrowany w przeglądarce, ale loguje się w innym miejscu, okno nie jest wyświetlane (lub pojawia się i natychmiast zamyka), a aplikacja przechodzi w stan zalogowania (wyświetla adres e-mail użytkownika i przycisk Wyloguj się).
Niektórzy deweloperzy mogą chcieć udostępnić selektor kont, nawet w przypadku pojedynczego użytkownika:
Aby to zrobić, usuń znacznik komentarza z wiersza provider.setCustomParameters({prompt: 'select_account'});
w szablonie internetowym w sposób opisany powyżej.
W przypadku wielu użytkowników pojawi się okno selektora konta (patrz poniżej). Jeśli użytkownik nie jest jeszcze zalogowany, wyświetli się odpowiedni komunikat. Jeśli jesteś już zalogowany(-a), wyskakujące okienko znika, a aplikacja przechodzi w stan zalogowania.
Stan zalogowania w module 21 wygląda tak samo jak w interfejsie modułu 20:
To samo dotyczy sytuacji, gdy użytkownik zaloguje się jako administrator:
W przeciwieństwie do modułu 21 Moduł 20 zawsze uzyskuje dostęp do logiki zawartości szablonu internetowego z aplikacji (kod po stronie serwera). Wadą Modułu 20 jest to, że jedna wizyta jest rejestrowana w chwili pierwszego uruchomienia aplikacji przez użytkownika, a druga przy pierwszym logowaniu się użytkownika.
W module 21 logika logowania odbywa się tylko w szablonie internetowym (kodem po stronie klienta). Aby określić, jakie treści wyświetlić, nie trzeba podróżować po stronie serwera. Jedynym wywołaniem do serwera jest sprawdzenie, czy użytkownik nie zaloguje się na swoje konto. Oznacza to, że na zalogowanie się i wylogowanie nie są rejestrowane dodatkowe wizyty, a lista ostatnich wizyt nie zmienia się w przypadku działań związanych z zarządzaniem użytkownikami. Zwróć uwagę, że powyższe zrzuty ekranu przedstawiają ten sam zestaw 4 wizyt za pomocą różnych loginów użytkownika.
Zrzuty ekranu z modułu 20 pokazują „błęd związany z podwójną wizytą”. na początku tego ćwiczenia. Dla każdego logowania lub wylogowania wyświetlane są osobne dzienniki wizyt. Sprawdź sygnatury czasowe ostatniej wizyty dla każdego zrzutu ekranu uporządkowanego chronologicznie.
Czyszczenie danych
Ogólne
Jeśli na razie wszystko jest gotowe, wyłącz aplikację App Engine, aby uniknąć naliczania opłat. Jeśli jednak chcesz jeszcze bardziej przetestować lub poeksperymentować, platforma App Engine ma bezpłatny limit. Dopóki nie przekroczysz tego limitu, nie pobierzemy żadnych opłat. Oznacza to obliczenia, ale mogą być też naliczane opłaty za odpowiednie usługi App Engine. Więcej informacji znajdziesz na stronie z cennikiem. Jeśli ta migracja obejmuje inne usługi Cloud, są one rozliczane osobno. W obu przypadkach zapoznaj się z sekcją „Zapoznaj się z tymi ćwiczeniami”. sekcji poniżej.
Aby w pełni wyjaśnić wszystkie kwestie, wdrożenie na bezserwerowej platformie obliczeniowej Google Cloud, takiej jak App Engine, wiąże się z niewielkimi kosztami kompilacji i przechowywania danych. Cloud Build ma własny bezpłatny limit, podobnie jak Cloud Storage. Przechowywanie tego obrazu wykorzystuje część tego limitu. Możesz jednak mieszkać w regionie, w którym nie ma takiego poziomu bezpłatnego. Dlatego pamiętaj o wykorzystaniu miejsca na dane, aby zminimalizować potencjalne koszty. Określone „foldery” Cloud Storage należy sprawdzić m.in.:
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
- Powyższe linki do przechowywania danych zależą od Twoich danych
PROJECT_ID
iLOC
, np. „us
” jeśli aplikacja jest hostowana w Stanach Zjednoczonych.
Jeśli natomiast nie zamierzasz dalej korzystać z tej aplikacji lub innych powiązanych z nią ćwiczeń w Codelabs i chcesz całkowicie usunąć wszystko, zamknij projekt.
Powiązane z tym ćwiczeniam z programowania
Wymienione poniżej usługi są dostępne tylko w ramach tego ćwiczenia z programowania. Więcej informacji znajdziesz w dokumentacji poszczególnych usług:
- Usługa App Engine Datastore jest świadczona przez Cloud Datastore (Cloud Firestore w trybie Datastore), który również ma poziom bezpłatny. więcej informacji znajdziesz na stronie z cennikiem.
- Korzystanie z Cloud Identity Platform jest w pewnym stopniu „bezpłatne”, w zależności od tego, z których usług korzystasz. Więcej informacji znajdziesz na stronie z cennikiem.
- Korzystanie z interfejsu Cloud Resource Manager API jest w większości bezpłatne, zgodnie z cennikiem.
Dalsze kroki
Oprócz tego samouczka dostępne są też inne moduły migracji koncentrujące się na odejściu od starszych pakietów usług, które warto rozważyć:
- Moduł 2. Migracja z App Engine
ndb
do Cloud NDB - Moduły 7–9. Migracja z kolejki zadań App Engine (zadań push) do Cloud Tasks
- Moduły 12–13: migracja z App Engine Memcache do Cloud Memorystore
- Moduły 15–16: migracja z App Engine Blobstore do Cloud Storage
- Moduły 18–19: migracja z kolejki zadań App Engine (pobierania zadań) do Cloud Pub/Sub
App Engine nie jest już jedyną bezserwerową platformą w Google Cloud. Jeśli masz małą aplikację App Engine lub taką, która ma ograniczoną funkcjonalność i chcesz przekształcić ją w samodzielny mikroserwis, albo chcesz podzielić aplikację monolityczną na kilka komponentów wielokrotnego użytku, rozważ przejście na Cloud Functions. Jeśli konteneryzacja stała się częścią przepływu pracy przy tworzeniu aplikacji, zwłaszcza jeśli składa się z potoku CI/CD (ciągła integracja/ciągłe dostarczanie lub wdrażanie), rozważ migrację do Cloud Run. Te scenariusze są opisane w tych modułach:
- Migracja z App Engine do Cloud Functions: patrz Moduł 11.
- Migracja z App Engine do Cloud Run: zapoznaj się z Modułem 4, aby skonteneryzować aplikację za pomocą Dockera, lub Moduł 5, aby zrobić to bez kontenerów, Dockera lub
Dockerfile
.
Przejście na inną bezserwerową platformę jest opcjonalne. Zalecamy, aby przed wprowadzeniem jakichkolwiek zmian wybrać najlepsze opcje dla swoich aplikacji i przypadków użycia.
Niezależnie od tego, który moduł migracji wykorzystasz w następnej kolejności, wszystkie materiały z serwerowej platformy migracji (laboratorium, filmy, kod źródłowy [jeśli jest dostępne]) są dostępne w repozytorium open source. README
repozytorium zawiera też wskazówki dotyczące migracji, które warto wziąć pod uwagę, i wszelkich odpowiednich „zamówień” modułów migracji.
8. Dodatkowe materiały
Poniżej znajdziesz dodatkowe materiały dla deweloperów zainteresowanych tym lub powiązanymi modułami migracji. Poniżej możesz przesłać opinię na temat tych treści, znaleźć linki do kodu i różne artykuły, które mogą Ci się przydać.
Problemy/opinie dotyczące ćwiczeń z programowania
Jeśli podczas korzystania z tych ćwiczeń z programowania zauważysz jakiekolwiek problemy, najpierw je wyszukaj. Linki do wyszukiwania i tworzenia nowych problemów:
Zasoby migracji
Linki do folderów repozytorium w modułach 20 (START) i modułach 21 (FINISH) znajdziesz w tabeli poniżej.
Codelab | Python 2 | Python 3 |
(nd.) | ||
Moduł 21 (to ćwiczenia z programowania) |
Dokumentacja online
Poniżej znajdziesz informacje na temat tego samouczka:
Cloud Identity Platform i Cloud Marketplace
- Strona usługi Identity Platform
- Uwierzytelnianie Firebase
- Porównanie usług Identity Platform i Uwierzytelniania Firebase
- Informacje o cenach usługi Identity Platform
- Limity usługi Identity Platform (i wykorzystanie bez instrumentu)
- Konfiguracja dostawców Identity Platform
- Strona usługi Cloud Marketplace
- Strona Identity Platform w Marketplace
Cloud Resource Manager, Cloud IAM, pakiet Firebase Admin SDK
- Strona usługi Menedżer zasobów
- Informacje o cenach Menedżera zasobów
- Biblioteka klienta Menedżera zasobów
- Omówienie Cloud IAM (role, allow-policy itp.)
- Pakiet SDK Firebase Admin (Python)
Użytkownicy App Engine, App Engine NDB, Cloud NDB, Cloud Datastore
- Omówienie użytkowników App Engine
- Dokumentacja App Engine NDB
- Repozytorium App Engine NDB
- Biblioteka klienta Cloud NDB
- Repozytorium Cloud NDB
- Strona usługi Cloud Datastore
- Informacje o cenach Cloud Datastore
Inne odwołania do modułu migracji
- Wprowadzenie do modułu migracji
- Wszystkie „serwerowe stacje migracji”
- Dokumentacja migracji do Pythona 3
- Moduł migracji 17 „Korzystanie z pakietów usług w środowiskach wykonawczych 2 generacji” ćwiczenie w Codelabs
- Moduł migracji 20 „Dodawanie usługi App Engine Users do aplikacji Flask” ćwiczenie w Codelabs
Migracja do App Engine
- Korzystanie z bibliotek innych firm w aplikacjach w języku Python 2
- Zmiany w interfejsie
app.yaml
w środowiskach wykonawczych drugiej generacji (Python 3) - Przewodnik po migracji do Cloud NDB
- Treść migracji do Cloud NDB
Platforma App Engine
- Dokumentacja App Engine
- Środowisko wykonawcze App Engine (środowisko standardowe) Pythona 2
- Korzystanie z wbudowanych bibliotek App Engine w Python 2 App Engine
- Środowisko wykonawcze App Engine w Pythonie 3 (środowisko standardowe)
- Różnice między Pythonem 2 a Pythonem 2 3 środowiska wykonawcze App Engine (w środowisku standardowym)
- Przewodnik po migracji do App Engine (w środowisku standardowym) w języku Python 2 do 3
- Informacje o cenach i limitach App Engine
- Wprowadzenie na rynek platformy App Engine drugiej generacji (2018)
- Porównanie pierwszych i platformy drugiej generacji
- Długoterminowa obsługa starszych środowisk wykonawczych
- Przykłady migracji dokumentacji
- Przykłady migracji dostarczonych przez społeczność
Pakiet SDK Cloud
- Pakiet SDK Google Cloud
- Narzędzie wiersza poleceń
gcloud
pakietu SDK Cloud - Włączanie i wyłączanie interfejsów API Google
- Menedżer interfejsów API konsoli Cloud (włącz/wyłącz interfejsy API)
- Włączanie interfejsów API Google w interfejsie
gcloud
- Wyświetlanie listy interfejsów API Google z użyciem
gcloud
Inne informacje o Google Cloud
- Python w Google Cloud
- Dokumentacja bibliotek klienta dla języka Python
- Repozytoria bibliotek klienta w języku Python
- „Zawsze bezpłatne” typ
- Pakiet SDK Cloud
- Narzędzie wiersza poleceń
gcloud
pakietu SDK Cloud - Cała dokumentacja Google Cloud
Filmy
- Stacja migracji bezserwerowej
- Ekspedycje bezserwerowe
- Zasubskrybuj Google Cloud Tech.
- Subskrybuj Google Developers.
Licencja
To zadanie jest licencjonowane na podstawie ogólnej licencji Creative Commons Attribution 2.0.