Szyfruj funkcje w Cloud Functions przy użyciu kluczy szyfrowania zarządzanych przez klienta (CMEK)

1. Wprowadzenie

Omówienie

Cloud Functions to wymagające niewielu zasobów rozwiązanie oparte na obliczeniach, które umożliwia programistom tworzenie jednozadaniowych, samodzielnych funkcji reagujących na zdarzenia w chmurze bez konieczności zarządzania serwerem lub środowiskiem wykonawczym.

Aby chronić Cloud Functions i powiązane z nimi dane w spoczynku, możesz używać kluczy szyfrowania zarządzanych przez klienta (CMEK) w usłudze Cloud Key Management Service. Wdrażanie funkcji za pomocą klucza CMEK chroni powiązane z nią dane za pomocą klucza szyfrowania, nad którym masz pełną kontrolę. Ten typ szyfrowania umożliwia spełnienie wymagań dotyczących zgodności w pewnych branżach, np. usług finansowych. Ponieważ klucz należy do Ciebie i nie jest on kontrolowany przez Google, nikt (łącznie z Tobą) nie ma dostępu do danych chronionych przez te klucze szyfrowania po wyłączeniu lub zniszczeniu kluczy.

W przypadku Cloud Functions CMEK szyfruje te elementy:

  • Kod źródłowy funkcji przesłany do wdrożenia i przechowywany przez Google w Cloud Storage, używany w procesie kompilacji.
  • Wyniki procesu kompilacji funkcji, w tym obraz kontenera utworzony na podstawie kodu źródłowego funkcji, każde wystąpienie wdrożonej funkcji.
  • Dane w spoczynku dla wewnętrznych kanałów transportu zdarzeń (tylko 1 generacji).

Więcej informacji o tym, jakie dane są szyfrowane, znajdziesz w dokumentacji Cloud Functions CMEK.

Co utworzysz

Z tego ćwiczenia w Codelabs dowiesz się, jak wdrożyć funkcję w Cloud Functions (1 lub 2 generacji) szyfrowaną za pomocą klucza CMEK. W tym laboratorium kodu na potrzeby demonstracji używamy publicznej funkcji w Cloud Functions, czyli takiej, która nie wymaga uwierzytelniania. Funkcję z uwierzytelnianiem CMEK możesz wywołać tak samo jak każdą inną funkcję w Cloud Functions, która wymaga uwierzytelniania.

Czego się nauczysz

  • Jak utworzyć klucz CMEK na istniejącym pęku kluczy symetrycznych
  • Jak utworzyć repozytorium Artifact Registry
  • Jak skonfigurować klucze CMEK w funkcji w Cloud Functions zarówno pierwszej, jak i drugiej generacji

2. Konfiguracja i wymagania

Wymagania wstępne

  • Jesteś zalogowany(-a) w konsoli Google Cloud
  • Masz już wdrożoną funkcję w Cloud Functions aktywowaną przez HTTP (aby sprawdzić, czy masz włączone odpowiednie role i interfejsy API)

Aktywowanie Cloud Shell

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

55efc1aaa7a4d3ad.png

Jeśli uruchamiasz Cloud Shell po raz pierwszy, zobaczysz ekran pośredni z wyjaśnieniem, co to jest. Jeśli został wyświetlony ekran pośredni, kliknij Dalej.

9c92662c6a846a5c.png

Uproszczenie i połączenie z Cloud Shell powinno zająć tylko kilka chwil.

9f0e51b578fecce5.png

Ta maszyna wirtualna zawiera wszystkie niezbędne narzędzia programistyczne. Zawiera stały katalog domowy o pojemności 5 GB i działa w Google Cloud, co znacznie zwiększa wydajność sieci i uwierzytelnianie. Większość, jeśli nie wszystkie, zadań w tym ćwiczeniu można wykonać w przeglądarce.

Po połączeniu z Cloud Shell powinieneś zobaczyć, że jesteś uwierzytelniony i że projekt jest ustawiony na identyfikator Twojego projektu.

  1. Aby potwierdzić uwierzytelnianie, 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 sprawdzić, czy 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 ustawić je za pomocą tego polecenia:

gcloud config set project <PROJECT_ID>

Dane wyjściowe polecenia

Updated property [core/project].

3. Tworzenie nowego pęku kluczy i klucza dla Cloud Functions

Upewnij się, że interfejs Cloud KMS API jest włączony. Aby to zrobić, uruchom to polecenie:

gcloud services enable cloudkms.googleapis.com

Najpierw utwórz zmienne środowiskowe do przechowywania nazwy pęku kluczy, nazwy klucza, regionu i innych zmiennych używanych w tym ćwiczeniu.

KEYRING_NAME="keyring-functions"
REGION="us-central1"
KEY_NAME="key-encrypted-function"
PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER="$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')"
USER_EMAIL="$(gcloud config list account --format "value(core.account)")"

Następnie utwórz pół, który jest zasobem głównym kluczy i wersji kluczy Cloud KMS.

gcloud kms keyrings create $KEYRING_NAME --location $REGION

Na koniec możesz utworzyć klucz symetryczny w nowym pęku kluczy w Cloud KMS.

gcloud kms keys create $KEY_NAME --keyring $KEYRING_NAME --location $REGION --purpose "encryption"

4. Tworzenie repozytorium Artifact Registry w formacie Dockera z włączoną funkcją CMEK

W tej sekcji utworzysz repozytorium w formacie Dockera w Artifact Registry z włączonym CMEK. Będzie to ten sam klucz, który został użyty do wdrożenia funkcji w Cloud Functions.

Najpierw musisz mieć konto usługi dla Artifact Registry. Możesz go utworzyć, uruchamiając to polecenie:

gcloud beta services identity create --service=artifactregistry.googleapis.com --project=$PROJECT_ID

Użyj tego polecenia, aby przyznać roli uprawnień Szyfrator/deszyfrator klucza CryptoKey (roles/cloudkms.cryptoKeyEncrypterDecrypter) kontu usługi Artifact Registry, aby uzyskać uprawnienia do klucza:

gcloud kms keys add-iam-policy-binding \
  $KEY_NAME --location $REGION --keyring=$KEYRING_NAME \
  --member serviceAccount:service-$PROJECT_NUMBER@gcp-sa-artifactregistry.iam.gserviceaccount.com \
  --role roles/cloudkms.cryptoKeyEncrypterDecrypter

Następnie przyznaj rolę podmiotowi, który utworzy repozytorium w rejestrze artefaktów, np. Twojemu bieżącemu aktywnemu kontu. Aby sprawdzić, czy Twoje aktualne aktywne konto jest prawidłowe, uruchom polecenie gcloud auth list.

gcloud kms keys add-iam-policy-binding \
       $KEY_NAME --location $REGION --keyring=$KEYRING_NAME \
       --member user:$USER_EMAIL \
       --role roles/cloudkms.cryptoKeyEncrypterDecrypter

Teraz możesz utworzyć repozytorium w formacie Dockera, które obsługuje klucze CMEK.

Uwaga: region musi być taki sam jak klucz CMEK.

REPO_NAME=my-cmek-encrypted-repo 

KEY_FULLPATH=projects/"$PROJECT_ID"/locations/"$REGION"/keyRings/"$KEYRING_NAME"/cryptoKeys/"$KEY_NAME" 

gcloud artifacts repositories create $REPO_NAME \
    --repository-format=docker \
    --location=$REGION \
    --kms-key=$KEY_FULLPATH \
    --async

Możesz wyświetlić nowe repozytorium Artifact Registry, w którym działa to polecenie:

gcloud artifacts repositories describe $REPO_NAME --location=$REGION

5. Przyznawanie kontom usługi dostępu do klucza (2 generacji)

W tej sekcji omawiamy tworzenie kont usług dla funkcji 2 generacji. Jeśli tworzysz funkcję 1 generacji, przejdź do następnej sekcji.

Musisz przyznać dostęp do klucza kilku agentom usługi, przyznając im rolę uprawnień Szyfrator/deszyfrator klucza CryptoKey (roles/cloudkms.cryptoKeyEncrypterDecrypter). Ci agenci usługi służą do uzyskiwania dostępu do kodu źródłowego przechowywanego w Cloud Storage, przechowywania obrazów funkcji w repozytorium chronionym przez CMEK w Artifact Registry oraz wdrażania funkcji Cloud szyfrowanej za pomocą CMEK.

Czynności do wykonania w przypadku funkcji 2 generacji

  1. Przypisz agentowi usługi Cloud Run dostęp do klucza:
CLOUDRUN_SA=service-$PROJECT_NUMBER@serverless-robot-prod.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$CLOUDRUN_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Przypisz agentowi usługi Eventarc dostęp do klucza:
EVENTARC_SA=service-$PROJECT_NUMBER@gcp-sa-eventarc.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$EVENTARC_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Przyznaj agentowi usługi Artifact Registry dostęp do klucza:
AR_SA=service-$PROJECT_NUMBER@gcp-sa-artifactregistry.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$AR_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Przypisz agentom usługi Cloud Storage dostęp do klucza:
STORAGE_SA=service-$PROJECT_NUMBER@gs-project-accounts.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$STORAGE_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter

W następnej sekcji dowiesz się, jak utworzyć i wdrażać funkcję szyfrowaną CMEK.

6. Przyznawanie kont usługi dostępu do klucza (pierwszej generacji)

W tej sekcji omawiamy tworzenie kont usługi dla funkcji 1 generacji. Jeśli masz już utworzone konta usługi dla funkcji 2 generacji, przejdź do następnej sekcji.

Musisz przyznać dostęp do klucza kilku agentom usługi, przyznając im rolę uprawnień Szyfrator/deszyfrator klucza CryptoKey (roles/cloudkms.cryptoKeyEncrypterDecrypter). Ci agenci usługi służą do uzyskiwania dostępu do kodu źródłowego przechowywanego w Cloud Storage, przechowywania obrazów funkcji w repozytorium chronionym za pomocą CMEK w Artifact Registry oraz wdrażania funkcji Cloud szyfrowanej za pomocą CMEK.

Instrukcje dotyczące funkcji 1 generacji

  1. Przyznaj agentowi usługi Cloud Functions dostęp do klucza:
FUNCTION_SA=service-$PROJECT_NUMBER@gcf-admin-robot.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$FUNCTION_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Przyznaj agentowi usługi Artifact Registry dostęp do klucza:
AR_SA=service-$PROJECT_NUMBER@gcp-sa-artifactregistry.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$AR_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Przypisz agentom usługi Cloud Storage dostęp do klucza:
STORAGE_SA=service-$PROJECT_NUMBER@gs-project-accounts.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$STORAGE_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter

W następnej sekcji dowiesz się, jak utworzyć i wdrożyć funkcję szyfrowaną za pomocą klucza CMEK.

7. Tworzenie funkcji szyfrowanej za pomocą CMEK (2 generacji)

Ta sekcja dotyczy tworzenia funkcji 2 generacji. Możesz przejść do następnej sekcji, aby zobaczyć instrukcje dotyczące pierwszej generacji.

Masz już repozytorium Artifact Registry skonfigurowane z włączonym kluczem CMEK, a dla Cloud Functions dostęp do Twojego klucza. Teraz możesz wdrożyć funkcję szyfrowaną przy użyciu Twojego klucza CMEK.

Czynności do wykonania w przypadku funkcji 2 generacji:

Utwórz kod źródłowy funkcji

Chociaż to ćwiczenie w Codelabs korzysta z Node.js, możesz użyć dowolnego obsługiwanego środowiska wykonawczego.

Najpierw utwórz w nim katalog i dysk cd.

mkdir ~/cmek-function-2ndgen && cd $_

Następnie utwórz plik package.json.

touch package.json

echo '{
  "dependencies": {
    "@google-cloud/functions-framework": "^2.1.0"
  }
}
' > package.json

Następnie utwórz plik źródłowy index.js.

touch index.js

echo 'const functions = require("@google-cloud/functions-framework");

functions.http("helloWorld", (req, res) => {
 res.send(`Hello ${req.query.name || req.body.name || "World"}!`);
});' > index.js

Wdrażanie funkcji 2 generacji w Cloud Functions przy użyciu szyfrowania CMEK

Uwaga: przykład poniżej pokazuje, jak wdrożyć funkcję, korzystając ze źródeł z bieżącego katalogu. Upewnij się, że znajdujesz się w tym samym katalogu co kod źródłowy funkcji.

FUNCTION_NAME=protect-me-cmek-2ndgen
ENTRY_POINT=helloWorld

REPO_FULLPATH=projects/"$PROJECT_ID"/locations/"$REGION"/repositories/$REPO_NAME

gcloud beta functions deploy $FUNCTION_NAME  \
--gen2 \
--region $REGION \
--kms-key $KEY_FULLPATH \
--docker-repository $REPO_FULLPATH \
--source . \
--trigger-http \
--allow-unauthenticated \
--runtime nodejs16 \
--entry-point $ENTRY_POINT

Po wykonaniu tego polecenia możesz zobaczyć klucz CMEK w wynikach

gcloud features description $FUNCTION_NAME –region $REGION | grep kmsKeyName

Przetestuj funkcję 2 generacji

Aby przetestować swoją funkcję, użyj curlingu:

FUNCTION_URL="$(gcloud functions describe $FUNCTION_NAME --region $REGION --format='get(serviceConfig.uri)')"

curl $FUNCTION_URL

W efekcie:

Hello World!

Dopóki klucz szyfrowania jest włączony, funkcja zwróci wartość sukcesu do wywołującego. Gdy jednak klucz szyfrowania zostanie wyłączony, wywołujący otrzyma komunikat o błędzie.

W następnej sekcji zobaczysz, co się dzieje, gdy wywołasz funkcję po wyłączeniu klucza.

8. Tworzenie funkcji szyfrowanej za pomocą CMEK (1 generacji)

W tej sekcji omawiamy tworzenie funkcji 1 generacji. Jeśli masz już utworzoną funkcję 2 generacji, przejdź do następnej sekcji.

Teraz, gdy masz skonfigurowane repozytorium Artifact Registry z włączonym CMEK i przyznałeś Cloud Functions dostęp do klucza, możesz wdrożyć funkcję zaszyfrowaną za pomocą klucza CMEK.

Czynności do wykonania w przypadku funkcji 1 generacji:

Utwórz kod źródłowy funkcji 1 generacji.

Chociaż to ćwiczenie w Codelabs korzysta z Node.js, możesz użyć dowolnego obsługiwanego środowiska wykonawczego.

Najpierw utwórz katalog i przejdź do niego.

mkdir ~/cmek-function-1stgen && cd $_

Następnie utwórz plik package.json.

touch package.json

echo '{
    "name": "function-cmek-codelab",
    "version": "0.0.1"
}' > package.json

Następnie utwórz plik źródłowy index.js.

touch index.js

echo "exports.helloWorld = (req, res) => {
    let message = req.query.message || req.body.message || 'Hello World!';
    res.status(200).send(message);
};" > index.js

Wdróż funkcję Cloud Functions 1 generacji za pomocą szyfrowania CMEK

Uwaga: przykład poniżej pokazuje, jak wdrożyć funkcję za pomocą źródeł z bieżącego katalogu. Upewnij się, że znajdujesz się w tym samym katalogu co kod źródłowy funkcji.

FUNCTION_NAME=protect-me-cmek-1stgen
ENTRY_POINT=helloWorld

REPO_FULLPATH=projects/"$PROJECT_ID"/locations/"$REGION"/repositories/$REPO_NAME

gcloud functions deploy $FUNCTION_NAME  \
--region $REGION \
--kms-key $KEY_FULLPATH \
--docker-repository $REPO_FULLPATH \
--source . \
--trigger-http \
--allow-unauthenticated \
--runtime nodejs16 \
--entry-point $ENTRY_POINT

Po wykonaniu tego polecenia możesz zobaczyć klucz CMEK w wynikach

gcloud functions describe $FUNCTION_NAME –region $REGION | grep kmsKeyName

Testowanie funkcji 1 generacji

Aby przetestować swoją funkcję, użyj curlingu:

FUNCTION_URL="$(gcloud functions describe $FUNCTION_NAME --region $REGION --format='get(httpsTrigger.url)')"

curl $FUNCTION_URL

W efekcie:

Hello World!

Dopóki klucz szyfrowania jest włączony, funkcja zwróci wartość sukcesu do wywołującego. Gdy jednak klucz szyfrowania zostanie wyłączony, wywołujący otrzyma komunikat o błędzie.

W następnej sekcji zobaczysz, co się dzieje, gdy wywołasz funkcję po wyłączeniu klucza.

9. Wywoływanie funkcji szyfrowanej za pomocą klucza CMEK, gdy klucz szyfrowania został wyłączony

W tej ostatniej sekcji unieważnisz klucz i ponownie wywołasz funkcję, aby zobaczyć powstały błąd.

Wyłącz klucz szyfrowania

Aby wyłączyć klucz, możesz uruchomić ten wiersz polecenia. Ponieważ ten projekt tworzy tylko jedną wersję klucza, wyłączysz wersję 1.

gcloud kms keys versions disable 1 \
    --key=$KEY_NAME \
    --keyring=$KEYRING_NAME \
    --location=$REGION

Powinny pojawić się informacje:

algorithm: GOOGLE_SYMMETRIC_ENCRYPTION
createTime: '2023-04-11T03:30:49.111832653Z'
generateTime: '2023-04-11T03:30:49.111832653Z'
name: projects/dogfood-gcf-saraford/locations/us-central1/keyRings/myKeyRing/cryptoKeys/encrypted-function/cryptoKeyVersions/1
protectionLevel: SOFTWARE
state: DISABLED

Wywołanie funkcji przy wyłączonym kluczu

Teraz ponownie curl funkcję.

curl $FUNCTION_URL

i tym razem nie otrzymasz odpowiedzi Hello World.

W logach funkcji w Cloud Functions zobaczysz

User's CMEK key has been disabled. CMEK key: projects/<PROJECT-NAME>/locations/us-central1/keyRings/myKeyRing/cryptoKeys/encrypted-function

Próba wyświetlenia zasobów, gdy klucz CMEK jest wyłączony

W tej sekcji zobaczysz, które zasoby stają się niedostępne, gdy klucz CMEK jest wyłączony:

  • Kod źródłowy funkcji
  • Kompilacja obrazu kontenera na podstawie kodu źródłowego

Na przykład po kliknięciu karty Źródło w przypadku funkcji w Cloud Functions pojawia się błąd podczas pobierania archiwum. Podobny błąd wystąpi, jeśli spróbujesz wyświetlić bezpośrednio w Cloud Storage plik ZIP zawierający kod źródłowy.

ac3307bb05d30e19.png

Nie będziesz też mieć dostępu do obrazu kontenera dla funkcji z Artifact Registry. Jeśli na przykład spróbujesz wdrożyć obraz kontenera do Cloud Run, pojawi się komunikat o błędzie, że obraz nie został znaleziony.

Pełną listę zaszyfrowanych zasobów znajdziesz w dokumentacji funkcji CMEK.

10. Gratulacje

Gratulacje. Udało Ci się ukończyć ćwiczenia z programowania.

Omówione zagadnienia

  • Jak utworzyć klucz CMEK w istniejącym symetrycznym pęku kluczy
  • Jak utworzyć repozytorium Artifact Registry
  • Jak skonfigurować CMEK w funkcji Cloud Functions

Więcej informacji

Więcej informacji o Cloud Functions i CMEK znajdziesz pod tymi linkami: