Skip to content

SignatureV4 not setting "x-amz-content-sha256" header for OpenSearch Serverless requests #3145

@juniortads

Description

@juniortads

Describe the bug

When using the AWS SDK for PHP's SignatureV4 class with OpenSearch Serverless (AOSS), the x-amz-content-sha256 header is not automatically added to requests. This results in 403 Forbidden errors when making requests to AOSS endpoints, as this header is required by the service for proper authentication, even for requests without a body (like HEAD requests).

The issue appears to be in the SignatureV4 class logic, where the header is only added when the unsigned-body option is explicitly set to true, despite the request using HTTPS.

Regression Issue

  • Select this option if this issue appears to be a regression.

Expected Behavior

The SignatureV4 class should automatically add the x-amz-content-sha256 header with the value UNSIGNED-PAYLOAD for requests to OpenSearch Serverless endpoints, especially for requests without a body (like HEAD requests).

Alternatively, the SDK should clearly document that the unsigned-body option must be set to true for services like OpenSearch Serverless that require this header.

Current Behavior

When making requests to OpenSearch Serverless endpoints, the x-amz-content-sha256 header is not included in the request by default, resulting in 403 Forbidden errors. This happens because the $this->unsigned property in the SignatureV4 class is false by default, and the condition to set the header is not met.

Reproduction Steps

  1. Create a PHP script with the following code:
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;
use Aws\Credentials\CredentialProvider;
use Aws\Signature\SignatureV4;

// Set up credentials and client
$provider = CredentialProvider::defaultProvider();
$credentials = $provider()->wait();
$httpClient = new Client();

// Set up request to OpenSearch Serverless
$region = 'us-east-1';
$endpoint = 'https://your-collection-endpoint.aoss.amazonaws.com';
$indexName = 'your-index';

// Create and sign the request
$checkRequest = new Request('HEAD', $endpoint . '/' . $indexName);
$signer = new SignatureV4('aoss', $region);
$signedCheckRequest = $signer->signRequest($checkRequest, $credentials);

// Send the request
$checkResponse = $httpClient->send($signedCheckRequest);
  1. Run the script
  2. Observe the 403 Forbidden error

Possible Solution

1. Explicitly set the unsigned-body option to true:

$signer = new SignatureV4('aoss', $region, ['unsigned-body' => true]);

This forces the SignatureV4 class to use UNSIGNED-PAYLOAD as the payload value and add the x-amz-content-sha256 header.

2. Manually add the header before signing the request:

$checkRequest = $checkRequest->withHeader('X-Amz-Content-Sha256', 'UNSIGNED-PAYLOAD');
$signer = new SignatureV4('aoss', $region);
$signedCheckRequest = $signer->signRequest($checkRequest, $credentials);

This explicitly adds the required header with the correct value before the request is signed.

Either of these approaches will resolve the 403 Forbidden error when working with OpenSearch Serverless endpoints.

Additional Information/Context

Questions

  1. Is this the expected behavior of the SignatureV4 class, or is it a bug?
  2. Should the unsigned-body option be set to true by default for certain services like OpenSearch Serverless?
  3. Would it make sense to have a list of services that require the x-amz-content-sha256 header and automatically set it for those services?
  4. Is there a more elegant approach to handle this issue than the workarounds I've identified?

SDK version used

PHP: 8.4.10

Environment details (Version of PHP (php -v)? OS name and version, etc.)

AWS SDK for PHP: 3.349.2 | OpenSearch PHP Client: 2.4.3 | GuzzleHTTP: 7.9.3

Metadata

Metadata

Labels

closing-soonThis issue will automatically close in 4 days unless further comments are made.guidanceQuestion that needs advice or information.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions