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) (#2090)

Co-authored-by: Jan Hübner <[email protected]>
Co-authored-by: Nicolas Ruflin <[email protected]>
  • Loading branch information
3 people authored Aug 30, 2022
1 parent a43d43c commit 878acd2
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Bumped `elasticsearch/elasticsearch` to `7.10` to be able to use `OpenPointInTime` class [#2113](https://github.com/ruflin/Elastica/pull/2113)
* Updated `php-cs-fixer` to `3.9.5` [#2110](https://github.com/ruflin/Elastica/pull/2110)
* Changed `Elastica\Index\Settings::get` adding ability to get default settings by @krasilnikovm [#2115](https://github.com/ruflin/Elastica/pull/2115)
* Update `AWSAuthV4 transport` to sanitize host name for AWS requests before signing [#2090](https://github.com/ruflin/Elastica/pull/2090)
* New method `Elastica\Aggregation\Terms::setMissingBucket`. For Composite Agg. Include in the response documents without a value for a given source. [#2117](https://github.com/ruflin/Elastica/pull/2117)
### Deprecated
### Removed
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 878acd2

Please sign in to comment.