AWS TransferManager теряет связанные с шифрованием метаданные при записи с AmazonS3Encryption - PullRequest
0 голосов
/ 16 апреля 2020

Нам нужно перенести несколько больших файлов на 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, поэтому мне интересно, что я что-то упустил. Спасибо за любую помощь.

...