Skip to content

S3 request signing broken for S3-compatible services #933

@Sumo-MBryant

Description

@Sumo-MBryant

If one is to use an S3-compatible service (e.g. for integration testing by mocking S3), signed requests are no longer valid as of this commit fbea753, which appears to use a heuristic to detect whether a request is being made to S3.

When using an S3-compatible service the ClientConfig.ServiceUrl might no longer satisfy the heuristic which appears to check the endpoint host name, and as such the resourcePath is double encoded and no longer signs correctly.

This is the heuristic:

private const string S3EndpointPattern = @"^(.+\.)?s3[.-]([a-z0-9-]+)\.";

and its use:

// S3 is a special case. For S3 skip the pre encode.
// For everything else URL pre encode the resource path segments.
if (!S3Uri.IsS3Uri(endpoint))
{
encodedSegments = encodedSegments.Select(segment => UrlEncode(segment, true));
pathWasPreEncoded = true;
}

Expected Behavior

When connecting to an S3-compatible service using ClientConfig.ServiceUrl, all S3 requests including those using characters that are transformed during URL encoding should be correctly signed according the version 4 signature scheme.

The CanonicalizeResourcePath() function should only single encode requests.

Current Behavior

The S3-compatible service rejects the request that include characters that are transformed during URL encoding.

Consider an attempt to store an object to a content bucket and object key: Alp?ha/Be%ta /Test&ing.

CanonicalizeResourcePath() was called with the following arguments:

endpoint = "http://192.168.99.100:33886/"
resourcePath = "/content/Alp?ha/Be%ta /Test&ing"
detectPreEncode = true

The function logged the following:

Double encoded /content/Alp?ha/Be%ta /Test&ing with endpoint http://192.168.99.100:33886/ for canonicalization: /content/Alp%253Fha/Be%2525ta%2520/Test%2526ing

Possible Solution

  1. It appears that the that signing code is invoked from the S3 client code which intrinsically knows only single URL encoding is required. Expose the functionality through the AWS4Signer such that all S3 requests are only single encoded.

  2. If that isn't possible, provide some means for configuration to disable the heuristic and double encoding.

Context

We have some integration tests that ensure our code correctly handles paths sensitive to URL encoding when storing objects in S3. Upon upgrade to AWSSDK.Core 3.3.21.15 and later, this test started to fail.

Your Environment

  • AWSSDK.Core version used: 3.3.21.20
  • Service assembly and version used: AWSSDK.S3 3.3.18
  • Operating System and version: Microsoft Windows 10
  • Targeted .NET platform: .NET Core 2.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugThis issue is a bug.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions