Skip to content

Commit

Permalink
Sanitize host name for AWS requests before signing in AWSAuthV4 trans…
Browse files Browse the repository at this point in the history
…port (#2090)
  • Loading branch information
Jan Hübner committed Jul 11, 2022
1 parent f72262d commit 857717a
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 3 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Updated `Query::create` PHPDoc to include supported types and propagate it to callers by @franmomu [#2088](https://github.com/ruflin/Elastica/pull/2088)
* Update some iterable types in PHPDoc to be more specific by @franmomu [#2092](https://github.com/ruflin/Elastica/pull/2092)
* Updated `AwsAuthV4Test` adding assertions for exception type by @franmomu [#2094](https://github.com/ruflin/Elastica/pull/2094)

* Update `AWSAuthV4 transport` to sanitize host name for AWS requests before signing [#2090](https://github.com/ruflin/Elastica/pull/2090)
### Deprecated
* Deprecated `Elastica\Reindex::WAIT_FOR_COMPLETION_FALSE`, use a boolean as parameter instead by @franmomu [#2070](https://github.com/ruflin/Elastica/pull/2070)
* Passing anything else than a boolean as 1st argument to `Reindex::setWaitForCompletion`, pass a boolean instead by @franmomu [#2070](https://github.com/ruflin/Elastica/pull/2070)
Expand Down
4 changes: 4 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,7 @@ parameters:
count: 1
path: tests/SnapshotTest.php

-
message: "#^Function GuzzleHttp\\\\Psr7\\\\modify_request not found\\.$#"
count: 1
path: src/Transport/AwsAuthV4.php
23 changes: 21 additions & 2 deletions src/Transport/AwsAuthV4.php
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use GuzzleHttp\Psr7;
use Psr\Http\Message\RequestInterface;

class AwsAuthV4 extends Guzzle
Expand Down Expand Up @@ -42,15 +43,33 @@ private function getSigningMiddleware(): callable
: \getenv('AWS_REGION');
$signer = new SignatureV4('es', $region);
$credProvider = $this->getCredentialProvider();
$transport = $this;

return Middleware::mapRequest(static function (RequestInterface $req) use (
$signer,
$credProvider
$credProvider,
$transport
) {
return $signer->signRequest($req, $credProvider()->wait());
return $signer->signRequest($transport->sanitizeRequest($req), $credProvider()->wait());
});
}

private function sanitizeRequest(RequestInterface $request): RequestInterface
{
// Trailing dots are valid parts of DNS host names (see RFC 1034),
// but interferes with header signing where AWS expects a stripped host name.
if ('.' === \substr($request->getHeader('host')[0], -1)) {
$changes = ['set_headers' => ['host' => \rtrim($request->getHeader('host')[0], '.')]];
if (\class_exists(Psr7\Utils::class)) {
$request = Psr7\Utils::modifyRequest($request, $changes);
} else {
$request = Psr7\modify_request($request, $changes);
}
}

return $request;
}

private function getCredentialProvider(): callable
{
$connection = $this->getConnection();
Expand Down
31 changes: 31 additions & 0 deletions tests/Transport/AwsAuthV4Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,35 @@ public function testSignsWithEnvironmentalCredentials(): void
);
}
}

/**
* @group unit
* @depends testSignsWithProvidedCredentials
*/
public function testStripsTrailingDotInHost(): void
{
$host = $this->_getHost();
$hostWithTrailingDot = $host.'.';

$config = [
'persistent' => false,
'transport' => 'AwsAuthV4',
'aws_access_key_id' => 'foo',
'aws_secret_access_key' => 'bar',
'aws_session_token' => 'baz',
'aws_region' => 'us-east-1',
'host' => $hostWithTrailingDot,
];
$client = $this->_getClient($config);

try {
$client->request('_stats');
} catch (GuzzleException $e) {
$guzzleException = $e->getGuzzleException();
$this->assertInstanceOf(ConnectException::class, $guzzleException);
$request = $guzzleException->getRequest();
$this->assertSame($host, $request->getHeader('host')[0]);
$this->assertSame($hostWithTrailingDot, $request->getUri()->getHost());
}
}
}

0 comments on commit 857717a

Please sign in to comment.