AWS request signing (SigV4)¶
Note
Not part of core. Install it separately:
composer require kinetis/aws-sigv4
Wraps any PSR-18 HTTP client and signs every outgoing request with AWS Signature Version 4 before delegating to it — for talking to an AWS-signed endpoint (Amazon OpenSearch Service, API Gateway, and others) directly over HTTP rather than through a dedicated SDK client.
use Kinetis\AwsSigV4\SigV4SigningClient;
use Kinetis\RevoltHttpClient\AmpHttpClientFactory;
use Symfony\Component\HttpClient\Psr18Client;
$signedClient = new SigV4SigningClient(
client: new Psr18Client(AmpHttpClientFactory::create()),
region: 'us-east-1',
service: 'es', // Amazon OpenSearch Service's signing name
);
$response = $signedClient->sendRequest($request);
$service is the AWS signing service name — "es" for Amazon
OpenSearch Service, "execute-api" for API Gateway. There’s no default;
guessing wrong produces a signature that fails verification rather than
an obvious error.
Credentials¶
Resolved automatically the standard AWS way: AWS_ACCESS_KEY_ID/
AWS_SECRET_ACCESS_KEY, a shared credentials file, or an IAM role,
whichever is available first. Pass a CredentialProvider directly as
the fourth constructor argument to use something else instead:
use AsyncAws\Core\Credentials\Credentials;
$client = new SigV4SigningClient(
client: new Psr18Client(AmpHttpClientFactory::create()),
region: 'us-east-1',
service: 'es',
credentialProvider: new Credentials('AKIA...', 'secret-key'),
);
Amazon OpenSearch Service¶
OpenSearch\TransportFactory::setHttpClient() (see Search (OpenSearch))
accepts any PSR-18 client — SigV4SigningClient is one, so it drops in
directly in place of the plain Psr18Client wrapper, replacing Basic
auth with IAM-based signing:
use Kinetis\AwsSigV4\SigV4SigningClient;
use Kinetis\RevoltHttpClient\AmpHttpClientFactory;
use OpenSearch\Client;
use OpenSearch\EndpointFactory;
use OpenSearch\TransportFactory;
use Symfony\Component\HttpClient\Psr18Client;
// OpenSearch requires an explicit JSON Content-Type on every request.
$httpClient = new Psr18Client(AmpHttpClientFactory::create([
'headers' => ['Content-Type' => 'application/json', 'Accept' => 'application/json'],
]));
$signedClient = new SigV4SigningClient(
client: $httpClient,
region: 'us-east-1',
service: 'es',
baseUri: 'https://search-my-domain.us-east-1.es.amazonaws.com',
);
$transport = (new TransportFactory())->setHttpClient($signedClient)->create();
$client = new Client($transport, new EndpointFactory());
Set baseUri on SigV4SigningClient itself, not on the wrapped
Psr18Client — the OpenSearch client builds requests carrying only a
path, and baseUri is what supplies the scheme and host for those.
Leave it unset when the request you’re signing already carries a full
URI of its own (e.g. a plain RequestInterface you built directly for
API Gateway).
OpenSearchClientFactory::fromConfig() itself only ever builds the plain
Basic-auth path — construct the client directly, as above, to use IAM/
SigV4 authentication instead.
See also¶
Appendix: Revolt HTTP Client — the non-blocking HTTP client every example above wraps.
Search (OpenSearch) — building an
OpenSearch\Clientthe rest of the way, and what it can do once you have one.