How to generate AWS S3 pre-signed URL using signature version 4

邮差的信 提交于 2019-12-23 17:19:27

问题


I am generating a pre-signed URL in a C# .NET Core 2.0 API controller class using the AWSSDK.S3 (3.3.31.11). The resulting URL is intended to be used by a client side Angular application to upload a file to an S3 bucket that is encrypted using SSE-KMS. Although the S3Client reports that the SignatureMethod is "HmacSHA256" and SignatureVersion is "4", when I try to upload a file using the pre-signed URL I get an error indicating "Requests specifying Server Side Encryption with AWS KMS managed keys require AWS Signature Version 4."

The S3Client is being injected as a dependency to the controller class. Instantiation of the object is managed by .NET Core DI framework using configuration settings in a config.json file:

{
    ...
    "AWS": {
        "Profile": "default",
        "Region": "us-east-1"
    }
    ...
}

I am testing the pre-signed URL using curl:

curl -H "Content-Type: application/pdf" -H "x-amz-server-side-encryption: aws:kms" -H "x-amz-server-side-encryption-aws-kms-key-id: {kms-key-id}" -k -T "filename.pdf" "https://mybucketname.s3.amazonaws.com/filename.pdf?AWSAccessKeyId={keyid}&Expires={expires}&x-amz-security-token={token}&Signature={signature}"

I've discovered that if I don't include the "Content-Type" header I receive a "SignatureDoesNotMatch" error code, rather than the "InvalidArgument" error.

This process had been working previously when using default AES-256 encryption for the S3 bucket, it is only in converting to SSE-KMS that I have encountered this problem.

// Controller Class
private readonly IAmazonS3 _s3Client;

public MyController(IAmazonS3 s3Client)
{
    _s3Client = s3Client;
}

[HttpPost]
public async Task<IActionResult> GetPreSignedUrl([FromBody] FileInfoDto fileInfo)
{
    ...
    GetPreSignedUrlRequest request = new GetPreSignedUrlRequest
    {
        BucketName = bucketName, 
        Key = fileInfo.name, 
        Verb = HttpVerb.PUT,
        ContentType = fileInfo.contentType, 
        Expires = DateTime.Now.AddMinutes(5),
        ServerSideEncryptionKeyManagementServiceKeyId = keyId, 
        ServerSideEncryptionMethod = ServerSideEncryptionMethod.AWSKMS
    };

    try
    {
        url = _s3Client.GetPreSignedURL(request);
    }
    ...
}

// Startup Class
public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddDefaultAWSOptions(_config.GetAWSOptions());
    services.AddAWSService<IAmazonS3>();
    ...
}

When uploading the file using curl and the pre-signed URL that was generated by the controller method, I am getting a response error code of "InvalidArgument" and message "Requests specifying Server Side Encryption with AWS KMS managed keys require AWS Signature Version 4." However, the S3Client reports that SignatureVersion is "4".

What should I be doing differently in order to generate the pre-signed URL using signature version 4?


回答1:


Despite the fact that the s3Client reports Signature Version as "4", the following line, added to the ConfigureServices method, resolves the issue and results in generating a pre-signed URL conforming to Signature Version 4:

AWSConfigsS3.UseSignatureVersion4 = true;

The pre-signed URL that is generated is as follows:

https://mybucketname.s3.amazonaws.com/filename.pdf?X-Amz-Expires=1800&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential={credential}/20190127/us-east-1/s3/aws4_request&X-Amz-Date={date}&X-Amz-SignedHeaders=content-type;host;x-amz-server-side-encryption&X-Amz-Signature={signature}


来源:https://stackoverflow.com/questions/54369427/how-to-generate-aws-s3-pre-signed-url-using-signature-version-4

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!