-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
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
- 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);- Run the script
- 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
- Is this the expected behavior of the
SignatureV4class, or is it a bug? - Should the
unsigned-bodyoption be set totrueby default for certain services like OpenSearch Serverless? - Would it make sense to have a list of services that require the
x-amz-content-sha256header and automatically set it for those services? - 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