Я пытаюсь использовать подписанную политику, сгенерированную моей серверной частью Node.js, чтобы авторизовать POST на основе браузера для S3 на внешнем интерфейсе, то есть Angular 6. Учетные данные, которые я использую, определенно правильны и могут быть использованы для успешногоs3.putObject()
или s3.upload()
из бэкэнда.Я изучил документацию и перепробовал много разных вещей, но, несмотря ни на что, я получаю, что эта кровавая подпись не соответствует ошибке.
Это то, что публикуется, как показано инструментами разработчика Chrome (заменил ключ доступа на XXXXXXXXXXXXXXXXXXXX по понятным причинам:
key: test
success_action_status: 204
Content-Type: image/tiff; charset=UTF-8
X-Amz-Credential: XXXXXXXXXXXXXXXXXXXX/20181024T144545679Z/us-east-1/s3/aws4_request
X-Amz-Algorithm: AWS4-HMAC-SHA256
X-Amz-Date: 20181024T144545679Z
Policy: eyJleHBpcmF0aW9uIjoiMjAxOC0xMC0yNFQxNTo0NTo0NS42NzlaIiwiY29uZGl0aW9ucyI6W3siYnVja2V0Ijoid21nLWZhc3QtdHJhY2stcWEtbWVkaWEifSxbInN0YXJ0cy13aXRoIiwiJENvbnRlbnQtVHlwZSIsImltYWdlLyJdLHsia2V5IjoidGVzdCJ9LHsieC1hbXotYWxnb3JpdGhtIjoiQVdTNC1ITUFDLVNIQTI1NiJ9LHsieC1hbXotY3JlZGVudGlhbCI6IkFLSUFKS1dKTzZBTzdBVFRPQktRLzIwMTgxMDI0VDE0NDU0NTY3OVovdXMtZWFzdC0xL3MzL2F3czRfcmVxdWVzdCJ9LHsieC1hbXotZGF0ZSI6IjIwMTgxMDI0VDE0NDU0NTY3OVoifSx7InN1Y2Nlc3NfYWN0aW9uX3N0YXR1cyI6IjIwNCJ9XX0=
X-Amz-Signature: 067960dfb2607b69b078eb625b63f2659d47f2e4c2b5af4dc135c5f317492e8e
file: (binary)
Вот как выглядит политика JSON при расширении и строковости:
{
"expiration": "2018-10-24T15:41:28.737Z",
"conditions": [
{
"bucket": "wmg-fast-track-qa-media"
},
[
"starts-with",
"$Content-Type",
"image/"
],
{
"key": "test"
},
{
"x-amz-algorithm": "AWS4-HMAC-SHA256"
},
{
"x-amz-credential": "XXXXXXXXXXXXXXXXXXXX/20181024T144128737Z/us-east-1/s3/aws4_request"
},
{
"x-amz-date": "20181024T144128737Z"
},
{
"success_action_status": 204
}
]
}
Далее я покажу маршрут Node.js / Express, который генерирует подписанную политику и подпись. Маршрут вызывает функцию getCredentials()
внизу, которая вызывает другие функции для генерации учетных данных:
'use strict';
const moment = require('moment');
const sha256 = require('js-sha256');
const utf8 = require('utf8');
const BUCKET = process.env.AWS_BUCKET_NAME;
const AWS_ACCESS_KEY_ID = process.env.AWS_ACCESS_KEY_ID;
const AWS_REGION = process.env.AWS_REGION;
const AWS_SECRET_ACCESS_KEY = process.env.AWS_SECRET_ACCESS_KEY;
async function hmac(key, secret) {
return sha256.hmac(key, secret)
}
async function hmacHex(key, secret) {
const hash = sha256.hmac.create(key);
hash.update(secret);
return hash.hex();
}
function getXAmzCredential(date) {
return `${AWS_ACCESS_KEY_ID}/${date}/${AWS_REGION}/s3/aws4_request`;
}
async function getStringToSign(date, type) {
const expDate = moment().add(1, 'h').toISOString();
const policy = {
"expiration": expDate,
"conditions": [
{"bucket": BUCKET},
["starts-with", "$Content-Type", `${type}/`],
{"key": "test"},
{"x-amz-algorithm": "AWS4-HMAC-SHA256"},
{"x-amz-credential": getXAmzCredential(date)},
{"x-amz-date": date},
{"success_action_status": 204}
]
};
const str = utf8.encode(JSON.stringify(policy).replace(/\r/g, ''));
return new Buffer.from(str).toString('base64');
}
async function getSigningKey(date) {
const dateKey = await hmac("AWS4" + AWS_SECRET_ACCESS_KEY, date);
const dateRegionKey = await hmac(dateKey, AWS_REGION);
const dateRegionServiceKey = await hmac(dateRegionKey, "s3");
return await hmac(dateRegionServiceKey, "aws4_request");
}
async function getCredentials(req, res) {
const type = req.body.upload_type;
const date = moment().toISOString();
const d = date.replace(/[:.-]/g,'');
const stringToSign = await getStringToSign(d, type);
const signingKey = await getSigningKey(d);
const signature = await hmacHex(signingKey, stringToSign);
const credential = getXAmzCredential(d);
console.log(`x-amz-credential: ${credential}`);
const response = {
policy: stringToSign,
signature: signature,
date: d,
xamzCredential: credential
};
res.json(response);
}
module.exports = {
getCredentials
};
Если кто-то может увидеть, что я здесь делаю неправильно или у меня есть предложение, я заранее благодарю вас.