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 obliczeniowe, które umożliwia programistom tworzenie samodzielnych funkcji o jednym przeznaczeniu, które reagują na zdarzenia w chmurze bez konieczności zarządzania serwerem lub środowiskiem wykonawczym.

Aby chronić funkcje Cloud Functions i powiązane z nimi dane w spoczynku, możesz używać kluczy szyfrowania zarządzanych przez klienta (CMEK) usługi Cloud Key Management Service. Wdrożenie funkcji z kluczem CMEK chroni powiązane z nią dane za pomocą klucza szyfrowania, który masz nad wszystkim pod kontrolą. Ten typ szyfrowania umożliwia spełnienie wymagań określonych w określonych branżach, takich jak usługi finansowe. 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 dane:

  • Kod źródłowy funkcji przesłany do wdrożenia i zapisany 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 z wewnętrznych kanałów transportu zdarzeń (tylko 1 generacji).

Więcej informacji o tym, które dane są szyfrowane, znajdziesz w dokumentacji funkcji CMEK w Cloud Functions.

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 ćwiczeniu w Codelabs korzysta się z publicznej funkcji w Cloud Functions, czyli takiej, która nie wymaga uwierzytelniania, do celów demonstracyjnych. Funkcję z uwierzytelnianiem CMEK możesz wywoływać tak samo jak każdą inną funkcję w Cloud Functions, która wymaga uwierzytelniania.

Czego się nauczysz

  • Jak utworzyć klucz CMEK w istniejącym symetrycznym pęku kluczy
  • 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 Cloud kliknij Aktywuj Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Jeśli uruchamiasz Cloud Shell po raz pierwszy, zobaczysz ekran pośredni z opisem tej usługi. Jeśli wyświetlił się ekran pośredni, kliknij Dalej.

9c92662c6a846a5c.png

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

9f0e51b578fecce5.png

Ta maszyna wirtualna ma wszystkie potrzebne narzędzia dla programistów. 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ść zadań w ramach tego ćwiczenia z programowania można wykonać w przeglądarce.

Po nawiązaniu połączenia z Cloud Shell powinno pojawić się potwierdzenie, że użytkownik jest uwierzytelniony, a projekt jest ustawiony na identyfikator Twojego projektu.

  1. Uruchom to polecenie w Cloud Shell, aby potwierdzić, że jesteś uwierzytelniony:
gcloud auth list

Dane wyjściowe polecenia

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Uruchom to polecenie w Cloud Shell, aby sprawdzić, czy polecenie gcloud zna Twój projekt:
gcloud config list project

Dane wyjściowe polecenia

[core]
project = <PROJECT_ID>

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

gcloud config set project <PROJECT_ID>

Dane wyjściowe polecenia

Updated property [core/project].

3. Utwórz nowy pęk kluczy i klucz dla Cloud Functions

Sprawdź, czy interfejs Cloud KMS API jest włączony, uruchamiając 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 z programowania.

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

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

Najpierw potrzebne będzie 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

Za pomocą tego polecenia przypisz rolę uprawnień Szyfrator/deszyfrator CryptoKey (roles/cloudkms.cryptoKeyEncrypterDecrypter) do konta usługi Artifact Registry, aby mieć 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

I przypisz rolę do zasady, która utworzy repozytorium w Artifact Registry, np. swoje obecne aktywne konto. Możesz zweryfikować bieżące aktywne konto, uruchamiając narzędzie 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ć tym samym regionem co 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ługi 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 rolę uprawnień Szyfrator/deszyfrator CryptoKey (roles/cloudkms.cryptoKeyEncrypterDecrypter). Te agenty usługi służą do uzyskiwania dostępu do kodu źródłowego zapisanego w Cloud Storage, przechowywania obrazów funkcji w repozytorium chronionym kluczem CMEK w Artifact Registry oraz do wdrażania funkcji w Cloud Functions zaszyfrowanych za pomocą klucza CMEK.

Kroki dla 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. Przyznaj kontom usługi dostęp do klucza (1 generacji)

Z tej sekcji dowiesz się, jak tworzyć konta usługi na potrzeby 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 rolę uprawnień Szyfrator/deszyfrator CryptoKey (roles/cloudkms.cryptoKeyEncrypterDecrypter). Te agenty usługi służą do uzyskiwania dostępu do kodu źródłowego zapisanego w Cloud Storage, przechowywania obrazów funkcji w repozytorium chronionym kluczem CMEK w Artifact Registry oraz do wdrażania funkcji w Cloud Functions zaszyfrowanych za pomocą klucza CMEK.

Kroki dla 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 zaszyfrowanej za pomocą klucza CMEK (2 generacji)

W tej sekcji omawiamy tworzenie funkcji 2 generacji. Instrukcje dotyczące 1 generacji znajdziesz w następnej sekcji.

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.

Kroki dla 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 w Cloud Functions 2 generacji z użyciem szyfrowania CMEK

Uwaga: przykład poniżej pokazuje, jak wdrożyć funkcję za pomocą źródeł z bieżącego katalogu. Upewnij się, że jesteś 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 uruchomieniu tego polecenia możesz zobaczyć klucz CMEK w wynikowych danych wyjściowych

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

Efektem jest to:

Hello World!

Dopóki klucz szyfrowania jest włączony, funkcja zwraca powodzenie w wyniku wywołania. Jednak po wyłączeniu klucza szyfrowania rozmówca zobaczy błąd.

W następnej sekcji dowiesz się, co się dzieje w przypadku wywołania funkcji po wyłączeniu klucza.

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

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

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.

Kroki dla 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 w nim katalog i dysk cd.

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 w Cloud Functions 1 generacji z użyciem szyfrowania CMEK

Uwaga: przykład poniżej pokazuje, jak wdrożyć funkcję za pomocą źródeł z bieżącego katalogu. Upewnij się, że jesteś 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 uruchomieniu tego polecenia możesz zobaczyć klucz CMEK w wynikowych danych wyjściowych

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

Przetestuj funkcję 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

Efektem jest to:

Hello World!

Dopóki klucz szyfrowania jest włączony, funkcja zwraca powodzenie w wyniku wywołania. Jednak po wyłączeniu klucza szyfrowania rozmówca zobaczy błąd.

W następnej sekcji dowiesz się, co się dzieje w przypadku wywołania funkcji po wyłączeniu klucza.

9. Wywołaj funkcję szyfrowaną za pomocą klucza CMEK, w której klucz szyfrowania został wyłączony

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

Wyłącz klucz szyfrowania

Aby wyłączyć klucz, możesz uruchomić to polecenie. Ponieważ w ramach tego ćwiczenia w Codelabs tworzona jest tylko jedna wersja klucza, wyłączysz wersję 1.

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

Powinien pojawić się następujący komunikat:

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łaj funkcję z wyłączonym klawiszem

Teraz curl ponownie wywołaj 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, że następujące zasoby staną się niedostępne, gdy klucz CMEK będzie wyłączony:

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

Na przykład otwarcie karty Źródło dla funkcji w Cloud Functions spowoduje wyświetlenie błędu 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 na potrzeby funkcji z Artifact Registry. Jeśli na przykład spróbujesz wdrożyć ten obraz kontenera w Cloud Run, wyświetli się komunikat o błędzie informujący o tym, że obrazu nie znaleziono.

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ć klucze CMEK w funkcji w Cloud Functions

Więcej informacji

Więcej informacji o Cloud Functions i CMEK znajdziesz w tych linkach: