Estou tentando migrar um servidor Discourse existente para um novo ambiente baseado em AWS, armazenando uploads no S3 em um bucket usando criptografia do lado do servidor com chaves gerenciadas pelo cliente (SSE-C). Durante o processo de restauração, os uploads não estão chegando ao S3 — cada upload falha. Com o uso criterioso de depuração tap|p, descobri que o upload está sendo feito, mas a validação do etag retornado está falhando porque o etag retornado do S3 após o upload é diferente a cada vez. Por exemplo, este é o valor de retorno da chamada put_object em duas tentativas diferentes de restauração:
# Execução 1
#
# Run 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>
# Execução 2:
#
# Run 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>
(Eu sei que são os mesmos arquivos porque também estou imprimindo a soma MD5 do lado do cliente e as opções de solicitação put_object, que incluem o nome do arquivo)
Acontece que o cabeçalho de resposta ETag se comporta… de forma diferente ao usar SSE-C:
Objetos criptografados por criptografia do lado do servidor com chaves fornecidas pelo cliente (SSE-C) ou chaves do AWS Key Management Service (AWS KMS) (SSE-KMS) têm ETags que não são um resumo MD5 de seus dados de objeto.
A única maneira que encontro de fazer a verificação de integridade de uploads com SSE-C é enviar o cabeçalho de solicitação Content-MD5, e deixar o S3 fazer a detecção de corrupção. Observe também que a verificação de já enviado também quebrará ao usar SSE-C, mas pelo menos isso pode ser desativado usando SKIP_ETAG_VERIFY.
Não estou enviando um PR imediatamente porque existem duas maneiras diferentes de abordar isso:
- Apenas estender o
SKIP_ETAG_VERIFYpara abranger a verificação pós-upload, que é barata e improvisada, e exige que os usuários saibam que seu uso de SSE-C significa que eles terão que ativá-lo; ou - Mudar para usar o cabeçalho Content-MD5 (preferencialmente sempre) para fazer a proteção de integridade do upload, que tem o benefício de funcionar para todos, ao custo de um PR muito maior.
(Como aparte, estou bastante perturbado que ninguém tenha encontrado isso antes — ninguém está usando Discourse com SSE-C para uploads?)