A criptografia transparente de dados (TDE) já existe há muito tempo no Percona Server para MySQL e MySQL. Mas você já se perguntou como isso funciona nos bastidores e que impacto a TDE pode ter em seu servidor? Nesta série de artigos, daremos uma olhada em como a TDE funciona internamente. Vamos começar com o armazenamento de chaves, pois isso é necessário para que qualquer criptografia funcione. Em seguida, examinaremos mais de perto como funciona a criptografia no Percona Server para MySQL / MySQL e quais recursos adicionais estão disponíveis no Percona Server para MySQL.
MySQL Keyring
Keyring são plug-ins que permitem ao servidor consultar, criar e excluir chaves em um arquivo local (keyring_file) ou em um servidor remoto (como no HashiCorp Vault). As chaves são sempre armazenadas em cache localmente para acelerar a recuperação.
Os plug-ins podem ser divididos em duas categorias:
- Armazenamento local. Por exemplo, um arquivo local (chamamos isso de chaveiro baseado em arquivo).
- Armazenamento remoto. Por exemplo, Vault Server (chamamos este chaveiro baseado em servidor).
Essa separação é importante porque diferentes tipos de armazenamento se comportam de maneira ligeiramente diferente, não apenas ao armazenar e recuperar chaves, mas também ao inicializar.
Ao usar um armazenamento de arquivo, na inicialização, todo o conteúdo do armazenamento é carregado no cache: ID da chave, usuário da chave, tipo de chave e a própria chave.
No caso de um vault de back-end (como um servidor Vault), apenas o ID da chave e o usuário principal são carregados na inicialização, portanto, obter todas as chaves não retarda a inicialização. As chaves são carregadas preguiçosamente. Ou seja, a própria chave é carregada do Vault apenas quando é realmente necessária. Depois de carregada, a chave é armazenada em cache na memória para que, no futuro, não haja necessidade de acessá-la por meio de conexões TLS com o servidor do Vault. A seguir, vamos ver quais informações estão presentes no armazenamento de chaves.
As principais informações contêm o seguinte:
- key id — , :
INNODBKey-764d382a-7324-11e9-ad8f-9cb6d0d5dc99-1
- key type — , , : «AES», «RSA» «DSA».
- key length — , AES: 16, 24 32, RSA 128, 256, 512 DSA 128, 256 384.
- user — . , , Master Key, . keyring_udf, .
A chave é identificada exclusivamente pelo par: key_id, user.
Também existem diferenças no armazenamento e descarte de chaves.
O armazenamento de arquivos é mais rápido. Pode-se supor que um armazenamento de chave é uma simples gravação única de uma chave em um arquivo, mas não - há mais operações acontecendo aqui. Qualquer modificação no armazenamento de arquivos criará primeiro um backup de todo o conteúdo. Digamos que o arquivo seja chamado my_biggest_secrets, então o backup será my_biggest_secrets.backup. Em seguida, o cache é alterado (as chaves são adicionadas ou removidas) e se tudo for bem-sucedido, o cache é liberado para um arquivo. Em casos raros, como uma falha do servidor, você pode ver este arquivo de backup. O arquivo de backup é excluído na próxima vez que as chaves são carregadas (geralmente após a reinicialização do servidor).
Ao salvar ou deletar uma chave no repositório do servidor, o repositório deve se conectar ao servidor MySQL com os comandos "send the key" / "request key deletion".
Vamos voltar à velocidade de inicialização do servidor. Além do fato de que o armazenamento em si afeta a velocidade de inicialização, também há a questão de quantas chaves do armazenamento você precisa obter na inicialização. Claro, isso é especialmente importante para armazenamento de back-end. Na inicialização, o servidor verifica qual chave é necessária para tabelas / espaços de tabela criptografados e solicita a chave do armazenamento. Em um servidor "limpo" com chave mestra - criptografia, deve haver uma chave mestra, que deve ser recuperada do armazenamento. No entanto, mais chaves podem ser necessárias, por exemplo, ao restaurar um backup do servidor primário para um servidor de backup. Nesses casos, uma rotação de chave mestra deve ser fornecida. Isso será discutido com mais detalhes em artigos futuros, embora aqui eu gostaria de apontar que o servidor,o uso de várias chaves mestras pode demorar um pouco mais para começar, especialmente ao usar um armazenamento de chaves do lado do servidor.
Agora vamos falar um pouco mais sobre keyring_file. Quando eu estava desenvolvendo keyring_file, também estava preocupado em como verificar as alterações de keyring_file enquanto o servidor estava em execução. No 5.7, a verificação era realizada com base nas estatísticas do arquivo, o que não era uma solução ideal, e no 8.0 foi substituída por uma soma de verificação SHA256.
Na primeira vez que você executa keyring_file, as estatísticas e a soma de verificação do arquivo são calculadas e lembradas pelo servidor, e as alterações são aplicadas apenas se corresponderem. A soma de verificação é atualizada quando o arquivo é alterado.
Já cobrimos muitas questões sobre keystores. No entanto, há outro tópico importante que é frequentemente esquecido ou mal compreendido - o compartilhamento de chaves entre servidores.
O que eu quero dizer? Cada servidor (por exemplo, Percona Server) no cluster deve ter um local separado no servidor Vault onde o Percona Server deve armazenar suas chaves. Cada chave mestra armazenada no repositório contém o GUID do Percona Server em seu identificador. Por que isso é importante? Imagine que você tem apenas um Vault Server e todos os Percona Servers no cluster estão usando esse único Vault Server. O problema parece óbvio. Se todos os Percona Servers estivessem usando a chave mestra sem identificadores exclusivos, como id = 1, id = 2, etc., todos os servidores no cluster usariam a mesma chave mestra. Isso é o que o GUID fornece - a distinção entre servidores. Por que então falar sobre o compartilhamento de chaves entre servidores quando já existe um GUID exclusivo? Existe mais um plugin - keyring_udf.Com este plugin, o usuário do servidor pode armazenar suas chaves no servidor Vault. O problema ocorre quando um usuário cria uma chave, por exemplo, no servidor1, e então tenta criar uma chave com o mesmo ID no servidor2, por exemplo:
--server1:
select keyring_key_store('ROB_1','AES',"123456789012345");
1
--1
--server2:
select keyring_key_store('ROB_1','AES',"543210987654321");
1
Esperar. Ambos os servidores estão usando o mesmo Vault Server. A função keyring_key_store não deveria falhar no server2? Curiosamente, se você tentar fazer o mesmo no mesmo servidor, receberá um erro:
--server1:
select keyring_key_store('ROB_1','AES',"123456789012345");
1
select keyring_key_store('ROB_1','AES',"543210987654321");
0
Isso mesmo, ROB_1 já existe.
Vamos discutir o segundo exemplo primeiro. Como dissemos anteriormente, keyring_vault ou qualquer outro plugin de chaveiro armazenará em cache todos os IDs de chave na memória. Assim, após a criação de uma nova chave, ROB_1 é adicionado ao server1, e além de enviar esta chave para o Vault, a chave também é adicionada ao cache. Agora, quando tentamos adicionar a mesma chave uma segunda vez, keyring_vault verifica se essa chave existe no cache e gera um erro.
No primeiro caso, a situação é diferente. Server1 e server2 têm caches separados. Depois de adicionar ROB_1 aos caches de chave em server1 e Vault, os caches de chave em server2 não são sincronizados. Não há nenhuma chave ROB_1 no cache do servidor2. Portanto, a chave ROB_1 é gravada em keyring_key_store e no servidor do Vault, que na verdade sobrescreve (!) O valor anterior. Agora, a chave ROB_1 no servidor do Vault é 543210987654321. Curiosamente, o servidor do Vault não bloqueia tais ações e sobrescreve facilmente o valor antigo.
Agora podemos ver porque a divisão por servidor por Vault pode ser importante - quando você está usando keyring_udf e deseja armazenar as chaves em um Vault. Como você fornece essa separação no servidor do Vault?
Existem duas maneiras de dividir em Vault. Você pode criar diferentes pontos de montagem para cada servidor ou usar caminhos diferentes dentro do mesmo ponto de montagem. Isso é melhor ilustrado com exemplos. Então, vamos dar uma olhada nos pontos de montagem individuais primeiro:
--server1:
vault_url = http://127.0.0.1:8200
secret_mount_point = server1_mount
token = (...)
vault_ca = (...)
--server2:
vault_url = http://127.0.0.1:8200
secret_mount_point = sever2_mount
token = (...)
vault_ca = (...)
Aqui você pode ver que server1 e server2 estão usando pontos de montagem diferentes. Ao dividir caminhos, a configuração ficará assim:
--server1:
vault_url = http://127.0.0.1:8200
secret_mount_point = mount_point/server1
token = (...)
vault_ca = (...)
--server2:
vault_url = http://127.0.0.1:8200
secret_mount_point = mount_point/sever2
token = (...)
vault_ca = (...)
Nesse caso, os dois servidores usam o mesmo mount_point, mas caminhos diferentes. Quando o primeiro segredo é criado no server1 ao longo deste caminho, o Vault cria automaticamente o diretório "server1". Para server2, tudo é o mesmo. Quando você remove o último segredo em mount_point / server1 ou mount_point / server2, o servidor do Vault também remove esses diretórios. Caso esteja usando divisão de caminho, você só precisa criar um ponto de montagem e alterar os arquivos de configuração para que os servidores usem caminhos separados. Um ponto de montagem pode ser criado usando uma solicitação HTTP. Com o CURL, isso pode ser feito assim:
curl -L -H "X-Vault-Token: TOKEN" –cacert VAULT_CA
--data '{"type":"generic"}' --request POST VAULT_URL/v1/sys/mounts/SECRET_MOUNT_POINT
Todos os campos (TOKEN, VAULT_CA, VAULT_URL, SECRET_MOUNT_POINT) correspondem aos parâmetros do arquivo de configuração. Claro, você pode usar os utilitários do Vault para fazer o mesmo. Mas isso torna mais fácil automatizar a criação do ponto de montagem. Espero que essas informações sejam úteis e nos veremos nos próximos artigos desta série.

Consulte Mais informação: