Нам нужно перенести несколько больших файлов на S3 и зашифровать их во время передачи. Я хотел бы использовать AWS TransferManager
, чтобы воспользоваться преимуществами многоэтапной загрузки и других функций.
Клиент AmazonS3Encryption
запишет два поля метаданных x-amz-iv
(вектор инициализации) и x-amz-key
(ключ содержимого) к местоположению S3, и эти два поля необходимы для расшифровки файла.
Однако TransferManager
теряет эти значения метаданных и не записывает их в местоположение. Я пытаюсь выяснить, можно ли каким-то образом добраться до них и заставить их записать или добавить их в расположение после завершения передачи.
Я обнаружил эту старую проблему, которая, кажется, очень тесно связаны, он довольно старый, и я думаю, что API изменились с тех пор, и предлагаемые обходные пути не работают для меня, потому что я не могу найти способ получить поля метаданных от клиента s3.
https://github.com/aws/aws-sdk-java/issues/367
Насколько я понимаю, ключ содержимого зашифрован для каждого клиента s3, а IV предоставляется для каждого файла, поэтому мне нужно было бы получить к клиенту сразу же после его записал каждый файл.
В соответствии с AWS документами я создаю AmazonS3Encryption
, например:
AmazonS3Encryption s3Encryption = AmazonS3EncryptionClientBuilder
.standard()
.withRegion(Regions.US_WEST_2)
.withCryptoConfiguration(new CryptoConfiguration(CryptoMode.EncryptionOnly))
.withEncryptionMaterials(new StaticEncryptionMaterialsProvider(new EncryptionMaterials(secretKey)))
.build();
, а затем создаем TransferManager
следующим образом:
TransferManager transferManager =
TransferManagerBuilder.standard().withS3Client(s3Encryption).build();
Я пробовал transferManager.upload()
, а также варианты, такие как uploadFileList()
, которые позволяют мне предоставить ObjectMetadataProvider
, но я не могу найти способ получить метаданные для записи.
Я нашел то, что Я думаю, что курение г un, класс UploadCallable
в AWS:
https://github.com/aws/aws-sdk-java/blob/ccfd63c097874e3a1e9ffda7bf171769b6bd3b21/aws-java-sdk-s3/src/main/java/com/amazonaws/services/s3/transfer/internal/UploadCallable.java#L131
private UploadResult uploadInOneChunk() {
PutObjectResult putObjectResult = s3.putObject(origReq);
UploadResult uploadResult = new UploadResult();
uploadResult.setBucketName(origReq.getBucketName());
uploadResult.setKey(origReq.getKey());
uploadResult.setETag(putObjectResult.getETag());
uploadResult.setVersionId(putObjectResult.getVersionId());
return uploadResult;
}
PutObjectResult
, возвращаемый из s3
, содержит необходимые метаданные , но, к сожалению, он просто игнорируется и возвращается другой результат.
Я копался в коде, пытаясь найти ловушку, чтобы сделать это, не прибегая к ужасным Java Reflection hacks. До сих пор я пытался:
- Подклассы
AmazonS3EncryptionClient
, что не может быть сделано, потому что его класс построителя public final
- Предоставление альтернативного
UploadCallable
для TransferManager
, не могу найти никакой ловушки для этого - Получение внутренних крипто-классов экземпляра
AmazonS3EncryptionClient
, которые содержат значения, которые мне нужны, но все они закрыты и скрыты на нескольких уровнях
и др c. На данном этапе я думаю, что мой единственный вариант - либо бросить свой собственный TransferManager
, либо просто жить с прямым клиентом s3, но это кажется довольно существенным недостатком в клиенте AWS, поэтому мне интересно, что я что-то упустил. Спасибо за любую помощь.