1. Przegląd
Chcesz zwiększyć bezpieczeństwo i prywatność zbiorów zadań przyspieszanych przez GPU? To ćwiczenie zawiera informacje o możliwościach Trusted Space, oferty zapewniającej silną izolację operatorów i obsługę akceleratorów w przypadku wrażliwych zbiorów zadań AI/ML.
Ochrona cennych danych, modeli i kluczy jest ważniejsza niż kiedykolwiek. Trusted Space zapewnia rozwiązanie, które gwarantuje, że Twoje zadania działają w bezpiecznym, zaufanym środowisku, do którego nawet operator zadania nie ma dostępu.
Oto co oferuje zaufana przestrzeń:
- Zwiększona prywatność i bezpieczeństwo: zaufana przestrzeń zapewnia zaufane środowisko wykonawcze, w którym Twoje zasoby wrażliwe (np. modele, cenne dane i klucze) pozostają chronione dzięki dowodom kryptograficznym.
- Izolacja operatora: wyeliminuj obawy dotyczące zakłóceń ze strony operatora. W przypadku zaufanej przestrzeni nawet operatorzy zbiorów zadań nie mają dostępu, co uniemożliwia im łączenie się przez SSH, uzyskiwanie dostępu do danych, instalowanie oprogramowania ani manipulowanie kodem.
- Obsługa akceleratorów: Trusted Space został zaprojektowany tak, aby bezproblemowo współpracować z szeroką gamą akceleratorów sprzętowych, w tym z procesorami graficznymi, takimi jak H100, A100, T4 i L4. Dzięki temu aplikacje AI/ML o kluczowym znaczeniu dla wydajności będą działać bez zakłóceń.
Czego się nauczysz
- Poznaj kluczowe oferty Trusted Space.
- Dowiedz się, jak wdrażać i konfigurować środowisko zaufanej przestrzeni, aby zabezpieczyć cenne zasoby zbioru zadań AI/ML.
Czego potrzebujesz
- Projekt Google Cloud Platform
- Podstawowa znajomość Google Compute Engine i akceleratorów.
- Podstawowa wiedza na temat kont usługi, zarządzania kluczami, federacji tożsamości zadań i warunków atrybutów.
- Podstawowa wiedza o kontenerach i Artifact Registry
Ochrona promptów do generowania kodu wrażliwego za pomocą Primus Company
W tym ćwiczeniu wcielimy się w rolę firmy Primus, która priorytetowo traktuje prywatność i bezpieczeństwo danych swoich pracowników. Firma Primus chce wdrożyć model generowania kodu, aby pomagać programistom w ich zadaniach związanych z kodowaniem. Obawiają się jednak o zachowanie poufności promptów przesyłanych przez pracowników, ponieważ często zawierają one fragmenty kodu z informacjami poufnymi, szczegóły projektów wewnętrznych lub algorytmy objęte prawem własności.
Dlaczego firma Primus nie ufa operatorowi?
Primus Corp działa na wysoce konkurencyjnym rynku. Ich baza kodu zawiera cenną własność intelektualną, w tym zastrzeżone algorytmy i wrażliwe fragmenty kodu, które zapewniają im przewagę konkurencyjną. Obawiają się szpiegostwa korporacyjnego ze strony operatorów zbiorów zadań. Dodatkowo prompty pracowników mogą zawierać poufne fragmenty kodu, do których dostęp jest ograniczony zasadą „potrzeby dostępu do informacji”, które Primus Corp chce chronić.
Aby rozwiązać ten problem, firma Primus Corp wykorzysta Trusted Space do odizolowania serwera wnioskowania, na którym działa model generowania kodu. Jak to działa:
- Szyfrowanie promptów: przed wysłaniem prompta do serwera wnioskowania każdy pracownik zaszyfruje go za pomocą klucza KMS zarządzanego przez Primus Corp w Google Cloud. Dzięki temu tylko środowisko zaufanej przestrzeni, w którym dostępny jest odpowiedni klucz odszyfrowywania, może odszyfrować prompt i uzyskać do niego dostęp w formie zwykłego tekstu. W rzeczywistości szyfrowanie po stronie klienta może być obsługiwane przez dostępne biblioteki (np. tink). W ramach tego ćwiczenia użyjemy tej przykładowej aplikacji klienckiej z szyfrowaniem kopertowym.
- Izolacja operatora: tylko serwer wnioskowania działający w środowisku zaufanej przestrzeni będzie mieć dostęp do klucza używanego do szyfrowania i będzie mógł odszyfrować prompt w zaufanym środowisku. Dostęp do klucza szyfrowania będzie chroniony przez pulę tożsamości zadań. Dzięki gwarancjom izolacji Poufnej przestrzeni nawet operator zadania nie ma dostępu do klucza używanego do szyfrowania ani do odszyfrowanych treści.
- Bezpieczne wnioskowanie z użyciem akceleratorów: serwer wnioskowania zostanie uruchomiony na chronionej maszynie wirtualnej (w ramach konfiguracji zaufanej przestrzeni), co zapewni, że instancja obciążenia nie została naruszona przez złośliwe oprogramowanie ani rootkity działające na etapie rozruchu lub na poziomie jądra systemu operacyjnego. Ten serwer odszyfrowuje prompt w środowisku Trusted Space, przeprowadza wnioskowanie przy użyciu modelu generowania kodu i zwraca wygenerowany kod pracownikowi.
2. Konfigurowanie zasobów w chmurze
Zanim zaczniesz
- Sklonuj to repozytorium za pomocą poniższego polecenia, aby uzyskać wymagane skrypty, które są używane w tym ćwiczeniu.
git clone https://github.com/GoogleCloudPlatform/confidential-space.git
- Zmień katalog tego ćwiczenia w Codelabs.
cd confidential-space/codelabs/trusted_space_codelab/scripts
- Sprawdź, czy masz ustawione wymagane zmienne środowiskowe projektu, jak pokazano poniżej. Więcej informacji o konfigurowaniu projektu GCP znajdziesz w tym ćwiczeniu w Codelabs. Więcej informacji o tym, jak uzyskać identyfikator projektu i czym różni się on od nazwy i numeru projektu, znajdziesz tutaj.
export PRIMUS_PROJECT_ID=<GCP project id of Primus>
- Włącz płatności w swoich projektach.
- Włącz interfejs Confidential Computing API i te interfejsy API w obu projektach.
gcloud services enable \
cloudapis.googleapis.com \
cloudresourcemanager.googleapis.com \
cloudkms.googleapis.com \
cloudshell.googleapis.com \
container.googleapis.com \
containerregistry.googleapis.com \
iam.googleapis.com \
confidentialcomputing.googleapis.com
- Przypisz wartości do zmiennych dla nazw zasobów określonych powyżej za pomocą tego polecenia. Te zmienne umożliwiają dostosowywanie nazw zasobów do potrzeb użytkownika, a także korzystanie z istniejących zasobów, jeśli zostały już utworzone. (np.
export PRIMUS_SERVICE_ACCOUNT='my-service-account')
- W projekcie Primus możesz ustawić te zmienne, używając nazw istniejących zasobów w chmurze. Jeśli zmienna jest ustawiona, zostanie użyty odpowiedni istniejący zasób w chmurze z projektu Primus. Jeśli zmienna nie jest ustawiona, nazwa zasobu w chmurze zostanie wygenerowana na podstawie nazwy projektu i zostanie utworzony nowy zasób w chmurze o tej nazwie. Poniżej znajdziesz obsługiwane zmienne nazw zasobów:
| Region, w którym zostaną utworzone zasoby regionalne dla firmy Primus. |
| Lokalizacja, w której zostaną utworzone zasoby dla firmy Primus. |
| Strefa, w której zostaną utworzone zasoby strefowe dla firmy Primus. |
| Pula tożsamości zadań firmy Primus do ochrony zasobów w chmurze. |
| Dostawca puli tożsamości zadań firmy Primus, który zawiera warunek autoryzacji do użycia w przypadku tokenów podpisanych przez usługę weryfikacji atestów. |
| Konto usługi firmy Primus, którego |
| Klucz KMS służy do szyfrowania promptów dostarczanych przez pracowników firmy Primus. |
| Pęk kluczy KMS, który zostanie użyty do utworzenia klucza szyfrującego |
| Wersja klucza KMS klucza szyfrowania |
| Repozytorium artefaktów, do którego zostanie przesłany obraz Dockera obciążenia. |
| Region repozytorium artefaktów, w którym będzie opublikowany obraz Dockera zbioru zadań. |
| Nazwa maszyny wirtualnej zadania. |
| Nazwa obrazu Dockera zadania. |
| Tag obrazu kontenera zbioru zadań. |
| Konto usługi, które ma uprawnienia dostępu do maszyny wirtualnej poufnego środowiska, na której działa zadanie. |
| Nazwa maszyny wirtualnej klienta, na której będzie uruchamiana aplikacja kliencka serwera wnioskowania. |
| Konto usługi używane przez |
- W projekcie
$PRIMUS_PROJECT_IDmusisz mieć role administratora pamięci masowej, administratora Artifact Registry, administratora Cloud KMS, administratora konta usługi i administratora pul tożsamości zadań IAM Workload Identity. W tym przewodniku znajdziesz informacje o tym, jak przyznawać role uprawnień za pomocą konsoli GCP. - W przypadku
$PRIMUS_PROJECT_IDuruchom ten skrypt, aby ustawić pozostałe nazwy zmiennych na wartości oparte na identyfikatorze projektu dla nazw zasobów.
source config_env.sh
Konfigurowanie zasobów firmy Primus
W ramach tego kroku skonfigurujesz wymagane zasoby w chmurze dla Primusa. Aby skonfigurować zasoby dla Primusa, uruchom ten skrypt. W ramach wykonania skryptu zostaną utworzone te zasoby:
- Klucz szyfrowania (
$PRIMUS_ENC_KEY) i pęk kluczy ($PRIMUS_ENC_KEYRING) w KMS do szyfrowania pliku danych klienta firmy Primus. - Pula tożsamości zadań (
$PRIMUS_WORKLOAD_IDENTITY_POOL) do weryfikowania deklaracji na podstawie warunków atrybutów skonfigurowanych u jej dostawcy. - Konto usługi (
$PRIMUS_SERVICE_ACCOUNT) dołączone do wspomnianej puli tożsamości zadań ($PRIMUS_WORKLOAD_IDENTITY_POOL) ma dostęp do odszyfrowywania danych za pomocą klucza KMS (za pomocą roliroles/cloudkms.cryptoKeyDecrypter), szyfrowania danych za pomocą klucza KMS (za pomocą roliroles/cloudkms.cryptoKeyEncrypter), odczytywania danych z zasobnika Cloud Storage (za pomocą roliobjectViewer) i łączenia konta usługi z pula tożsamości zadań (za pomocą roliroles/iam.workloadIdentityUser).
./setup_primus_resources.sh
3. Tworzenie zadania
Tworzenie konta usługi zadania
Teraz utworzysz konto usługi dla zadania z wymaganymi rolami i uprawnieniami. Uruchom ten skrypt, aby utworzyć konto usługi obciążenia w projekcie Primus. To konto usługi będzie używane przez maszynę wirtualną, na której działa serwer wnioskowania.
To konto usługi obciążenia ($WORKLOAD_SERVICEACCOUNT) będzie miało przypisane te role:
confidentialcomputing.workloadUser, aby uzyskać token atestu.logging.logWriter– zapisywanie logów w Cloud Logging.
./create_workload_service_account.sh
Tworzenie zadania
W ramach tego kroku utworzysz obraz Dockera z obciążeniem. Zadanie zostanie utworzone przez firmę Primus. Obciążenie użyte w tym module to kod w Pythonie, który korzysta z modelu codegemma z publicznie dostępnego zasobnika GCS (z bazy modeli Vertex). Zadanie wczyta model codegemma i uruchomi serwer wnioskowania, który będzie obsługiwać żądania generowania kodu od deweloperów Primusa.
W żądaniu wygenerowania kodu zadanie otrzyma opakowany klucz DEK wraz z zaszyfrowanym promptem. Obciążenie wywoła interfejs KMS API, aby odszyfrować klucz DEK, a następnie odszyfruje prompt przy użyciu tego klucza. Klucze szyfrowania (w przypadku klucza DEK) będą chronione za pomocą puli tożsamości zadań, a dostęp do nich będą miały zbiory zadań spełniające warunki atrybutów. Warunki atrybutów są szczegółowo opisane w następnej sekcji dotyczącej autoryzacji obciążenia. Gdy serwer wnioskowania otrzyma odszyfrowany prompt, wygeneruje kod za pomocą załadowanego modelu i zwróci odpowiedź.
Uruchom ten skrypt, aby utworzyć zadanie, w którym wykonywane są te czynności:
- Utwórz Artifact Registry(
$PRIMUS_ARTIFACT_REGISTRY) należący do Primusa. - Zaktualizuj kod zbioru zadań, podając nazwy wymaganych zasobów.
- Utwórz zadanie serwera wnioskowania i plik Dockerfile do utworzenia obrazu Dockera z kodem zadania. Tutaj znajdziesz plik Dockerfile użyty w tych ćwiczeniach z programowania.
- Utwórz obraz Dockera i opublikuj go w Artifact Registry (
$PRIMUS_ARTIFACT_REGISTRY) należącym do firmy Primus. - Przyznaj usłudze
$WORKLOAD_SERVICEACCOUNTuprawnienia do odczytu$PRIMUS_ARTIFACT_REGISTRY. Jest to potrzebne, aby kontener zbioru zadań mógł pobrać obraz Dockera zbioru zadań z Artifact Registry.
./create_workload.sh
Dla Twojej wygody podajemy metodę generate() zbioru zadań, który jest tworzony i używany w tym ćwiczeniu z programowania (cały kod zbioru zadań znajdziesz tutaj).
def generate():
try:
data = request.get_json()
ciphertext = base64.b64decode(data["ciphertext"])
wrapped_dek = base64.b64decode(data["wrapped_dek"])
unwrapped_dek_response = kms_client.decrypt(
request={"name": key_name, "ciphertext": wrapped_dek}
)
unwrapped_dek = unwrapped_dek_response.plaintext
f = Fernet(unwrapped_dek)
plaintext = f.decrypt(ciphertext)
prompt = plaintext.decode("utf-8")
tokens = tokenizer(prompt, return_tensors="pt")
outputs = model.generate(**tokens, max_new_tokens=128)
generated_code = tokenizer.decode(outputs[0])
generated_code_bytes = generated_code.encode("utf-8")
response = f.encrypt(generated_code_bytes)
ciphertext_base64 = base64.b64encode(response).decode("utf-8")
response = {"generated_code_ciphertext": ciphertext_base64}
return jsonify(response)
except (ValueError, TypeError, KeyError) as e:
return jsonify({"error": str(e)}), 500
4. Autoryzowanie i uruchamianie zbioru zadań
Autoryzowanie zadania
Firma Primus chce autoryzować zbiory zadań do uzyskiwania dostępu do klucza KMS używanego do szyfrowania promptów na podstawie atrybutów tych zasobów:
- Co: kod, który został zweryfikowany.
- Gdzie: bezpieczne środowisko
- Kto: zaufany operator
Primus używa federacji tożsamości zadań, aby egzekwować zasady dostępu oparte na tych wymaganiach. Federacja tożsamości zadań umożliwia określanie warunków atrybutów. Te warunki ograniczają tożsamości, które mogą uwierzytelniać się w puli tożsamości zadań. Usługę weryfikacji zaświadczeń można dodać do puli tożsamości zadań jako dostawcę puli tożsamości zadań, aby przedstawiać pomiary i egzekwować zasady.
Pula tożsamości zadań została utworzona wcześniej w ramach kroku konfiguracji zasobów w chmurze. Primus utworzy teraz nowego dostawcę puli tożsamości zadań OIDC. Określony --attribute-condition autoryzuje dostęp do kontenera zbioru zadań. Wymagania:
- Co: najnowsza wersja
$WORKLOAD_IMAGE_NAMEzostała przesłana do repozytorium$PRIMUS_ARTIFACT_REPOSITORY. - Miejsce: zaufane środowisko wykonawcze Poufnej przestrzeni działa na w pełni obsługiwanym obrazie maszyny wirtualnej Poufnej przestrzeni.
- Kto: konto usługi Primus
$WORKLOAD_SERVICE_ACCOUNT.
export WORKLOAD_IMAGE_DIGEST=$(gcloud artifacts docker images describe ${PRIMUS_PROJECT_REPOSITORY_REGION}-docker.pkg.dev/$PRIMUS_PROJECT_ID/$PRIMUS_ARTIFACT_REPOSITORY/$WORKLOAD_IMAGE_NAME:$WORKLOAD_IMAGE_TAG --format="value(image_summary.digest)" --project ${PRIMUS_PROJECT_ID})
gcloud iam workload-identity-pools providers create-oidc $PRIMUS_WIP_PROVIDER \
--location="global" \
--project="$PRIMUS_PROJECT_ID" \
--workload-identity-pool="$PRIMUS_WORKLOAD_IDENTITY_POOL" \
--issuer-uri="https://confidentialcomputing.googleapis.com/" \
--allowed-audiences="https://sts.googleapis.com" \
--attribute-mapping="google.subject='assertion.sub'" \
--attribute-condition="assertion.swname == 'HARDENED_SHIELDED' && assertion.hwmodel == 'GCP_SHIELDED_VM' &&
assertion.submods.container.image_digest == '${WORKLOAD_IMAGE_DIGEST}' &&
assertion.submods.container.image_reference == '${PRIMUS_PROJECT_REPOSITORY_REGION}-docker.pkg.dev/$PRIMUS_PROJECT_ID/$PRIMUS_ARTIFACT_REPOSITORY/$WORKLOAD_IMAGE_NAME:$WORKLOAD_IMAGE_TAG' &&
'$WORKLOAD_SERVICEACCOUNT@$PRIMUS_PROJECT_ID.iam.gserviceaccount.com' in assertion.google_service_accounts"
Powyższe polecenie sprawdza, czy zbiór zadań działa w zaufanym środowisku, weryfikując, czy wartość hwmodel to „GCP_SHIELDED_VM”, a wartość swname to „HARDENED_SHIELDED”. Obejmuje ona również asercje dotyczące konkretnych zadań, takie jak image_digest i image_reference, które zwiększają bezpieczeństwo i zapewniają integralność uruchomionego zadania.
Uruchamianie zadania
W ramach tego kroku uruchomimy zadanie na maszynie wirtualnej w zaufanej przestrzeni, do której będzie dołączony akcelerator. Wymagane argumenty TEE są przekazywane za pomocą flagi metadanych. Argumenty kontenera zbioru zadań są przekazywane za pomocą części „tee-cmd” flagi. Aby wyposażyć maszynę wirtualną z obciążeniem w procesor graficzny Nvidia Tesla T4, użyjemy flagi --accelerator=type=nvidia-tesla-t4,count=1. Spowoduje to podłączenie jednego GPU do maszyny wirtualnej. W flagach metadanych musimy też umieścić symbol tee-install-gpu-driver=true, aby uruchomić instalację odpowiedniego sterownika GPU.
gcloud compute instances create ${WORKLOAD_VM} \
--accelerator=type=nvidia-tesla-t4,count=1 \
--machine-type=n1-standard-16 \
--shielded-secure-boot \
--image-project=conf-space-images-preview \
--image=confidential-space-0-gpupreview-796705b \
--zone=${PRIMUS_PROJECT_ZONE} \
--maintenance-policy=TERMINATE \
--boot-disk-size=40 \
--scopes=cloud-platform \
--service-account=${WORKLOAD_SERVICEACCOUNT}@${PRIMUS_PROJECT_ID}.iam.gserviceaccount.com \
--metadata="^~^tee-image-reference=${PRIMUS_PROJECT_REPOSITORY_REGION}-docker.pkg.dev/${PRIMUS_PROJECT_ID}/${PRIMUS_ARTIFACT_REPOSITORY}/${WORKLOAD_IMAGE_NAME}:${WORKLOAD_IMAGE_TAG}~tee-install-gpu-driver=true~tee-restart-policy=Never"
Uruchamianie zapytania o wnioskowanie
Po pomyślnym uruchomieniu serwera wnioskowania dotyczącego obciążenia pracownicy firmy Primus mogą wysyłać do niego żądania generowania kodu.
W ramach tego ćwiczenia użyjemy poniższego skryptu do skonfigurowania aplikacji klienckiej, która będzie wchodzić w interakcje z serwerem wnioskowania. Uruchom ten skrypt, aby skonfigurować kliencką maszynę wirtualną.
./setup_client.sh
Poniższe kroki pokazują, jak połączyć się przez SSH z maszyną wirtualną klienta i uruchomić przykładową aplikację kliencką w wirtualnym środowisku Pythona. Ta przykładowa aplikacja wykorzystuje szyfrowanie kopertowe z biblioteką Fernet, ale pamiętaj, że konkretne biblioteki szyfrowania można dostosować do różnych przypadków użycia.
gcloud compute ssh ${CLIENT_VM} --zone=${PRIMUS_PROJECT_ZONE}
Uruchom te polecenia, aby aktywować środowisko wirtualne Pythona na maszynie wirtualnej klienta i wykonać aplikację kliencką.
source venv/bin/activate
python3 inference_client.py
Dane wyjściowe tej przykładowej aplikacji klienckiej będą zawierać żądania szyfrowania i tekstu jawnego oraz odpowiadające im zaszyfrowane i odszyfrowane odpowiedzi.
5. Czyszczenie
Tutaj znajdziesz skrypt, którego możesz użyć do zwolnienia miejsca z zasobów utworzonych w ramach tego ćwiczenia z programowania. W ramach tego czyszczenia zostaną usunięte te zasoby:
- Konto usługi Primus (
$PRIMUS_SERVICEACCOUNT). - Klucz szyfrowania Primus (
$PRIMUS_ENC_KEY). - Repozytorium artefaktów Primus (
$PRIMUS_ARTIFACT_REPOSITORY). - Pula tożsamości zadań Primus (
$PRIMUS_WORKLOAD_IDENTITY_POOL) z dostawcą. - Konto usługi Primus (
$WORKLOAD_SERVICEACCOUNT). - Maszyna wirtualna obciążenia (
$WORKLOAD_VM) i maszyna wirtualna klienta ($CLIENT_VM).
./cleanup.sh
Jeśli skończysz eksplorowanie, rozważ usunięcie projektu.
- Otwórz konsolę Cloud Platform.
- Wybierz projekt, który chcesz wyłączyć, a następnie kliknij „Usuń” u góry. Spowoduje to zaplanowanie usunięcia projektu.