Как использовать AWS Signature v4 при создании предварительно назначенного URL-адреса S3? - PullRequest
0 голосов
/ 29 апреля 2018

Я наследую кодовую базу, которая использует Java AWS SDK для генерации предопределенных URL-адресов S3 для объектов Puting и Getting. Код выглядит примерно так:

GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucket, filename);
request.setMethod(HttpMethod.PUT);
request.setExpiration(new DateTime().plusMinutes(30).toDate());
request.setContentType("image/jpeg");
String url = awss3.generatePresignedUrl(request);

И эта существующая кодовая база всегда работала и очень близка к работе. Однако одно бизнес-требование, которое изменилось, заключается в том, что нам необходимо зашифровать содержимое корзины S3. Поэтому, естественно, я установил шифрование по умолчанию в корзине на AWS-KMS (так как оно казалось самым современным) и выбрал ключ по умолчанию «aws / s3», который был создан для моей учетной записи.

Однако теперь, когда конечный пользователь пытается фактически использовать URL-адреса, которые я генерирую в их браузере, появляется следующее сообщение об ошибке:

<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <code>InvalidArgument</code>
  <Message>Requests specifying Server Side Encryption with AWS KMS managed keys require AWS Signature Version 4.</Message>
  <ArgumentName>Authorization</ArgumentName>
  <ArgumentValue>null</ArgumentValue>
  <RequestId>...</RequestId>
  <HostId>...</HostId>
</Error>

Мой вопрос совершенно неясен: как мне снова заставить это работать? На мой взгляд, есть два разных пути, по которым я мог бы пойти. Либо: 1) я мог бы понизить кодирование с AWS-KMS до AES-256 и надеяться, что все это работает, или 2) я могу внести некоторые изменения в свой клиентский код для поддержки KMS, что, вероятно, потребует загрузки ключ KMS через AWS SDK и использование его для подписи запросов, а также, возможно, добавление авторизации и других заголовков.

Вариант 1 выглядит менее трудоемким, но также менее идеальным, потому что кто знает, всегда ли будет поддерживаться менее безопасная форма шифрования. Вариант 2 кажется более концептуально лучшим выбором, но он также вызывает некоторые опасения, потому что он кажется намного более трудоемким, и я беспокоюсь о необходимости включать дополнительные заголовки. Код, который я показал выше, отражает эквивалент запроса PutObject (прокси через сгенерированный URL), но есть также эквиваленты запросов GetObject для загрузки изображений, которые, возможно, отображаются непосредственно в браузере. Было бы намного сложнее написать там код внешнего интерфейса, чтобы использовать разные заголовки только для визуализации изображения. (Интересно, могут ли параметры запроса заменять заголовки?)

В любом случае, что мне нужно изменить в Java, чтобы это работало с AWS KMS? Нужно ли использовать AWS SDK для «загрузки» ключа KMS, как я и подозревал? И должен ли я пойти по этому пути, или AES-256 действительно будет лучшим вариантом?

1 Ответ

0 голосов
/ 30 апреля 2018

Подписание подписи verion 4 было по умолчанию уже несколько лет. Если вы не переопределяете подпись в своем профиле AWS SDK, то вы используете версию 4. Вы можете переопределить это, используя следующий код:

AmazonS3Client s3 = new AmazonS3Client(new  ClientConfiguration().withSignerOverride("AWSS3V4SignerType"));

Скорее всего, реальная проблема заключается в том, что вам необходимо указать шифрование на стороне сервера при создании предварительно заданного URL-адреса.

GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(
    myBucket, myKey, HttpMethod.PUT)
    .withSSEAlgorithm(SSEAlgorithm.KMS.getAlgorithm());

request.setExpiration(new DateTime().plusMinutes(30).toDate());
request.setContentType("image/jpeg");

URL puturl = s3.generatePresignedUrl(request);
...