.netamazon-web-servicesamazon-s3

`Invalid payload signature` with GarageHQ and Dotnet SDK


I'm trying to use GarageHQ with AWSSDK.S3 in my dotnet 8.0 API. I've followed the quick start guide and can successfully interact with my bucket using the aws cli.

However, it does not work in code. This is my implementation:

using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;

[HttpPost]
public async Task<IActionResult> UploadFile(IFormFile file)
{
    await using var memoryStream = new MemoryStream();
    await file.CopyToAsync(memoryStream);

    AmazonS3Client client = new(
      new BasicAWSCredentials("my_access_key", "my_secret_key"),
      new AmazonS3Config()
      {
          ServiceURL = "http://localhost:3900",
          ForcePathStyle = true,
          AuthenticationRegion = "garage",
      }
    );

    var uploadRequest = new PutObjectRequest()
    {
        AutoResetStreamPosition = true,
        BucketName = "my_bucket",
        InputStream = memoryStream,
        Key = file.FileName,
        CannedACL = S3CannedACL.PublicRead,
        ContentType = "image/png",
    };

    await _amazonS3Client.PutObjectAsync(uploadRequest);
}

But it fails. Here are the debug logs from garage:

2025-05-02T14:56:57.294311Z DEBUG garage_api_common::generic_server: Request { 
    method: PUT, 
    uri: /my_bucket/chewbacca.png, 
    version: HTTP/1.1, 
    headers: {
        "expect": "100-continue",
        "x-amz-acl": "public-read",
        "amz-sdk-invocation-id": "a60b0f52-d955-402c-a0d4-a8f2714ec4f4",
        "amz-sdk-request": "attempt=1; max=3",
        "x-amz-sdk-checksum-algorithm": "CRC32",
        "host": "localhost:3900",
        "x-amz-date": "20250502T145657Z",
        "x-amz-trailer": "x-amz-checksum-crc32",
        "x-amz-decoded-content-length": "56680",
        "x-amz-content-sha256": "STREAMING-AWS4-HMAC-SHA256-PAYLOAD-TRAILER",
        "authorization": "AWS4-HMAC-SHA256 Credential=my_access_key/20250502/garage/s3/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-acl;x-amz-content-sha256;x-amz-date;x-amz-decoded-content-length;x-amz-sdk-checksum-algorithm;x-amz-trailer, Signature=my_secret_key",
        "user-agent": "aws-sdk-dotnet-coreclr/4.0.0.1 ua/2.1 os/windows#10.0.26100.0 md/ARCH#X64 lang/.NET_Core#8.0.15 md/aws-sdk-dotnet-core#4.0.0.2 api/S3#4.0.0.1 md/ClientAsync cfg/init-coll#0 m/b,P,e,N,E,U,Z",
        "traceparent": "00-300b7b442da993dcf76354055fd2e441-1516c614a5337b41-00",
        "content-length": "56976",
        "content-type": "image/png"
    }, 
    body: Body(Streaming)
}
2025-05-02T14:56:57.294540Z DEBUG garage_api_common::generic_server: Endpoint: PutObject
2025-05-02T14:56:57.294821Z DEBUG garage_api_common::signature::streaming: Content signature mode: StreamingPayload { trailer: true, signed: true }
2025-05-02T14:56:57.295561Z DEBUG garage_api_s3::put: Object headers: [("content-type", "image/png")]
2025-05-02T14:56:57.305368Z  INFO garage_api_common::generic_server: Response: error 400 Bad Request, Bad request: Invalid payload signature

Thanks for the assistance


Solution

  • You might be getting Invalid payload signature because the AWS SDK is using chunked transfer encoding, which GarageHQ doesn't support.

    In your AmazonConfig set UseChunkEncoding = false