Criptografar Cloud Functions usando chaves de criptografia gerenciadas pelo cliente (CMEK)

1. Introdução

Visão geral

O Cloud Functions é uma solução de computação leve para desenvolvedores. Ele cria funções autônomas e de finalidade única que respondem a eventos do Cloud sem a necessidade de gerenciar um servidor ou um ambiente de execução.

É possível usar as chaves de criptografia gerenciadas pelo cliente (CMEK, na sigla em inglês) do Cloud Key Management Service para proteger o Cloud Functions e os dados em repouso relacionados. A implantação de uma função com uma CMEK protege os dados associados a ela usando uma chave de criptografia que está sob seu controle total. Esse tipo de criptografia permite que você atenda aos requisitos de conformidade em determinados setores, como serviços financeiros. Como a chave é de sua propriedade e não é controlada pelo Google, ninguém (incluindo você) pode acessar os dados protegidos por essas chaves de criptografia quando elas estão desativadas ou destruídas.

Para o Cloud Functions, a CMEK criptografa o seguinte:

  • Código-fonte da função enviado para implantação e armazenado pelo Google no Cloud Storage, usado no processo de build.
  • Os resultados do processo de build da função, incluindo a imagem do contêiner criada usando o código-fonte da função, cada instância da função implantada.
  • Dados em repouso para canais internos de transporte de eventos (somente na 1ª geração).

Saiba mais sobre quais dados são criptografados na documentação da CMEK do Cloud Functions.

O que você vai criar

Este codelab mostra como implantar uma função do Cloud (de 1ª ou 2ª geração) criptografada usando a CMEK. Este codelab usa uma função do Cloud pública, ou seja, uma que não exige autenticação, para fins de demonstração. É possível invocar uma função autenticada ativada para CMEK como qualquer outra função do Cloud que exija autenticação.

O que você vai aprender

  • Como criar uma chave CMEK em um keyring simétrico existente
  • Como criar um repositório do Artifact Registry
  • Como configurar a CMEK em uma função do Cloud para a 1ª e a 2ª geração

2. Configuração e requisitos

Pré-requisitos

  • Você fez login no console do Cloud.
  • Você já implantou uma função do Cloud acionada por HTTP (para verificar se você tem os papéis e as APIs adequados ativados).

Ativar o Cloud Shell

  1. No console do Cloud, clique em Ativar o Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Se esta for a primeira vez que você inicia o Cloud Shell, uma tela intermediária será exibida descrevendo o que ele é. Se você recebeu uma tela intermediária, clique em Continuar.

9c92662c6a846a5c.png

Leva apenas alguns instantes para provisionar e se conectar ao Cloud Shell.

9f0e51b578fecce5.png

Essa máquina virtual contém todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Neste codelab, quase todo o trabalho pode ser feito com um navegador.

Depois de se conectar ao Cloud Shell, você vai ver que sua conta está autenticada e que o projeto está configurado com o ID do seu projeto.

  1. Execute o seguinte comando no Cloud Shell para confirmar se a conta está autenticada:
gcloud auth list

Resposta ao comando

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Execute o seguinte comando no Cloud Shell para confirmar se o comando gcloud conhece seu projeto:
gcloud config list project

Resposta ao comando

[core]
project = <PROJECT_ID>

Se o projeto não estiver configurado, faça a configuração usando este comando:

gcloud config set project <PROJECT_ID>

Resposta ao comando

Updated property [core/project].

3. Criar um novo keyring e uma nova chave para o Cloud Functions

Verifique se a API Cloud KMS está ativada executando o seguinte comando:

gcloud services enable cloudkms.googleapis.com

Primeiro, crie variáveis de ambiente para conter o nome do keyring, o nome da chave, a região e outras variáveis usadas neste codelab.

KEYRING_NAME="keyring-functions"
REGION="us-central1"
KEY_NAME="key-encrypted-function"
PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER="$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')"
USER_EMAIL="$(gcloud config list account --format "value(core.account)")"

Em seguida, crie um keyring, que é o recurso raiz para chaves e versões de chaves do Cloud KMS.

gcloud kms keyrings create $KEYRING_NAME --location $REGION

Por fim, agora é possível criar uma chave simétrica no novo keyring no Cloud KMS.

gcloud kms keys create $KEY_NAME --keyring $KEYRING_NAME --location $REGION --purpose "encryption"

4. Criar um repositório do Artifact Registry com formato Docker ativado para CMEK

Nesta seção, você vai criar um repositório com formato Docker no Artifact Registry que tem a CMEK ativada. Essa será a mesma chave usada para implantar a função do Cloud.

Primeiro, você precisará da conta de serviço do Artifact Registry. É possível criar uma executando este comando:

gcloud beta services identity create --service=artifactregistry.googleapis.com --project=$PROJECT_ID

Use o comando a seguir para conceder o papel do IAM de Criptografador/Descriptografador de CryptoKey (roles/cloudkms.cryptoKeyEncrypterDecrypter) à conta de serviço do Artifact Registry para ter permissões para a chave:

gcloud kms keys add-iam-policy-binding \
  $KEY_NAME --location $REGION --keyring=$KEYRING_NAME \
  --member serviceAccount:service-$PROJECT_NUMBER@gcp-sa-artifactregistry.iam.gserviceaccount.com \
  --role roles/cloudkms.cryptoKeyEncrypterDecrypter

Conceda o papel ao principal que vai criar o repositório no Artifact Registry, por exemplo, sua conta ativa atual. É possível verificar sua conta ativa atual executando o comando gcloud auth list.

gcloud kms keys add-iam-policy-binding \
       $KEY_NAME --location $REGION --keyring=$KEYRING_NAME \
       --member user:$USER_EMAIL \
       --role roles/cloudkms.cryptoKeyEncrypterDecrypter

Agora é possível criar um repositório com formato Docker ativado para CMEK.

Observação:a região precisa ser a mesma da chave CMEK.

REPO_NAME=my-cmek-encrypted-repo 

KEY_FULLPATH=projects/"$PROJECT_ID"/locations/"$REGION"/keyRings/"$KEYRING_NAME"/cryptoKeys/"$KEY_NAME" 

gcloud artifacts repositories create $REPO_NAME \
    --repository-format=docker \
    --location=$REGION \
    --kms-key=$KEY_FULLPATH \
    --async

É possível visualizar o novo repositório do Artifact Registry executando este comando:

gcloud artifacts repositories describe $REPO_NAME --location=$REGION

5. Conceder acesso à chave para contas de serviço (2ª geração)

Esta seção aborda a criação de contas de serviço para funções de 2ª geração. Se você estiver criando uma função de 1ª geração, avance para a próxima seção.

É necessário conceder acesso à chave a vários agentes de serviço concedendo o papel do IAM de Criptografador/Descriptografador de CryptoKey (roles/cloudkms.cryptoKeyEncrypterDecrypter). Esses agentes de serviço são usados para acessar o código-fonte armazenado no Cloud Storage, armazenar imagens de função em um repositório protegido por CMEK no Artifact Registry e implantar uma função do Cloud criptografada por CMEK.

Etapas para funções de 2ª geração

  1. Conceda ao agente de serviço do Cloud Run acesso à chave:
CLOUDRUN_SA=service-$PROJECT_NUMBER@serverless-robot-prod.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$CLOUDRUN_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Conceda ao agente de serviço do Eventarc acesso à chave:
EVENTARC_SA=service-$PROJECT_NUMBER@gcp-sa-eventarc.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$EVENTARC_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Conceda ao agente de serviço do Artifact Registry acesso à chave:
AR_SA=service-$PROJECT_NUMBER@gcp-sa-artifactregistry.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$AR_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Conceda aos agentes de serviço do Cloud Storage acesso à chave:
STORAGE_SA=service-$PROJECT_NUMBER@gs-project-accounts.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$STORAGE_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter

Na próxima seção, você vai aprender a criar e implantar uma função criptografada por CMEK.

6. Conceder acesso à chave para contas de serviço (1ª geração)

Esta seção aborda a criação de contas de serviço para funções de 1ª geração. Se você já criou contas de serviço para uma função de 2ª geração, avance para a próxima seção.

É necessário conceder acesso à chave a vários agentes de serviço concedendo o papel do IAM de Criptografador/Descriptografador de CryptoKey (roles/cloudkms.cryptoKeyEncrypterDecrypter). Esses agentes de serviço são usados para acessar o código-fonte armazenado no Cloud Storage, armazenar imagens de função em um repositório protegido por CMEK no Artifact Registry e implantar uma função do Cloud criptografada por CMEK.

Etapas para funções de 1ª geração

  1. Conceda ao agente de serviço do Cloud Functions acesso à chave:
FUNCTION_SA=service-$PROJECT_NUMBER@gcf-admin-robot.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$FUNCTION_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Conceda ao agente de serviço do Artifact Registry acesso à chave:
AR_SA=service-$PROJECT_NUMBER@gcp-sa-artifactregistry.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$AR_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Conceda aos agentes de serviço do Cloud Storage acesso à chave:
STORAGE_SA=service-$PROJECT_NUMBER@gs-project-accounts.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$STORAGE_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter

Na próxima seção, você vai aprender a criar e implantar uma função criptografada por CMEK.

7. Criar uma função criptografada por CMEK (2ª geração)

Esta seção aborda a criação de funções de 2ª geração. Avance para a próxima seção para instruções da 1ª geração.

Agora que você tem um repositório do Artifact Registry configurado com a CMEK ativada e concedeu ao Cloud Functions acesso à sua chave, é possível implantar uma função criptografada usando a chave CMEK.

Etapas para funções de 2ª geração:

Criar o código-fonte da função

Embora este codelab use o Node.js, é possível usar qualquer ambiente de execução compatível.

Primeiro, crie um diretório e cd nesse diretório.

mkdir ~/cmek-function-2ndgen && cd $_

Em seguida, crie o arquivo package.json.

touch package.json

echo '{
  "dependencies": {
    "@google-cloud/functions-framework": "^2.1.0"
  }
}
' > package.json

Depois, crie o arquivo de origem index.js.

touch index.js

echo 'const functions = require("@google-cloud/functions-framework");

functions.http("helloWorld", (req, res) => {
 res.send(`Hello ${req.query.name || req.body.name || "World"}!`);
});' > index.js

Implantar a função do Cloud (2ª geração) usando a criptografia CMEK

Observação:o exemplo abaixo mostra como implantar uma função usando origens do diretório atual. Verifique se você está no mesmo diretório que o código-fonte da função.

FUNCTION_NAME=protect-me-cmek-2ndgen
ENTRY_POINT=helloWorld

REPO_FULLPATH=projects/"$PROJECT_ID"/locations/"$REGION"/repositories/$REPO_NAME

gcloud beta functions deploy $FUNCTION_NAME  \
--gen2 \
--region $REGION \
--kms-key $KEY_FULLPATH \
--docker-repository $REPO_FULLPATH \
--source . \
--trigger-http \
--allow-unauthenticated \
--runtime nodejs16 \
--entry-point $ENTRY_POINT

É possível conferir a chave CMEK na saída resultante executando este comando

gcloud functions describe $FUNCTION_NAME –region $REGION | grep kmsKeyName

Testar a função de 2ª geração

É possível testar a função usando o comando curl:

FUNCTION_URL="$(gcloud functions describe $FUNCTION_NAME --region $REGION --format='get(serviceConfig.uri)')"

curl $FUNCTION_URL

que resulta no seguinte:

Hello World!

Enquanto a chave de criptografia estiver ativada, a função retornará sucesso para o autor da chamada. No entanto, quando a chave de criptografia for desativada, o autor da chamada receberá um erro.

Na próxima seção, você vai ver o que acontece quando invoca a função depois que a chave é desativada.

8. Criar uma função criptografada por CMEK (1ª geração)

Esta seção aborda a criação de funções de 1ª geração. Se você já criou uma função de 2ª geração, avance para a próxima seção.

Agora que você tem um repositório do Artifact Registry configurado com a CMEK ativada e concedeu ao Cloud Functions acesso à sua chave, é possível implantar uma função criptografada usando a chave CMEK.

Etapas para funções de 1ª geração:

Criar o código-fonte da função de 1ª geração

Embora este codelab use o Node.js, é possível usar qualquer ambiente de execução compatível.

Primeiro, crie um diretório e cd nesse diretório.

mkdir ~/cmek-function-1stgen && cd $_

Em seguida, crie o arquivo package.json.

touch package.json

echo '{
    "name": "function-cmek-codelab",
    "version": "0.0.1"
}' > package.json

Depois, crie o arquivo de origem index.js.

touch index.js

echo "exports.helloWorld = (req, res) => {
    let message = req.query.message || req.body.message || 'Hello World!';
    res.status(200).send(message);
};" > index.js

Implantar a função do Cloud (1ª geração) usando a criptografia CMEK

Observação:o exemplo abaixo mostra como implantar uma função usando origens do diretório atual. Verifique se você está no mesmo diretório que o código-fonte da função.

FUNCTION_NAME=protect-me-cmek-1stgen
ENTRY_POINT=helloWorld

REPO_FULLPATH=projects/"$PROJECT_ID"/locations/"$REGION"/repositories/$REPO_NAME

gcloud functions deploy $FUNCTION_NAME  \
--region $REGION \
--kms-key $KEY_FULLPATH \
--docker-repository $REPO_FULLPATH \
--source . \
--trigger-http \
--allow-unauthenticated \
--runtime nodejs16 \
--entry-point $ENTRY_POINT

É possível conferir a chave CMEK na saída resultante executando este comando

gcloud functions describe $FUNCTION_NAME –region $REGION | grep kmsKeyName

Testar a função de 1ª geração

É possível testar a função usando o comando curl:

FUNCTION_URL="$(gcloud functions describe $FUNCTION_NAME --region $REGION --format='get(httpsTrigger.url)')"

curl $FUNCTION_URL

que resulta no seguinte:

Hello World!

Enquanto a chave de criptografia estiver ativada, a função retornará sucesso para o autor da chamada. No entanto, quando a chave de criptografia for desativada, o autor da chamada receberá um erro.

Na próxima seção, você vai ver o que acontece quando invoca a função depois que a chave é desativada.

9. Invocar uma função criptografada por CMEK em que a chave de criptografia foi desativada

Nesta seção final, você vai invalidar a chave e invocar a função novamente para conferir o erro resultante.

Desativar a chave de criptografia

É possível executar este comando para desativar a chave. Como este codelab cria apenas uma versão da chave, você vai desativar a versão 1.

gcloud kms keys versions disable 1 \
    --key=$KEY_NAME \
    --keyring=$KEYRING_NAME \
    --location=$REGION

e você vai ver as informações resultantes:

algorithm: GOOGLE_SYMMETRIC_ENCRYPTION
createTime: '2023-04-11T03:30:49.111832653Z'
generateTime: '2023-04-11T03:30:49.111832653Z'
name: projects/dogfood-gcf-saraford/locations/us-central1/keyRings/myKeyRing/cryptoKeys/encrypted-function/cryptoKeyVersions/1
protectionLevel: SOFTWARE
state: DISABLED

Invocar a função com uma chave desativada

Agora, curl a função novamente.

curl $FUNCTION_URL

e você não vai receber uma resposta "Hello World" desta vez.

Nos registros da função do Cloud, você vai encontrar

User's CMEK key has been disabled. CMEK key: projects/<PROJECT-NAME>/locations/us-central1/keyRings/myKeyRing/cryptoKeys/encrypted-function

Tentar visualizar recursos quando a chave CMEK está desativada

Nesta seção, você vai conferir os seguintes recursos que ficam indisponíveis quando a chave CMEK está desativada:

  • Código-fonte da função
  • Build da imagem do contêiner do código-fonte

Por exemplo, acessar a guia "Origem" da função do Cloud mostra um erro ao buscar o arquivo. Você vai receber um erro semelhante se tentar visualizar o arquivo .zip que contém o código-fonte diretamente no Cloud Storage.

ac3307bb05d30e19.png

Além disso, você não terá acesso para usar a imagem do contêiner da função do Artifact Registry. Por exemplo, se você tentar implantar essa imagem de contêiner no Cloud Run, vai receber um erro informando que a imagem não foi encontrada.

Consulte os documentos das funções CMEK para conferir uma lista completa de recursos criptografados.

10. Parabéns

Parabéns, você concluiu o codelab.

O que abordamos

  • Como criar uma chave CMEK em um keyring simétrico existente
  • Como criar um repositório do Artifact Registry
  • Como configurar a CMEK em uma função do Cloud

Para mais informações

Confira mais informações sobre o Cloud Functions e a CMEK nos links a seguir: