Używanie usługi Secret Manager z Pythonem

1. Przegląd

W tym laboratorium skupisz się na używaniu usługi Secret Manager w Pythonie.

Usługa Secret Manager umożliwia przechowywanie obiektów tajnych w postaci binarnych obiektów blob lub ciągów tekstowych, a także zarządzanie nimi i uzyskiwanie do nich dostępu. Jeśli masz odpowiednie uprawnienia, możesz wyświetlić zawartość klucza tajnego.

Usługa Secret Manager sprawdza się w przechowywaniu informacji konfiguracyjnych, takich jak hasła do baz danych, klucze interfejsu API czy certyfikaty TLS potrzebne aplikacji w czasie wykonywania.

Czego się nauczysz

  • Jak korzystać z Cloud Shell
  • Instalowanie biblioteki klienta Secret Manager dla Pythona
  • Jak tworzyć obiekty tajne i uzyskiwać do nich dostęp za pomocą biblioteki klienta w Pythonie
  • Jak uzyskać dostęp do obiektów tajnych w Cloud Functions za pomocą biblioteki klienta w Pythonie

Czego potrzebujesz

  • Projekt Google Cloud
  • przeglądarka, np. Chrome lub Firefox;
  • znajomość języka Python 3,

Ankieta

Jak zamierzasz korzystać z tego samouczka?

Tylko przeczytaj Przeczytaj i wykonaj ćwiczenia

Jak oceniasz swoje doświadczenie z Pythonem?

Początkujący Średnio zaawansowany Zaawansowany

Jak oceniasz korzystanie z usług Google Cloud?

Początkujący Średnio zaawansowany Zaawansowany

2. Konfiguracja i wymagania

Samodzielne konfigurowanie środowiska

  1. Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub użyj istniejącego. Jeśli nie masz jeszcze konta Gmail ani Google Workspace, musisz je utworzyć.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Nazwa projektu to wyświetlana nazwa uczestników tego projektu. Jest to ciąg znaków, który nie jest używany przez interfejsy API Google. Możesz ją zaktualizować w dowolnym momencie.
  • Identyfikator projektu musi być unikalny we wszystkich projektach Google Cloud i jest niezmienny (nie można go zmienić po ustawieniu). Konsola Cloud automatycznie generuje unikalny ciąg znaków. Zwykle nie musisz się nim przejmować. W większości ćwiczeń z programowania musisz odwoływać się do identyfikatora projektu (zwykle jest on oznaczony jako PROJECT_ID). Jeśli wygenerowany identyfikator Ci się nie podoba, możesz wygenerować inny losowy identyfikator. Możesz też spróbować własnej nazwy i sprawdzić, czy jest dostępna. Po tym kroku nie można go zmienić i będzie obowiązywać przez cały czas trwania projektu.
  • Warto wiedzieć, że istnieje też trzecia wartość, czyli numer projektu, z której korzystają niektóre interfejsy API. Więcej informacji o tych 3 wartościach znajdziesz w dokumentacji.
  1. Następnie musisz włączyć płatności w konsoli Cloud, aby korzystać z zasobów i interfejsów API Google Cloud. Ukończenie tego laboratorium nie powinno wiązać się z dużymi kosztami, a nawet z żadnymi. Aby wyłączyć zasoby i uniknąć naliczania opłat po zakończeniu tego samouczka, możesz usunąć utworzone zasoby lub cały projekt. Nowi użytkownicy Google Cloud mogą skorzystać z bezpłatnego okresu próbnego, w którym mają do dyspozycji środki w wysokości 300 USD.

Uruchamianie Cloud Shell

Z Google Cloud można korzystać zdalnie na laptopie, ale w tym module praktycznym będziesz używać Google Cloud Shell, czyli środowiska wiersza poleceń działającego w chmurze.

Aktywowanie Cloud Shell

  1. W konsoli Cloud kliknij Aktywuj Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Jeśli uruchamiasz Cloud Shell po raz pierwszy, zobaczysz ekran pośredni (część strony widoczna po przewinięciu) z opisem tego środowiska. W takim przypadku kliknij Dalej, a ten ekran nie będzie się już wyświetlać. Ten wyświetlany jednorazowo ekran wygląda tak:

9c92662c6a846a5c.png

Uzyskanie dostępu do środowiska Cloud Shell i połączenie się z nim powinno zająć tylko kilka chwil.

9f0e51b578fecce5.png

Ta maszyna wirtualna zawiera wszystkie potrzebne narzędzia dla programistów. Zawiera również stały katalog domowy o pojemności 5 GB i działa w Google Cloud, co znacznie zwiększa wydajność sieci i usprawnia proces uwierzytelniania. Większość zadań w tym module, a być może wszystkie, możesz wykonać w przeglądarce lub na Chromebooku.

Po połączeniu z Cloud Shell zobaczysz, że uwierzytelnianie zostało już przeprowadzone, a projekt jest już ustawiony na Twój identyfikator projektu.

  1. Aby potwierdzić, że uwierzytelnianie zostało przeprowadzone, uruchom w Cloud Shell to polecenie:
gcloud auth list

Wynik polecenia

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Aby potwierdzić, że polecenie gcloud zna Twój projekt, uruchom w Cloud Shell to polecenie:
gcloud config list project

Wynik polecenia

[core]
project = <PROJECT_ID>

Jeśli nie, możesz go ustawić za pomocą tego polecenia:

gcloud config set project <PROJECT_ID>

Wynik polecenia

Updated property [core/project].

3. Włączanie interfejsu Secret Manager API

Zanim zaczniesz korzystać z interfejsu Secret Manager API, musisz go włączyć. W Cloud Shell możesz włączyć interfejs API za pomocą tego polecenia:

gcloud services enable secretmanager.googleapis.com

Powinny się wyświetlić dane wyjściowe podobne do tych:

Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.

4. Instalowanie biblioteki klienta Secret Manager dla Pythona

Zainstaluj bibliotekę klienta Secret Manager:

pip3 install --user google-cloud-secret-manager==2.10.0

5. Uruchamianie interaktywnego Pythona

W części tego samouczka będziesz używać interaktywnego interpretera Pythona o nazwie IPython, który jest wstępnie zainstalowany w Cloud Shell. Rozpocznij sesję, uruchamiając ipython w Cloud Shell:

ipython

Powinien pojawić się ekran podobny do tego:

Python 3.9.2 (default, Feb 28 2021, 17:03:44)
Type 'copyright', 'credits' or 'license' for more information
IPython 8.3.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]:

6. Tworzenie obiektów tajnych

Obiekt tajny zawiera co najmniej jedną wersję obiektu tajnego. Można je tworzyć za pomocą gcloud wiersza poleceń, ale także w języku Python.

Aby użyć obiektu tajnego, musisz najpierw utworzyć go, podając jego nazwę, a następnie dodać jego wersję, czyli wartość.

Ustaw identyfikator projektu w IPython:

PROJECT_ID = "<PROJECT_ID>"

Tworzenie obiektu tajnego

Skopiuj ten kod do sesji IPython:

from google.cloud import secretmanager

def create_secret(secret_id):
    # Create the Secret Manager client.
    client = secretmanager.SecretManagerServiceClient()

    # Build the resource name of the parent project.
    parent = f"projects/{PROJECT_ID}"

    # Build a dict of settings for the secret
    secret = {'replication': {'automatic': {}}}

    # Create the secret
    response = client.create_secret(secret_id=secret_id, parent=parent, secret=secret)

    # Print the new secret name.
    print(f'Created secret: {response.name}')   

Wywołaj funkcję, aby utworzyć nowy obiekt tajny o nazwie my_secret_value:

create_secret("my_secret_value")

Powinny się wyświetlić te dane wyjściowe:

Created secret: projects/<PROJECT_NUM>/secrets/my_secret_value

Dodawanie wersji obiektu tajnego

Gdy obiekt tajny już istnieje, możesz przypisać mu wartość, tworząc wersję.

Skopiuj ten kod do sesji IPython:

def add_secret_version(secret_id, payload):
    # Create the Secret Manager client.
    client = secretmanager.SecretManagerServiceClient()

    # Build the resource name of the parent secret.
    parent = f"projects/{PROJECT_ID}/secrets/{secret_id}"

    # Convert the string payload into a bytes. This step can be omitted if you
    # pass in bytes instead of a str for the payload argument.
    payload = payload.encode('UTF-8')

    # Add the secret version.
    response = client.add_secret_version(parent=parent, payload={'data': payload})

    # Print the new secret version name.
    print(f'Added secret version: {response.name}')   

Wywołaj funkcję, aby utworzyć nową wersję obiektu tajnego:

add_secret_version("my_secret_value", "Hello Secret Manager")

Powinny się wyświetlić te dane wyjściowe:

Added secret version: projects/<PROJECT_NUM>/secrets/my_secret_value/versions/1

Obiekty tajne mogą mieć wiele wersji. Ponownie wywołaj funkcję z inną wartością:

add_secret_version("my_secret_value", "Hello Again, Secret Manager")

Powinny się wyświetlić te dane wyjściowe:

Added secret version: projects/<PROJECT_NUM>/secrets/my_secret_value/versions/2

Zwróć uwagę, że nowa wersja obiektu tajnego jest znacznie dłuższa od pierwotnej. Ten atrybut będzie używany później.

7. Dostęp do obiektów tajnych

Uzyskanie dostępu do wersji obiektu tajnego powoduje zwrócenie zawartości obiektu tajnego oraz dodatkowych metadanych dotyczących tej wersji. Gdy uzyskujesz dostęp do wersji obiektu tajnego, możesz podać konkretną wersję lub po prostu poprosić o najnowszą wersję, wpisując „latest”.

Obiekty tajne powinny być tajne. Dane logowania do bazy danych przechowuj jako obiekty tajne, a potem używaj ich do uwierzytelniania. Możesz też przechowywać certyfikaty i ich używać. Nie drukuj jednak bezpośrednio obiektów tajnych, ponieważ podważa to cel ich przechowywania w tajemnicy.

Będziesz wykonywać operacje na naszych tajnych informacjach, oceniając ich wartość bez bezpośredniego drukowania. Zamiast tego wydrukujesz hash wartości tajnego kodu.

Skopiuj ten kod do sesji IPython:

def access_secret_version(secret_id, version_id="latest"):
    # Create the Secret Manager client.
    client = secretmanager.SecretManagerServiceClient()

    # Build the resource name of the secret version.
    name = f"projects/{PROJECT_ID}/secrets/{secret_id}/versions/{version_id}"

    # Access the secret version.
    response = client.access_secret_version(name=name)

    # Return the decoded payload.
    return response.payload.data.decode('UTF-8')
    
import hashlib

def secret_hash(secret_value): 
  # return the sha224 hash of the secret value
  return hashlib.sha224(bytes(secret_value, "utf-8")).hexdigest()

Wywołaj funkcję, aby pobrać tajny klucz jako skrót jego wartości:

secret_hash(access_secret_version("my_secret_value"))

Powinny pojawić się dane wyjściowe przypominające hash (dokładna wartość może się różnić od tych danych):

83f8a4edb555cde4271029354395c9f4b7d79706ffa90c746e021d11

Nie podano wersji, więc pobrano najnowszą wartość.

Aby potwierdzić, wywołaj funkcję, dodając oczekiwany numer wersji:

secret_hash(access_secret_version("my_secret_value", version_id=2))

Powinny się wyświetlić te same dane wyjściowe co w przypadku ostatniego polecenia:

83f8a4edb555cde4271029354395c9f4b7d79706ffa90c746e021d11

Ponownie wywołaj funkcję, ale tym razem określ pierwszą wersję:

secret_hash(access_secret_version("my_secret_value", version_id=1))

Tym razem powinien pojawić się inny hash, co oznacza inne dane wyjściowe:

9a3fc8b809ddc611c82aee950c636c7557e220893560ec2c1eeeb177

8. Używanie Secret Manager z Cloud Functions

Z obiektów tajnych możesz korzystać w wielu usługach Google Cloud. W tej sekcji skupisz się na Cloud Functions, czyli bezserwerowej usłudze obliczeniowej Google opartej na zdarzeniach.

Jeśli chcesz używać Pythona w Cloud Functions, możesz skorzystać z samouczka dotyczącego funkcji HTTP w Google Cloud Functions w Pythonie.

Zamknij IPython, wywołując funkcję exit:

exit

Powinna wyświetlić się sesja Cloud Shell:

yourname@cloudshell:~ (<PROJECT_ID>)$

Zanim zaczniesz korzystać z interfejsu Cloud Functions API, musisz go włączyć. W Cloud Shell możesz włączyć interfejs API za pomocą tego polecenia:

gcloud services enable cloudfunctions.googleapis.com cloudbuild.googleapis.com

Utwórz nowy folder, w którym będziemy tworzyć funkcję, i utwórz puste pliki, do których będziemy zapisywać dane:

mkdir secret-manager-api-demo
cd secret-manager-api-demo
touch main.py
touch requirements.txt

Otwórz edytor kodu w prawym górnym rogu Cloud Shell:

7651a97c51e11a24.png

Przejdź do pliku main.py w folderze secret-manager-api-demo. W tym miejscu umieścisz cały kod.

9. Pisanie funkcji Cloud Functions w celu uzyskania dostępu do wpisów tajnych

Przechowywanie i pobieranie wartości tajnych z wiersza poleceń lub terminala IPython jest przydatne, ale znacznie bardziej użyteczna jest możliwość uzyskania dostępu do tych obiektów tajnych w funkcji.

Możesz użyć utworzonej wcześniej funkcji access_secret_version jako podstawy funkcji Cloud Functions.

Skopiuj ten kod do pliku main.py:

main.py

import os

from google.cloud import secretmanager

project_id = os.environ["PROJECT_ID"]

client = secretmanager.SecretManagerServiceClient()
name = f"projects/{project_id}/secrets/my_secret_value/versions/latest"
response = client.access_secret_version(name=name)
my_secret_value = response.payload.data.decode("UTF-8")


def secret_hello(request):
    if "Again" in my_secret_value:
        return "We meet again!\n"

    return "Hello there.\n"

Zanim wdrożysz funkcję, musisz dokończyć konfigurację środowiska. Wymaga to skonfigurowania zależności funkcji.

Utwórz nowy plik o nazwie requirements.txt i dodaj do niego pakiet google-cloud-secret-manager:

requirements.txt

google-cloud-secret-manager==2.10.0

Powinien się teraz wyświetlić folder zawierający tylko main.pyrequirements.txt.

Zezwalanie na dostęp do obiektu tajnego

Zanim wdrożysz funkcję, musisz zezwolić Cloud Functions na dostęp do Twojego sekretu.

Wróć do terminala:

c5b686edf94b5222.png

Przyznaj kontu usługi Cloud Functions dostęp do Twojego sekretu:

export PROJECT_ID=$(gcloud config get-value core/project)

gcloud secrets add-iam-policy-binding my_secret_value \
    --role roles/secretmanager.secretAccessor \
    --member serviceAccount:${PROJECT_ID}@appspot.gserviceaccount.com

Powinny się wyświetlić te dane wyjściowe:

Updated IAM policy for secret [my_secret_value].
bindings:
- members:
  - serviceAccount:<PROJECT_ID>@appspot.gserviceaccount.com
  role: roles/secretmanager.secretAccessor
etag: BwWiRUt2oB4=
version: 1

10. Wdrażanie funkcji w Cloud Functions

Po skonfigurowaniu środowiska w poprzednich sekcjach możesz teraz wdrożyć i przetestować funkcję w Cloud Functions.

W folderze zawierającym tylko 2 utworzone przez Ciebie pliki wdróż funkcję:

gcloud functions deploy secret_hello \
    --runtime python39 \
    --set-env-vars PROJECT_ID=${PROJECT_ID} \
    --trigger-http \
    --allow-unauthenticated

Powinny pojawić się te dane wyjściowe (skrócone):

Deploying function (may take a while - up to 2 minutes)...done.

...

entryPoint: secret_hello
httpsTrigger:
  url: https://<REGION>-<PROJECT_ID>.cloudfunctions.net/secret_hello
...
status: ACTIVE
...

Pobierz adres URL funkcji (httpsTrigger.url metadata) za pomocą tego polecenia:

FUNCTION_URL=$(gcloud functions describe secret_hello --format 'value(httpsTrigger.url)')

Teraz możesz przetestować funkcję, wywołując ją i sprawdzając, czy zwraca oczekiwaną wartość:

curl $FUNCTION_URL

Powinny się wyświetlić te dane wyjściowe:

We meet again!

Ta funkcja odwołuje się do najnowszej wersji obiektu tajnego, która została ustawiona tak, aby zawierała ciąg „Again”, więc działa zgodnie z oczekiwaniami.

11. Gratulacje!

Wiesz już, jak korzystać z interfejsu Secret Manager API za pomocą Pythona.

Czyszczenie danych

Aby uniknąć obciążenia konta Google Cloud opłatami za zasoby zużyte w tym samouczku:

  • W Cloud Console otwórz stronę Zarządzanie zasobami.
  • Na liście projektów wybierz projekt, a następnie kliknij Usuń.
  • W oknie wpisz identyfikator projektu i kliknij Wyłącz, aby usunąć projekt.

Więcej informacji

Licencja

To zadanie jest licencjonowane na podstawie ogólnej licencji Creative Commons Attribution 2.0.