From 642d9321decd6658a8f2e6b9f87885c3d55ac6be Mon Sep 17 00:00:00 2001 From: Jonathan Eskew Date: Mon, 6 Jan 2020 05:18:53 -0500 Subject: [PATCH] Support an aws_credential_provider connection parameter for more flexible credentials strategies (#1667) --- CHANGELOG.md | 3 +- lib/Elastica/Transport/AwsAuthV4.php | 9 ++- test/Elastica/Transport/AwsAuthV4Test.php | 81 +++++++++++++++++++++++ 3 files changed, 90 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e33ea24e69..7e36836690 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,9 +11,10 @@ All notable changes to this project will be documented in this file based on the * Fixed handling of Search::OPTION_SEARCH_IGNORE_UNAVAILABLE inside Scroll object ### Added -Added `DiversifiedSampler` aggregation [#1735](https://github.com/ruflin/Elastica/pull/1735) +* Added `DiversifiedSampler` aggregation [#1735](https://github.com/ruflin/Elastica/pull/1735) * Added `\Elastica\Query\DistanceFeature` [#1730](https://github.com/ruflin/Elastica/pull/1730) +* Added support for injecting a callable AWS credential provider to use static, cached, or custom-sourced credentials [#1667](https://github.com/ruflin/Elastica/pull/1667) ### Improvements diff --git a/lib/Elastica/Transport/AwsAuthV4.php b/lib/Elastica/Transport/AwsAuthV4.php index 99fff2dcb6..184ca54aca 100755 --- a/lib/Elastica/Transport/AwsAuthV4.php +++ b/lib/Elastica/Transport/AwsAuthV4.php @@ -35,7 +35,7 @@ protected function _getBaseUrl(Connection $connection): string return parent::_getBaseUrl($connection); } - private function getSigningMiddleware() + private function getSigningMiddleware(): callable { $region = $this->getConnection()->hasParam('aws_region') ? $this->getConnection()->getParam('aws_region') @@ -51,9 +51,14 @@ private function getSigningMiddleware() }); } - private function getCredentialProvider() + private function getCredentialProvider(): callable { $connection = $this->getConnection(); + + if ($connection->hasParam('aws_credential_provider')) { + return $connection->getParam('aws_credential_provider'); + } + if ($connection->hasParam('aws_secret_access_key')) { return CredentialProvider::fromCredentials(new Credentials( $connection->getParam('aws_access_key_id'), diff --git a/test/Elastica/Transport/AwsAuthV4Test.php b/test/Elastica/Transport/AwsAuthV4Test.php index cb15a16d65..6ae409ae0e 100644 --- a/test/Elastica/Transport/AwsAuthV4Test.php +++ b/test/Elastica/Transport/AwsAuthV4Test.php @@ -2,6 +2,8 @@ namespace Elastica\Test\Transport; +use Aws\Credentials\CredentialProvider; +use Aws\Credentials\Credentials; use Elastica\Exception\Connection\GuzzleException; use GuzzleHttp\Exception\RequestException; @@ -14,6 +16,85 @@ public static function setUpBeforeClass() } } + /** + * @group unit + */ + public function testSignsWithProvidedCredentialProvider() + { + $config = [ + 'persistent' => false, + 'transport' => 'AwsAuthV4', + 'aws_credential_provider' => CredentialProvider::fromCredentials( + new Credentials('foo', 'bar', 'baz') + ), + 'aws_region' => 'us-east-1', + ]; + + $client = $this->_getClient($config); + + try { + $client->request('_status', 'GET'); + } catch (GuzzleException $e) { + $guzzleException = $e->getGuzzleException(); + if ($guzzleException instanceof RequestException) { + $request = $guzzleException->getRequest(); + $expected = 'AWS4-HMAC-SHA256 Credential=foo/' + .\date('Ymd').'/us-east-1/es/aws4_request, '; + $this->assertStringStartsWith( + $expected, + $request->getHeaderLine('Authorization') + ); + $this->assertSame( + 'baz', + $request->getHeaderLine('X-Amz-Security-Token') + ); + } else { + throw $e; + } + } + } + + /** + * @group unit + */ + public function testPrefersCredentialProviderToHardCodedCredentials() + { + $config = [ + 'persistent' => false, + 'transport' => 'AwsAuthV4', + 'aws_credential_provider' => CredentialProvider::fromCredentials( + new Credentials('foo', 'bar', 'baz') + ), + 'aws_access_key_id' => 'snap', + 'aws_secret_access_key' => 'crackle', + 'aws_session_token' => 'pop', + 'aws_region' => 'us-east-1', + ]; + + $client = $this->_getClient($config); + + try { + $client->request('_status', 'GET'); + } catch (GuzzleException $e) { + $guzzleException = $e->getGuzzleException(); + if ($guzzleException instanceof RequestException) { + $request = $guzzleException->getRequest(); + $expected = 'AWS4-HMAC-SHA256 Credential=foo/' + .\date('Ymd').'/us-east-1/es/aws4_request, '; + $this->assertStringStartsWith( + $expected, + $request->getHeaderLine('Authorization') + ); + $this->assertSame( + 'baz', + $request->getHeaderLine('X-Amz-Security-Token') + ); + } else { + throw $e; + } + } + } + /** * @group unit */