putObject通过加密S3存储桶上的预签名url返回签名不匹配



我有一个无服务器的aws lambda,它将通过预签名的url将对象获取/放入加密的S3桶中。getObject工作得很好。putObject在我加密bucket后生成SignatureDoesNotMatch错误,我不明白为什么。我打过头球之类的比赛,但仍然无法发挥作用。以下代码/政策:

λ

const generatepresignedurl = (req, res, callback) => {
var fileurls = [];
const body = JSON.parse(req.body);
const theBucket = body['theBucket'];
const theKey = body['theKey'];
const theContentType = body['theContentType'];
const theOperation = body['theOperation'];
/*setting the presigned url expiry time in seconds, also check if user making the request is an authorized user
for your app (this will be specific to your app’s auth mechanism so i am skipping it)*/
const signedUrlExpireSeconds = 60 * 60;
if (theOperation == 'getObject') {
var params = {
Bucket: theBucket,
Key: theKey,
Expires: signedUrlExpireSeconds
};
} else {
var params = {
Bucket: theBucket,
Key: theKey,
Expires: signedUrlExpireSeconds,
ACL: 'bucket-owner-full-control',
ContentType: theContentType,
ServerSideEncryption: 'AES256'
};
}
s3.getSignedUrl(theOperation, params, function (err, url) {
if (err) {
console.log('Error Getting Presigned URL from AWS S3');
// callback(null, ({ success: false, message: 'Pre-Signed URL error', urls: fileurls }));
callback(null, {error: err});
}
else {
fileurls[0] = url;
console.log('Presigned URL: ', fileurls[0]);
callback(null, { success: true, message: 'AWS SDK S3 Pre-signed urls generated successfully.', urls: fileurls });
}
});
}

呼叫代码在这里:

生成预签名Url

Function callStandAloneAWSService(lambda As String, request As String, contentType As String) As String
Dim httpserver As New MSXML2.XMLHTTP
With httpserver
Dim theURL As String
theURL = AWS_WEBSERVICE_URL_DEV
.Open "POST", theURL & lambda 'variable that contains generatepresignedurl
.setRequestHeader "Content-type", contentType
.send request
Do: DoEvents: Loop Until .readyState = 4 'make sure we are ready to recieve response
callStandAloneAWSService = .responseText
End With
End Function

上传到预签名URL(原始问题没有服务器端加密头(

Function uploadToPreSignedURL(url As String, whichFile As String, contentType) As Boolean
'code to create binaryFile
Dim httpserver As New MSXML2.XMLHTTP
With httpserver
.Open "POST", url
.setRequestHeader "Content-type", "text/plain" 'contentType
.send binaryFile
Do: DoEvents: Loop Until .readyState = 4 'make sure we are ready to recieve response
If Len(.responseText) = 0 Then
uploadToPreSignedURL = True
Else
'extract error message from xml and write to report mail
End If
End With
End Function

存储桶策略

{
"Version": "2012-10-17",
"Id": "S3PolicyId1",
"Statement": [
{
"Sid": "DenyIncorrectEncryptionHeader",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::mybiggetybucket/*",
"Condition": {
"StringNotEquals": {
"s3:x-amz-server-side-encryption": "AES256"
}
}
},
{
"Sid": "DenyUnEncryptedObjectUploads",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::mybiggetybucket/*",
"Condition": {
"Null": {
"s3:x-amz-server-side-encryption": "true"
}
}
}
]
}

FWIW,我可以通过aws-cli运行它并使其工作:

aws s3api put object--bucket mybiggetybucket--key test.json--body package-lock.json--服务器端加密"AES256">

引用服务器端加密文档:

您不能对使用预签名的URL。只能使用指定服务器端加密AWS管理控制台或HTTP请求标头。了解更多信息有关信息,请参阅在策略中指定条件。

我也能做一些类似的工作。我需要使用PUT而不是POST,并且我需要提供x-amz-server-side-encryption:AES256作为标头,如下所示:

const axios = require('axios');
const AWS = require('aws-sdk');
const s3 = new AWS.S3();
const params = {
Bucket: 'mybucket',
Key: 'myfolder/myfile.txt',
Expires: 60 * 60,
ACL: 'bucket-owner-full-control',
ContentType: 'text/plain',
ServerSideEncryption: 'AES256',
};
const axiosConfig = {
headers: {
'Content-Type': 'text/plain',
'x-amz-server-side-encryption': 'AES256',
},
};
const uploadTextFile = (presignedurl) => {
axios.put(presignedurl, 'some text here', axiosConfig).then((res) => {
console.log('File uploaded');
}).catch((error) => {
console.error(error);
});
};
s3.getSignedUrl('putObject', params, (err, url) => {
if (err) {
console.error(err);
} else {
console.log('Pre-signed URL:', url);
uploadTextFile(url);
}
});

最新更新