Estoy intentando migrar un servidor Discourse existente a un nuevo entorno basado en AWS, almacenando subidas en S3 en un bucket que utiliza cifrado del lado del servidor con claves administradas por el cliente (SSE-C). Durante el proceso de restauración, las subidas no llegan a S3; cada subida falla. Con el uso juicioso de la depuración tap|p, he descubierto que la subida se realiza, pero la validación del etag devuelto falla porque el etag devuelto por S3 después de la subida es diferente cada vez. Por ejemplo, este es el valor de retorno de la llamada put_object en dos intentos de restauración diferentes:
# Ejecución 1
#
# <struct Aws::S3::Types::PutObjectOutput expiration=nil, etag="\"d49ec2006cfd6fe957af2f711edd9a4b\"", checksum_crc32=nil, checksum_crc32c=nil, checksum_sha1=nil, checksum_sha256=nil, server_side_encryption="aws:kms", version_id="xAF23wQ.zwpoxVmmGiTjxfX0svMZbHAe", sse_customer_algorithm=nil, sse_customer_key_md5=nil, ssekms_key_id="**redacted**", ssekms_encryption_context=nil, bucket_key_enabled=true, request_charged=nil>
# Ejecución 2:
#
# <struct Aws::S3::Types::PutObjectOutput expiration=nil, etag="\"05edffee421c6aef950b3d4418ada293\"", checksum_crc32=nil, checksum_crc32c=nil, checksum_sha1=nil, checksum_sha256=nil, server_side_encryption="aws:kms", version_id="H2_8SVh.Yx2LKB4GIjhyPbVoj_.Vc1E2", sse_customer_algorithm=nil, sse_customer_key_md5=nil, ssekms_key_id="**redacted**", ssekms_encryption_context=nil, bucket_key_enabled=true, request_charged=nil>
(Sé que son los mismos archivos porque también estoy imprimiendo la suma MD5 del lado del cliente y las opciones de solicitud de put_object, que incluyen el nombre del archivo).
Resulta que la cabecera de respuesta ETag se comporta… de manera diferente cuando se utiliza SSE-C:
Los objetos cifrados por el cifrado del lado del servidor con claves proporcionadas por el cliente (SSE-C) o claves de AWS Key Management Service (AWS KMS) (SSE-KMS) tienen ETags que no son un resumen MD5 de sus datos de objeto.
La única forma que encuentro para verificar la integridad de las subidas con SSE-C es enviar la cabecera de solicitud Content-MD5, y dejar que S3 haga la detección de corrupción. Tenga en cuenta también que la comprobación de ya subido también fallará al usar SSE-C, pero al menos eso se puede deshabilitar usando SKIP_ETAG_VERIFY.
No estoy enviando un PR de inmediato porque hay dos formas diferentes de abordar esto:
- Simplemente extender
SKIP_ETAG_VERIFYpara que abarque la verificación posterior a la subida, lo cual es barato y un hackeo, y requiere que los usuarios sepan que su uso de SSE-C significa que tendrán que activarlo; o - Cambiar al uso de la cabecera Content-MD5 (preferiblemente siempre) para la protección de la integridad de la subida, lo que tiene el beneficio de funcionar para todos, a costa de un PR mucho más grande.
(Como aparte, me perturba bastante que nadie haya encontrado esto antes: ¿nadie está usando Discourse con SSE-C para las subidas?)