当前位置: 首页 > 知识库问答 >
问题:

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

微生慈
2023-03-14

我有一个无服务器的aws lambda,它将通过预先签名的URL将对象获取/放入加密的S3存储桶。getObject工作得很好。一旦我加密存储桶,putObject就会生成SignatureDesNotMatch错误,我无法理解原因。我玩过头球之类的游戏,但仍然无法让它发挥作用。守则/政策如下:

λ

    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

上传到PreSigned URL(原始问题没有serversid加密头)

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对象--bucket mybiggetybucket--key test.json--body package-lock.json--服务器端加密“AES256”

共有1个答案

柏阳炎
2023-03-14

要引用服务器端加密文档,请执行以下操作:

您不能对使用预签名URL上载的对象强制执行SSE-S3加密。只能使用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);
  }
});
 类似资料:
  • 标题说明一切。这是我的代码; 我使用节点强大的文件。 成功上传后,url变量返回s3 url,类似以下内容; 下面是我的参数 我错过了什么?

  • 有没有办法让预签名的aws上传URL在出现错误时返回json响应,而不是xml响应。 目前,如果url过期,它会返回如下内容。 如果这是json响应就好了。

  • 我正试图通过一个预先签名的URL将一个文件上传到Amazon S3 bucket,这是我从第三个服务获得的。意思是,我没有生成这个URL。我已经阅读了AWS文档,但我不能把它们全部放在一起。这就是我指的。 预选。php 目前,我的代码是这样的。请注意,

  • 使用curl或postman,我得到403禁止: Lambda函数具有以下权限: S3桶具有以下CORS规则:

  • 我试图上传一个图像使用预先签名的网址 我得到了一个类似的url https://s3.eu-west-1.amazonaws.com/bucket/folder/access.JPG?AWSAccessKeyId=xxxx 我已经尝试上传文件与内容类型图像/jpg,多部分/表单数据。 尝试生成没有文件类型和上传的网址。 尝试了放后法 但似乎什么都不管用 错误总是: 我们计算的请求签名与您提供的签名

  • 我试图使用S3预签名的PUT url执行文档上传。我使用java AWSSDK(GeneratePresignedUrlRequest.java)生成url。此url生成代码位于AWS API网关后面的lambda函数中。 然而,当我在Postman中复制生成的url时,我遇到了以下错误 生成的url是“https:// 关于在生成url时需要更正的内容,有什么建议吗?