Я пытаюсь мигрировать существующий сервер Discourse в новую среду на базе AWS, сохраняя загрузки в бакет S3 с использованием серверного шифрования с ключами, управляемыми клиентом (SSE-C). В процессе восстановления загрузки не попадают в S3 — каждая попытка загрузки завершается ошибкой. С помощью тщательной отладки с использованием tap|p я обнаружил, что загрузка выполняется, но валидация возвращённого etag не проходит, потому что etag, возвращаемый S3 после загрузки, каждый раз разный. Например, вот результат вызова put_object при двух разных попытках восстановления:
# Запуск 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>
# Запуск 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>
(Я знаю, что это одни и те же файлы, потому что также вывожу контрольную сумму MD5 на стороне клиента и опции запроса put_object, которые включают имя файла.)
Оказывается, заголовок ответа ETag ведёт себя… иначе при использовании SSE-C:
Объекты, зашифрованные с помощью серверного шифрования с ключами, предоставленными клиентом (SSE-C), или ключами AWS Key Management Service (SSE-KMS), имеют ETag, который не является дайджестом MD5 их данных.
Единственный способ, который я нашёл для проверки целостности загрузок при использовании SSE-C, — это отправлять заголовок запроса Content-MD5 и доверить S3 обнаружение повреждений. Обратите также внимание, что проверка уже загруженных файлов также сломается при использовании SSE-C, но хотя бы её можно отключить с помощью SKIP_ETAG_VERIFY.
Я пока не отправляю PR, потому что есть два разных подхода к решению этой проблемы:
- Просто расширить
SKIP_ETAG_VERIFY, чтобы он охватывал проверку после загрузки. Это дёшево и немного хаки, но требует от пользователей знать, что использование SSE-C означает необходимость включить эту опцию; или - Перейти на использование заголовка
Content-MD5(предпочтительно всегда) для защиты целостности загрузок. Это имеет преимущество работы для всех, но потребует гораздо большего PR.
(Кстати, меня несколько беспокоит, что никто до сих пор не столкнулся с этой проблемой — неужели никто не использует Discourse с SSE-C для загрузок?!?)