Neste guia, Alex e Bola querem descobrir quem tem o salário mais alto sem revelar números um ao outro. Eles decidem usar o Confidential Space para manter os dados confidenciais e concordam em assumir os seguintes papéis:
Alex: colaborador de dados, autor de carga de trabalho
Bola: colaborador de dados, operador de carga de trabalho
Essa organização foi criada para simplificar ao máximo este guia. No entanto, é possível que o autor e o operador da carga de trabalho sejam totalmente independentes dos colaboradores de dados, e você pode ter quantos colaboradores quiser.
Antes de começar
Neste guia, você vai conferir um cenário do Confidential Space usando uma única conta em uma organização com acesso a vários projetos. Assim, é possível conferir todo o processo. Em uma implantação de produção, os colaboradores, autores de carga de trabalho e operadores de carga de trabalho têm contas separadas e os próprios projetos contidos em organizações discretas, inacessíveis uns aos outros e mantendo os dados confidenciais separados.
O Confidential Space pode interagir com muitos serviços do Google Cloudpara produzir resultados, incluindo, entre outros:
Neste guia, usamos e pressupomos uma compreensão básica de todos esses recursos.
Funções exigidas
Para conseguir as permissões necessárias a fim de concluir este guia, peça ao administrador para conceder a você os seguintes papéis do IAM no projeto:
-
Administrador do Cloud KMS (
roles/cloudkms.admin) para os colaboradores de dados (Alex e Bola). -
Administrador de pool de Identidade da carga de trabalho do IAM (
roles/iam.workloadIdentityPoolAdmin) para os colaboradores de dados (Alex e Bola). -
Administrador do Service Usage (
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 para o operador de carga de trabalho (Bola). -
Administrador da conta de serviço (
roles/iam.serviceAccountAdmin) para o operador de carga de trabalho (Bola). -
Administrador do Compute (
roles/compute.admin) para o operador de carga de trabalho (Bola). -
Administrador de segurança (
roles/securityAdmin) para o operador de 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 concessão de papéis, consulte Gerenciar o acesso a projetos, pastas e organizações.
Também é possível conseguir as permissões necessárias usando papéis personalizados ou outros papéis predefinidos.
Configurar recursos de colaboradores de dados
Alex e Bola precisam de projetos independentes que contenham os seguintes recursos:
Os dados confidenciais em si.
Uma chave para criptografar esses dados e mantê-los confidenciais.
Um bucket do Cloud Storage para armazenar os dados criptografados.
Um pool de identidade da carga de trabalho. A carga de trabalho que processa os dados confidenciais usa o pool para acessar os dados particulares e descriptografá-los.
Para começar, acesse o console do Google Cloud :
Acessar o console do Google Cloud
Configurar os recursos do Alex
Para configurar os recursos do Alex, siga as instruções a seguir.
- Clique em Ativar o Cloud Shell.
-
No Cloud Shell, insira o comando a seguir para criar um projeto para o Alex, substituindo ALEX_PROJECT_ID por um nome de sua escolha:
gcloud projects create ALEX_PROJECT_ID -
Alterne para o projeto recém-criado:
gcloud config set project ALEX_PROJECT_ID -
Ative as APIs que o Alex exige como colaborador de dados e autor da carga de trabalho:
gcloud services enable \ artifactregistry.googleapis.com \ cloudkms.googleapis.com \ iamcredentials.googleapis.com -
Crie um keyring e uma chave de criptografia 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 ao Alex o papel
cloudkms.cryptoKeyEncrypterpara que ele possa usar a chave recém-criada para criptografar 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 pool de identidades de carga de trabalho do Alex:
gcloud iam workload-identity-pools create ALEX_POOL_NAME \ --location=global -
Crie um bucket 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 arquivo que contenha apenas o salário do Alex como número:
echo 123456 > ALEX_SALARY.txt -
Criptografe o arquivo e faça upload dele para o bucket do 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
Configurar os recursos do Bola
Para configurar os recursos do Bola, siga as instruções a seguir.
-
No Cloud Shell, digite o seguinte comando para criar um projeto para o Bola, substituindo BOLA_PROJECT_ID por um nome de sua escolha:
gcloud projects create BOLA_PROJECT_ID -
Alterne para o projeto recém-criado:
gcloud config set project BOLA_PROJECT_ID -
Ative as APIs que o Bola exige 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 keyring e uma chave de criptografia 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 ao Bola o papel
cloudkms.cryptoKeyEncrypterpara que ele possa usar a chave recém-criada para criptografar 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 pool de identidades da carga de trabalho do Bola:
gcloud iam workload-identity-pools create BOLA_POOL_NAME \ --location=global -
Crie um bucket 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 arquivo que contenha apenas o salário de Bola como número:
echo 111111 > BOLA_SALARY.txt -
Criptografe o arquivo e faça upload dele para o bucket do 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, Bola opera e executa a carga de trabalho, mas qualquer pessoa pode assumir esses papéis, incluindo terceiros. A instância de VM criada por Bola para executar a carga de trabalho tem uma conta de serviço anexada, que tem permissão para gerar tokens de comprovação, gravar registros, ler os dados criptografados de Alex e Bola e gravar resultados em buckets específicos do Cloud Storage.
Conclua as etapas a seguir no projeto do 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 ao Bola o papel
iam.serviceAccountUserpara que ele possa anexar a conta de serviço à VM de 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 o papel
confidentialcomputing.workloadUserpara que ela possa gerar um token de atestado: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 o papel
logging.logWriterpara gravar registros no Cloud Logging, assim é possível 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 buckets do Alex e do Bola que contêm os dados criptografados e acesso de gravação para cada um dos buckets de resultados:
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.objectAdminIsso pressupõe que o usuário que concede o acesso tenha o papel de Administrador do Storage (
roles/storage.admin) no projeto que contém o bucket do Cloud Storage que está sendo operado.
Criar a carga de trabalho
Neste guia, Alex fornece o código para a carga de trabalho e cria uma imagem do Docker para contê-la, mas qualquer pessoa pode assumir esses papéis, incluindo um terceiro.
Alex precisa criar os seguintes recursos para a carga de trabalho:
O código que executa a carga de trabalho.
Um repositório do Docker no Artifact Registry que pode ser acessado pela conta de serviço que executa a carga de trabalho.
Uma imagem do Docker que contém e executa o código da carga de trabalho.
Para criar e configurar os recursos, conclua as seguintes etapas no projeto do Alex:
Alterne para o projeto do Alex:
gcloud config set project ALEX_PROJECT_IDClique em Abrir editor para abrir o editor do Cloud Shell e crie um novo arquivo com o nome
salary.go. Copie o código a seguir no arquivo e salve-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 }Verifique se todas as partes leem e auditam o código-fonte.
Crie um arquivo chamado
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"Esse
Dockerfileusa um build de várias etapas para primeiro compilar o código Go e depois copia a versão compilada desse código para o contêiner de carga de trabalho final. Ele também permite que variáveis de ambiente específicas sejam usadas nesse contêiner de carga de trabalho. Os valores dessas variáveis de ambiente são mapeados posteriormente para os recursos específicos de que a carga de trabalho precisa para operar.Clique em Abrir terminal para voltar ao Cloud Shell ou invoque o terminal integrado ao editor do Cloud Shell no menu Visualizar.
Criar um repositório do Docker no Artifact Registry:
gcloud artifacts repositories create REPOSITORY_NAME \ --repository-format=docker \ --location=usConceda à conta de serviço que executará a carga de trabalho o papel de Leitor do Artifact Registry (
roles/artifactregistry.reader) para que ela possa ler 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 suas credenciais do Docker para incluir o nome de domínio
us-docker.pkg.dev:gcloud auth configure-docker us-docker.pkg.devCrie uma imagem do Docker a partir de
Dockerfile. Para isso, digite o seguinte comando no terminal:docker build -t \ "us-docker.pkg.dev/ALEX_PROJECT_ID/\ REPOSITORY_NAME/WORKLOAD_CONTAINER_NAME:latest" .Envie a imagem do Docker para o Artifact Registry:
docker push \ us-docker.pkg.dev/ALEX_PROJECT_ID/REPOSITORY_NAME/WORKLOAD_CONTAINER_NAMEA resposta do push do Docker lista o resumo SHA256 da imagem, que será necessário mais tarde para autorizar a carga de trabalho. A saída será assim:
sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855Copie o resumo da imagem (incluindo o prefixo
sha256:) em um local onde você possa fazer referência a ele. Você também pode inserir o resumo no exemplo de código a seguir para preencher o restante dos exemplos de código neste guia que precisam do valor:WORKLOAD_CONTAINER_IMAGE_DIGESTCertifique-se de que todas as partes auditem a imagem do Docker e verifique se ela é confiável antes de autorizar o uso.
Autorizar a carga de trabalho
Com a carga de trabalho aprovada por ambas as partes, Alex e Bola precisam adicionar o atestado do Google Cloud como um provedor aos pools de identidade da carga de trabalho. O provedor especifica o serviço de atestado a ser usado e as propriedades que a carga de trabalho precisa corresponder para poder operar nos dados de Alex ou Bola. Se uma pessoa mal-intencionada mudar a imagem do Docker ou alterar outra propriedade medida, o acesso à carga de trabalho será negado.
Este guia usa mapeamentos de atributos para fornecer acesso direto aos recursos da carga de trabalho com base no resumo da imagem. No entanto, em outras situações, talvez seja melhor usar a representação de uma conta de serviço para acessar os recursos. Consulte Acesso a cargas de trabalho externas para saber mais.
Para configurar os provedores do Alex e do Bola com as condições necessárias, siga estas etapas:
Digite o seguinte comando para criar o provedor do 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'"Receba o número do projeto do Alex para o próximo comando:
gcloud projects describe ALEX_PROJECT_ID --format="value(projectNumber)"Conceda à identidade federada definida pelo provedor de Alex a função
cloudkms.cryptoKeyDecrypter, especificando o atributoimage_digestpara que apenas contêineres de carga de trabalho com o resumo especificado possam descriptografar as 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.cryptoKeyDecrypterMude para o projeto do Bola:
gcloud config set project BOLA_PROJECT_IDDigite o seguinte comando para criar o provedor do 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'"Receba o número do projeto do Bola para o próximo comando:
gcloud projects describe BOLA_PROJECT_ID --format="value(projectNumber)"Conceda à identidade federada definida pelo provedor de Bola o papel
cloudkms.cryptoKeyDecrypter, especificando o atributoimage_digestpara que apenas contêineres de carga de trabalho com o resumo especificado possam descriptografar as 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
Testar a carga de trabalho
Com os provedores adicionados aos pools de identidade da carga de trabalho do Alex e do Bola e os recursos necessários ativos, é hora do operador da carga de trabalho testar a carga de trabalho.
Para testar a carga de trabalho, crie uma instância de VM confidencial no projeto do Bola que tenha as seguintes propriedades:
Uma configuração compatível com AMD SEV, Intel TDX ou Intel TDX com NVIDIA Confidential Computing (pré-lançamento).
Inicialização segura ativada.
Um SO baseado na imagem de depuração do Confidential Space, para facilitar a solução de problemas.
Uma referência à imagem do Docker que Alex criou anteriormente. Ele é carregado sobre a imagem do Confidential Space.
Uma conta de serviço anexada que Bola criou antes e que executa a carga de trabalho.
STDOUTeSTDERRredirecionados para o Cloud Logging e o console serial.O recurso detalha a carga de trabalho necessária definida como variáveis de ambiente.
Para testar a carga de trabalho, digite o seguinte comando no Cloud Shell do Bola:
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 andamento
É possível ver o progresso da carga de trabalho no projeto do Bola acessando o Explorador de registros.
Acessar o "Explorador de registros"
Para mostrar apenas as entradas de registro do Confidential Space, filtre pelos seguintes campos de registro, se estiverem disponíveis:
Tipo de recurso: instância de VM
ID da instância: o ID da instância da VM
Nome do registro: confidencial-space-launcherer
Para atualizar o registro, clique em Ir para o momento atual. Você também pode rolar para resultados anteriores e depois para o final do registro novamente para carregar as entradas mais recentes.
Ver os resultados
Se a tarefa da carga de trabalho terminar e retornar 0, isso significa que não ocorreram erros
e é hora de verificar a saída nos buckets de saída de Alex e Bola:
Alterne para o projeto do Alex:
gcloud config set project ALEX_PROJECT_IDListe todos os arquivos no bucket de resultados:
gcloud storage ls gs://ALEX_OUTPUT_BUCKET_NAMELeia o arquivo mais recente listado, substituindo
ALEX_OUTPUT_CLOUD_STORAGE_PATHpelo caminho do arquivo, incluindo ogs://:gcloud storage cat ALEX_OUTPUT_CLOUD_STORAGE_PATHSe nenhum arquivo estiver presente, depure sua carga de trabalho.
Mude para o projeto do Bola:
gcloud config set project BOLA_PROJECT_IDListe todos os arquivos no bucket de resultados:
gcloud storage ls gs://BOLA_OUTPUT_BUCKET_NAMELeia o arquivo mais recente listado, substituindo
BOLA_RESULTS_CLOUD_STORAGE_PATHpelo caminho do arquivo, incluindo ogs://:gcloud storage cat BOLA_RESULTS_CLOUD_STORAGE_PATHSe nenhum arquivo estiver presente, depure sua carga de trabalho.
Depois de ler os resultados, pare a instância de VM:
gcloud compute instances stop WORKLOAD_VM_2_NAME --zone=us-west1-b
Ao ler os arquivos, Alex e Bola descobrem quem ganha mais sem nunca revelar o salário um para o outro.
Depurar e reiniciar a carga de trabalho
Um ambiente do Confidential Space tem muitas partes, e é possível que algo tenha sido configurado incorretamente, causando a falha da carga de trabalho.
Ao contrário da imagem de produção do Confidential Space, a imagem de depuração mantém a instância de VM em execução após a conclusão da carga de trabalho. Isso significa que, se os registros não revelarem o suficiente para resolver o problema, a próxima etapa será se conectar à instância de VM por SSH e continuar a depuração.
Depois de concluir 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 a VM novamente:
gcloud compute instances start WORKLOAD_VM_2_NAME --zone=us-west1-b
Reforçar o ambiente para produção
Depois de testar a carga de trabalho, é hora de
reforçar o ambiente do Confidential Space para implantação em produção. Alex e Bola
precisam adicionar uma
declaração support_attributes
aos provedores para verificar se a imagem de produção do Confidential Space é usada
para a carga de trabalho:
Alterne para o projeto do Alex:
gcloud config set project ALEX_PROJECT_IDDigite o seguinte comando para atualizar o provedor do 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"Mude para o projeto do Bola:
gcloud config set project BOLA_PROJECT_IDDigite o seguinte comando para atualizar o provedor do 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"
Implantar a carga de trabalho de produção
Bola precisa criar uma instância de VM separada para executar a carga de trabalho de produção. As seguintes coisas são diferentes em comparação com a carga de trabalho de teste:
O SO é baseado na imagem de produção do Confidential Space. O SSH fica desativado, e a instância de VM é interrompida após a conclusão da carga de trabalho.
O redirecionamento de geração de registros é removido. Somente os registros básicos que não expõem informações sensíveis são mostrados no Cloud Logging.
Para implantar a carga de trabalho de produção, digite o seguinte comando no Cloud Shell do Bola:
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 maneira de ver o progresso e conferir os resultados é a mesma de quando você testou a carga de trabalho.
Quando a carga de trabalho de produção é concluída, a instância de VM é interrompida. Para conferir resultados diferentes, mude os salários, criptografe e faça upload deles novamente para os respectivos buckets do Cloud Storage. Em seguida, reinicie a instância de VM para executar a carga de trabalho outra vez:
gcloud compute instances start WORKLOAD_VM_NAME --zone=us-west1-b
Limpeza
Para remover os recursos criados neste guia, siga as instruções a seguir.
Limpar os recursos do Alex
Alterne para o projeto do Alex:
gcloud config set project ALEX_PROJECT_IDExclua o pool de identidades de carga de trabalho do Alex:
gcloud iam workload-identity-pools delete ALEX_POOL_NAME \ --location=globalExclua os buckets do Cloud Storage do Alex:
gcloud storage rm gs://ALEX_INPUT_BUCKET_NAME \ gs://ALEX_OUTPUT_BUCKET_NAME --recursiveExclua os arquivos de salário do Alex, o código do 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 do Alex.
Opcional: Encerre o projeto do Alex.
Limpar os recursos do Bola
Mude para o projeto do Bola:
gcloud config set project BOLA_PROJECT_IDExclua a VM que executou o fluxo de trabalho de teste:
gcloud compute instances delete WORKLOAD_VM_2_NAME --zone=us-west1-bExclua a VM que executou o fluxo de trabalho de produção:
gcloud compute instances delete WORKLOAD_VM_NAME --zone=us-west1-bExclua 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.comExclua o pool de identidades da carga de trabalho do Bola:
gcloud iam workload-identity-pools delete BOLA_POOL_NAME \ --location=globalExclua os buckets do Cloud Storage do Bola:
gcloud storage rm gs://BOLA_INPUT_BUCKET_NAME \ gs://BOLA_OUTPUT_BUCKET_NAME --recursiveExclua os arquivos de salário do Bola:
rm BOLA_SALARY.txt \ BOLA_ENCRYPTED_SALARY_FILEOpcional: desative ou destrua a chave do Cloud Key Management Service do Bola.
Opcional: Encerre o projeto do Bola.