In questa guida, Alex e Bola vogliono scoprire chi ha lo stipendio più alto senza rivelarsi i numeri. Decide di utilizzare Confidential Space per mantenere riservati i propri dati e accetta di assumere i seguenti ruoli:
Alex: collaboratore dei dati, autore del carico di lavoro
Bola: collaboratore dei dati, operatore del carico di lavoro
Questa disposizione è progettata per mantenere le cose il più semplici possibile per questa guida. Tuttavia, è possibile che l'autore e l'operatore del carico di lavoro siano completamente indipendenti dai collaboratori dei dati e puoi avere tutti i collaboratori che vuoi.
Prima di iniziare
Questa guida mostra uno scenario di Confidential Space che utilizza un singolo account in un'unica organizzazione con accesso a più progetti, in modo da poter sperimentare l'intera procedura. In un deployment di produzione, i collaboratori, gli autori e gli operatori dei carichi di lavoro hanno account separati e i propri progetti contenuti in organizzazioni distinte, inaccessibili l'una all'altra e che mantengono separati i dati riservati.
Confidential Space può interagire con molti dei servizi di Google Cloudper produrre i suoi risultati, tra cui, a titolo esemplificativo:
Questa guida utilizza e presuppone una conoscenza di base di tutte queste funzionalità.
API obbligatorie
Per poter completare questa guida, devi abilitare le seguenti API nei progetti specificati.
Nome API | Titolo dell'API | Attiva in questi progetti |
---|---|---|
cloudkms.googleapis.com |
Cloud KMS | Collaboratori dei dati (progetti di Alex e Bola) |
iamcredentials.googleapis.com |
API IAM Service Account Credentials |
Collaboratori dei dati (progetto di Alex) In questa guida, solo Alex deve attivare questa API. Tuttavia, se sono coinvolte più di due parti, l'API IAM per le credenziali dell'account di servizio deve essere attivata in ogni progetto del collaboratore dei dati che non ospita l'account di servizio del carico di lavoro. |
artifactregistry.googleapis.com |
Artifact Registry | Autore del carico di lavoro (progetto di Alex) |
compute.googleapis.com |
Compute Engine | Operatore di workload (progetto Bola) |
confidentialcomputing.googleapis.com |
Confidential Computing | Operatore di workload (progetto Bola) |
Ruoli obbligatori
Per ottenere le autorizzazioni necessarie per completare questa guida, chiedi all'amministratore di concederti i seguenti ruoli IAM nel progetto:
-
Amministratore Cloud KMS (
roles/cloudkms.admin
) per i collaboratori dei dati (Alex e Bola). -
IAM Workload Identity Pool Admin (
roles/iam.workloadIdentityPoolAdmin
) per i collaboratori dei dati (Alex e Bola). -
Amministratore Service Usage (
roles/serviceusage.serviceUsageAdmin
) per i collaboratori dei dati (Alex e Bola). -
Amministratore account di servizio (
roles/iam.serviceAccountAdmin
) per i collaboratori dei dati (Alex e Bola). -
Amministratore dello spazio di archiviazione (
roles/storage.admin
) per i collaboratori dei dati (Alex e Bola) e l'operatore del carico di lavoro (Bola). -
Amministratore Compute (
roles/compute.admin
) per l'operatore del carico di lavoro (Bola). -
Amministratore sicurezza (
roles/securityAdmin
) per l'operatore del carico di lavoro (Bola). -
Amministratore di Artifact Registry (
roles/artifactregistry.admin
) per l'autore del workload (Alex).
Per saperne di più sulla concessione dei ruoli, consulta Gestire l'accesso a progetti, cartelle e organizzazioni.
Potresti anche riuscire a ottenere le autorizzazioni richieste tramite i ruoli personalizzati o altri ruoli predefiniti.
Configurare le risorse dei collaboratori dei dati
Sia Alex che Bola hanno bisogno di progetti indipendenti contenenti le seguenti risorse:
I dati riservati stessi.
Una chiave di crittografia per criptare i dati e mantenerli riservati.
Un bucket Cloud Storage in cui archiviare i dati criptati.
Un account di servizio che ha accesso alla chiave di crittografia, in modo da poter decriptare i dati riservati.
Un pool di identità del workload con l'account di servizio collegato. Il carico di lavoro che elabora i dati riservati utilizza il pool per rubare l'identità dell'account di servizio e recuperare i dati non criptati.
Per iniziare, vai alla console Google Cloud:
Configurare le risorse di Alex
Per configurare le risorse per Alex, completa le seguenti istruzioni.
- Fai clic su Attiva Cloud Shell.
-
In Cloud Shell, inserisci il seguente comando per creare un progetto per Alex, sostituendo ALEX_PROJECT_ID con un nome a tua scelta:
gcloud projects create ALEX_PROJECT_ID
-
Passa al progetto appena creato:
gcloud config set project ALEX_PROJECT_ID
-
Se non l'hai ancora fatto, abilita le API di cui Alex ha bisogno in qualità di collaboratore dei dati e autore del carico di lavoro:
gcloud services enable cloudkms.googleapis.com artifactregistry.googleapis.com iamcredentials.googleapis.com
-
Crea un portachiavi e una chiave di crittografia con Cloud Key Management Service:
gcloud kms keyrings create ALEX_KEYRING_NAME \ --location=global
gcloud kms keys create ALEX_KEY_NAME \ --location=global \ --keyring=ALEX_KEYRING_NAME \ --purpose=encryption
-
Concedi ad Alex il ruolo
cloudkms.cryptoKeyEncrypter
in modo che possa utilizzare la chiave di crittografia appena creata per criptare i dati:gcloud kms keys add-iam-policy-binding \ projects/ALEX_PROJECT_ID/locations/global/keyRings/ALEX_KEYRING_NAME/cryptoKeys/ALEX_KEY_NAME \ --member=user:$(gcloud config get-value account) \ --role=roles/cloudkms.cryptoKeyEncrypter
-
Crea un account di servizio che verrà utilizzato in un secondo momento dal carico di lavoro per decriptare i dati:
gcloud iam service-accounts create ALEX_SERVICE_ACCOUNT_NAME
-
Concedi all'account di servizio il ruolo
cloudkms.cryptoKeyDecrypter
in modo che possa utilizzare la chiave di crittografia che hai appena creato per decriptare i dati:gcloud kms keys add-iam-policy-binding \ projects/ALEX_PROJECT_ID/locations/global/keyRings/ALEX_KEYRING_NAME/cryptoKeys/ALEX_KEY_NAME \ --member=serviceAccount:ALEX_SERVICE_ACCOUNT_NAME@ALEX_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/cloudkms.cryptoKeyDecrypter
-
Crea un pool di identità del workload e collegalo all'account di servizio con un ruolo
iam.workloadIdentityUser
:gcloud iam workload-identity-pools create ALEX_POOL_NAME \ --location=global
gcloud iam service-accounts add-iam-policy-binding \ ALEX_SERVICE_ACCOUNT_NAME@ALEX_PROJECT_ID.iam.gserviceaccount.com \ --member="principalSet://iam.googleapis.com/projects/"$(gcloud projects describe ALEX_PROJECT_ID \ --format="value(projectNumber)")"/locations/global/workloadIdentityPools/ALEX_POOL_NAME/*" \ --role=roles/iam.workloadIdentityUser
-
Crea un bucket Cloud Storage per i dati di input e un altro per memorizzare i risultati:
gcloud storage buckets create gs://ALEX_INPUT_BUCKET_NAME \ gs://ALEX_RESULTS_BUCKET_NAME
-
Crea un file contenente solo il salario di Alex come numero:
echo 123456 > ALEX_SALARY.txt
-
Cripta il file e caricalo nel bucket di Alex:
gcloud kms encrypt \ --ciphertext-file="ALEX_ENCRYPTED_SALARY_FILE" \ --plaintext-file="ALEX_SALARY.txt" \ --key=projects/ALEX_PROJECT_ID/locations/global/keyRings/ALEX_KEYRING_NAME/cryptoKeys/ALEX_KEY_NAME
gcloud storage cp ALEX_ENCRYPTED_SALARY_FILE gs://ALEX_INPUT_BUCKET_NAME
Configura le risorse di Bola
Per configurare le risorse per Bola, completa le seguenti istruzioni.
-
In Cloud Shell, inserisci il seguente comando per creare un progetto per Bola, sostituendo BOLA_PROJECT_ID con un nome a tua scelta:
gcloud projects create BOLA_PROJECT_ID
-
Passa al progetto appena creato:
gcloud config set project BOLA_PROJECT_ID
-
Se non l'hai ancora fatto, attiva le API richieste da Bola come collaboratore dei dati e operatore del carico di lavoro:
gcloud services enable cloudkms.googleapis.com compute.googleapis.com confidentialcomputing.googleapis.com
-
Crea un portachiavi e una chiave di crittografia con Cloud Key Management Service:
gcloud kms keyrings create BOLA_KEYRING_NAME \ --location=global
gcloud kms keys create BOLA_KEY_NAME \ --location=global \ --keyring=BOLA_KEYRING_NAME \ --purpose=encryption
-
Concedi a Bola il ruolo
cloudkms.cryptoKeyEncrypter
in modo che possa utilizzare la chiave di crittografia appena creata per criptare i dati:gcloud kms keys add-iam-policy-binding \ projects/BOLA_PROJECT_ID/locations/global/keyRings/BOLA_KEYRING_NAME/cryptoKeys/BOLA_KEY_NAME \ --member=user:$(gcloud config get-value account) \ --role=roles/cloudkms.cryptoKeyEncrypter
-
Crea un account di servizio che verrà utilizzato in un secondo momento dal carico di lavoro per decriptare i dati:
gcloud iam service-accounts create BOLA_SERVICE_ACCOUNT_NAME
-
Concedi all'account di servizio il ruolo
cloudkms.cryptoKeyDecrypter
in modo che possa utilizzare la chiave di crittografia che hai appena creato per decriptare i dati:gcloud kms keys add-iam-policy-binding \ projects/BOLA_PROJECT_ID/locations/global/keyRings/BOLA_KEYRING_NAME/cryptoKeys/BOLA_KEY_NAME \ --member=serviceAccount:BOLA_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/cloudkms.cryptoKeyDecrypter
-
Crea un pool di identità del workload e collegalo all'account di servizio con un ruolo
iam.workloadIdentityUser
:gcloud iam workload-identity-pools create BOLA_POOL_NAME \ --location=global
gcloud iam service-accounts add-iam-policy-binding \ BOLA_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --member="principalSet://iam.googleapis.com/projects/"$(gcloud projects describe BOLA_PROJECT_ID \ --format="value(projectNumber)")"/locations/global/workloadIdentityPools/BOLA_POOL_NAME/*" \ --role=roles/iam.workloadIdentityUser
-
Crea un bucket Cloud Storage per i dati di input e un altro per memorizzare i risultati:
gcloud storage buckets create gs://BOLA_INPUT_BUCKET_NAME \ gs://BOLA_RESULTS_BUCKET_NAME
-
Crea un file contenente solo il salario di Bola come numero:
echo 111111 > BOLA_SALARY.txt
-
Cripta il file e caricalo nel bucket di Bola:
gcloud kms encrypt \ --ciphertext-file="BOLA_ENCRYPTED_SALARY_FILE" \ --plaintext-file="BOLA_SALARY.txt" \ --key=projects/BOLA_PROJECT_ID/locations/global/keyRings/BOLA_KEYRING_NAME/cryptoKeys/BOLA_KEY_NAME
gcloud storage cp BOLA_ENCRYPTED_SALARY_FILE gs://BOLA_INPUT_BUCKET_NAME
Crea un account di servizio per il carico di lavoro
Oltre agli account di servizio configurati da Alex e Bola per decriptare i loro dati, è necessario un altro account di servizio per eseguire il carico di lavoro. Poiché gli account di servizio vengono utilizzati sia per decriptare i dati riservati sia per elaborarli, la visibilità dei dati è limitata ai relativi proprietari.
In questa guida, Bola gestisce e esegue il carico di lavoro, ma chiunque può assumere questi ruoli, inclusa una terza parte.
Per configurare l'account di servizio, completa i seguenti passaggi nel progetto di Bola:
Crea un account di servizio per eseguire il carico di lavoro:
gcloud iam service-accounts create WORKLOAD_SERVICE_ACCOUNT_NAME
Concedi a Bola il ruolo
iam.serviceAccountUser
per rubare l'identità dell'account di servizio, necessario per creare in un secondo momento una VM per il workload:gcloud iam service-accounts add-iam-policy-binding \ WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --member=user:$(gcloud config get-value account) \ --role=roles/iam.serviceAccountUser
Concedi all'account di servizio il ruolo
confidentialcomputing.workloadUser
in modo che possa generare un token di attestazione:gcloud projects add-iam-policy-binding BOLA_PROJECT_ID \ --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/confidentialcomputing.workloadUser
Concedi all'account di servizio il ruolo
logging.logWriter
per scrivere log in Cloud Logging, in modo da poter controllare lo stato di avanzamento del carico di lavoro:gcloud projects add-iam-policy-binding BOLA_PROJECT_ID \ --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/logging.logWriter
Concedi all'account di servizio l'accesso in lettura ai bucket di Alex e Bola che contengono i loro dati criptati e l'accesso in scrittura a ciascuno dei loro bucket dei risultati:
gcloud storage buckets add-iam-policy-binding gs://ALEX_INPUT_BUCKET_NAME \ --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/storage.objectViewer
gcloud storage buckets add-iam-policy-binding gs://BOLA_INPUT_BUCKET_NAME \ --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/storage.objectViewer
gcloud storage buckets add-iam-policy-binding gs://ALEX_RESULTS_BUCKET_NAME \ --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/storage.objectAdmin
gcloud storage buckets add-iam-policy-binding gs://BOLA_RESULTS_BUCKET_NAME \ --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/storage.objectAdmin
Si presume che l'utente che concede l'accesso abbia il ruolo Amministratore archiviazione (
roles/storage.admin
) per il progetto che contiene il bucket Cloud Storage su cui si sta operando.
Crea il workload
In questa guida, Alex fornisce il codice per il carico di lavoro e crea un'immagine Docker per contenerlo, ma chiunque può assumere questi ruoli, inclusa una terza parte.
Alex deve creare le seguenti risorse per il workload:
Il codice che esegue il carico di lavoro.
Un repository Docker in Artifact Registry a cui ha accesso l'account di servizio che esegue il carico di lavoro.
Un'immagine Docker che contiene ed esegue il codice del carico di lavoro.
Per creare e configurare le risorse, completa i seguenti passaggi nel progetto di Alex:
Passa al progetto di Alex:
gcloud config set project ALEX_PROJECT_ID
Crea un repository Docker in Artifact Registry:
gcloud artifacts repositories create REPOSITORY_NAME \ --repository-format=docker \ --location=us
Concedi all'account di servizio che eseguirà il carico di lavoro il ruolo Lettore del registry degli elementi (
roles/artifactregistry.reader
) in modo che possa leggere dal repository:gcloud artifacts repositories add-iam-policy-binding REPOSITORY_NAME \ --location=us \ --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/artifactregistry.reader
Fai clic su Apri editor per aprire l'editor di Cloud Shell, quindi crea un nuovo file denominato
salary.go
. Copia il seguente codice nel file e poi salvatelo:// READ ME FIRST: Before compiling, customize the details in the USER VARIABLES // SECTION starting at line 30. package main import ( kms "cloud.google.com/go/kms/apiv1" "cloud.google.com/go/storage" "context" "fmt" "google.golang.org/api/option" kmspb "google.golang.org/genproto/googleapis/cloud/kms/v1" "io/ioutil" "strconv" "strings" "time" ) type collaborator struct { name string wipName string sa string keyName string inputBucket string inputFile string outputBucket string outputFile string } // ============================ // START USER VARIABLES SECTION // You need to customize this section, replacing each const's value with your // own. // To get a project number, use the following command, and substitute // <PROJECT_ID> for the data collaborator's project ID. // gcloud projects describe <PROJECT_ID> --format="value(projectNumber)" // Alex's values const collaborator1Name string = "Alex" // Alex's name const collaborator1EncryptedSalaryFileName string = "" // The name of Alex's encrypted salary file const collaborator1BucketInputName string = "" // The name of the storage bucket that contains Alex's encrypted salary file const collaborator1BucketOutputName string = "" // The name of the storage bucket to store Alex's results in const collaborator1BucketOutputFileName string = "" // The name of Alex's output file that contains the results const collaborator1KMSKeyringName string = "" // Alex's Key Management Service key ring const collaborator1KMSKeyName string = "" // Alex's Key Management Service key const collaborator1ProjectName string = "" // Alex's project ID const collaborator1ProjectNumber string = "" // Alex's project number const collaborator1PoolName string = "" // Alex's workload identity pool name const collaborator1ServiceAccountName string = "" // The name of Alex's service account that can decrypt their salary // Bola's values const collaborator2Name string = "Bola" // Bola's name const collaborator2EncryptedSalaryFileName string = "" // The name of Bola's encrypted salary file const collaborator2BucketInputName string = "" // The name of the storage bucket that contains Bola's encrypted salary file const collaborator2BucketOutputName string = "" // The name of the storage bucket to store Bola's results in const collaborator2BucketOutputFileName string = "" // The name of Bola's output file that contains the results const collaborator2KMSKeyringName string = "" // Bola's Key Management Service key ring const collaborator2KMSKeyName string = "" // Bola's Key Management Service key const collaborator2ProjectName string = "" // Bola's project ID const collaborator2ProjectNumber string = "" // Bola's project number const collaborator2PoolName string = "" // Bola's workload identity pool name const collaborator2ServiceAccountName string = "" // The name of Bola's service account that can decrypt their salary // END USER VARIABLES SECTION // ========================== var collaborators = [2]collaborator{ { collaborator1Name, "projects/" + collaborator1ProjectNumber + "/locations/global/workloadIdentityPools/" + collaborator1PoolName + "/providers/attestation-verifier", collaborator1ServiceAccountName + "@" + collaborator1ProjectName + ".iam.gserviceaccount.com", "projects/" + collaborator1ProjectName + "/locations/global/keyRings/" + collaborator1KMSKeyringName + "/cryptoKeys/" + collaborator1KMSKeyName, collaborator1BucketInputName, collaborator1EncryptedSalaryFileName, collaborator1BucketOutputName, collaborator1BucketOutputFileName, }, { collaborator2Name, "projects/" + collaborator2ProjectNumber + "/locations/global/workloadIdentityPools/" + collaborator2PoolName + "/providers/attestation-verifier", collaborator2ServiceAccountName + "@" + collaborator2ProjectName + ".iam.gserviceaccount.com", "projects/" + collaborator2ProjectName + "/locations/global/keyRings/" + collaborator2KMSKeyringName + "/cryptoKeys/" + collaborator2KMSKeyName, collaborator2BucketInputName, collaborator2EncryptedSalaryFileName, collaborator2BucketOutputName, collaborator2BucketOutputFileName, }, } const credentialConfig = `{ "type": "external_account", "audience": "//iam.googleapis.com/%s", "subject_token_type": "urn:ietf:params:oauth:token-type:jwt", "token_url": "https://sts.googleapis.com/v1/token", "credential_source": { "file": "/run/container_launcher/attestation_verifier_claims_token" }, "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/%s:generateAccessToken" }` func main() { fmt.Println("workload started") ctx := context.Background() storageClient, err := storage.NewClient(ctx) // using the default credential on the Compute Engine VM if err != nil { panic(err) } // get and decrypt s0, err := getSalary(ctx, storageClient, collaborators[0]) if err != nil { panic(err) } s1, err := getSalary(ctx, storageClient, collaborators[1]) if err != nil { panic(err) } res := "" if s0 > s1 { res = fmt.Sprintf("%s earns more!\n", collaborators[0].name) } else if s1 < s0 { res = fmt.Sprintf("%s earns more!\n", collaborators[1].name) } else { res = "earns same\n" } now := time.Now() for _, cw := range collaborators { outputWriter := storageClient.Bucket(cw.outputBucket).Object(fmt.Sprintf("%s-%d", cw.outputFile, now.Unix())).NewWriter(ctx) _, err = outputWriter.Write([]byte(res)) if err != nil { fmt.Printf("Could not write: %v", err) panic(err) } if err = outputWriter.Close(); err != nil { fmt.Printf("Could not close: %v", err) panic(err) } } } func getSalary(ctx context.Context, storageClient *storage.Client, cw collaborator) (float64, error) { encryptedBytes, err := getFile(ctx, storageClient, cw.inputBucket, cw.inputFile) if err != nil { return 0.0, err } decryptedByte, err := decryptByte(ctx, cw.keyName, cw.sa, cw.wipName, encryptedBytes) if err != nil { return 0.0, err } decryptedNumber := strings.TrimSpace(string(decryptedByte)) num, err := strconv.ParseFloat(decryptedNumber, 64) if err != nil { return 0.0, err } return num, nil } func decryptByte(ctx context.Context, keyName, trustedServiceAccountEmail, wippro string, encryptedData []byte) ([]byte, error) { cc := fmt.Sprintf(credentialConfig, wippro, trustedServiceAccountEmail) kmsClient, err := kms.NewKeyManagementClient(ctx, option.WithCredentialsJSON([]byte(cc))) if err != nil { return nil, fmt.Errorf("creating a new KMS client with federated credentials: %w", err) } decryptRequest := &kmspb.DecryptRequest{ Name: keyName, Ciphertext: encryptedData, } decryptResponse, err := kmsClient.Decrypt(ctx, decryptRequest) if err != nil { return nil, fmt.Errorf("could not decrypt ciphertext: %w", err) } return decryptResponse.Plaintext, nil } func getFile(ctx context.Context, c *storage.Client, bucketName string, objPath string) ([]byte, error) { bucketHandle := c.Bucket(bucketName) objectHandle := bucketHandle.Object(objPath) objectReader, err := objectHandle.NewReader(ctx) if err != nil { return nil, err } defer objectReader.Close() s, err := ioutil.ReadAll(objectReader) if err != nil { return nil, err } return s, nil }
Modifica
USER VARIABLES SECTION
nel codice sorgente, sostituendo i valori vuoticonst
con i nomi delle risorse pertinenti come descritto nei commenti del codice. Se hai modificato le variabili segnaposto comeALEX_PROJECT_ID
mostrate in questa guida, i valori sono inclusi nel seguente esempio di codice, che puoi copiare e incollare sopra il codice esistente:// Alex's values const collaborator1Name string = "Alex" // Alex's name const collaborator1EncryptedSalaryFileName string = "ALEX_ENCRYPTED_SALARY_FILE" // The name of Alex's encrypted salary file const collaborator1BucketInputName string = "ALEX_INPUT_BUCKET_NAME" // The name of the storage bucket that contains Alex's encrypted salary file const collaborator1BucketOutputName string = "ALEX_RESULTS_BUCKET_NAME" // The name of the storage bucket to store Alex's results in const collaborator1BucketOutputFileName string = "ALEX_RESULTS_FILE_NAME" // The name of Alex's output file that contains the results const collaborator1KMSKeyringName string = "ALEX_KEYRING_NAME" // Alex's Key Management Service key ring const collaborator1KMSKeyName string = "ALEX_KEY_NAME" // Alex's Key Management Service key const collaborator1ProjectName string = "ALEX_PROJECT_ID" // Alex's project ID const collaborator1ProjectNumber string = "ALEX_PROJECT_NUMBER" // Alex's project number const collaborator1PoolName string = "ALEX_POOL_NAME" // Alex's workload identity pool name const collaborator1ServiceAccountName string = "ALEX_SERVICE_ACCOUNT_NAME" // The name of Alex's service account that can decrypt their salary // Bola's values const collaborator2Name string = "Bola" // Bola's name const collaborator2EncryptedSalaryFileName string = "BOLA_ENCRYPTED_SALARY_FILE" // The name of Bola's encrypted salary file const collaborator2BucketInputName string = "BOLA_INPUT_BUCKET_NAME" // The name of the storage bucket that contains Bola's encrypted salary file const collaborator2BucketOutputName string = "BOLA_RESULTS_BUCKET_NAME" // The name of the storage bucket to store Bola's results in const collaborator2BucketOutputFileName string = "BOLA_RESULTS_FILE_NAME" // The name of Bola's output file that contains the results const collaborator2KMSKeyringName string = "BOLA_KEYRING_NAME" // Bola's Key Management Service key ring const collaborator2KMSKeyName string = "BOLA_KEY_NAME" // Bola's Key Management Service key const collaborator2ProjectName string = "BOLA_PROJECT_ID" // Bola's project ID const collaborator2ProjectNumber string = "BOLA_PROJECT_NUMBER" // Bola's project number const collaborator2PoolName string = "BOLA_POOL_NAME" // Bola's workload identity pool name const collaborator2ServiceAccountName string = "BOLA_SERVICE_ACCOUNT_NAME" // The name of Bola's service account that can decrypt their salary
Assicurati di aggiornare anche i numeri di progetto per Alex e Bola. Puoi recuperarli con il seguente comando:
gcloud projects describe PROJECT_ID --format="value(projectNumber)"
Assicurati che tutte le parti leggano e controllino il codice sorgente.
Fai clic su Terminale > Nuovo terminale per aprire un terminale nell'editor di Cloud Shell.
Inserisci i seguenti comandi nel terminale per configurare l'ambiente Go:
go mod init salary go get cloud.google.com/go/kms/apiv1 cloud.google.com/go/storage google.golang.org/api/option google.golang.org/genproto/googleapis/cloud/kms/v1
Inserisci il seguente comando per compilare il codice sorgente in un file binario collegato in modo statico:
CGO_ENABLED=0 go build -trimpath
Crea un file denominato
Dockerfile
nell'editor di Cloud Shell contenente il seguente contenuto:FROM alpine:latest WORKDIR /test COPY salary /test ENTRYPOINT ["/test/salary"] CMD []
Aggiorna le credenziali Docker per includere il nome di dominio
us-docker.pkg.dev
:gcloud auth configure-docker us-docker.pkg.dev
Crea un'immagine Docker da
Dockerfile
inserendo il seguente comando nel terminale:docker build -t \ us-docker.pkg.dev/ALEX_PROJECT_ID/REPOSITORY_NAME/WORKLOAD_CONTAINER_NAME:latest .
Esegui il push dell'immagine Docker in Artifact Registry:
docker push \ us-docker.pkg.dev/ALEX_PROJECT_ID/REPOSITORY_NAME/WORKLOAD_CONTAINER_NAME
Dalla risposta del push di Docker, copia il digest dell'immagine Docker (incluso il prefisso
sha256:
) in un luogo sicuro per utilizzarlo in un secondo momento.Assicurati che tutte le parti controllino l'immagine Docker e verifica che sia affidabile prima di autorizzarne l'utilizzo.
Autorizza il carico di lavoro
Una volta approvato il carico di lavoro da entrambe le parti, Alex e Bola devono aggiungere il servizio di verifica dell'attestazione Confidential Space come provider ai pool di identità del loro carico di lavoro. In questo modo, l'account di servizio collegato al workload può simulare l'identità degli account di servizio collegati ai relativi pool e accedere ai relativi dati, a condizione che vengano soddisfatte determinate condizioni degli attributi. Ciò significa che le condizioni degli attributi fungono da criteri di attestazione.
Le condizioni degli attributi utilizzate in questa guida sono le seguenti:
Il digest dell'immagine Docker in esecuzione
L'indirizzo email dell'account di servizio che esegue il carico di lavoro
Se un attore malintenzionato modifica l'immagine Docker o un altro account di servizio viene associato al carico di lavoro, a quest'ultimo non sarà consentito accedere ai dati di Alex o Bola.
Per visualizzare le condizioni degli attributi disponibili, consulta Affermazioni di attestazione.
Per configurare i fornitori per Alex e Bola con le condizioni richieste, completa i seguenti passaggi:
Inserisci il seguente comando per creare il provider per Alex:
gcloud iam workload-identity-pools providers create-oidc attestation-verifier \ --location=global \ --workload-identity-pool=ALEX_POOL_NAME \ --issuer-uri="https://confidentialcomputing.googleapis.com/" \ --allowed-audiences="https://sts.googleapis.com" \ --attribute-mapping="google.subject=assertion.sub" \ --attribute-condition="assertion.submods.container.image_digest == 'DOCKER_IMAGE_DIGEST' \ && 'WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com' in assertion.google_service_accounts \ && assertion.swname == 'CONFIDENTIAL_SPACE' \ && 'STABLE' in assertion.submods.confidential_space.support_attributes"
Passa al progetto di Bola:
gcloud config set project BOLA_PROJECT_ID
Inserisci il comando seguente per creare il provider per Bola:
gcloud iam workload-identity-pools providers create-oidc attestation-verifier \ --location=global \ --workload-identity-pool=BOLA_POOL_NAME \ --issuer-uri="https://confidentialcomputing.googleapis.com/" \ --allowed-audiences="https://sts.googleapis.com" \ --attribute-mapping="google.subject=assertion.sub" \ --attribute-condition="assertion.submods.container.image_digest == 'DOCKER_IMAGE_DIGEST' \ && 'WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com' in assertion.google_service_accounts \ && assertion.swname == 'CONFIDENTIAL_SPACE' \ && 'STABLE' in assertion.submods.confidential_space.support_attributes"
Esegui il deployment del carico di lavoro
Ora che i provider sono stati aggiunti ai pool di identità dei workload di Alex e Bola e le risorse richieste sono state implementate, è il momento per l'operatore del workload di eseguirlo.
Per eseguire il deployment del carico di lavoro, crea una nuova istanza Confidential VM nel progetto di Bola con le seguenti proprietà:
Una configurazione supportata per un'istanza VM AMD SEV o Intel TDX Confidential.
Un sistema operativo basato sull'immagine di Confidential Space.
Avvio protetto abilitato.
L'immagine Docker collegata creata in precedenza da Alex.
L'account di servizio collegato che esegue il carico di lavoro.
Inserisci il seguente comando in Cloud Shell di Bola per eseguire il deployment del carico di lavoro:
gcloud compute instances create WORKLOAD_VM_NAME \
--confidential-compute-type=SEV \
--shielded-secure-boot \
--scopes=cloud-platform \
--zone=us-west1-b \
--maintenance-policy=MIGRATE \
--min-cpu-platform="AMD Milan" \
--image-project=confidential-space-images \
--image-family=confidential-space \
--service-account=WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \
--metadata="^~^tee-image-reference=us-docker.pkg.dev/ALEX_PROJECT_ID/REPOSITORY_NAME/WORKLOAD_CONTAINER_NAME:latest"
Puoi visualizzare l'avanzamento del carico di lavoro nel progetto di Bola andando a Esplora log.
Per trovare i log Confidential Space, filtra in base ai seguenti campi di log, se disponibili:
Tipo di risorsa:Istanza VM
ID istanza:l'ID istanza della VM
Nome del log: confidential-space-launcher
Per aggiornare il log, fai clic su Vai a più recenti.
Al termine del carico di lavoro, l'istanza VM viene arrestata. Se vuoi modificare i file dei salari criptati ed eseguire nuovamente il deployment del carico di lavoro, devi solo avviare la VM esistente:
gcloud compute instances start WORKLOAD_VM_NAME --zone=us-west1-b
Esegui il debug del carico di lavoro
Puoi utilizzare Logs Explorer per risolvere problemi come la mancata configurazione corretta delle risorse o condizioni degli attributi nei provider che non corrispondono alle rivendicazioni fatte dal workload Confidential Space.
A questo scopo, devi apportare le seguenti modifiche:
Aggiorna i provider dei pool di identità del workload di Alex e Bola per rimuovere l'affermazione
support_attributes
. Devi utilizzare l'immagine di debug di Confidential Space per eseguire la risoluzione dei problemi più approfondita e questa immagine non ha attributi di assistenza da verificare.Crea la VM del workload utilizzando l'immagine di debug di Confidential Space e imposta i metadati della VM per reindirizzare
STDOUT
eSTDERR
a Cloud Logging in modo da acquisire tutto l'output del workload.
Per apportare le modifiche, segui questi passaggi:
Passa al progetto di Alex:
gcloud config set project ALEX_PROJECT_ID
Aggiorna il fornitore di Alex per rimuovere l'affermazione
support_attributes
:gcloud iam workload-identity-pools providers update-oidc attestation-verifier \ --location=global \ --workload-identity-pool=ALEX_POOL_NAME \ --issuer-uri="https://confidentialcomputing.googleapis.com/" \ --allowed-audiences="https://sts.googleapis.com" \ --attribute-mapping="google.subject=assertion.sub" \ --attribute-condition="assertion.submods.container.image_digest == 'DOCKER_IMAGE_DIGEST' \ && 'WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com' in assertion.google_service_accounts \ && assertion.swname == 'CONFIDENTIAL_SPACE'"
Passa al progetto di Bola:
gcloud config set project BOLA_PROJECT_ID
Aggiorna il fornitore di Bola per rimuovere l'affermazione
support_attributes
:gcloud iam workload-identity-pools providers update-oidc attestation-verifier \ --location=global \ --workload-identity-pool=BOLA_POOL_NAME \ --issuer-uri="https://confidentialcomputing.googleapis.com/" \ --allowed-audiences="https://sts.googleapis.com" \ --attribute-mapping="google.subject=assertion.sub" \ --attribute-condition="assertion.submods.container.image_digest == 'DOCKER_IMAGE_DIGEST' \ && 'WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com' in assertion.google_service_accounts \ && assertion.swname == 'CONFIDENTIAL_SPACE'"
Crea una nuova VM con l'immagine di debug Confidential Space e imposta
tee-container-log-redirect
sutrue
nei metadati.gcloud compute instances create WORKLOAD_VM_2_NAME \ --confidential-compute-type=SEV \ --shielded-secure-boot \ --scopes=cloud-platform \ --zone=us-west1-b \ --maintenance-policy=MIGRATE \ --min-cpu-platform="AMD Milan" \ --image-project=confidential-space-images \ --image-family=confidential-space-debug \ --service-account=WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --metadata="^~^tee-image-reference=us-docker.pkg.dev/ALEX_PROJECT_ID/REPOSITORY_NAME/WORKLOAD_CONTAINER_NAME:latest~tee-container-log-redirect=true"
A differenza dell'immagine di produzione, l'immagine di debug mantiene la VM in esecuzione al termine del carico di lavoro. Ciò significa che puoi utilizzare SSH per connetterti alla VM e continuare il debug.
Visualizza i risultati
Una volta completato il carico di lavoro, sia Alex che Bola possono visualizzare i risultati nei rispettivi bucket di risultati:
Passa al progetto di Alex:
gcloud config set project ALEX_PROJECT_ID
Elenca tutti i file nel bucket dei risultati:
gcloud storage ls gs://ALEX_RESULTS_BUCKET_NAME
Quindi leggi l'ultimo file:
gcloud storage cat gs://ALEX_RESULTS_BUCKET_NAME/ALEX_RESULTS_FILE_NAME
Passa al progetto di Bola:
gcloud config set project BOLA_PROJECT_ID
Per Bola, elenca tutti i file nel bucket dei risultati:
gcloud storage ls gs://BOLA_RESULTS_BUCKET_NAME
Quindi leggi l'ultimo file:
gcloud storage cat gs://BOLA_RESULTS_BUCKET_NAME/BOLA_RESULTS_FILE_NAME
Leggendo i file, Alex e Bola scoprono chi guadagna di più senza mai rivelare i loro stipendi.
Esegui la pulizia
Per rimuovere le risorse create in questa guida, completa le seguenti istruzioni.
Ripulire le risorse di Alex
Passa al progetto di Alex:
gcloud config set project ALEX_PROJECT_ID
Elimina l'account di servizio che decripta i dati di Alex:
gcloud iam service-accounts delete \ ALEX_SERVICE_ACCOUNT_NAME@ALEX_PROJECT_ID.iam.gserviceaccount.com
Elimina il pool di identità del workload di Alex:
gcloud iam workload-identity-pools delete ALEX_POOL_NAME \ --location=global
Elimina i bucket Cloud Storage di Alex:
gcloud storage rm gs://ALEX_INPUT_BUCKET_NAME \ gs://ALEX_RESULTS_BUCKET_NAME --recursive
Elimina i file dello stipendio di Alex e il codice Go:
rm ALEX_SALARY.txt \ ALEX_ENCRYPTED_SALARY_FILE \ salary.go salary \ go.mod go.sum
(Facoltativo) Disattiva o distruggi la chiave di Cloud Key Management Service di Alex.
(Facoltativo) Chiudi il progetto di Alex.
Ripulire le risorse di Bola
Passa al progetto di Bola:
gcloud config set project BOLA_PROJECT_ID
Elimina la VM del carico di lavoro:
gcloud compute instances delete WORKLOAD_VM_NAME --zone=us-west1-b
Elimina l'account di servizio che decripta i dati di Bola e l'account di servizio che esegue il carico di lavoro:
gcloud iam service-accounts delete \ BOLA_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com
gcloud iam service-accounts delete \ WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com
Elimina il pool di identità del workload di Bola:
gcloud iam workload-identity-pools delete BOLA_POOL_NAME \ --location=global
Elimina i bucket Cloud Storage di Bola:
gcloud storage rm gs://BOLA_INPUT_BUCKET_NAME \ gs://BOLA_RESULTS_BUCKET_NAME --recursive
Elimina i file dello stipendio di Bola:
rm BOLA_SALARY.txt \ BOLA_ENCRYPTED_SALARY_FILE
(Facoltativo) Disattiva o elimina la chiave di Cloud Key Management Service di Bola.
(Facoltativo) Chiudi il progetto di Bola.