1. Visão geral
Tudo pronto para aumentar a segurança e a privacidade das cargas de trabalho aceleradas por GPU? Este codelab vai orientar você pelas funcionalidades do Trusted Space, uma oferta para fornecer isolamento de operador forte e suporte de acelerador 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 garantindo que as cargas de trabalho operem em um ambiente seguro e confiável em que nem mesmo o operador da carga de trabalho tenha 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 valiosos) permanecem protegidos, com suporte de prova criptográfica.
- Isolamento do operador:elimine as preocupações com a interferência do operador. Com o Trusted Space, nem mesmo os operadores da carga de trabalho têm acesso, impedindo que eles façam SSH, acessem dados, instalem software ou adulterem seu código.
- Suporte de 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 críticos para a performance 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 recursos valiosos da 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 atributos.
- Conhecimento básico de contêineres e do Artifact Registry
Como proteger comandos 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 nas tarefas de programação. No entanto, eles estão preocupados em proteger a confidencialidade dos comandos enviados pelos funcionários, já que esses comandos geralmente contêm snippets de código sensíveis, detalhes internos do projeto 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 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 com "necessidade de saber" que a Primus Corp quer proteger.
Para resolver essa preocupação, a Primus Corp vai aproveitar 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, em que a chave de descriptografia correspondente está disponível, possa descriptografá-lo 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 (por exemplo, tink). Como parte deste codelab, vamos usar este aplicativo cliente de amostra com criptografia de envelope.
- Isolamento do operador:apenas 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 será 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 será iniciado em uma VM protegida (como parte da configuração do Trusted Space), o que garante que a instância da carga de trabalho não tenha sido 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 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 deste 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 mais detalhes sobre 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 seus projetos.
- Ative a API Computação confidencial e as seguintes APIs 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 também usar recursos atuais, se eles já tiverem sido criados. (por exemplo,
export PRIMUS_SERVICE_ACCOUNT='my-service-account')
- É possível definir as seguintes variáveis com nomes de recursos do Cloud atuais no projeto da Primus. Se a variável estiver definida, o recurso do Cloud correspondente do projeto da Primus será usado. Se a variável não estiver definida, o nome do recurso do Cloud será gerado com base no nome do projeto, e um novo recurso do Cloud será criado com esse nome. Confira as variáveis compatíveis para nomes de recursos:
| Região em que os recursos regionais serão criados para a empresa Primus. |
| Local em que os recursos serão criados para a empresa Primus. |
| Zona em que os recursos zonais serão criados para a empresa Primus. |
| Pool de identidade da carga de trabalho da empresa Primus para proteger os recursos do Cloud. |
| Provedor do 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 atestado. |
| Conta de serviço da empresa Primus que |
| 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 do 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 da 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 cliente do servidor de inferência. |
| A conta de serviço usada pela |
- Você vai precisar das funções 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 o
$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 recursos da Primus Company
Como parte desta etapa, você vai configurar os recursos do Cloud necessários para a Primus. Execute o script a seguir para configurar os recursos da Primus. Os seguintes recursos serão criados como parte da execução do script:
- Chave de criptografia (
$PRIMUS_ENC_KEY) e keyring ($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 da carga de trabalho mencionado acima ($PRIMUS_WORKLOAD_IDENTITY_POOL) tem acesso para descriptografar dados usando a chave do KMS (usando o papelroles/cloudkms.cryptoKeyDecrypter), criptografar dados usando a chave do KMS (usando o papelroles/cloudkms.cryptoKeyEncrypter), ler dados do bucket do Cloud Storage (usando o papelobjectViewer) e conectar a conta de serviço ao pool de identidade da carga de trabalho (usandoroles/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 permissões necessários. Execute o script a seguir para criar uma conta de serviço da carga de trabalho no projeto da Primus. Essa conta de serviço será 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 da carga de trabalho. A carga de trabalho será 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 modelo de jardim do Vertex). A carga de trabalho vai carregar o modelo codegemma e iniciar o servidor de inferência que atenderá às solicitações de geração de código dos desenvolvedores da Primus.
Na solicitação de geração de código, a carga de trabalho vai receber a DEK encapsulada junto com um comando criptografado. Em seguida, a carga de trabalho vai fazer a chamada de API KMS para descriptografar a DEK e, em seguida, descriptografar o comando usando essa DEK. As chaves de criptografia (para DEK) serão protegidas pelo pool de identidade da carga de trabalho, e o acesso será concedido às cargas de trabalho que atendem às condições de atributos. Essas condições de atributos são descritas com mais detalhes na próxima seção sobre como autorizar a 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 seguinte script 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 de recursos necessários.
- Crie a carga de trabalho do servidor de inferência e crie o Dockerfile para criar uma imagem Docker do código da carga de trabalho. Confira 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 Docker da carga de trabalho do Artifact Registry.
./create_workload.sh
Para sua referência, confira o método generate() da carga de trabalho criada e usada neste codelab (o código completo da carga de trabalho está disponível 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 para 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
A 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 atributos. Essas condições restringem quais identidades podem ser autenticadas com o pool de identidade 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 identidade da carga de trabalho já foi criado anteriormente como parte da etapa de configuração dos recursos do Cloud. Agora, a Primus vai criar um novo provedor de pool de identidade da carga de trabalho do OIDC. A --attribute-condition especificada autoriza o acesso ao contêiner da carga de trabalho. Ela requer:
- O quê:
$WORKLOAD_IMAGE_NAMEmais recente enviado ao 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 totalmente compatível.
- Quem: conta de serviço
$WORKLOAD_SERVICE_ACCOUNTda 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á em execução em um ambiente de espaço confiável, verificando 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 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 de TEE necessários são transmitidos usando a flag de metadados. Os argumentos do contêiner da carga de trabalho são transmitidos usando a parte "tee-cmd" da flag. Para equipar a VM da 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 será necessário 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 da carga de trabalho for iniciado, os funcionários da empresa Primus poderão enviar as solicitações de geração de código para o servidor de inferência.
Como parte deste codelab, vamos usar o script a seguir para configurar o aplicativo cliente que vai interagir com o servidor de inferência. Execute esse 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 cliente de amostra 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 atender a 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 desse aplicativo cliente de amostra vai mostrar as solicitações de criptografia e de comandos de texto simples e as respostas criptografadas e descriptografadas correspondentes.
5. Limpeza
Aqui está o script que pode ser usado para liberar espaço dos recursos que criamos como parte deste codelab. Como parte dessa limpeza, os seguintes recursos serão excluídos:
- Conta de serviço da Primus (
$PRIMUS_SERVICEACCOUNT). - Chave de criptografia da Primus (
$PRIMUS_ENC_KEY). - Repositório de artefatos da Primus (
$PRIMUS_ARTIFACT_REPOSITORY). - Pool de identidade da carga de trabalho da Primus (
$PRIMUS_WORKLOAD_IDENTITY_POOL) com o provedor. - Conta de serviço da carga de trabalho da Primus (
$WORKLOAD_SERVICEACCOUNT). - VM da carga de trabalho (
$WORKLOAD_VM) e VM do cliente ($CLIENT_VM).
./cleanup.sh
Se você já terminou de explorar, exclua o projeto.
- Acesse o console do Cloud Platform.
- Selecione o projeto que você quer desligar e clique em "Excluir" na parte de cima: isso programa o projeto para exclusão.