Uso de claves de encriptación

Descripción general

Según la configuración predeterminada, Cloud Storage encripta todos los datos de objetos mediante claves de encriptación administradas por Google y el algoritmo de encriptación AES256. Sin embargo, también puedes usar uno de los dos tipos de claves de encriptación: las que proporcionas, llamadas claves de encriptación proporcionadas por el cliente (CSEK) o las que administras a través de Google Cloud KMS, llamadas claves de encriptación administradas por el cliente (CMEK). Cloud Storage no almacena de forma permanente las CSEK en los servidores de Google ni las administra de otra manera. Puedes obtener más información sobre estas opciones de encriptación en CMEK y CSEK.

gsutil acepta las CSEK para que interactúen con objetos de Cloud Storage mediante la API de JSON. Las claves se proporcionan a través del archivo de configuración .boto de la siguiente manera:

[GSUtil]
encryption_key = ...
decryption_key1 = ...
decryption_key2 = ...

Cada clave es una string codificada en Base64 RFC 4648 de 256 bits de datos para usar con el algoritmo de encriptación AES256.

gsutil también acepta las CMEK para encriptar objetos mediante la API de JSON. Ten en cuenta que si tu objetivo es usar una CMEK para encriptar todos los objetos recién escritos en algún depósito, debes establecer la clave KMS predeterminada de ese depósito (consulta ayuda de KMS para gsutil). Como alternativa, puedes especificar las CMEK deseadas en el archivo de configuración .boto, pero solo necesitas especificar el atributo encryption_key:

[GSUtil]
encryption_key = projects/PROJECT_ID/locations/LOCATION/keyRings/KEYRING/cryptoKeys/KEYNAME

Si bien desencriptar un objeto encriptado con CSEK requiere proporcionar la CSEK en uno de los atributos decryption_key, esto no es necesario para desencriptar objetos encriptados con CMEK, ya que el nombre de la CMEK que se usa con el fin de encriptar el objeto se almacena en los metadatos del objeto.

Ten en cuenta que si deseas especificar las CMEK por comando sin necesidad de editar tu archivo boto, puedes especificar el nombre de la clave como opción boto de nivel superior:

gsutil -o 'GSUtil:encryption_key=projects/PROJECT_ID/locations/LOCATION/keyRings/KEYRING/cryptoKeys/KEYNAME' \
       cp /some/local/file gs://my-bucket/

Comportamiento de la encriptación

Se puede especificar una sola encryption_key en el archivo de configuración .boto y varias decryption_keys.

Si la encryption_key existe en el archivo de configuración .boto, gsutil garantiza que los datos que escribe o copia en Cloud Storage estén encriptados con esa clave. Si no se proporciona la encryption_key, gsutil garantiza que todos los datos que escribe o copia usen el tipo de encriptación predeterminado del bucket de destino en su lugar. Si el bucket tiene configurada una clave KMS predeterminada, esa CMEK se usa para la encriptación; de lo contrario, se usa la encriptación administrada por Google.

Los objetos encriptados con CSEK requieren la clave de desencriptación correspondiente cada vez que se descargan o copian (a través de los comandos de gsutil cat, cp, mv o rsync). La visualización de los hash CRC32C o MD5 de estos objetos (a través de los comandos ls -L o stat) también requiere la clave de desencriptación correspondiente.

Si existe una clave coincidente en la configuración .boto, gsutil la proporciona según sea necesario en las solicitudes a Cloud Storage y opera en los resultados desencriptados; gsutil nunca almacena datos encriptados en el disco local.

gsutil detecta de forma automática la CSEK correcta para usar en un objeto de la nube mediante la comparación del hash SHA256 de la clave con el hash de la CSEK. gsutil considera la clave de encriptación configurada y hasta 100 claves de desencriptación cuando se busca una coincidencia. Las claves de desencriptación se deben enumerar en el archivo de configuración boto en orden numérico ascendente a partir de 1. Por ejemplo, en la siguiente configuración:

decryption_key1 = ...
decryption_key9 = ...
decryption_key10 = ...
decryption_key11 = ...

decryption_keys 9, 10 y 11 se ignorarán porque no se proporcionan valores para decryption_keys de 2 a 8.

Operaciones reanudables y claves de encriptación

Si la encryption_key en el archivo de configuración boto cambia durante una operación de escritura o copia completada de forma parcial (por ejemplo, si vuelves a ejecutar una carga de objeto gsutil cp después de presionar ^C o de encontrar un tiempo de espera de red), gsutil reiniciará la operación incompleta para garantizar que el objeto de destino se escriba con la clave nueva.

Genera claves de encriptación proporcionadas por el cliente

Se puede generar una string codificada en Base64 RFC 4648 de 256 bits para usarla como clave de encriptación con facilidad con Python:

python -c 'import base64; import os;\
           print(base64.encodestring(os.urandom(32)))'

Administra claves de encriptación proporcionadas por el cliente

Debido a que Google no almacena las CSEK, si pierdes el CSEK, perderás el acceso de forma permanente a todos los datos encriptados con esa clave. Por lo tanto, se recomienda crear una copia de seguridad de cada clave de encriptación en una ubicación segura. El archivo de configuración .boto nunca debe ser el único lugar donde se almacena la clave.

Además, cuando creas una CSEK, cualquier persona que tenga la clave y acceso a los objetos puede leer los datos de esos objetos. Toma precauciones para asegurarte de que las claves de encriptación no se compartan con grupos que no sean de confianza.

Rota las claves

A fin de rotar las CSEK, puedes cambiar el valor de configuración de encryption_key a un valor de configuración de decryption_key y, luego, usa un valor nuevo para encryption_key. Luego, puedes usar el comando de reescritura para rotar las claves en la nube sin descargar y volver a subir los datos. Por ejemplo, si la configuración inicial es la siguiente:

# Old encryption key
encryption_key = keyA...

Puedes cambiarla a lo siguiente:

# New encryption key
encryption_key = keyB...
# Encryption key prior to rotation
decryption_key1 = keyA...

Y rotar la clave de encriptación en un objeto mediante la ejecución de lo siguiente:

gsutil rewrite -k gs://bucket/object temp-file

También puedes hacer esto para aplicar diferentes CMEK, pero no es necesario que agregues CMEK a los valores de configuración de decryption_key. De manera similar, puedes cambiar entre la encriptación CSEK y CMEK según el tipo de clave que se especifica en el valor de configuración de encryption_key.

Implicaciones de rendimiento para las claves de encriptación

Cuando se realiza una lista de objetos, los metadatos de los objetos encriptados con una CSEK o CMEK no incluirán los hash CRC32C o MD5 de los objetos. Para los comandos de gsutil que requieren estos campos, como gsutil ls -L, gsutil realiza una solicitud GET de metadatos adicional por cada objeto encriptado con una CSEK o CMEK. Por lo tanto, enumerar esos objetos con la marca -L requerirá una operación adicional por objeto, que será mucho más lenta que enumerar los objetos encriptados con claves de Google.

Implicaciones de seguridad para las claves de encriptación proporcionadas por el cliente

gsutil siempre envía claves de encriptación a través de HTTPS, por lo que las CSEK nunca serán visibles en la red. Sin embargo, las claves están presentes en el archivo de configuración .boto y en la memoria de la máquina que ejecuta gsutil. Por lo tanto, si este archivo o la máquina están vulnerados, las claves de encriptación también deben considerarse vulneradas, y debes realizar la rotación de claves de inmediato para todos los objetos encriptados con las claves vulneradas.

API de XML no admitida

gsutil no admite el uso de la API de XML para interactuar con objetos encriptados y usará la API de JSON si se especifica alguna encryption_key o decryption_keys en la configuración.