Criar e personalizar cargas de trabalho


Uma carga de trabalho é criada por um autor e processa os dados confidenciais com que os colaboradores de dados querem trabalhar.

Um autor de carga de trabalho precisa reunir os seguintes recursos para criar uma carga de trabalho:

  • Um aplicativo para processar os dados confidenciais. Você pode escrever seu aplicativo em qualquer linguagem que escolher, desde que crie uma imagem em contêiner que a ofereça suporte.

  • Uma imagem conteinerizada para empacotar o aplicativo usando o Docker.

  • Um repositório no Artifact Registry para armazenar a imagem do Docker.

  • As políticas de execução definidas na imagem do contêiner controlam como uma carga de trabalho pode ser executada e restringem a capacidade de um operador de carga de trabalho malicioso.

Para implantar a carga de trabalho, uma VM confidencial é executada por um operador de carga de trabalho com base na imagem do Confidential Space. Isso recupera a imagem contêinerizada do Artifact Registry e a executa.

Os colaboradores de dados precisam validar as declarações de uma carga de trabalho antes de acessar os dados.

Antes de começar

Escrever uma carga de trabalho para o Confidential Space é mais do que apenas código e depuração. Você também precisa conversar com colaboradores de dados para avaliar as necessidades deles, configurar seu ambiente, empacotar seu código em uma imagem contêinerizada e trabalhar com um operador de carga de trabalho para garantir que tudo seja implantado corretamente.

Converse com os colaboradores de dados

Antes de começar a escrever seu aplicativo, converse com seus colaboradores de dados sobre os dados particulares que eles querem que você trabalhe. Você pode fazer perguntas como:

  • Quais são os IDs das organizações envolvidas?

  • Quais são os números dos projetos envolvidos?

  • Quais são os recursos Google Cloud que preciso acessar e quais são os IDs e nomes deles?

  • Há recursos que preciso acessar que não são gerenciados pelo Google Cloud IAM?

  • Como o aplicativo deve comparar e processar os dados particulares?

  • Em qual formato a saída deve estar?

  • Onde a saída deve ser armazenada e ela precisa ser criptografada?

  • Todos os colaboradores de dados estão vendo o mesmo resultado, ou as saídas são exclusivas para cada um?

Além disso, cada colaborador de dados também pode ter requisitos de privacidade exclusivos que você precisa atender. É muito importante que nenhum dado particular seja exposto como resultado de uma carga de trabalho.

Criar sua solução do Confidential Space

É útil configurar dois (ou mais) projetos com as permissões adequadas como um ambiente de teste, como em Criar seu primeiro ambiente do Confidential Space. Tente espelhar as configurações de projeto dos colaboradores de dados da melhor forma possível. Assim, você ganha experiência com permissões entre projetos e recupera os dados necessários de recursos específicos do Google Cloud . Ele também pode dar uma ideia das funções de operador de carga de trabalho e colaborador de dados e das responsabilidades delas.

Durante a fase inicial de criação, é útil observar as seguintes práticas:

  • Ao trabalhar como colaborador de dados, mantenha a validação de atestado no mínimo para aumentar a velocidade de desenvolvimento.

  • Ao trabalhar como operador de carga de trabalho, use a imagem de depuração do Confidential Space em vez da produção ao implantar a carga de trabalho. Isso oferece mais maneiras de resolver problemas na carga de trabalho.

À medida que o aplicativo amadurece e o estado dele se torna mais previsível, é possível bloquear cada vez mais a solução com validação de atestado e políticas de lançamento, além de mudar para a imagem de produção do Confidential Space.

Depois que sua carga de trabalho estiver funcionando corretamente no ambiente de teste, você poderá mudar para testes nos projetos dos colaboradores de dados com recursos reais, mas dados falsos. Assim, você pode demonstrar aos colaboradores de dados como tudo funciona. Nesse momento, você pode começar a trabalhar com um operador de carga de trabalho independente.

Quando tudo estiver funcionando e a saída for a esperada, comece a testar com dados de produção. Depois que o teste for concluído e todas as partes aprovarem os resultados, a carga de trabalho estará pronta para ser colocada em produção.

Ter cuidado com a saída

Ao testar seu código, pode ser tentador depurar imprimindo em STDOUT ou STDERR. Se você optar por fazer isso, tome cuidado para não expor dados particulares que outras partes possam ler ao acessar os registros. Antes de o código começar a funcionar na produção, verifique se ele não está gerando nada além do que é estritamente necessário.

O mesmo vale para a saída final. Forneça apenas um resultado final que não comprometa a privacidade e a sensibilidade dos dados originais.

Criar uma imagem conteinerizada com o Docker

Os aplicativos precisam ser empacotados em uma imagem em contêiner criada pelo Docker, que é armazenada no Artifact Registry. Quando uma carga de trabalho é implantada, a imagem do Docker é extraída do repositório do Artifact Registry pela imagem e execução do Confidential Space, e o aplicativo pode começar a trabalhar nos recursos apropriados do projeto.

Ao criar a imagem do Docker, considere o seguinte:

Outros recursos do Linux

A carga de trabalho do Confidential Space é executada em um contêiner do Linux usando o containerd. Esse contêiner é executado usando recursos padrão do Linux.

Para adicionar recursos, use tee-added-capabilities.

Limites de disco e memória

O Confidential Space redimensiona automaticamente a partição com estado do disco de inicialização ao usar tamanhos maiores de disco de inicialização. O tamanho da partição é aproximadamente o tamanho do disco de inicialização menos 5 GB.

Como parte das proteções do sistema de arquivos de integridade do Confidential Space, ele armazena tags de integridade do disco na memória. Isso usa aproximadamente 1% de sobrecarga de memória para cada byte de disco. Por exemplo, um disco de 100 GB requer 1 GB de memória e um disco de 10 TB requer 100 GB de memória.

Mantenha os limites de memória da VM. A troca de memória está desativada nas VMs do Confidential Space, o que significa que o uso excessivo de memória pode causar uma falha na carga de trabalho. Verifique se a seleção de máquina oferece suporte ao uso de memória da carga de trabalho, além da sobrecarga de integridade do disco.

Tokens OIDC expirados

Um token OIDC é disponibilizado para consumo pela carga de trabalho quando ela é iniciada. Ele contém declarações de atestado verificadas sobre a VM da carga de trabalho e é armazenado no contêiner de carga de trabalho em /run/container_launcher/attestation_verifier_claims_token. O token expira após 60 minutos.

Se o token expirar, uma atualização será feita em segundo plano usando a espera exponencial até ser bem-sucedida. Se uma atualização falhar (devido a problemas de rede, uma falha do serviço de atestado ou outra causa), o código da carga de trabalho precisará ser capaz de lidar com essa falha.

A carga de trabalho pode lidar com uma falha na atualização do token de uma das seguintes maneiras:

  • Ignorar o token expirado, supondo que ele não seja mais necessário após o uso inicial.

  • Aguardar a atualização do token expirado.

  • Sair da carga de trabalho.

Montagens de scratch na memória

O Confidential Space permite adicionar espaços de trabalho temporários na memória. Isso usa a memória disponível na VM do Confidential Space. Como o espaço de trabalho usa a memória da VM confidencial, ele tem as mesmas propriedades de integridade e confidencialidade da VM confidencial.

Use tee-dev-shm-size para aumentar o tamanho da montagem de memória compartilhada /dev/shm para a carga de trabalho. O tamanho /dev/shm é especificado em KB.

É possível usar tee-mount para especificar montagens tmpfs no contêiner em execução usando configurações separadas por ponto e vírgula. O type e o source são sempre tmpfs. O destination é o ponto de montagem, que interage com a política de inicialização tee.launch_policy.allow_mount_destinations. Opcionalmente, especifique o tamanho do tmpfs em bytes. O tamanho padrão é 50% da memória da VM.

Portas de entrada

Por padrão, as VMs do Confidential Space operam com uma regra de firewall para bloquear todas as portas de entrada. Ao usar a versão de imagem do Confidential Space 230600 ou superior, é possível especificar as portas de entrada que devem permanecer abertas no Dockerfile ao criar a imagem da carga de trabalho.

Para abrir portas, adicione a palavra-chave EXPOSE ao seu Dockerfile, com o número da porta que deve permanecer aberta e um protocolo opcional de tcp ou udp. Se você não especificar o protocolo para uma porta, ambos serão permitidos: TCP e UDP. Confira um exemplo de Dockerfile que expõe portas de entrada:

FROM alpine:latest
EXPOSE 80
EXPOSE 443/tcp
EXPOSE 81/udp
WORKDIR /test
COPY salary /test
ENTRYPOINT ["/test/salary"]
CMD []

Dependendo da imagem de base usada, algumas portas já podem estar expostas. Seu Dockerfile expõe apenas portas adicionais. Ele não pode bloquear portas que já foram abertas pela imagem de base.

Os operadores de carga de trabalho precisam verificar se as portas expostas estão abertas no firewall da VPC antes de executar a carga de trabalho. Os números de porta podem ser fornecidos pelo autor da carga de trabalho ou extraídos das informações da imagem Docker.

As portas expostas são registradas no console e redirecionadas para o Cloud Logging ao usar a variável de metadados tee-container-log-redirect.

Políticas de lançamento

As políticas de inicialização substituem as variáveis de metadados da VM definidas pelos operadores de carga de trabalho para restringir ações maliciosas. Um autor de carga de trabalho pode definir políticas com um rótulo como parte da criação da imagem do contêiner.

Por exemplo, em um Dockerfile:

LABEL "tee.launch_policy.allow_cmd_override"="true"

Em um arquivo BUILD do Bazel:

container_image(
    ...
    labels={"tee.launch_policy.allow_cmd_override":"true"}
    ...
)

As políticas de lançamento disponíveis estão na seguinte tabela:

Política Tipo Descrição

tee.launch_policy.allow_capabilities

Interage com:

Booleano (o padrão é false) Determina se o operador de carga de trabalho pode adicionar outros recursos do Linux ao contêiner de carga de trabalho.

tee.launch_policy.allow_cgroups

Interage com:

  • Operador de carga de trabalho: a variável de metadados tee-cgroup-ns.
Booleano (o padrão é false) Determina se o contêiner de carga de trabalho pode incluir uma montagem de cgroup com namespace em /sys/fs/cgroup.

tee.launch_policy.allow_cmd_override

Interage com:

Booleano (o padrão é false) Determina se o CMD especificado no Dockerfile do contêiner de carga de trabalho pode ser substituído por um operador de carga de trabalho com o valor de metadados tee-cmd.

tee.launch_policy.allow_env_override

Interage com:

String separada por vírgulas Uma string separada por vírgulas de nomes de variável de ambiente permitidas que podem ser definidas por um operador de carga de trabalho com valores de metadados tee-env-ENVIRONMENT_VARIABLE_NAME.

tee.launch_policy.allow_mount_destinations

Interage com:

  • Operador de carga de trabalho: a variável de metadados tee-mount.
String separada por dois-pontos

Uma string separada por dois pontos de diretórios de montagem permitidos que o operador de carga de trabalho pode montar usando tee-mount.

Por exemplo: /run/tmp:/var/tmp:/tmp

tee.launch_policy.log_redirect

Interage com:

String definida

Determina como a geração de registros funciona se tee-container-log-redirect for definido como true por um operador de carga de trabalho.

Os valores válidos são:

  • debugonly (padrão): só permite redirecionamentos de stdout e stderr ao usar uma imagem de depuração.
  • always: sempre permite redirecionamentos de stdout e stderr.
  • never: nunca permite redirecionamentos de stdout e stderr.

tee.launch_policy.monitoring_memory_allow

Interage com:

String definida

Determina como o monitoramento do uso de memória da carga de trabalho funciona se tee-memory-monitoring-enable for definido como true por um operador de carga de trabalho.

Os valores válidos são:

  • debugonly (padrão): só permite o monitoramento do uso de memória ao usar uma imagem de depuração.
  • always: sempre permitir o monitoramento do uso da memória.
  • never: nunca permitir o monitoramento do uso de memória.

Várias execuções de carga de trabalho

Para garantir um ambiente limpo, é preciso reiniciar uma VM para recomeçar uma carga de trabalho. Isso criptografa o disco da VM com uma chave temporária para lidar com o vetor de ataque da modificação de uma imagem de carga de trabalho no disco após o download e a medição.

Isso também adiciona sobrecargas, como tempo de inicialização e extração da imagem da carga de trabalho a cada execução da carga de trabalho. Se essas sobrecargas afetarem muito o desempenho da carga de trabalho, é possível codificar uma reinicialização para a própria carga de trabalho ao custo de aumentar seu perfil de risco.

Cgroups com namespace

Por padrão, a carga de trabalho do Confidential Space é executada sem uma montagem de cgroup.

Para gerenciar cgroups no contêiner de carga de trabalho, use tee-cgroup-ns. Isso vai criar uma montagem em /sys/fs/cgroup no sistema de arquivos do contêiner.

Imagens de contêiner reproduzíveis

Criar uma imagem de contêiner de maneira reproduzível pode ajudar a aumentar a confiança entre as partes. É possível criar imagens reproduzíveis com o Bazel.

Recursos não gerenciados pelo Google Cloud IAM

Para acessar recursos não gerenciados pelo IAM Google Cloud , sua carga de trabalho precisa especificar um público-alvo personalizado.

Para mais informações, consulte Acessar recursos não gerenciados pelo Google Cloud IAM.

Imagens de contêiner assinadas

É possível assinar uma imagem de contêiner com uma chave pública, que um colaborador de dados pode usar para atestado em vez de especificar um resumo de imagem na política de WIP.

Isso significa que os colaboradores de dados não precisam atualizar as políticas de WIP sempre que uma carga de trabalho é atualizada, e a carga de trabalho pode continuar acessando recursos protegidos sem interrupções.

É possível usar o Sigstore Cosign para assinar a imagem do contêiner. Para garantir que o Confidential Space possa buscar as assinaturas, os operadores de carga de trabalho precisam adicionar as informações de assinatura à variável de metadados tee-signed-image-repos antes de implantar a carga de trabalho.

Durante a execução, as assinaturas são enviadas ao serviço de atestado do Confidential Space para verificação. O serviço de atestado retorna um token de declarações de atestado que contém as declarações de assinatura verificadas. Confira um exemplo de reivindicação de assinatura:

"image_signatures": [
  {
    "key_id": "hexadecimal-sha256-fingerprint-public-key1",
    "signature": "base64-encoded-signature",
    "signature_algorithm": "RSASSA_PSS_SHA256"
  },
  {
    "key_id": "hexadecimal-sha256-fingerprint-public-key2",
    "signature": "base64-encoded-signature",
    "signature_algorithm": "RSASSA_PSS_SHA256",
  },
  {
    "key_id": "hexadecimal-sha256-fingerprint-public-key3",
    "signature": "base64-encoded-signature",
    "signature_algorithm": "RSASSA_PSS_SHA256",
  }
],

Para configurar a assinatura de imagens de contêiner, consulte o codelab de imagens de contêiner assinadas.