1. Visão geral
Tudo pronto para melhorar a segurança e a privacidade das suas cargas de trabalho aceleradas por GPU? Este codelab vai orientar você pelos recursos do Espaço confiável, uma oferta que oferece suporte a isolamento de operador e aceleração para cargas de trabalho sensíveis de IA/ML.
Proteger dados, modelos e chaves valiosos é mais importante do que nunca. O Trusted Space oferece uma solução para garantir que suas cargas de trabalho funcionem em um ambiente seguro e confiável, em que nem mesmo o operador da carga de trabalho tem acesso.
Confira o que o Espaço confiável oferece:
- Privacidade e segurança aprimoradas:o Espaço confiável oferece um ambiente de execução confiável em que seus recursos sensíveis (por exemplo, modelos, dados valiosos e chaves) permanecem protegidos, com suporte de prova criptográfica.
- Isolamento do operador:elimine as preocupações com a interferência do operador. Com o Espaço confiável, nem mesmo os operadores de carga de trabalho têm acesso, o que impede a execução de SSH, o acesso a dados, a instalação de software ou a adulteração do código.
- Suporte a acelerador:o Trusted Space foi projetado para funcionar perfeitamente com uma ampla variedade de aceleradores de hardware, incluindo GPUs como H100, A100, T4 e L4. Isso garante que seus aplicativos de IA/ML essenciais para o desempenho sejam executados sem problemas.
O que você vai aprender
- Entenda as principais ofertas do Trusted Space.
- Aprenda a implantar e configurar um ambiente do Trusted Space para proteger os recursos valiosos da sua carga de trabalho de IA/ML.
O que é necessário
- Um projeto do Google Cloud Platform
- Conhecimento básico do Google Compute Engine e dos aceleradores.
- Conhecimento básico de contas de serviço, gerenciamento de chaves, federação de identidade da carga de trabalho e condições de atributo.
- Conhecimento básico de containers e Artifact Registry
Como proteger solicitações de geração de código sensível com a Primus Company
Neste codelab, vamos nos colocar no lugar da Primus, uma empresa que prioriza a privacidade e a segurança dos dados dos funcionários. A Primus quer implantar um modelo de geração de código para ajudar os desenvolvedores nas tarefas de programação. No entanto, ele quer proteger a confidencialidade das solicitações enviadas pelos funcionários, já que elas geralmente contêm trechos de código sensíveis, detalhes internos do projeto ou algoritmos proprietários.
Por que a empresa Primus não confia no operador?
A Primus Corp opera em um mercado altamente competitivo. A base de código contém propriedade intelectual valiosa, incluindo algoritmos reservados e snippets de código sensíveis que oferecem uma vantagem competitiva. Ele está preocupado com a possibilidade de espionagem corporativa por parte dos operadores de carga de trabalho. Além disso, as solicitações de funcionários podem incluir partes confidenciais do código "Necessário saber" que a Primus Corp quer proteger.
Para resolver esse problema, a Primus Corp vai usar o Espaço confiável para isolar o servidor de inferência que executa o modelo para geração de código. Veja como funciona:
- Criptografia de comando:antes de enviar um comando para o servidor de inferência, cada funcionário o criptografa usando uma chave KMS gerenciada pela Primus Corp no Google Cloud. Isso garante que apenas o ambiente do Espaço confiável, em que a chave de descriptografia correspondente está disponível, possa descriptografar e acessar o prompt de texto simples. Em um cenário real, a criptografia do lado do cliente pode ser processada pelas bibliotecas disponíveis (por exemplo, tink). Como parte deste codelab, usaremos este aplicativo de exemplo de cliente com criptografia de envelope.
- Isolamento do operador:somente o servidor de inferência, executado em um ambiente do Trusted Space, terá acesso à chave usada para criptografia e poderá descriptografar a solicitação em um ambiente confiável. O acesso à chave de criptografia seria protegido pelo pool de identidade da carga de trabalho. Devido às garantias de isolamento do Trusted Space, nem mesmo o operador da carga de trabalho pode acessar a chave usada para criptografia e o conteúdo descriptografado.
- Inferência segura usando aceleradores: o servidor de inferência seria iniciado em uma VM protegida (como parte da configuração do espaço confiável), o que garantiria que a instância de carga de trabalho não foi comprometida por malware ou rootkits no nível do kernel ou da inicialização. Esse servidor descriptografa o comando no ambiente do Espaço confiável, realiza a inferência usando o modelo de geração de código e retorna o código gerado ao funcionário.
2. Configurar recursos do Cloud
Antes de começar
- Clone este repositório usando o comando abaixo para receber os scripts necessários que são usados como parte deste codelab.
git clone https://github.com/GoogleCloudPlatform/confidential-space.git
- Mude o diretório para este codelab.
cd confidential-space/codelabs/trusted_space_codelab/scripts
- Verifique se você definiu as variáveis de ambiente do projeto necessárias, conforme mostrado abaixo. Para mais informações sobre como configurar um projeto do GCP, consulte este codelab. Consulte este link para saber como recuperar o ID do projeto e como ele é diferente do nome e do número do projeto.
export PRIMUS_PROJECT_ID=<GCP project id of Primus>
- Ative o faturamento dos projetos.
- Ative a API Confidential Computing e as APIs a seguir para os dois projetos.
gcloud services enable \
cloudapis.googleapis.com \
cloudresourcemanager.googleapis.com \
cloudkms.googleapis.com \
cloudshell.googleapis.com \
container.googleapis.com \
containerregistry.googleapis.com \
iam.googleapis.com \
confidentialcomputing.googleapis.com
- Atribua valores às variáveis dos nomes de recursos especificados acima usando o comando a seguir. Essas variáveis permitem personalizar os nomes dos recursos conforme necessário e usar recursos existentes, se já criados. (por exemplo,
export PRIMUS_SERVICE_ACCOUNT='my-service-account'
)
- É possível definir as variáveis a seguir com nomes de recursos do Cloud no projeto Primus. Se a variável for definida, o recurso de nuvem correspondente do projeto Primus será usado. Se a variável não for definida, o nome do recurso da nuvem será gerado com base no nome do projeto, e um novo recurso da nuvem será criado com esse nome. Confira a seguir as variáveis compatíveis para nomes de recursos:
| Região em que os recursos regionais seriam criados para a empresa Primus. |
| Local em que os recursos seriam criados para a empresa Primus. |
| Zona em que os recursos zonais seriam criados para a empresa Primus. |
| Pool de identidade da carga de trabalho da empresa Primus para proteger os recursos da nuvem. |
| O provedor de pool de identidade da carga de trabalho da empresa Primus, que inclui a condição de autorização a ser usada para tokens assinados pelo serviço de verificação de atestados. |
| A conta de serviço da empresa Primus que |
| A chave do KMS é usada para criptografar as solicitações fornecidas pelos funcionários da empresa Primus. |
| O keyring do KMS que será usado para criar a chave de criptografia |
| A versão da chave KMS da chave de criptografia |
| O repositório de artefatos para onde a imagem do contêiner da carga de trabalho será enviada. |
| A região do repositório de artefatos que teria a imagem do Docker da carga de trabalho publicada. |
| Nome da VM de carga de trabalho. |
| Nome da imagem do Docker da carga de trabalho. |
| Tag da imagem do contêiner da carga de trabalho. |
| A conta de serviço que tem permissão para acessar a VM confidencial que executa a carga de trabalho. |
| Nome da VM do cliente que executaria o aplicativo do cliente do servidor de inferência. |
| A conta de serviço usada pelo |
- Você vai precisar dos papéis de administrador do Storage, administrador do Artifact Registry, administrador do Cloud KMS, administrador da conta de serviço e administrador do pool de Identidade da carga de trabalho do IAM para o projeto
$PRIMUS_PROJECT_ID
. Consulte este guia para saber como conceder papéis do IAM usando o console do GCP. - Para
$PRIMUS_PROJECT_ID
, execute o script abaixo para definir os nomes das variáveis restantes como valores com base no ID do projeto para nomes de recursos.
source config_env.sh
Configurar recursos da Primus Company
Nesta etapa, você vai configurar os recursos de nuvem necessários para o Primus. Execute o script abaixo para configurar os recursos do Primus. Os seguintes recursos serão criados como parte da execução do script:
- Chave de criptografia (
$PRIMUS_ENC_KEY
) e chaveiro ($PRIMUS_ENC_KEYRING
) no KMS para criptografar o arquivo de dados do cliente da empresa Primus. - Pool de Identidade da carga de trabalho (
$PRIMUS_WORKLOAD_IDENTITY_POOL
) para validar declarações com base nas condições de atributos configuradas no provedor. - A conta de serviço (
$PRIMUS_SERVICE_ACCOUNT
) anexada ao pool de identidade de carga de trabalho ($PRIMUS_WORKLOAD_IDENTITY_POOL
) mencionado acima tem acesso para descriptografar dados usando a chave KMS (usando o papelroles/cloudkms.cryptoKeyDecrypter
), criptografar dados usando a chave KMS (usando o papelroles/cloudkms.cryptoKeyEncrypter
), ler dados do bucket de armazenamento em nuvem (usando o papelobjectViewer
) e conectar a conta de serviço ao pool de identidade de carga de trabalho (usandoroles/iam.workloadIdentityUser
).
./setup_primus_resources.sh
3. Criar carga de trabalho
Criar uma conta de serviço de carga de trabalho
Agora, você vai criar uma conta de serviço para a carga de trabalho com as funções e permissões necessárias. Execute o script abaixo para criar uma conta de serviço de carga de trabalho no projeto Primus. Essa conta de serviço seria usada pela VM que executa o servidor de inferência.
Essa conta de serviço de carga de trabalho ($WORKLOAD_SERVICEACCOUNT
) terá as seguintes funções:
confidentialcomputing.workloadUser
para receber um token de atestadologging.logWriter
para gravar registros no Cloud Logging.
./create_workload_service_account.sh
Criar carga de trabalho
Nesta etapa, você vai criar uma imagem do Docker de carga de trabalho. A carga de trabalho seria criada pela empresa Primus. A carga de trabalho usada neste codelab é um código Python que usa o modelo codegemma do bucket do GCS disponível publicamente (do jardim de modelos de vértices). A carga de trabalho vai carregar o modelo de codegemma e iniciar o servidor de inferência, que vai atender às solicitações de geração de código dos desenvolvedores do Primus.
Na solicitação de geração de código, a carga de trabalho vai receber a DEK encapsulada com uma solicitação criptografada. A carga de trabalho vai fazer a chamada da API do KMS para descriptografar a DEK e, em seguida, descriptografar o prompt usando essa DEK. As chaves de criptografia (para chaves de criptografia de dados) seriam protegidas pelo pool de identidade da carga de trabalho, e o acesso seria concedido às cargas de trabalho que atendem às condições de atributo. Essas condições de atributo são descritas em mais detalhes na próxima seção sobre como autorizar a carga de trabalho. Quando o servidor de inferência tiver a solicitação descriptografada, ele vai gerar o código usando um modelo carregado e retornar a resposta.
Execute o script abaixo para criar uma carga de trabalho em que as etapas a seguir estão sendo realizadas:
- Crie o Artifact Registry(
$PRIMUS_ARTIFACT_REGISTRY
) de propriedade da Primus. - Atualize o código da carga de trabalho com os nomes dos recursos necessários.
- Crie a carga de trabalho do servidor de inferência e o Dockerfile para criar uma imagem do Docker do código da carga de trabalho. Este é o Dockerfile usado neste codelab.
- Crie e publique a imagem do Docker no Artifact Registry (
$PRIMUS_ARTIFACT_REGISTRY
) de propriedade da Primus. - Conceda a permissão de leitura
$WORKLOAD_SERVICEACCOUNT
para$PRIMUS_ARTIFACT_REGISTRY
. Isso é necessário para que o contêiner da carga de trabalho extraia a imagem do Docker da carga de trabalho do Artifact Registry.
./create_workload.sh
Para sua referência, aqui está o método generate() da carga de trabalho criada e usada neste codelab. Você pode encontrar o código completo da carga de trabalho aqui.
def generate():
try:
data = request.get_json()
ciphertext = base64.b64decode(data["ciphertext"])
wrapped_dek = base64.b64decode(data["wrapped_dek"])
unwrapped_dek_response = kms_client.decrypt(
request={"name": key_name, "ciphertext": wrapped_dek}
)
unwrapped_dek = unwrapped_dek_response.plaintext
f = Fernet(unwrapped_dek)
plaintext = f.decrypt(ciphertext)
prompt = plaintext.decode("utf-8")
tokens = tokenizer(prompt, return_tensors="pt")
outputs = model.generate(**tokens, max_new_tokens=128)
generated_code = tokenizer.decode(outputs[0])
generated_code_bytes = generated_code.encode("utf-8")
response = f.encrypt(generated_code_bytes)
ciphertext_base64 = base64.b64encode(response).decode("utf-8")
response = {"generated_code_ciphertext": ciphertext_base64}
return jsonify(response)
except (ValueError, TypeError, KeyError) as e:
return jsonify({"error": str(e)}), 500
4. Autorizar e executar a carga de trabalho
Autorizar a carga de trabalho
A Primus quer autorizar cargas de trabalho a acessar a chave do KMS usada para criptografia imediata com base nos atributos dos seguintes recursos:
- O que é: código verificado
- Onde: um ambiente seguro
- Quem: um operador confiável
O Primus usa a federação de identidade da carga de trabalho para aplicar uma política de acesso com base nesses requisitos. A federação de identidade da carga de trabalho permite especificar condições de atributo. Essas condições restringem quais identidades podem ser autenticadas com o pool de identidade da carga de trabalho (WIP, na sigla em inglês). É possível adicionar o serviço de verificação de atestados ao WIP como um provedor de pool de identidade da carga de trabalho para apresentar medições e aplicar a política.
O pool de Identidade da carga de trabalho já foi criado anteriormente como parte da etapa de configuração dos recursos da nuvem. Agora, o Primus vai criar um novo provedor de pool de identidade de carga de trabalho do OIDC. O --attribute-condition
especificado autoriza o acesso ao contêiner de carga de trabalho. Ela requer:
- O quê: o
$WORKLOAD_IMAGE_NAME
mais recente foi enviado por upload para o repositório$PRIMUS_ARTIFACT_REPOSITORY
. - Onde: o ambiente de execução confiável do Confidential Space está em execução na imagem de VM do Confidential Space com suporte total.
- Quem: conta de serviço
$WORKLOAD_SERVICE_ACCOUNT
da Primus.
export WORKLOAD_IMAGE_DIGEST=$(gcloud artifacts docker images describe ${PRIMUS_PROJECT_REPOSITORY_REGION}-docker.pkg.dev/$PRIMUS_PROJECT_ID/$PRIMUS_ARTIFACT_REPOSITORY/$WORKLOAD_IMAGE_NAME:$WORKLOAD_IMAGE_TAG --format="value(image_summary.digest)" --project ${PRIMUS_PROJECT_ID})
gcloud iam workload-identity-pools providers create-oidc $PRIMUS_WIP_PROVIDER \
--location="global" \
--project="$PRIMUS_PROJECT_ID" \
--workload-identity-pool="$PRIMUS_WORKLOAD_IDENTITY_POOL" \
--issuer-uri="https://confidentialcomputing.googleapis.com/" \
--allowed-audiences="https://sts.googleapis.com" \
--attribute-mapping="google.subject='assertion.sub'" \
--attribute-condition="assertion.swname == 'HARDENED_SHIELDED' && assertion.hwmodel == 'GCP_SHIELDED_VM' &&
assertion.submods.container.image_digest == '${WORKLOAD_IMAGE_DIGEST}' &&
assertion.submods.container.image_reference == '${PRIMUS_PROJECT_REPOSITORY_REGION}-docker.pkg.dev/$PRIMUS_PROJECT_ID/$PRIMUS_ARTIFACT_REPOSITORY/$WORKLOAD_IMAGE_NAME:$WORKLOAD_IMAGE_TAG' &&
'$WORKLOAD_SERVICEACCOUNT@$PRIMUS_PROJECT_ID.iam.gserviceaccount.com' in assertion.google_service_accounts"
O comando acima verifica se a carga de trabalho está sendo executada em um ambiente de espaço confiável, conferindo se hwmodel
está definido como "GCP_SHIELDED_VM" e swname
está definido como "HARDENED_SHIELDED". Além disso, ele inclui declarações específicas da carga de trabalho, como image_digest
e image_reference
, para melhorar a segurança e garantir a integridade da carga de trabalho em execução.
Executar carga de trabalho
Nesta etapa, vamos executar a carga de trabalho na VM do espaço confiável, que terá um acelerador anexado. Os argumentos necessários do TEE são transmitidos usando a flag de metadados. Os argumentos para o contêiner de carga de trabalho são transmitidos usando a parte "tee-cmd
" da flag. Para equipar a VM de carga de trabalho com uma GPU Nvidia Tesla T4, usaremos a flag --accelerator=type=nvidia-tesla-t4,count=1
. Isso vai anexar uma GPU à VM. Também precisamos incluir tee-install-gpu-driver=true
nas flags de metadados para acionar a instalação do driver de GPU apropriado.
gcloud compute instances create ${WORKLOAD_VM} \
--accelerator=type=nvidia-tesla-t4,count=1 \
--machine-type=n1-standard-16 \
--shielded-secure-boot \
--image-project=conf-space-images-preview \
--image=confidential-space-0-gpupreview-796705b \
--zone=${PRIMUS_PROJECT_ZONE} \
--maintenance-policy=TERMINATE \
--boot-disk-size=40 \
--scopes=cloud-platform \
--service-account=${WORKLOAD_SERVICEACCOUNT}@${PRIMUS_PROJECT_ID}.iam.gserviceaccount.com \
--metadata="^~^tee-image-reference=${PRIMUS_PROJECT_REPOSITORY_REGION}-docker.pkg.dev/${PRIMUS_PROJECT_ID}/${PRIMUS_ARTIFACT_REPOSITORY}/${WORKLOAD_IMAGE_NAME}:${WORKLOAD_IMAGE_TAG}~tee-install-gpu-driver=true~tee-restart-policy=Never"
Executar consulta de inferência
Depois que o servidor de inferência de carga de trabalho é iniciado, os funcionários da empresa Primus podem enviar as solicitações de geração de código para o servidor de inferência.
Como parte deste codelab, usaremos o script a seguir para configurar o aplicativo cliente que interage com o servidor de inferência. Execute este script para configurar a VM do cliente.
./setup_client.sh
As etapas a seguir demonstram como fazer SSH na VM do cliente e executar um aplicativo de exemplo em um ambiente virtual do Python. Este aplicativo de exemplo usa a criptografia de envelope com a biblioteca Fernet, mas lembre-se de que as bibliotecas de criptografia específicas podem ser adaptadas para diferentes casos de uso.
gcloud compute ssh ${CLIENT_VM} --zone=${PRIMUS_PROJECT_ZONE}
Execute os comandos abaixo para ativar o ambiente virtual do Python na VM cliente e executar o aplicativo cliente.
source venv/bin/activate
python3 inference_client.py
A saída deste aplicativo de exemplo mostra as solicitações de texto simples e criptografia e as respostas criptografadas e descriptografadas correspondentes.
5. Limpeza
Este é o script que pode ser usado para limpar os recursos criados como parte deste codelab. Como parte dessa limpeza, os seguintes recursos serão excluídos:
- Conta de serviço Primus (
$PRIMUS_SERVICEACCOUNT
). - Chave de criptografia Primus (
$PRIMUS_ENC_KEY
). - Repositório de artefatos do Primus (
$PRIMUS_ARTIFACT_REPOSITORY
). - Pool de identidade de carga de trabalho Primus (
$PRIMUS_WORKLOAD_IDENTITY_POOL
) com o provedor. - Conta de serviço de carga de trabalho do Primus (
$WORKLOAD_SERVICEACCOUNT
). - VM de carga de trabalho (
$WORKLOAD_VM
) e VM de cliente ($CLIENT_VM
).
./cleanup.sh
Se você já terminou de explorar, considere excluir seu projeto.
- Acesse o Console do Cloud Platform.
- Selecione o projeto que você quer encerrar e clique em "Excluir" na parte de cima. Isso vai programar o projeto para exclusão.