Neste guia, o Alex e a Bola querem saber quem tem o salário mais elevado sem revelarem os números um ao outro. Decidem usar o espaço confidencial para manter os respetivos dados confidenciais e aceitam assumir as seguintes funções:
Alex: colaborador de dados, autor de cargas de trabalho
Bola: colaborador de dados, operador de carga de trabalho
Esta disposição foi concebida para manter as coisas o mais simples possível para este guia. No entanto, é possível que o autor e o operador da carga de trabalho sejam totalmente independentes dos colaboradores de dados, e pode ter quantos colaboradores quiser.
Antes de começar
Este guia demonstra um cenário do espaço confidencial com uma única conta numa única organização com acesso a vários projetos, para que possa experimentar todo o processo. Numa implementação de produção, os colaboradores, os autores de cargas de trabalho e os operadores de cargas de trabalho têm contas separadas e os seus próprios projetos contidos em organizações discretas, inacessíveis entre si e mantendo os respetivos dados confidenciais separados.
O espaço confidencial pode interagir com muitos dos serviços do Google Cloudpara produzir os respetivos resultados, incluindo, entre outros:
Este guia usa e pressupõe uma compreensão básica de todas estas funcionalidades.
Funções necessárias
Para receber as autorizações de que precisa para concluir este guia, peça ao seu administrador para lhe conceder as seguintes funções de IAM no projeto:
-
Administrador do Cloud KMS (
roles/cloudkms.admin) para os colaboradores de dados (Alex e Bola). -
Administrador do Workload Identity Pool do IAM (
roles/iam.workloadIdentityPoolAdmin) para os colaboradores de dados (Alex e Bola). -
Administrador de utilização de serviços (
roles/serviceusage.serviceUsageAdmin) para os colaboradores de dados (Alex e Bola). -
Administrador de armazenamento (
roles/storage.admin) para os colaboradores de dados (Alex e Bola) e o operador da carga de trabalho (Bola). -
Administrador da conta de serviço (
roles/iam.serviceAccountAdmin) para o operador da carga de trabalho (Bola). -
Administrador de computação (
roles/compute.admin) para o operador de cargas de trabalho (Bola). -
Administrador de segurança (
roles/securityAdmin) para o operador da carga de trabalho (Bola). -
Administrador do Artifact Registry (
roles/artifactregistry.admin) para o autor da carga de trabalho (Alex).
Para mais informações sobre a atribuição de funções, consulte o artigo Faça a gestão do acesso a projetos, pastas e organizações.
Também pode conseguir as autorizações necessárias através de funções personalizadas ou outras funções predefinidas.
Configure recursos de colaborador de dados
O Alex e a Bola precisam de projetos independentes que contenham os seguintes recursos:
Os próprios dados confidenciais.
Uma chave de encriptação para encriptar esses dados e mantê-los confidenciais.
Um contentor do Cloud Storage para armazenar os dados encriptados.
Um Workload Identity Pool. A carga de trabalho que processa os dados confidenciais usa o conjunto para aceder aos dados privados e desencriptá-los.
Para começar, aceda à Google Cloud consola:
Configure os recursos do Alex
Para configurar os recursos para o Alex, conclua as seguintes instruções.
- Clique em Ativar Cloud Shell.
-
No Cloud Shell, introduza o seguinte comando para criar um projeto para Alex, substituindo ALEX_PROJECT_ID por um nome à sua escolha:
gcloud projects create ALEX_PROJECT_ID -
Mude para o projeto recém-criado:
gcloud config set project ALEX_PROJECT_ID -
Ative as APIs de que o Alex precisa como colaborador de dados e autor de cargas de trabalho:
gcloud services enable \ artifactregistry.googleapis.com \ cloudkms.googleapis.com \ iamcredentials.googleapis.com -
Crie um conjunto de chaves e uma chave de encriptação com o 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 -
Conceda à Alex a função
cloudkms.cryptoKeyEncrypterpara que possa usar a chave de encriptação criada recentemente para encriptar dados: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 -
Crie o Workload Identity Pool do Alex:
gcloud iam workload-identity-pools create ALEX_POOL_NAME \ --location=global -
Crie um contentor do Cloud Storage para os dados de entrada e outro para armazenar os resultados:
gcloud storage buckets create gs://ALEX_INPUT_BUCKET_NAME \ gs://ALEX_OUTPUT_BUCKET_NAME -
Crie um ficheiro que contenha apenas o salário de Alex como um número:
echo 123456 > ALEX_SALARY.txt -
Encriptar o ficheiro e, de seguida, carregá-lo para o contentor de 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
Configure os recursos da Bola
Para configurar os recursos para o Bola, conclua as seguintes instruções.
-
No Cloud Shell, introduza o seguinte comando para criar um projeto para a Bola, substituindo BOLA_PROJECT_ID por um nome à sua escolha:
gcloud projects create BOLA_PROJECT_ID -
Mude para o projeto recém-criado:
gcloud config set project BOLA_PROJECT_ID -
Ative as APIs que a Bola requer como colaborador de dados e operador de carga de trabalho:
gcloud services enable \ cloudkms.googleapis.com \ compute.googleapis.com \ confidentialcomputing.googleapis.com \ iamcredentials.googleapis.com -
Crie um conjunto de chaves e uma chave de encriptação com o 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 -
Conceda à Bola a função
cloudkms.cryptoKeyEncrypterpara que possa usar a chave de encriptação criada recentemente para encriptar dados: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 -
Crie o Workload Identity Pool da Bola:
gcloud iam workload-identity-pools create BOLA_POOL_NAME \ --location=global -
Crie um contentor do Cloud Storage para os dados de entrada e outro para armazenar os resultados:
gcloud storage buckets create gs://BOLA_INPUT_BUCKET_NAME \ gs://BOLA_OUTPUT_BUCKET_NAME -
Crie um ficheiro que contenha apenas o salário de Bola como um número:
echo 111111 > BOLA_SALARY.txt -
Encriptar o ficheiro e, em seguida, carregá-lo para o contentor de 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
Crie uma conta de serviço para a carga de trabalho
Neste guia, a Bola opera e executa a carga de trabalho, mas qualquer pessoa pode assumir estas funções, incluindo um terceiro. A instância de VM que o Bola cria para executar a carga de trabalho tem uma conta de serviço anexada, que tem autorização para gerar tokens de atestação, escrever registos, ler os dados encriptados do Alex e do Bola e escrever resultados em contentores específicos do Cloud Storage.
Conclua os passos seguintes no projeto de Bola para configurar a conta de serviço:
Crie uma conta de serviço para executar a carga de trabalho:
gcloud iam service-accounts create WORKLOAD_SERVICE_ACCOUNT_NAMEConceda à Bola a função
iam.serviceAccountUserpara que possa anexar a conta de serviço à VM da carga de trabalho mais tarde: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.serviceAccountUserConceda à conta de serviço a função
confidentialcomputing.workloadUserpara que possa gerar um token de atestação:gcloud projects add-iam-policy-binding BOLA_PROJECT_ID \ --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/confidentialcomputing.workloadUserConceda à conta de serviço a função
logging.logWriterpara escrever registos no Cloud Logging, para que possa verificar o progresso da carga de trabalho:gcloud projects add-iam-policy-binding BOLA_PROJECT_ID \ --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/logging.logWriterConceda à conta de serviço acesso de leitura aos contentores de Alex e Bola que contêm os respetivos dados encriptados e acesso de escrita aos contentores de resultados de cada um:
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://ALEX_OUTPUT_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_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_OUTPUT_BUCKET_NAME \ --member=serviceAccount:WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.com \ --role=roles/storage.objectAdminIsto pressupõe que o utilizador que concede o acesso tem a função de administrador do armazenamento (
roles/storage.admin) para o projeto que contém o contentor do Cloud Storage no qual está a ser realizada a operação.
Crie a carga de trabalho
Neste guia, o Alex fornece o código para a carga de trabalho e cria uma imagem do Docker para a conter, mas qualquer pessoa pode assumir estas funções, incluindo terceiros.
O Alex tem de criar os seguintes recursos para a carga de trabalho:
O código que executa a carga de trabalho.
Um repositório Docker no Artifact Registry ao qual a conta de serviço que executa a carga de trabalho tem acesso.
Uma imagem do Docker que contém e executa o código da carga de trabalho.
Para criar e configurar os recursos, conclua os seguintes passos no projeto de Alex:
Mudar para o projeto do Alex:
gcloud config set project ALEX_PROJECT_IDClique em Abrir editor para abrir o editor do Cloud Shell e, de seguida, crie um novo ficheiro denominado
salary.go. Copie o código seguinte para o ficheiro e, de seguida, guarde-o:package main import ( "context" "fmt" "io" "os" "strconv" "strings" "time" kms "cloud.google.com/go/kms/apiv1" kmspb "cloud.google.com/go/kms/apiv1/kmspb" "cloud.google.com/go/storage" "google.golang.org/api/option" ) type collaborator struct { name string wipName string keyName string inputBucket string inputFile string outputBucket string } // The following values are pulled from environment variables // Alex's values var collaborator1Name string = os.Getenv("COLLAB_1_NAME") // Alex's name var collaborator1EncryptedSalaryFileName string = os.Getenv("COLLAB_1_ENCRYPTED_SALARY") // The name of Alex's encrypted salary file. var collaborator1BucketInputName string = os.Getenv("COLLAB_1_INPUT_BUCKET") // The name of the storage bucket that contains Alex's encrypted salary file. var collaborator1BucketOutputName string = os.Getenv("COLLAB_1_OUTPUT_BUCKET") // The name of the storage bucket to store Alex's results in. var collaborator1KMSKeyringName string = os.Getenv("COLLAB_1_KEYRING_NAME") // Alex's Key Management Service key ring. var collaborator1KMSKeyName string = os.Getenv("COLLAB_1_KEY_NAME") // Alex's Key Management Service key. var collaborator1ProjectName string = os.Getenv("COLLAB_1_PROJECT_ID") // Alex's project ID. var collaborator1ProjectNumber string = os.Getenv("COLLAB_1_PROJECT_NUMBER") // Alex's project number. var collaborator1PoolName string = os.Getenv("COLLAB_1_POOL_NAME") // Alex's workload identity pool name. // Bola's values var collaborator2Name string = os.Getenv("COLLAB_2_NAME") // Bola's name var collaborator2EncryptedSalaryFileName string = os.Getenv("COLLAB_2_ENCRYPTED_SALARY") // The name of Bola's encrypted salary file. var collaborator2BucketInputName string = os.Getenv("COLLAB_2_INPUT_BUCKET") // The name of the storage bucket that contains Bola's encrypted salary file. var collaborator2BucketOutputName string = os.Getenv("COLLAB_2_OUTPUT_BUCKET") // The name of the storage bucket to store Bola's results in. var collaborator2KMSKeyringName string = os.Getenv("COLLAB_2_KEYRING_NAME") // Bola's Key Management Service key ring. var collaborator2KMSKeyName string = os.Getenv("COLLAB_2_KEY_NAME") // Bola's Key Management Service key. var collaborator2ProjectName string = os.Getenv("COLLAB_2_PROJECT_ID") // Bola's project ID. var collaborator2ProjectNumber string = os.Getenv("COLLAB_2_PROJECT_NUMBER") // Bola's project number. var collaborator2PoolName string = os.Getenv("COLLAB_2_POOL_NAME") // Bola's workload identity pool name. var collaborators = [2]collaborator{ { collaborator1Name, "projects/" + collaborator1ProjectNumber + "/locations/global/workloadIdentityPools/" + collaborator1PoolName + "/providers/attestation-verifier", "projects/" + collaborator1ProjectName + "/locations/global/keyRings/" + collaborator1KMSKeyringName + "/cryptoKeys/" + collaborator1KMSKeyName, collaborator1BucketInputName, collaborator1EncryptedSalaryFileName, collaborator1BucketOutputName, }, { collaborator2Name, "projects/" + collaborator2ProjectNumber + "/locations/global/workloadIdentityPools/" + collaborator2PoolName + "/providers/attestation-verifier", "projects/" + collaborator2ProjectName + "/locations/global/keyRings/" + collaborator2KMSKeyringName + "/cryptoKeys/" + collaborator2KMSKeyName, collaborator2BucketInputName, collaborator2EncryptedSalaryFileName, collaborator2BucketOutputName, }, } 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" } }` 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 = "You earn the same!\n" } now := time.Now() for _, cw := range collaborators { outputWriter := storageClient.Bucket(cw.outputBucket).Object(fmt.Sprintf("comparison-result-%d", 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.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, wippro string, encryptedData []byte) ([]byte, error) { cc := fmt.Sprintf(credentialConfig, wippro) 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 := io.ReadAll(objectReader) if err != nil { return nil, err } return s, nil }Certifique-se de que todas as partes leem e auditam o código-fonte.
Crie um ficheiro denominado
Dockerfileno editor do Cloud Shell com o seguinte conteúdo:# Compile the provided Go code to a statically linked binary FROM golang:latest AS build WORKDIR /build COPY salary.go . RUN go mod init salary RUN 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 RUN CGO_ENABLED=0 go build -trimpath # Build the workload container image FROM alpine:latest AS run WORKDIR /test COPY --from=build /build/salary /test/salary ENTRYPOINT ["/test/salary"] CMD [] # Allow the workload to access the following environment variables LABEL "tee.launch_policy.allow_env_override"="\ COLLAB_1_NAME,\ COLLAB_2_NAME,\ COLLAB_1_ENCRYPTED_SALARY,\ COLLAB_2_ENCRYPTED_SALARY,\ COLLAB_1_INPUT_BUCKET,\ COLLAB_2_INPUT_BUCKET,\ COLLAB_1_OUTPUT_BUCKET,\ COLLAB_2_OUTPUT_BUCKET,\ COLLAB_1_KEYRING_NAME,\ COLLAB_2_KEYRING_NAME,\ COLLAB_1_KEY_NAME,\ COLLAB_2_KEY_NAME,\ COLLAB_1_PROJECT_ID,\ COLLAB_2_PROJECT_ID,\ COLLAB_1_PROJECT_NUMBER,\ COLLAB_2_PROJECT_NUMBER,\ COLLAB_1_POOL_NAME,\ COLLAB_2_POOL_NAME"Esta
Dockerfileusa uma compilação de várias fases para compilar primeiro o código Go e, em seguida, copia a versão compilada desse código para o contentor de carga de trabalho final. Também permite que sejam usadas variáveis de ambiente específicas nesse contentor de carga de trabalho. Os valores destas variáveis de ambiente são mapeados posteriormente para os recursos específicos nos quais a carga de trabalho tem de operar.Clique em Abrir terminal para voltar ao Cloud Shell ou invoque o terminal integrado no editor do Cloud Shell a partir do menu Ver.
Crie um repositório Docker no Artifact Registry:
gcloud artifacts repositories create REPOSITORY_NAME \ --repository-format=docker \ --location=usConceda à conta de serviço que vai executar a carga de trabalho a função Leitor do Artifact Registry (
roles/artifactregistry.reader) para que possa ler a partir do repositório: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.readerAtualize as suas credenciais do Docker para incluir o nome do domínio
us-docker.pkg.dev:gcloud auth configure-docker us-docker.pkg.devCrie uma imagem de Docker a partir de
Dockerfileintroduzindo o seguinte comando no terminal:docker build -t \ "us-docker.pkg.dev/ALEX_PROJECT_ID/\ REPOSITORY_NAME/WORKLOAD_CONTAINER_NAME:latest" .Envie a imagem de Docker para o Artifact Registry:
docker push \ us-docker.pkg.dev/ALEX_PROJECT_ID/REPOSITORY_NAME/WORKLOAD_CONTAINER_NAMEA resposta do Docker push apresenta o resumo SHA256 da imagem, que é necessário posteriormente para autorizar a carga de trabalho. O resumo tem um aspeto semelhante ao do seguinte exemplo:
sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855Copie o resumo da imagem (incluindo o prefixo
sha256:) para um local onde o possa consultar. Também pode introduzir o resumo no seguinte exemplo de código para pré-preencher o resto dos exemplos de código neste guia que precisam do valor:WORKLOAD_CONTAINER_IMAGE_DIGESTCertifique-se de que todas as partes auditam a imagem do Docker e verificam se é fidedigna antes de autorizar a respetiva utilização.
Autorize a carga de trabalho
Com a carga de trabalho aprovada por ambas as partes, Alex e Bola têm de adicionar a atestação do Google Cloud como um fornecedor aos respetivos conjuntos de identidades da carga de trabalho. O fornecedor especifica o serviço de atestação a usar e as propriedades que a carga de trabalho tem de corresponder para poder operar nos dados de Alex ou Bola. Se um interveniente malicioso alterar a imagem do Docker ou alterar outra propriedade medida, o acesso ao volume de trabalho é recusado.
Este guia usa mapeamentos de atributos para fornecer acesso direto aos recursos à carga de trabalho com base no resumo da imagem. No entanto, noutras situações, pode preferir usar a representação da conta de serviço para aceder aos recursos. Consulte o artigo Acesso a cargas de trabalho externas para saber mais.
Para configurar os fornecedores para o Alex e a Bola com as condições necessárias, conclua os seguintes passos:
Introduza o seguinte comando para criar o fornecedor para o 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=\"gcpcs\ ::\"+assertion.submods.container.image_digest+\"\ ::\"+assertion.submods.gce.project_number+\"\ ::\"+assertion.submods.gce.instance_id,\ attribute.image_digest=assertion.submods.container.image_digest" \ --attribute-condition="assertion.swname == 'CONFIDENTIAL_SPACE'"Obtenha o número do projeto de Alex para o próximo comando:
gcloud projects describe ALEX_PROJECT_ID --format="value(projectNumber)"Conceda à identidade federada definida pelo fornecedor de Alex a função
cloudkms.cryptoKeyDecrypter, especificando o atributoimage_digest, para que apenas os contentores de carga de trabalho com o resumo especificado possam desencriptar as respetivas chaves do KMS:gcloud kms keys add-iam-policy-binding \ "projects/ALEX_PROJECT_ID/locations/global/\ keyRings/ALEX_KEYRING_NAME/\ cryptoKeys/ALEX_KEY_NAME" \ --member="principalSet://iam.googleapis.com/\ projects/ALEX_PROJECT_NUMBER/locations/global/\ workloadIdentityPools/ALEX_POOL_NAME/\ attribute.image_digest/WORKLOAD_CONTAINER_IMAGE_DIGEST" \ --role=roles/cloudkms.cryptoKeyDecrypterMudar para o projeto de Bola:
gcloud config set project BOLA_PROJECT_IDIntroduza o seguinte comando para criar o fornecedor para 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=\"gcpcs\ ::\"+assertion.submods.container.image_digest+\"\ ::\"+assertion.submods.gce.project_number+\"\ ::\"+assertion.submods.gce.instance_id,\ attribute.image_digest=assertion.submods.container.image_digest" \ --attribute-condition="assertion.swname == 'CONFIDENTIAL_SPACE'"Obtenha o número do projeto de Bola para o comando seguinte:
gcloud projects describe BOLA_PROJECT_ID --format="value(projectNumber)"Conceda à identidade federada definida pelo fornecedor da Bola a função
cloudkms.cryptoKeyDecrypter, especificando o atributoimage_digestpara que apenas os contentores de cargas de trabalho com o resumo especificado possam desencriptar as respetivas chaves do KMS:gcloud kms keys add-iam-policy-binding \ "projects/BOLA_PROJECT_ID/locations/global/\ keyRings/BOLA_KEYRING_NAME/\ cryptoKeys/BOLA_KEY_NAME" \ --member="principalSet://iam.googleapis.com/\ projects/BOLA_PROJECT_NUMBER/locations/global/\ workloadIdentityPools/BOLA_POOL_NAME/\ attribute.image_digest/WORKLOAD_CONTAINER_IMAGE_DIGEST" \ --role=roles/cloudkms.cryptoKeyDecrypter
Teste a carga de trabalho
Com os fornecedores adicionados aos Workload Identity Pools de Alex e Bola e os recursos necessários implementados, é altura de o operador da carga de trabalho testar a carga de trabalho.
Para testar a carga de trabalho, cria uma nova instância de VM confidencial no projeto de Bola com as seguintes propriedades:
Uma configuração suportada com AMD SEV, Intel TDX ou Intel TDX com computação confidencial da NVIDIA (pré-visualização).
Arranque seguro ativado.
Um SO baseado na imagem de depuração do Confidential Space para facilitar a resolução de problemas.
Uma referência à imagem do Docker que o Alex criou anteriormente. Esta é carregada sobre a imagem do Confidential Space.
Uma conta de serviço que o Bola criou anteriormente, que executa a carga de trabalho.
STDOUTeSTDERRredirecionados para o Cloud Logging e a consola série.Os detalhes dos recursos que a carga de trabalho precisa de definir como variáveis de ambiente.
Introduza o seguinte comando no Cloud Shell de Bola para testar a carga de trabalho:
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\
~tee-env-COLLAB_1_NAME=Alex\
~tee-env-COLLAB_2_NAME=Bola\
~tee-env-COLLAB_1_ENCRYPTED_SALARY=ALEX_ENCRYPTED_SALARY_FILE\
~tee-env-COLLAB_2_ENCRYPTED_SALARY=BOLA_ENCRYPTED_SALARY_FILE\
~tee-env-COLLAB_1_INPUT_BUCKET=ALEX_INPUT_BUCKET_NAME\
~tee-env-COLLAB_2_INPUT_BUCKET=BOLA_INPUT_BUCKET_NAME\
~tee-env-COLLAB_1_OUTPUT_BUCKET=ALEX_OUTPUT_BUCKET_NAME\
~tee-env-COLLAB_2_OUTPUT_BUCKET=BOLA_OUTPUT_BUCKET_NAME\
~tee-env-COLLAB_1_KEYRING_NAME=ALEX_KEYRING_NAME\
~tee-env-COLLAB_2_KEYRING_NAME=BOLA_KEYRING_NAME\
~tee-env-COLLAB_1_KEY_NAME=ALEX_KEY_NAME\
~tee-env-COLLAB_2_KEY_NAME=BOLA_KEY_NAME\
~tee-env-COLLAB_1_PROJECT_ID=ALEX_PROJECT_ID\
~tee-env-COLLAB_2_PROJECT_ID=BOLA_PROJECT_ID\
~tee-env-COLLAB_1_PROJECT_NUMBER=ALEX_PROJECT_NUMBER\
~tee-env-COLLAB_2_PROJECT_NUMBER=BOLA_PROJECT_NUMBER\
~tee-env-COLLAB_1_POOL_NAME=ALEX_POOL_NAME\
~tee-env-COLLAB_2_POOL_NAME=BOLA_POOL_NAME"
Ver progresso
Pode ver o progresso da carga de trabalho no projeto de Bola acedendo ao Explorador de registos.
Aceda ao Explorador de registos
Para mostrar apenas entradas de registo do Confidential Space, filtre pelos seguintes campos de registo, se estiverem disponíveis:
Tipo de recurso: instância de VM
ID da instância: o ID da instância da VM
Nome do registo: confidential-space-launcher
Para atualizar o registo, clique em Ir para agora. Também pode deslocar a página para resultados anteriores e, em seguida, deslocá-la novamente para o fim do registo para carregar as entradas mais recentes.
Veja os resultados
Se a tarefa de carga de trabalho terminar e devolver 0, significa que não ocorreram erros e que é altura de verificar o resultado nos contentores de resultados do Alex e da Bola:
Mudar para o projeto do Alex:
gcloud config set project ALEX_PROJECT_IDListe todos os ficheiros no respetivo conjunto de resultados:
gcloud storage ls gs://ALEX_OUTPUT_BUCKET_NAMELeia o ficheiro mais recente apresentado, substituindo
ALEX_OUTPUT_CLOUD_STORAGE_PATHpelo caminho do ficheiro, incluindogs://:gcloud storage cat ALEX_OUTPUT_CLOUD_STORAGE_PATHSe não existir nenhum ficheiro, tem de depurar a sua carga de trabalho.
Mudar para o projeto de Bola:
gcloud config set project BOLA_PROJECT_IDListe todos os ficheiros no respetivo conjunto de resultados:
gcloud storage ls gs://BOLA_OUTPUT_BUCKET_NAMELeia o ficheiro mais recente apresentado, substituindo
BOLA_RESULTS_CLOUD_STORAGE_PATHpelo caminho do ficheiro, incluindogs://:gcloud storage cat BOLA_RESULTS_CLOUD_STORAGE_PATHSe não existir nenhum ficheiro, tem de depurar a sua carga de trabalho.
Depois de ler os resultados com êxito, pare a instância de VM:
gcloud compute instances stop WORKLOAD_VM_2_NAME --zone=us-west1-b
Ao lerem os ficheiros, o Alex e a Bola descobrem quem ganha mais sem nunca revelarem os seus salários um ao outro.
Depure e reinicie a carga de trabalho
Um ambiente do espaço confidencial tem muitas partes e é possível que algo tenha sido configurado incorretamente, o que faz com que a carga de trabalho falhe.
Ao contrário da imagem do espaço confidencial de produção, a imagem de depuração mantém a instância da VM em execução após a conclusão da carga de trabalho. Isto significa que, se os registos não revelarem informações suficientes para resolver o problema, o passo seguinte é estabelecer ligação à instância de VM através de SSH e continuar a depuração.
Depois de terminar a depuração, pare a instância de VM:
gcloud compute instances stop WORKLOAD_VM_2_NAME --zone=us-west1-b
Para executar a carga de trabalho no ambiente depurado, inicie novamente a VM:
gcloud compute instances start WORKLOAD_VM_2_NAME --zone=us-west1-b
Proteja o ambiente para produção
Depois de testar com êxito a carga de trabalho, é altura de
reforçar o ambiente do espaço confidencial para a implementação em produção. O Alex e a Bola têm de adicionar uma declaração support_attributes aos respetivos fornecedores para verificar se a imagem do espaço confidencial de produção é usada para a carga de trabalho:
Mudar para o projeto do Alex:
gcloud config set project ALEX_PROJECT_IDIntroduza o seguinte comando para atualizar o fornecedor de Alex:
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=\"gcpcs\ ::\"+assertion.submods.container.image_digest+\"\ ::\"+assertion.submods.gce.project_number+\"\ ::\"+assertion.submods.gce.instance_id,\ attribute.image_digest=assertion.submods.container.image_digest" \ --attribute-condition="assertion.swname == 'CONFIDENTIAL_SPACE' \ && 'STABLE' in assertion.submods.confidential_space.support_attributes"Mudar para o projeto de Bola:
gcloud config set project BOLA_PROJECT_IDIntroduza o seguinte comando para atualizar o fornecedor de Bola:
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=\"gcpcs\ ::\"+assertion.submods.container.image_digest+\"\ ::\"+assertion.submods.gce.project_number+\"\ ::\"+assertion.submods.gce.instance_id,\ attribute.image_digest=assertion.submods.container.image_digest" \ --attribute-condition="assertion.swname == 'CONFIDENTIAL_SPACE' \ && 'STABLE' in assertion.submods.confidential_space.support_attributes"
Implemente a carga de trabalho de produção
O Bola tem de criar uma instância de VM separada para executar a carga de trabalho de produção. As seguintes aspetos são diferentes em comparação com a carga de trabalho de teste:
O SO baseia-se na imagem de produção do Confidential Space. Esta opção tem o SSH desativado e a instância de VM para após a conclusão da carga de trabalho.
O redirecionamento de registo é removido. Apenas os registos básicos que não expõem informações confidenciais são apresentados no Cloud Logging.
Introduza o seguinte comando no Cloud Shell de Bola para implementar a carga de trabalho de produção:
gcloud compute instances create WORKLOAD_VM_NAME \
--confidential-compute-type=SEV \
--shielded-secure-boot \
--scopes=cloud-platform \
--zone=us-west1-b \
--maintenance-policy=MIGRATE \
--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\
~tee-env-COLLAB_1_NAME=Alex\
~tee-env-COLLAB_2_NAME=Bola\
~tee-env-COLLAB_1_ENCRYPTED_SALARY=ALEX_ENCRYPTED_SALARY_FILE\
~tee-env-COLLAB_2_ENCRYPTED_SALARY=BOLA_ENCRYPTED_SALARY_FILE\
~tee-env-COLLAB_1_INPUT_BUCKET=ALEX_INPUT_BUCKET_NAME\
~tee-env-COLLAB_2_INPUT_BUCKET=BOLA_INPUT_BUCKET_NAME\
~tee-env-COLLAB_1_OUTPUT_BUCKET=ALEX_OUTPUT_BUCKET_NAME\
~tee-env-COLLAB_2_OUTPUT_BUCKET=BOLA_OUTPUT_BUCKET_NAME\
~tee-env-COLLAB_1_KEYRING_NAME=ALEX_KEYRING_NAME\
~tee-env-COLLAB_2_KEYRING_NAME=BOLA_KEYRING_NAME\
~tee-env-COLLAB_1_KEY_NAME=ALEX_KEY_NAME\
~tee-env-COLLAB_2_KEY_NAME=BOLA_KEY_NAME\
~tee-env-COLLAB_1_PROJECT_ID=ALEX_PROJECT_ID\
~tee-env-COLLAB_2_PROJECT_ID=BOLA_PROJECT_ID\
~tee-env-COLLAB_1_PROJECT_NUMBER=ALEX_PROJECT_NUMBER\
~tee-env-COLLAB_2_PROJECT_NUMBER=BOLA_PROJECT_NUMBER\
~tee-env-COLLAB_1_POOL_NAME=ALEX_POOL_NAME\
~tee-env-COLLAB_2_POOL_NAME=BOLA_POOL_NAME"
A forma como vê o progresso e vê os resultados é a mesma que quando testou a carga de trabalho.
Quando a carga de trabalho de produção termina, a instância de VM é interrompida. Para ver resultados diferentes, pode alterar os salários, voltar a encriptá-los, voltar a carregá-los para os respetivos contentores do Cloud Storage e, em seguida, reiniciar a instância de VM para executar novamente a carga de trabalho:
gcloud compute instances start WORKLOAD_VM_NAME --zone=us-west1-b
Limpeza
Para remover os recursos criados neste guia, conclua as seguintes instruções.
Limpe os recursos do Alex
Mudar para o projeto do Alex:
gcloud config set project ALEX_PROJECT_IDElimine o Workload Identity Pool do Alex:
gcloud iam workload-identity-pools delete ALEX_POOL_NAME \ --location=globalElimine os contentores do Cloud Storage de Alex:
gcloud storage rm gs://ALEX_INPUT_BUCKET_NAME \ gs://ALEX_OUTPUT_BUCKET_NAME --recursiveEliminar os ficheiros de salário do Alex, o código Go e o
Dockerfile:rm ALEX_SALARY.txt \ ALEX_ENCRYPTED_SALARY_FILE \ salary.go \ DockerfileOpcional: desative ou destrua a chave do Cloud Key Management Service de Alex.
Opcional: Encerra o projeto do Alex.
Limpe os recursos do Bola
Mudar para o projeto de Bola:
gcloud config set project BOLA_PROJECT_IDElimine a VM que executou o fluxo de trabalho de teste:
gcloud compute instances delete WORKLOAD_VM_2_NAME --zone=us-west1-bElimine a VM que executou o fluxo de trabalho de produção:
gcloud compute instances delete WORKLOAD_VM_NAME --zone=us-west1-bElimine a conta de serviço que executou a carga de trabalho:
gcloud iam service-accounts delete \ WORKLOAD_SERVICE_ACCOUNT_NAME@BOLA_PROJECT_ID.iam.gserviceaccount.comElimine o Workload Identity Pool da Bola:
gcloud iam workload-identity-pools delete BOLA_POOL_NAME \ --location=globalElimine os contentores do Cloud Storage de Bola:
gcloud storage rm gs://BOLA_INPUT_BUCKET_NAME \ gs://BOLA_OUTPUT_BUCKET_NAME --recursiveElimine os ficheiros de salário de Bola:
rm BOLA_SALARY.txt \ BOLA_ENCRYPTED_SALARY_FILEOpcional: desative ou destrua a chave do Cloud Key Management Service da Bola.
Opcional: Encerra o projeto do Bola.