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

1. Wprowadzenie

Przegląd

Cloud Functions to wymagające niewielu zasobów rozwiązanie do przetwarzania danych, które umożliwia programistom tworzenie samodzielnych funkcji o ściśle zdefiniowanym przeznaczeniu reagujących na zdarzenia w chmurze bez konieczności zarządzania serwerem lub środowiskiem wykonawczym.

Do ochrony funkcji Cloud Functions i powiązanych danych w spoczynku możesz używać kluczy szyfrowania zarządzanych przez klienta (CMEK) w usłudze Cloud Key Management Service. Wdrożenie funkcji z kluczem CMEK chroni powiązane z nią dane za pomocą klucza szyfrowania, nad którym masz pełną kontrolę. Ten typ szyfrowania pozwala spełnić wymagania dotyczące zgodności w określonych branżach, np. w przypadku usług finansowych. Klucz jest Twoją własnością i nie jest kontrolowany przez Google, więc nikt (łącznie z Tobą) nie może uzyskać dostępu do danych chronionych przez te klucze szyfrowania, gdy są one wyłączone lub zniszczone.

W przypadku Cloud Functions CMEK szyfruje te elementy:

  • Kod źródłowy funkcji przesłany na potrzeby 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żda wdrożona instancja funkcji.
  • Dane w spoczynku w przypadku wewnętrznych kanałów przesyłania zdarzeń (tylko 1 generacja).

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

Co utworzysz

W tym module dowiesz się, jak wdrożyć funkcję w Cloud Functions (1 lub 2 generacji) zaszyfrowaną za pomocą klucza CMEK. W tym samouczku do celów demonstracyjnych używamy publicznej funkcji w Cloud Functions, czyli takiej, która nie wymaga uwierzytelniania. Funkcję z włączonym 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 w istniejącym pęku kluczy symetrycznych
  • Tworzenie repozytorium Artifact Registry
  • Jak skonfigurować klucz CMEK w Cloud Functions zarówno w środowiskach pierwszej, jak i drugiej generacji

2. Konfiguracja i wymagania

Wymagania wstępne

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

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 z opisem tego środowiska. Jeśli pojawił się ekran pośredni, kliknij Dalej.

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.

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. Tworzenie nowego pęku kluczy i klucza dla Cloud Functions

Sprawdź, czy interfejs Cloud KMS API jest włączony. W tym celu uruchom to polecenie:

gcloud services enable cloudkms.googleapis.com

Najpierw utwórz zmienne środowiskowe zawierające nazwę pęku kluczy, nazwę klucza, region i inne zmienne używane w tym module.

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ęk kluczy, który jest zasobem głównym dla kluczy Cloud KMS i wersji kluczy.

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łączonym kluczem CMEK

W tej sekcji utworzysz repozytorium w formacie Dockera w Artifact Registry z włączonym szyfrowaniem 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 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ć kontu usługi Artifact Registry rolę Szyfrator/deszyfrator klucza CryptoKey Uprawnienia (roles/cloudkms.cryptoKeyEncrypterDecrypter) i tym samym przyznać mu 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 usłudze Artifact Registry, np. Twojemu bieżącemu aktywnemu kontu. Aby sprawdzić, które konto jest obecnie aktywne, 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

Możesz teraz utworzyć repozytorium w formacie Dockera z włączonym szyfrowaniem CMEK.

Uwaga: region musi być taki sam jak region klucza 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

Aby wyświetlić nowe repozytorium Artifact Registry, uruchom to polecenie:

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

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

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

Musisz przyznać kilku agentom usługi dostęp do klucza, przyznając im rolę uprawnień Szyfrator/deszyfrator klucza CryptoKey (roles/cloudkms.cryptoKeyEncrypterDecrypter). Ci agenci usługi są używani 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 do wdrażania funkcji w Cloud Functions zaszyfrowanej za pomocą CMEK.

Czynności w przypadku funkcji 2 generacji

  1. Przyznaj 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. Przyznaj 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. Przyznaj 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.

6. Przyznawanie kontom usługi dostępu do klucza (1 generacji)

W tej sekcji znajdziesz informacje o tworzeniu 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ć kilku agentom usługi dostęp do klucza, przyznając im rolę uprawnień Szyfrator/deszyfrator klucza CryptoKey (roles/cloudkms.cryptoKeyEncrypterDecrypter). Ci agenci usługi są używani 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 do wdrażania funkcji w Cloud Functions zaszyfrowanej za pomocą CMEK.

Czynności w przypadku 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. Przyznaj 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ą klucza CMEK (2 generacji)

Ta sekcja zawiera informacje o tworzeniu funkcji 2 generacji. Instrukcje dotyczące 1 generacji znajdziesz w następnej sekcji.

Po skonfigurowaniu repozytorium Artifact Registry z włączonym CMEK i przyznaniu Cloud Functions dostępu do klucza możesz wdrożyć funkcję zaszyfrowaną za pomocą klucza CMEK.

Czynności do wykonania w przypadku funkcji 2 generacji:

Tworzenie kodu źródłowego funkcji

W tym samouczku używamy Node.js, ale możesz użyć dowolnego obsługiwanego środowiska wykonawczego.

Najpierw utwórz katalog i przejdź do niego.

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: w przykładzie poniżej pokazujemy, jak wdrożyć funkcję przy użyciu źródeł z bieżącego katalogu. Sprawdź, czy 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

Aby wyświetlić klucz CMEK w danych wyjściowych, uruchom to polecenie:

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

Testowanie funkcji 2 generacji

Możesz przetestować funkcję, wywołując ją:

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

curl $FUNCTION_URL

co powoduje:

Hello World!

Dopóki klucz szyfrowania jest włączony, funkcja zwraca do wywołującego wartość wskazującą powodzenie. Gdy klucz szyfrowania zostanie wyłączony, rozmówca otrzyma komunikat o błędzie.

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

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

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

Po skonfigurowaniu repozytorium Artifact Registry z włączonym CMEK i przyznaniu Cloud Functions dostępu do klucza możesz wdrożyć funkcję zaszyfrowaną za pomocą klucza CMEK.

Czynności w przypadku funkcji 1 generacji:

Tworzenie kodu źródłowego funkcji 1 generacji

W tym samouczku używamy Node.js, ale 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

Wdrażanie funkcji Cloud Functions 1 generacji za pomocą szyfrowania CMEK

Uwaga: w przykładzie poniżej pokazujemy, jak wdrożyć funkcję przy użyciu źródeł z bieżącego katalogu. Sprawdź, czy 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

Aby wyświetlić klucz CMEK w danych wyjściowych, uruchom to polecenie:

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

Testowanie funkcji 1 generacji

Możesz przetestować funkcję, zwijając ją:

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

curl $FUNCTION_URL

co powoduje:

Hello World!

Dopóki klucz szyfrowania jest włączony, funkcja zwraca do wywołującego wartość wskazującą powodzenie. Gdy klucz szyfrowania zostanie wyłączony, rozmówca otrzyma komunikat o błędzie.

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

9. Wywoływanie funkcji zaszyfrowanej za pomocą CMEK, w której klucz szyfrowania został wyłączony

W tej ostatniej sekcji unieważnisz klucz i ponownie wywołasz funkcję, aby zobaczyć wynikający z tego błąd.

Wyłączanie klucza szyfrowania

Aby wyłączyć klucz, możesz uruchomić to polecenie. W tym laboratorium tworzymy tylko jedną wersję klucza, więc wyłączysz wersję 1.

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

Powinny się wyświetlić te 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ływanie funkcji za pomocą wyłączonego klucza

Teraz ponownie curl funkcję.

curl $FUNCTION_URL

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, że po wyłączeniu klucza CMEK te zasoby staną się niedostępne:

  • Kod źródłowy funkcji
  • Obraz kontenera utworzony na podstawie kodu źródłowego

Na przykład otwarcie karty Źródło w przypadku funkcji Cloud Function powoduje wyświetlenie błędu podczas pobierania archiwum. Podobny błąd pojawi się, jeśli spróbujesz wyświetlić plik ZIP zawierający kod źródłowy bezpośrednio w Cloud Storage.

ac3307bb05d30e19.png

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

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

10. Gratulacje

Gratulacje! Codelab został ukończony.

Omówione zagadnienia

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

Więcej informacji

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