Criar uma implantação com criptografia TLS no Kubernetes

O Spanner Omni usa o TLS 1.3 para criptografar os dados que fluem entre o cliente e o servidor, e entre os servidores do Spanner Omni. O Spanner Omni oferece mTLS para maior segurança, em que ambas as partes estabelecem a autenticidade uma da outra antes de trocar dados. Se você usar criptografia, seus servidores precisarão se comunicar por mTLS. Você pode escolher se o cliente e o servidor também usam mTLS.

Antes de começar

Verifique se você atende aos seguintes requisitos:

  • Criar um cluster do Kubernetes A configuração é compatível com o Google Kubernetes Engine (GKE) e o Amazon Elastic Kubernetes Service (Amazon EKS). Talvez seja necessário personalizar a configuração para que ela funcione em outros ambientes.

  • Verifique se o cluster do Kubernetes pode acessar o artefato do Artifact Registry que hospeda o contêiner do Spanner Omni.

  • Instale e configure a ferramenta de linha de comando kubectl e o Helm.

  • Se você configurar o ambiente do Kubernetes em máquinas da plataforma de virtualização vSphere, desative a virtualização do contador de carimbo de data/hora (TSC, na sigla em inglês) adicionando monitor_control.virtual_rdtsc = FALSE ao arquivo de configuração .vmx da máquina virtual. Isso garante que o TrueTime funcione corretamente.

  • Verifique se o ambiente atende aos requisitos do sistema do Spanner Omni.

Etapa 1: gerar os certificados

Você precisa criar três conjuntos de certificados:

  • Certificados de API: ajudam a proteger o servidor de API do Spanner Omni.

  • Certificados de servidor: ajudam a proteger a comunicação entre servidores.

  • Certificados do cliente: os usuários finais ou aplicativos usam esses certificados para estabelecer a identidade e a confiança deles com os servidores do Spanner Omni.

Uma autoridade certificadora (CA) emite esses certificados. O Spanner Omni oferece ferramentas para criar uma CA autoassinada e todos os três tipos de certificados.

Siga as etapas abaixo em uma das suas máquinas. As etapas pressupõem que o namespace é spanner-ns. Mude para o namespace que você pretende usar na implantação.

É possível criar esses certificados na estação de trabalho usando a CLI do Spanner Omni.

1. Criar autoridades certificadoras

É preciso criar duas autoridades certificadoras (CAs) separadas para isolar a comunicação interna entre servidores da comunicação externa de clientes e APIs:

  • CA do servidor interno (ca.crt): emite certificados de servidor (server.crt) usados exclusivamente para comunicação mTLS interna entre servidores do Spanner Omni.
  • API e CA do cliente (ca-api.crt): emite o certificado do servidor de API (api.crt) e os certificados mTLS do cliente (client.crt). Como alternativa, é possível usar uma CA confiável externamente ou a CA da sua organização para os certificados de API e do cliente.
  1. Crie a CA do servidor interno para comunicação entre servidores:

    ./google/spanner/bin/spanner certificates create-ca --ca-certificate-directory=certs
    

    Esse comando cria o certificado de CA do servidor interno (certs/ca.crt) e grava a chave privada dele em $HOME/.spanner/private-keys/ca.key.

  2. Crie uma CA separada para os certificados de API e de cliente e copie o certificado de CA para certs/ca-api.crt:

    ./google/spanner/bin/spanner certificates create-ca \
        --ca-certificate-directory=api-certs \
        --ca-private-key-directory=$HOME/.spanner/api-private-keys
    cp api-certs/ca.crt certs/ca-api.crt
    

    Esses comandos criam o certificado de CA da API e do cliente (api-certs/ca.crt, copiado para certs/ca-api.crt) e gravam a chave privada em $HOME/.spanner/api-private-keys/ca.key.

Faça backup e proteja $HOME/.spanner/private-keys e $HOME/.spanner/api-private-keys. Os usuários com acesso a essas chaves privadas podem assinar certificados arbitrários em que a implantação confia.

2. Gerar certificados do servidor

É preciso gerar dois tipos de certificados de servidor:

  • Certificado de API: use esse certificado para criptografar a comunicação de sistemas que interagem com a implantação.

  • Certificado do servidor do Spanner: os servidores do Spanner Omni usam esse certificado para criptografar a comunicação entre si.

Essa configuração oferece flexibilidade no gerenciamento desses certificados. Por exemplo, ele permite usar a rotação de certificados.

Criar o certificado do servidor do Spanner

Crie o certificado do servidor:

# Comma-separate names of the Spanner servers; wildcards are supported.
SERVER_NAMES=*.pod.NAMESPACE
./google/spanner/bin/spanner certificates create-server --hostnames=${SERVER_NAMES} --ca-certificate-directory certs --output-directory certs

Esse comando cria server.crt e server.key no diretório certs.

Criar o certificado da API

Crie o certificado de API usando a CA de API:

OMNI_ENDPOINT=spanner.NAMESPACE.svc
./google/spanner/bin/spanner certificates create-server \
    --filename-prefix=api \
    --hostnames=${OMNI_ENDPOINT} \
    --ca-certificate-directory=api-certs \
    --ca-private-key-directory=$HOME/.spanner/api-private-keys \
    --output-directory=certs

Esse comando cria api.crt e api.key no diretório certs. Se necessário, use uma CA confiável externamente para os certificados de API.

3. Gerar certificados do cliente

É possível usar certificados do cliente para autenticar usuários e aplicativos. Os certificados do cliente ativam o mTLS entre o cliente e o servidor. Pule esta etapa se não planeja usar o mTLS.

Assine os certificados do cliente com a API e a AC do cliente (api-certs/ca.crt, que corresponde a certs/ca-api.crt) e inclua um nome de usuário para autorização. Não assine certificados de cliente com a CA do servidor interno (certs/ca.crt). Para este exemplo, use o usuário admin, que é o usuário padrão de cada novo banco de dados. Para mais informações, consulte Autenticação e autorização no Spanner Omni.

Crie o certificado do cliente:

USERNAME=admin
./google/spanner/bin/spanner certificates create-client $USERNAME \
    --output-directory=clientcerts \
    --ca-certificate-directory=api-certs \
    --ca-private-key-directory=$HOME/.spanner/api-private-keys

Esse comando cria client.crt e client.key no diretório clientcerts. Envie esses arquivos para qualquer máquina que se conecte à implantação.

Se você planeja usar certificados do cliente com a biblioteca de cliente Java, é necessário gerar a chave do certificado no formato PKCS#8. Use o comando a seguir:

USERNAME=admin
./google/spanner/bin/spanner certificates create-client $USERNAME \
    --output-directory=clientcerts \
    --ca-certificate-directory=api-certs \
    --ca-private-key-directory=$HOME/.spanner/api-private-keys \
    --generate-pkcs8-key

4. Gerar o conjunto de chaves do wrapper

O Spanner Omni usa um conjunto de chaves de encapsulamento de chave de criptografia de chaves (KEK) montado em /spanner/kms/wrapper_key em cada pod de servidor para criptografar chaves internas, como chaves de criptografia e assinatura de token.

Para gerar um novo arquivo de conjunto de chaves de wrapper usando spanner keys create-keyset, execute o seguinte comando:

./google/spanner/bin/spanner keys create-keyset --output-file=kms/wrapper_key

Por padrão, spanner keys create-keyset gera uma chave AES256_GCM. Para gerar um tipo diferente de chave, use a flag --key-template com um dos seguintes valores de tipo de chave: AES256_GCM, AES128_GCM, AES256_GCM_RAW, CHACHA20_POLY1305 ou XCHACHA20_POLY1305.

Etapa 2: enviar os certificados, o conjunto de chaves do wrapper e a senha do administrador para o cluster do Kubernetes

Execute os comandos a seguir para criar o namespace e enviar os certificados, o conjunto de chaves de wrapper e a senha de administrador para o cluster do Kubernetes:

  1. Crie o namespace:

    kubectl create namespace NAMESPACE
    
  2. Envie os certificados TLS para um secret:

    kubectl create secret generic tls-certs \
      --from-file=ca.crt="certs/ca.crt" \
      --from-file=ca-api.crt="certs/ca-api.crt" \
      --from-file=server.crt="certs/server.crt" \
      --from-file=server.key="certs/server.key" \
      --from-file=api.crt="certs/api.crt" \
      --from-file=api.key="certs/api.key" \
      -n NAMESPACE
    
  3. Envie o conjunto de chaves do wrapper para um secret (wrapper-key), que é montado em /spanner/kms em cada pod do servidor:

    kubectl create secret generic wrapper-key \
      --from-file=wrapper_key="kms/wrapper_key" \
      -n NAMESPACE
    
  4. Crie um arquivo de senha que contenha a senha do usuário admin padrão, com permissões restritas (legível apenas pelo proprietário, permissões 600):

    printf '%s' 'PASSWORD' > admin_password.txt
    chmod 600 admin_password.txt
    

    A senha precisa atender aos seguintes requisitos:

    • Entre 8 e 32 caracteres.
    • Pelo menos um caractere maiúsculo.
    • Pelo menos um caractere minúsculo.
    • Pelo menos um número.
    • Pelo menos um caractere especial.
  5. Crie um secret para a senha de administrador:

    kubectl create secret generic spanner-admin-password \
      --from-file=password=admin_password.txt \
      -n NAMESPACE
    

Etapa 3: criar a implantação com criptografia TLS

Siga estas etapas para criar sua implantação com criptografia TLS.

1. Preparar a configuração do Helm

Consulte Criar uma configuração de gráfico Helm e crie a configuração de implantação para seu ambiente.

Para ativar o TLS e configurar a senha de administrador, defina os seguintes valores na configuração do gráfico Helm:

# Enables TLS
global:
  insecureMode: false

# Enables client certificate authentication (mTLS)
deployment:
  enableClientCertificateAuthentication: true
  # Name of the secret containing the administrator password
  adminPasswordSecret: spanner-admin-password

2. Criar a implantação

Execute o seguinte comando para criar a implantação:

kubectl create ns monitoring

helm upgrade --install spanner-omni oci://us-docker.pkg.dev/spanner-omni/charts/spanner-omni \
  --version VERSION \
  --set global.platform=gke \
  --set global.insecureMode=false \
  --set deployment.enableClientCertificateAuthentication=true \
  --set deployment.adminPasswordSecret=spanner-admin-password \
  --namespace NAMESPACE \
  --set monitoring.enabled=true

O comando aciona um job de inicialização. Para acompanhar o progresso, observe os registros desse job:

kubectl logs -n NAMESPACE -l app.kubernetes.io/component=bootstrap -f

A saída indica o progresso. Quando terminar, você vai receber uma mensagem informando que a implantação foi criada.

3. Verifique o status dos pods

Execute o comando a seguir para verificar o status do pod:

kubectl get pods --watch --namespace NAMESPACE

Todos os pods estão no estado READY.

4. Atualizar o certificado e a implantação com detalhes do balanceador de carga

Esta etapa é necessária se você quiser que os clientes se conectem de fora do cluster do Kubernetes.

# Get the service details
kubectl get service spanner -n NAMESPACE

# The EXTERNAL-IP:PORT is the API or deployment endpoint for your deployment.
# Update the API certificate with these details.
OMNI_ENDPOINT=EXTERNAL_IP,spanner.NAMESPACE.svc
./google/spanner/bin/spanner certificates update \
    --certificate-file=certs/api.crt \
    --certificate-key-file=certs/api.key \
    --hostnames=${OMNI_ENDPOINT} \
    --ca-certificate-directory=api-certs \
    --ca-private-key-directory=$HOME/.spanner/api-private-keys

# Update the secrets in Kubernetes
kubectl patch secret tls-certs -n NAMESPACE -p "{\"data\":{\"api.crt\":\"$(base64 -w 0 certs/api.crt)\"}}"

Etapa 4: interagir com o Spanner Omni

É possível interagir com a implantação do Spanner Omni em qualquer VM usando a CLI do Spanner Omni.

Se você ativou o mTLS para clientes, use as seguintes flags com cada comando:

  • --client-certificate-directory=CLIENT_CERTIFICATE_DIRECTORY

  • --ca-certificate-file=API_CA_CERT_FILE_PATH

1. Fazer login no Spanner Omni (opcional)

Faça login no Spanner Omni (esta etapa é opcional se você usar certificados do cliente):

./google/spanner/bin/spanner auth login admin \
    --ca-certificate-file=certs/ca-api.crt \
    --deployment-endpoint=DEPLOYMENT_ENDPOINT

Quando solicitado, digite a senha configurada em admin_password.txt.

Successfully logged in as "admin"

2. Criar um banco de dados

Execute o comando a seguir para criar um banco de dados:

./google/spanner/bin/spanner --deployment-endpoint=DEPLOYMENT_ENDPOINT databases create DATABASE_NAME --ca-certificate-file=certs/ca-api.crt --client-certificate-directory=clientcerts

3. Abra o SQL Shell.

Execute o seguinte comando para abrir o shell:

./google/spanner/bin/spanner sql --database=DATABASE_NAME --deployment-endpoint=DEPLOYMENT_ENDPOINT --ca-certificate-file=certs/ca-api.crt --client-certificate-directory=clientcerts

4. Criar uma tabela e adicionar dados

Execute os seguintes comandos SQL:

spanner> CREATE TABLE names (nameId INT64 NOT NULL, name String(100)) PRIMARY KEY (nameId);
Query OK, 0 rows affected (4.62 sec)

spanner> INSERT names (nameId, name) VALUES (1, "Jack");
Query OK, 1 rows affected (0.18 sec)

5. Verificar a implantação

Para listar os bancos de dados, execute o seguinte comando:

./google/spanner/bin/spanner databases list --ca-certificate-file=certs/ca-api.crt --client-certificate-directory=clientcerts --deployment-endpoint=DEPLOYMENT_ENDPOINT

A saída será assim:

NOME ESTADO VERSION_RETENTION_PERIOD EARLIEST_VERSION_TIME ENABLE_DROP_PROTECTION
DATABASE_NAME READY 1h 2025-02-07T12:25:30Z falso

Para consultar os dados, execute o seguinte comando:

./google/spanner/bin/spanner sql --database=DATABASE_NAME --ca-certificate-file=certs/ca-api.crt --client-certificate-directory=clientcerts --deployment-endpoint=DEPLOYMENT_ENDPOINT

Execute os seguintes comandos SQL:

SHOW TABLES;
SELECT * FROM names;

Como alternativa, siga as instruções em Como usar o PGAdapter com o Spanner Omni para configurar o PGAdapter e interagir usando ferramentas como psql.

Etapa 5: monitorar a implantação

Se você instalou o Spanner Omni com monitoring.enabled=true, o Prometheus coleta métricas. É possível usar o Grafana para visualizar essas métricas.

1. Acessar os detalhes do serviço

Execute os comandos a seguir para ver os detalhes do serviço:

# Prometheus service details. Default port is 9090.
kubectl get service prometheus-service -n monitoring

# Grafana service details. Default port is 3000.
kubectl get service grafana -n monitoring

A seguir