1. Visão geral
Tudo pronto para aumentar a segurança e a privacidade das suas cargas de trabalho aceleradas por GPU? Este codelab vai mostrar os recursos do Trusted Space, uma oferta que fornece isolamento robusto do operador e suporte a aceleradores para suas cargas de trabalho sensíveis de IA/ML.
Nunca foi tão importante proteger dados, modelos e chaves valiosos. O Trusted Space oferece uma solução garantindo que suas cargas de trabalho operem em um ambiente seguro e confiável, em que nem mesmo o operador da carga de trabalho tem acesso.
Confira o que o Trusted Space oferece:
- Privacidade e segurança aprimoradas:o Trusted Space oferece um ambiente de execução confiável em que seus recursos sensíveis (por exemplo, modelos, dados e chaves valiosas) permanecem protegidos, com suporte de comprovação criptográfica.
- Isolamento do operador:elimina preocupações com a interferência do operador. Com o Trusted Space, nem mesmo os operadores de carga de trabalho têm acesso, o que impede que eles façam SSH, acessem dados, instalem software ou adulterem seu código.
- Suporte a aceleradores: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 funcionem sem problemas.
O que você vai aprender
- Entenda as principais ofertas do Trusted Space.
- Saiba como implantar e configurar um ambiente do Trusted Space para proteger 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 contêineres e do Artifact Registry
Proteção de solicitações sensíveis de geração de código 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 com as tarefas de programação. No entanto, eles se preocupam em proteger a confidencialidade dos comandos enviados pelos funcionários, já que eles geralmente contêm snippets de código sensíveis, detalhes de projetos internos ou algoritmos proprietários.
Por que a Primus Company não confia no operador?
A Primus Corp opera em um mercado altamente competitivo. A base de código deles contém propriedade intelectual valiosa, incluindo algoritmos proprietários e snippets de código sensíveis que oferecem uma vantagem competitiva. Eles estão preocupados com a possibilidade de espionagem corporativa por operadores de carga de trabalho. Além disso, os comandos dos funcionários podem incluir partes confidenciais do código "Need To Know" que a Primus Corp quer proteger.
Para resolver esse problema, a Primus Corp vai usar o Trusted Space para isolar o servidor de inferência que executa o modelo de geração de código. Veja como funciona:
- Criptografia de comandos:antes de enviar um comando ao servidor de inferência, cada funcionário vai criptografá-lo usando uma chave do KMS gerenciada pela Primus Corp no Google Cloud. Isso garante que apenas o ambiente do Trusted Space, onde a chave de descriptografia correspondente está disponível, possa descriptografar e acessar o comando de texto simples. Em um cenário real, a criptografia do lado do cliente pode ser processada pelas bibliotecas disponíveis, como tink. Como parte deste codelab, vamos usar este aplicativo cliente de exemplo 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 o comando 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 garante 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 Trusted Space, realiza a inferência usando o modelo de geração de código e retorna o código gerado para o 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 deste codelab.
cd confidential-space/codelabs/trusted_space_codelab/scripts
- Verifique se você definiu as variáveis de ambiente necessárias do projeto, 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 a diferença entre ele, o nome e o 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 seguintes APIs nos 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 seguinte comando. Essas variáveis permitem personalizar os nomes dos recursos conforme necessário e usar os recursos existentes, se já tiverem sido criados. (por exemplo,
export PRIMUS_SERVICE_ACCOUNT='my-service-account')
- É possível definir as seguintes variáveis com nomes de recursos de nuvem existentes no projeto do Primus. Se a variável estiver definida, o recurso de nuvem correspondente do projeto Primus será usado. Se a variável não estiver definida, o nome do recurso de nuvem será gerado com base no nome do projeto, e um novo recurso de nuvem será criado com esse nome. Estas são as variáveis compatíveis com 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. |
| Provedor de pool de identidades da carga de trabalho da empresa Primus, que inclui a condição de autorização para usar tokens assinados pelo serviço de verificação de atestado. |
| Conta de serviço da empresa Primus que o |
| A chave do KMS é usada para criptografar os comandos fornecidos pelos funcionários da empresa Primus. |
| O keyring do KMS que será usado para criar a chave de criptografia |
| A versão da chave do KMS da chave de criptografia |
| O repositório de artefatos em que a imagem Docker 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 Docker da carga de trabalho. |
| Tag da imagem do contêiner de carga de trabalho. |
| A conta de serviço com permissão para acessar a VM confidencial que executa a carga de trabalho. |
| Nome da VM do cliente que executaria o aplicativo 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 sobre como conceder papéis do IAM usando o console do GCP. - Para
$PRIMUS_PROJECT_ID, execute o script a seguir para definir os nomes de variáveis restantes como valores com base no ID do projeto para nomes de recursos.
source config_env.sh
Configurar os recursos da empresa Primus
Como parte desta etapa, você vai configurar os recursos de nuvem necessários para o Primus. Execute o script a seguir 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 identidades 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 identidades da carga de trabalho ($PRIMUS_WORKLOAD_IDENTITY_POOL) mencionado acima tem acesso para descriptografar dados usando a chave do KMS (com a funçãoroles/cloudkms.cryptoKeyDecrypter), criptografar dados usando a chave do KMS (com a funçãoroles/cloudkms.cryptoKeyEncrypter), ler dados do bucket do Cloud Storage (com a funçãoobjectViewer) e conectar a conta de serviço ao pool de identidades da carga de trabalho (com a funçãoroles/iam.workloadIdentityUser).
./setup_primus_resources.sh
3. Criar carga de trabalho
Criar conta de serviço da carga de trabalho
Agora, você vai criar uma conta de serviço para a carga de trabalho com os papéis e as permissões necessários. Execute o seguinte script 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 da carga de trabalho ($WORKLOAD_SERVICEACCOUNT) terá os seguintes papéis:
confidentialcomputing.workloadUserpara receber um token de atestadologging.logWriterpara gravar registros no Cloud Logging.
./create_workload_service_account.sh
Criar carga de trabalho
Como parte desta 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 público do GCS (do jardim de modelos da Vertex). A carga de trabalho vai carregar o modelo do 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 e um comando criptografado. Em seguida, a carga de trabalho fará a chamada da API KMS para descriptografar a DEK e o comando usando essa DEK. As chaves de criptografia (para DEK) 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 autorização da carga de trabalho. Depois que o servidor de inferência tiver o comando descriptografado, ele vai gerar o código usando um modelo carregado e retornar a resposta.
Execute o script a seguir para criar uma carga de trabalho em que as seguintes etapas 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 crie o Dockerfile para criar uma imagem do Docker do código da carga de trabalho. Aqui está o Dockerfile usado neste codelab.
- Crie e publique a imagem Docker no Artifact Registry (
$PRIMUS_ARTIFACT_REGISTRY) de propriedade da Primus. - Conceda permissão de leitura
$WORKLOAD_SERVICEACCOUNTpara$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 carga de trabalho
A Primus quer autorizar cargas de trabalho a acessar a chave do KMS usada para criptografia de comandos com base nos atributos dos seguintes recursos:
- O quê: 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. Com a federação de identidade da carga de trabalho, é possível especificar condições de atributo. Essas condições restringem quais identidades podem ser autenticadas com o pool de identidades da carga de trabalho (WIP). É possível adicionar o serviço de verificação de atestado 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 identidades de carga de trabalho já foi criado como parte da etapa de configuração dos recursos da nuvem. Agora, o Primus vai criar um provedor de pool de identidades de carga de trabalho OIDC. O --attribute-condition especificado autoriza o acesso ao contêiner da carga de trabalho. Ela requer:
- O quê: o
$WORKLOAD_IMAGE_NAMEmais recente foi enviado por upload para o repositório$PRIMUS_ARTIFACT_REPOSITORY. - Onde: o ambiente de execução confiável do Confidential Space está sendo executado na imagem de VM do Confidential Space totalmente compatível.
- Quem: conta de serviço do Primus
$WORKLOAD_SERVICE_ACCOUNT.
export WORKLOAD_IMAGE_DIGEST=$(gcloud artifacts docker images describe ${PRIMUS_PROJECT_REPOSITORY_REGION}-docker.pkg.dev/$PRIMUS_PROJECT_ID/$PRIMUS_ARTIFACT_REPOSITORY/$WORKLOAD_IMAGE_NAME:$WORKLOAD_IMAGE_TAG --format="value(image_summary.digest)" --project ${PRIMUS_PROJECT_ID})
gcloud iam workload-identity-pools providers create-oidc $PRIMUS_WIP_PROVIDER \
--location="global" \
--project="$PRIMUS_PROJECT_ID" \
--workload-identity-pool="$PRIMUS_WORKLOAD_IDENTITY_POOL" \
--issuer-uri="https://confidentialcomputing.googleapis.com/" \
--allowed-audiences="https://sts.googleapis.com" \
--attribute-mapping="google.subject='assertion.sub'" \
--attribute-condition="assertion.swname == 'HARDENED_SHIELDED' && assertion.hwmodel == 'GCP_SHIELDED_VM' &&
assertion.submods.container.image_digest == '${WORKLOAD_IMAGE_DIGEST}' &&
assertion.submods.container.image_reference == '${PRIMUS_PROJECT_REPOSITORY_REGION}-docker.pkg.dev/$PRIMUS_PROJECT_ID/$PRIMUS_ARTIFACT_REPOSITORY/$WORKLOAD_IMAGE_NAME:$WORKLOAD_IMAGE_TAG' &&
'$WORKLOAD_SERVICEACCOUNT@$PRIMUS_PROJECT_ID.iam.gserviceaccount.com' in assertion.google_service_accounts"
O comando acima verifica se a carga de trabalho está sendo executada em um ambiente de espaço confiável. Para isso, ele verifica se hwmodel está definido como "GCP_SHIELDED_VM" e swname como "HARDENED_SHIELDED". Além disso, ele inclui declarações específicas da carga de trabalho, como image_digest e image_reference, para aumentar a segurança e garantir a integridade da carga de trabalho em execução.
Executar carga de trabalho
Como parte desta etapa, vamos executar a carga de trabalho na VM do Trusted Space, 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, vamos usar 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 adequado.
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 for iniciado, os funcionários da empresa Primus poderão enviar solicitações de geração de código para ele.
Como parte deste codelab, vamos usar o seguinte script para configurar o aplicativo cliente que vai interagir com o servidor de inferência. Execute este script para configurar a VM do cliente.
./setup_client.sh
As etapas a seguir mostram como fazer SSH na VM do cliente e executar um aplicativo cliente de exemplo em um ambiente virtual Python. Este aplicativo de exemplo usa 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 a seguir para ativar o ambiente virtual do Python na VM do cliente e executar o aplicativo cliente.
source venv/bin/activate
python3 inference_client.py
A saída deste aplicativo cliente de exemplo vai mostrar as solicitações de criptografia e texto simples e as respostas criptografadas e descriptografadas correspondentes.
5. Limpeza
Aqui está 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 do Primus (
$PRIMUS_SERVICEACCOUNT). - Chave de criptografia do Primus (
$PRIMUS_ENC_KEY). - Repositório de artefatos do Primus (
$PRIMUS_ARTIFACT_REPOSITORY). - Pool de identidade da carga de trabalho do 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 o projeto.
- Acesse o Console do Cloud Platform.
- Selecione o projeto que você quer encerrar e clique em "Excluir" na parte de cima. Isso programa a exclusão do projeto.