diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index be563a1..f2c0fe5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,8 @@ jobs: strategy: matrix: operating-system: [ubuntu-latest] - php-versions: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4'] + php-versions: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] + fail-fast: false name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.operating-system }} steps: diff --git a/composer.json b/composer.json index 513e8a1..81f9745 100644 --- a/composer.json +++ b/composer.json @@ -47,7 +47,7 @@ "ext-sockets": "*", "drupal/coder": "^8.3", "symfony/dotenv": "^3.4", - "phpunit/phpunit": "^5.7|^6.6|^7.5", + "phpunit/phpunit": "^5.7|^6.6|^9.3", "monolog/monolog": "^1.24", "composer/composer": "^1.8", "mikey179/vfsstream": "^1.6", diff --git a/src/Credential/Config.php b/src/Credential/Config.php index f43902b..e83b0a2 100644 --- a/src/Credential/Config.php +++ b/src/Credential/Config.php @@ -41,7 +41,7 @@ class Config public $expiration = 0; - public $enableIMDSv2 = false; + public $disableIMDSv1 = false; public $metadataTokenDuration = 21600; diff --git a/src/EcsRamRoleCredential.php b/src/EcsRamRoleCredential.php index fb19c26..8662f77 100644 --- a/src/EcsRamRoleCredential.php +++ b/src/EcsRamRoleCredential.php @@ -24,7 +24,7 @@ class EcsRamRoleCredential implements CredentialsInterface /** * @var boolean */ - private $enableIMDSv2; + private $disableIMDSv1; /** * @var int @@ -37,15 +37,15 @@ class EcsRamRoleCredential implements CredentialsInterface * * @param $role_name */ - public function __construct($role_name = null, $enable_IMDS_v2 = false, $metadata_token_duration = 21600 ) + public function __construct($role_name = null, $disable_imdsv1 = false, $metadata_token_duration = 21600 ) { Filter::roleName($role_name); $this->roleName = $role_name; - Filter::enableIMDSv2($enable_IMDS_v2); + Filter::disableIMDSv1($disable_imdsv1); - $this->enableIMDSv2 = $enable_IMDS_v2; + $this->disableIMDSv1 = $disable_imdsv1; Filter::metadataTokenDuration($metadata_token_duration); @@ -136,7 +136,7 @@ public function getAccessKeyId() protected function getSessionCredential() { $config = [ - 'enableIMDSv2' => $this->enableIMDSv2, + 'disableIMDSv1' => $this->disableIMDSv1, 'metadataTokenDuration' => $this->metadataTokenDuration, ]; return (new EcsRamRoleProvider($this, $config))->get(); @@ -172,4 +172,12 @@ public function getExpiration() return $this->getSessionCredential()->getExpiration(); } + /** + * @return bool + */ + public function isDisableIMDSv1() + { + return $this->disableIMDSv1; + } + } diff --git a/src/Filter.php b/src/Filter.php index 215695d..1811a33 100644 --- a/src/Filter.php +++ b/src/Filter.php @@ -100,12 +100,12 @@ public static function roleName($role_name) } /** - * @param boolean|null $enable_IMDS_v2 + * @param boolean|null $disable_IMDS_v1 */ - public static function enableIMDSv2($enable_IMDS_v2) + public static function disableIMDSv1($disable_imdsv1) { - if (!is_bool($enable_IMDS_v2)) { - throw new InvalidArgumentException('enable_IMDS_v2 must be a string'); + if (!is_bool($disable_imdsv1)) { + throw new InvalidArgumentException('disable_IMDS_v1 must be a boolean'); } } diff --git a/src/Providers/EcsRamRoleProvider.php b/src/Providers/EcsRamRoleProvider.php index 1f09482..b2c53b7 100644 --- a/src/Providers/EcsRamRoleProvider.php +++ b/src/Providers/EcsRamRoleProvider.php @@ -42,7 +42,7 @@ class EcsRamRoleProvider extends Provider /** * @var string */ - private $metadataToken; + private $metadataToken = null; /** * @var string @@ -84,13 +84,13 @@ public function get() } - protected function getEnableECSIMDSv2() + protected function getDisableECSIMDSv1() { - if (Helper::envNotEmpty('ALIBABA_CLOUD_ECS_IMDSV2_ENABLE')) { - return Helper::env('ALIBABA_CLOUD_ECS_IMDSV2_ENABLE') === true ? true : false; + if (Helper::envNotEmpty('ALIBABA_CLOUD_IMDSV1_DISABLE')) { + return Helper::env('ALIBABA_CLOUD_IMDSV1_DISABLE') === true ? true : false; } - if(isset($this->config['enableIMDSv2'])) { - return $this->config['enableIMDSv2']; + if(isset($this->config['disableIMDSv1'])) { + return $this->config['disableIMDSv1']; } return false; } @@ -113,8 +113,8 @@ public function request() 'connect_timeout' => 1, ]; - if ($this->getEnableECSIMDSv2()) { - $this->refreshMetadataToken(); + $this->metadataToken = $this->refreshMetadataToken(); + if(!is_null($this->metadataToken)) { $options['headers']['X-aliyun-ecs-metadata-token'] = $this->metadataToken; } @@ -135,14 +135,14 @@ public function request() /** * Get metadata token by request. * - * @return ResponseInterface + * @return bool * @throws Exception * @throws GuzzleException */ protected function refreshMetadataToken() { if(!$this->needToRefresh()) { - return; + return $this->metadataToken; } $credential = $this->credential; $url = $this->metadataHost . $this->metadataTokenUri; @@ -161,12 +161,12 @@ protected function refreshMetadataToken() if ($result->getStatusCode() != 200) { $this->staleTime = $tmpTime; - throw new RuntimeException('Failed to get token from ECS Metadata Service. HttpCode= ' . $result->getStatusCode()); + if ($this->getDisableECSIMDSv1()) { + throw new RuntimeException('Failed to get token from ECS Metadata Service. HttpCode= ' . $result->getStatusCode()); + } + return null; } - - $this->metadataToken = $result->getBody(); - - return; + return (string) $result->getBody(); } diff --git a/tests/Feature/CredentialTest.php b/tests/Feature/CredentialTest.php index a797fe8..29f1704 100644 --- a/tests/Feature/CredentialTest.php +++ b/tests/Feature/CredentialTest.php @@ -9,6 +9,7 @@ use GuzzleHttp\Exception\GuzzleException; use PHPUnit\Framework\TestCase; use ReflectionException; +use RuntimeException; /** * Class CredentialTest @@ -51,6 +52,13 @@ public function testEcsRamRoleCredential() ]); $credential = new Credential($config); + $this->expectException(\GuzzleHttp\Exception\ConnectException::class); + if (method_exists($this, 'expectExceptionMessageMatches')) { + $this->expectExceptionMessageMatches('/timed/'); + } elseif (method_exists($this, 'expectExceptionMessageRegExp')) { + $this->expectExceptionMessageRegExp('/timed/'); + } + // Assert $this->assertEquals('foo', $credential->getRoleName()); $this->assertEquals('ecs_ram_role', $credential->getType()); @@ -98,11 +106,13 @@ public function testRsaKeyPairCredential() 'privateKeyFile' => $privateKeyFile, ]); $credential = new Credential($config); - + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Specified access key type is not match with signature type.'); // Assert $this->assertTrue(null !== $credential->getAccessKeyId()); $this->assertTrue(null !== $credential->getAccessKeySecret()); $this->assertEquals('rsa_key_pair', $credential->getType()); + $credential->getAccessKeySecret(); } diff --git a/tests/Unit/AccessKeyCredentialTest.php b/tests/Unit/AccessKeyCredentialTest.php index a066674..07dad10 100644 --- a/tests/Unit/AccessKeyCredentialTest.php +++ b/tests/Unit/AccessKeyCredentialTest.php @@ -5,6 +5,7 @@ use AlibabaCloud\Credentials\AccessKeyCredential; use AlibabaCloud\Credentials\Signature\ShaHmac1Signature; use PHPUnit\Framework\TestCase; +use InvalidArgumentException; /** * Class AccessKeyCredentialTest @@ -39,6 +40,9 @@ public function testAccessKeyIdEmpty() $accessKeyId = ''; $accessKeySecret = 'bar'; + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('access_key_id cannot be empty'); + new AccessKeyCredential($accessKeyId, $accessKeySecret); } @@ -52,6 +56,9 @@ public function testAccessKeyIdFormat() $accessKeyId = null; $accessKeySecret = 'bar'; + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('access_key_id must be a string'); + new AccessKeyCredential($accessKeyId, $accessKeySecret); } @@ -65,6 +72,9 @@ public function testAccessKeySecretEmpty() $accessKeyId = 'foo'; $accessKeySecret = ''; + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('access_key_secret cannot be empty'); + // Test new AccessKeyCredential($accessKeyId, $accessKeySecret); } @@ -79,6 +89,9 @@ public function testAccessKeySecretFormat() $accessKeyId = 'foo'; $accessKeySecret = null; + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('access_key_secret must be a string'); + // Test new AccessKeyCredential($accessKeyId, $accessKeySecret); } diff --git a/tests/Unit/BearerTokenCredentialTest.php b/tests/Unit/BearerTokenCredentialTest.php index 54333f1..a3f6b5b 100644 --- a/tests/Unit/BearerTokenCredentialTest.php +++ b/tests/Unit/BearerTokenCredentialTest.php @@ -5,6 +5,7 @@ use AlibabaCloud\Credentials\BearerTokenCredential; use AlibabaCloud\Credentials\Signature\BearerTokenSignature; use InvalidArgumentException; +use Exception; use PHPUnit\Framework\TestCase; /** @@ -19,24 +20,30 @@ class BearerTokenCredentialTest extends TestCase * @expectedException \InvalidArgumentException * @expectedExceptionMessage bearer_token cannot be empty */ - public static function testBearerTokenEmpty() + public function testBearerTokenEmpty() { // Setup $bearerToken = ''; + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('bearer_token cannot be empty'); // Test new BearerTokenCredential($bearerToken); + } /** * @expectedException \InvalidArgumentException * @expectedExceptionMessage bearer_token must be a string */ - public static function testBearerTokenFormat() + public function testBearerTokenFormat() { // Setup $bearerToken = null; + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('bearer_token must be a string'); + // Test new BearerTokenCredential($bearerToken); } diff --git a/tests/Unit/ChainProviderTest.php b/tests/Unit/ChainProviderTest.php index e55c285..ca72caf 100644 --- a/tests/Unit/ChainProviderTest.php +++ b/tests/Unit/ChainProviderTest.php @@ -6,6 +6,8 @@ use AlibabaCloud\Credentials\Providers\ChainProvider; use AlibabaCloud\Credentials\Tests\Unit\Ini\VirtualAccessKeyCredential; use PHPUnit\Framework\TestCase; +use RuntimeException; +use InvalidArgumentException; /** * Class ChainProviderTest @@ -20,6 +22,8 @@ class ChainProviderTest extends TestCase */ public function testNoProvides() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('No providers in chain'); ChainProvider::set(); } @@ -59,6 +63,8 @@ public function testSetIniWithDIYFile() ChainProvider::ini() ); self::assertTrue(ChainProvider::hasCustomChain()); + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Credentials file is not readable: /a/c'); ChainProvider::customProvider(ChainProvider::getDefaultName()); } @@ -83,6 +89,7 @@ public function testInOpenBaseDir() public function testDefaultProvider() { ChainProvider::defaultProvider(ChainProvider::getDefaultName()); + self::assertTrue(true); } public function testSetEnv() @@ -127,7 +134,10 @@ public function testDefaultName() ); } - protected function setUp() + /** + * @before + */ + protected function initialize() { parent::setUp(); putenv('ALIBABA_CLOUD_ACCESS_KEY_ID=foo'); diff --git a/tests/Unit/CredentialTest.php b/tests/Unit/CredentialTest.php index 1eb056c..f5a2d55 100644 --- a/tests/Unit/CredentialTest.php +++ b/tests/Unit/CredentialTest.php @@ -23,6 +23,7 @@ public function testLoad() } catch (Exception $exception) { self::assertEquals($exception->getMessage(), "Credential 'default' not found"); } + self::assertTrue(true); } /** @@ -36,8 +37,9 @@ public function testException(array $config, $message) try { new Credential($config); } catch (Exception $e) { - self::assertEquals($message, $e->getMessage()); + self::assertEquals(strtolower($message), strtolower($e->getMessage())); } + self::assertTrue(true); } /** @@ -175,16 +177,16 @@ public function exceptionCases() [ 'type' => 'ecs_ram_role', 'role_name' => 'test', - 'enableIMDSv2' => 'false', + 'disableIMDSv1' => 'false', ], - 'enable_IMDS_v2 must be a string', + 'disable_IMDS_v1 must be a boolean', ], [ [ 'type' => 'ecs_ram_role', 'role_name' => 'test', - 'enableIMDSv2' => false, + 'disableIMDSv1' => false, 'metadataTokenDuration' => 3600, ], 'metadata_token_duration must be a int', diff --git a/tests/Unit/CredentialsTest.php b/tests/Unit/CredentialsTest.php index 16a7764..ff94133 100644 --- a/tests/Unit/CredentialsTest.php +++ b/tests/Unit/CredentialsTest.php @@ -6,6 +6,7 @@ use AlibabaCloud\Credentials\Providers\ChainProvider; use PHPUnit\Framework\TestCase; use ReflectionException; +use RuntimeException; /** * Class CredentialsTest @@ -35,6 +36,8 @@ public function testGet() */ public function testGetNotFound() { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage("Credential 'no' not found"); Credentials::get('no'); } @@ -49,5 +52,6 @@ public function testLoad() Credentials::flush(); ChainProvider::flush(); Credentials::get(ChainProvider::getDefaultName()); + self::assertTrue(true); } } diff --git a/tests/Unit/EcsRamRoleCredentialTest.php b/tests/Unit/EcsRamRoleCredentialTest.php index 9b5a224..b163da9 100644 --- a/tests/Unit/EcsRamRoleCredentialTest.php +++ b/tests/Unit/EcsRamRoleCredentialTest.php @@ -20,10 +20,11 @@ class EcsRamRoleCredentialTest extends TestCase protected $credential; /** + * @before * Sets up the fixture, for example, open a network connection. * This method is called before a test is executed. */ - public function setUp() + protected function initialize() { parent::setUp(); $this->credential = new EcsRamRoleCredential('EcsRamRoleTest'); @@ -62,16 +63,16 @@ public function testConstructWithIMDSv2() { // Setup $roleName = 'role_arn'; - $enableIMDSv2 = true; + $disabl1e_imdsv1 = true; $metadataTokenDuration = 3600; - $credential = new EcsRamRoleCredential($roleName, $enableIMDSv2, $metadataTokenDuration); + $credential = new EcsRamRoleCredential($roleName, $disabl1e_imdsv1, $metadataTokenDuration); - self::assertEquals(true, $this->getPrivateField($credential, 'enableIMDSv2')); + self::assertEquals(true, $this->getPrivateField($credential, 'disableIMDSv1')); self::assertEquals(3600, $this->getPrivateField($credential, 'metadataTokenDuration')); $credential = new EcsRamRoleCredential($roleName); - self::assertEquals(false, $this->getPrivateField($credential, 'enableIMDSv2')); + self::assertEquals(false, $this->getPrivateField($credential, 'disableIMDSv1')); self::assertEquals(21600, $this->getPrivateField($credential, 'metadataTokenDuration')); } @@ -87,6 +88,7 @@ public function testDefault() 'AccessKeySecret' => 'bar', 'SecurityToken' => 'token', ]; + Credentials::mockResponse(200, [], 'Token'); Credentials::mockResponse(200, [], 'RoleName'); Credentials::mockResponse(200, [], $result); @@ -107,6 +109,13 @@ public function testDefault404() Credentials::mockResponse(404, [], 'RoleName'); + $this->expectException(InvalidArgumentException::class); + if (method_exists($this, 'expectExceptionMessageMatches')) { + $this->expectExceptionMessageMatches('/The role name was not found in the instance/'); + } elseif (method_exists($this, 'expectExceptionMessageRegExp')) { + $this->expectExceptionMessageRegExp('/The role name was not found in the instance/'); + } + self::assertEquals('foo', $this->credential->getAccessKeyId()); } @@ -121,6 +130,13 @@ public function testDefault500() Credentials::mockResponse(500, [], 'RoleName'); + $this->expectException(RuntimeException::class); + + if (method_exists($this, 'expectExceptionMessageMatches')) { + $this->expectExceptionMessageMatches('/Error retrieving credentials from result: RoleName/'); + } elseif (method_exists($this, 'expectExceptionMessageRegExp')) { + $this->expectExceptionMessageRegExp('/Error retrieving credentials from result: RoleName/'); + } self::assertEquals('foo', $this->credential->getAccessKeyId()); } @@ -134,7 +150,13 @@ public function testDefaultEmpty() $this->credential = new EcsRamRoleCredential(); Credentials::mockResponse(200, [], ''); - + $this->expectException(RuntimeException::class); + if (method_exists($this, 'expectExceptionMessageMatches')) { + $this->expectExceptionMessageMatches('/Error retrieving credentials from result is empty/'); + } elseif (method_exists($this, 'expectExceptionMessageRegExp')) { + $this->expectExceptionMessageRegExp('/Error retrieving credentials from result is empty/'); + } + self::assertEquals('foo', $this->credential->getAccessKeyId()); } @@ -152,6 +174,7 @@ public function testSts() 'AccessKeySecret' => 'bar', 'SecurityToken' => 'token', ]; + Credentials::mockResponse(200, [], 'Token'); Credentials::mockResponse(200, [], $result); self::assertEquals('foo', $this->credential->getAccessKeyId()); @@ -173,8 +196,10 @@ public function testStsIncomplete() 'AccessKeyId' => 'foo', ]; $credential = new EcsRamRoleCredential('EcsRamRoleTest2'); + Credentials::mockResponse(200, [], 'Token'); Credentials::mockResponse(200, [], $result); - + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Result contains no credentials'); // Test self::assertEquals('foo', $credential->getAccessKeyId()); } @@ -192,8 +217,11 @@ public function testSts404() 'AccessKeyId' => 'foo', ]; $credential = new EcsRamRoleCredential('EcsRamRoleTest3'); + Credentials::mockResponse(200, [], 'Token'); Credentials::mockResponse(404, [], $result); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('The role was not found in the instance'); // Test self::assertEquals('foo', $credential->getAccessKeyId()); } @@ -212,8 +240,16 @@ public function testSts500() ]; $credential = new EcsRamRoleCredential('EcsRamRoleTest3'); + Credentials::mockResponse(200, [], 'Token'); Credentials::mockResponse(500, [], $result); + $this->expectException(RuntimeException::class); + if (method_exists($this, 'expectExceptionMessageMatches')) { + $this->expectExceptionMessageMatches('/Error retrieving credentials from result/'); + } elseif (method_exists($this, 'expectExceptionMessageRegExp')) { + $this->expectExceptionMessageRegExp('/Error retrieving credentials from result/'); + } + // Test self::assertEquals('foo', $credential->getAccessKeyId()); } @@ -227,6 +263,8 @@ public function testRoleNameEmpty() // Setup $roleName = ''; + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('role_name cannot be empty'); // Test new EcsRamRoleCredential($roleName); } @@ -243,6 +281,12 @@ public function testStsWithoutMock() $credential = new EcsRamRoleCredential('EcsRamRoleTest4'); + $this->expectException(RuntimeException::class); + if (method_exists($this, 'expectExceptionMessageMatches')) { + $this->expectExceptionMessageMatches('/timed/'); + } elseif (method_exists($this, 'expectExceptionMessageRegExp')) { + $this->expectExceptionMessageRegExp('/timed/'); + } // Test self::assertEquals('foo', $credential->getAccessKeyId()); } diff --git a/tests/Unit/EcsRamRoleProviderTest.php b/tests/Unit/EcsRamRoleProviderTest.php index 3b7d7b3..ab47920 100644 --- a/tests/Unit/EcsRamRoleProviderTest.php +++ b/tests/Unit/EcsRamRoleProviderTest.php @@ -16,7 +16,10 @@ class EcsRamRoleProviderTest extends TestCase { - public function setUp() + /** + * @before + */ + protected function initialize() { parent::setUp(); Credentials::cancelMock(); @@ -30,7 +33,7 @@ public function testConstruct() $roleName = 'test'; // Setup $config = [ - 'enableIMDSv2' => true, + 'disableIMDSv1' => true, 'metadataTokenDuration' => 3600, ]; @@ -41,7 +44,7 @@ public function testConstruct() $sessionConfig = $this->getPrivateField($sessionCredential, 'config'); - self::assertEquals(true, $sessionConfig['enableIMDSv2']); + self::assertEquals(true, $sessionConfig['disableIMDSv1']); self::assertEquals(3600, $sessionConfig['metadataTokenDuration']); } @@ -61,12 +64,12 @@ private function invokeProtectedFunc($instance, $method) { /** * @throws GuzzleException */ - public function testGetEnableECSIMDSv2() + public function testgetDisableECSIMDSv1() { // Setup $roleName = 'test'; $config = [ - 'enableIMDSv2' => true, + 'disableIMDSv1' => true, 'metadataTokenDuration' => 3600, ]; @@ -75,7 +78,7 @@ public function testGetEnableECSIMDSv2() $sessionCredential = new EcsRamRoleProvider($credential, $config); - self::assertEquals(true, $this->invokeProtectedFunc($sessionCredential, 'getEnableECSIMDSv2')); + self::assertEquals(true, $this->invokeProtectedFunc($sessionCredential, 'getDisableECSIMDSv1')); $config = [ 'metadataTokenDuration' => 3600, @@ -83,31 +86,31 @@ public function testGetEnableECSIMDSv2() $sessionCredential = new EcsRamRoleProvider($credential, $config); - self::assertEquals(false, $this->invokeProtectedFunc($sessionCredential, 'getEnableECSIMDSv2')); + self::assertEquals(false, $this->invokeProtectedFunc($sessionCredential, 'getDisableECSIMDSv1')); - putenv('ALIBABA_CLOUD_ECS_IMDSV2_ENABLE=true'); + putenv('ALIBABA_CLOUD_IMDSV1_DISABLE=true'); - self::assertEquals(true, $this->invokeProtectedFunc($sessionCredential, 'getEnableECSIMDSv2')); + self::assertEquals(true, $this->invokeProtectedFunc($sessionCredential, 'getDisableECSIMDSv1')); - putenv('ALIBABA_CLOUD_ECS_IMDSV2_ENABLE=TRUE'); + putenv('ALIBABA_CLOUD_IMDSV1_DISABLE=TRUE'); - self::assertEquals(true, $this->invokeProtectedFunc($sessionCredential, 'getEnableECSIMDSv2')); + self::assertEquals(true, $this->invokeProtectedFunc($sessionCredential, 'getDisableECSIMDSv1')); - putenv('ALIBABA_CLOUD_ECS_IMDSV2_ENABLE=ok'); + putenv('ALIBABA_CLOUD_IMDSV1_DISABLE=ok'); - self::assertEquals(false, $this->invokeProtectedFunc($sessionCredential, 'getEnableECSIMDSv2')); + self::assertEquals(false, $this->invokeProtectedFunc($sessionCredential, 'getDisableECSIMDSv1')); - putenv('ALIBABA_CLOUD_ECS_IMDSV2_ENABLE=1'); + putenv('ALIBABA_CLOUD_IMDSV1_DISABLE=1'); - self::assertEquals(false, $this->invokeProtectedFunc($sessionCredential, 'getEnableECSIMDSv2')); + self::assertEquals(false, $this->invokeProtectedFunc($sessionCredential, 'getDisableECSIMDSv1')); - putenv('ALIBABA_CLOUD_ECS_IMDSV2_ENABLE=false'); + putenv('ALIBABA_CLOUD_IMDSV1_DISABLE=false'); - self::assertEquals(false, $this->invokeProtectedFunc($sessionCredential, 'getEnableECSIMDSv2')); + self::assertEquals(false, $this->invokeProtectedFunc($sessionCredential, 'getDisableECSIMDSv1')); - putenv('ALIBABA_CLOUD_ECS_IMDSV2_ENABLE='); + putenv('ALIBABA_CLOUD_IMDSV1_DISABLE='); - self::assertEquals(false, $this->invokeProtectedFunc($sessionCredential, 'getEnableECSIMDSv2')); + self::assertEquals(false, $this->invokeProtectedFunc($sessionCredential, 'getDisableECSIMDSv1')); } private function getPrivateField($instance, $field) { @@ -125,7 +128,7 @@ public function testRefreshMetadataTokenDefault() // Setup $roleName = 'test'; $config = [ - 'enableIMDSv2' => true, + 'disableIMDSv1' => true, 'metadataTokenDuration' => 3600, ]; @@ -136,13 +139,13 @@ public function testRefreshMetadataTokenDefault() Credentials::mockResponse(200, [], 'Token'); - $this->invokeProtectedFunc($sessionCredential, 'refreshMetadataToken'); + $token = $this->invokeProtectedFunc($sessionCredential, 'refreshMetadataToken'); $histroy = Credentials::getHistroy(); $request = end($histroy)['request']; $headers = $request->getHeaders(); - self::assertEquals('Token', $this->getPrivateField($sessionCredential, 'metadataToken')); + self::assertEquals('Token', $token); self::assertEquals('3600', $headers['X-aliyun-ecs-metadata-token-ttl-seconds'][0]); } @@ -156,7 +159,7 @@ public function testDefault404() // Setup $roleName = 'test'; $config = [ - 'enableIMDSv2' => true, + 'disableIMDSv1' => true, 'metadataTokenDuration' => 3600, ]; @@ -166,10 +169,40 @@ public function testDefault404() $sessionCredential = new EcsRamRoleProvider($credential, $config); Credentials::mockResponse(404, [], 'Error'); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Failed to get token from ECS Metadata Service. HttpCode= 404'); + $this->invokeProtectedFunc($sessionCredential, 'refreshMetadataToken'); } + public function testEnableV1404() + { + // Setup + $roleName = 'test'; + $config = [ + 'disableIMDSv1' => false, + 'metadataTokenDuration' => 3600, + ]; + + // Test + $credential = new EcsRamRoleCredential($roleName); + + $sessionCredential = new EcsRamRoleProvider($credential, $config); + + Credentials::mockResponse(404, [], 'Error'); + $token = $this->invokeProtectedFunc($sessionCredential, 'refreshMetadataToken'); + + $histroy = Credentials::getHistroy(); + + $request = end($histroy)['request']; + $headers = $request->getHeaders(); + self::assertEquals(null, $token); + self::assertEquals(0, $this->getPrivateField($sessionCredential, 'staleTime')); + + } + /** * @throws GuzzleException */ @@ -178,7 +211,7 @@ public function testNeedToRefresh() // Setup $roleName = 'test'; $config = [ - 'enableIMDSv2' => true, + 'disableIMDSv1' => true, 'metadataTokenDuration' => 5, ]; diff --git a/tests/Unit/MockTraitTest.php b/tests/Unit/MockTraitTest.php index 0f27615..0cc6d13 100644 --- a/tests/Unit/MockTraitTest.php +++ b/tests/Unit/MockTraitTest.php @@ -14,7 +14,10 @@ */ class MockTraitTest extends TestCase { - public function setUp() + /** + * @before + */ + protected function initialize() { parent::setUp(); Credentials::cancelMock(); @@ -35,6 +38,8 @@ public function testRequestException() 'policy' => [], ]); + $this->expectException(\GuzzleHttp\Exception\RequestException::class); + $this->expectExceptionMessage('Error'); self::assertEquals('STS.**************', $credential->getAccessKeyId()); } } diff --git a/tests/Unit/RamRoleArnCredentialTest.php b/tests/Unit/RamRoleArnCredentialTest.php index c05557e..789d4da 100644 --- a/tests/Unit/RamRoleArnCredentialTest.php +++ b/tests/Unit/RamRoleArnCredentialTest.php @@ -6,6 +6,8 @@ use AlibabaCloud\Credentials\RamRoleArnCredential; use AlibabaCloud\Credentials\Signature\ShaHmac1Signature; use Exception; +use RuntimeException; +use InvalidArgumentException; use PHPUnit\Framework\TestCase; class RamRoleArnCredentialTest extends TestCase @@ -119,7 +121,8 @@ public function testStsIncomplete() 'role_session_name' => 'role_session_name2', 'policy' => '', ]); - + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Result contains no credentials'); // Test self::assertEquals('TMPSK.**************', $credential->getAccessKeyId()); } @@ -131,6 +134,8 @@ public function testStsIncomplete() public function testAccessKeyIdEmpty() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('access_key_id cannot be empty'); // Test new RamRoleArnCredential([ 'access_key_id' => '', @@ -147,6 +152,8 @@ public function testAccessKeyIdEmpty() */ public function testAccessKeyIdFormat() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Missing required access_key_secret option in config for ram_role_arn'); // Test new RamRoleArnCredential([ 'access_key_id' => 'access_key_id', @@ -157,7 +164,10 @@ public function testAccessKeyIdFormat() ]); } - protected function setUp() + /** + * @before + */ + protected function initialize() { // Setup Credentials::cancelMock(); diff --git a/tests/Unit/RsaKeyPairCredentialTest.php b/tests/Unit/RsaKeyPairCredentialTest.php index 3b737b8..55cb084 100644 --- a/tests/Unit/RsaKeyPairCredentialTest.php +++ b/tests/Unit/RsaKeyPairCredentialTest.php @@ -8,6 +8,8 @@ use AlibabaCloud\Credentials\Signature\ShaHmac1Signature; use AlibabaCloud\Credentials\Tests\Unit\Ini\VirtualRsaKeyPairCredential; use Exception; +use RuntimeException; +use InvalidArgumentException; use GuzzleHttp\Exception\GuzzleException; use PHPUnit\Framework\TestCase; @@ -34,8 +36,8 @@ public static function testNotFoundFile() new RsaKeyPairCredential($publicKeyId, $privateKeyFile); } catch (Exception $e) { self::assertEquals( - "file_get_contents($privateKeyFile): failed to open stream: No such file or directory", - $e->getMessage() + strtolower("file_get_contents($privateKeyFile): failed to open stream: No such file or directory"), + strtolower($e->getMessage()) ); } } @@ -135,6 +137,10 @@ public function testStsIncomplete() } }'; Credentials::mockResponse(200, [], $result); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Result contains no credentials'); + $credential = new RsaKeyPairCredential($publicKeyId, $privateKeyFile); // Test @@ -151,6 +157,8 @@ public function testPublicKeyIdEmpty() $publicKeyId = ''; $privateKeyFile = VirtualRsaKeyPairCredential::privateKeyFileUrl(); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('public_key_id cannot be empty'); // Test new RsaKeyPairCredential($publicKeyId, $privateKeyFile); } @@ -165,6 +173,8 @@ public function testPublicKeyIdFormat() $publicKeyId = null; $privateKeyFile = VirtualRsaKeyPairCredential::privateKeyFileUrl(); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('public_key_id must be a string'); // Test new RsaKeyPairCredential($publicKeyId, $privateKeyFile); } @@ -179,6 +189,8 @@ public function testPrivateKeyFileEmpty() $publicKeyId = 'publicKeyId'; $privateKeyFile = ''; + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('private_key_file cannot be empty'); // Test new RsaKeyPairCredential($publicKeyId, $privateKeyFile); } @@ -193,11 +205,16 @@ public function testPrivateKeyFileFormat() $publicKeyId = 'publicKeyId'; $privateKeyFile = null; + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('private_key_file must be a string'); // Test new RsaKeyPairCredential($publicKeyId, $privateKeyFile); } - protected function setUp() + /** + * @before + */ + protected function initialize() { // Setup Credentials::cancelMock(); diff --git a/tests/Unit/Signature/ShaHmac256WithRsaSignatureTest.php b/tests/Unit/Signature/ShaHmac256WithRsaSignatureTest.php index 9b67f75..c800d5e 100644 --- a/tests/Unit/Signature/ShaHmac256WithRsaSignatureTest.php +++ b/tests/Unit/Signature/ShaHmac256WithRsaSignatureTest.php @@ -5,6 +5,7 @@ use AlibabaCloud\Credentials\Signature\ShaHmac256WithRsaSignature; use AlibabaCloud\Credentials\Tests\Unit\Ini\VirtualRsaKeyPairCredential; use PHPUnit\Framework\TestCase; +use InvalidArgumentException; /** * Class ShaHmac256WithRsaSignatureTest @@ -46,6 +47,13 @@ public function testShaHmac256SignatureBadPrivateKey() $string = 'string'; $privateKeyFile = VirtualRsaKeyPairCredential::badPrivateKey(); + $this->expectException(InvalidArgumentException::class); + if (method_exists($this, 'expectExceptionMessageMatches')) { + $this->expectExceptionMessageMatches('/supplied key param cannot be coerced into a private key/i'); + } elseif (method_exists($this, 'expectExceptionMessageRegExp')) { + $this->expectExceptionMessageRegExp('/supplied key param cannot be coerced into a private key/i'); + } + // Test $signature = new ShaHmac256WithRsaSignature(); diff --git a/tests/Unit/StsCredentialTest.php b/tests/Unit/StsCredentialTest.php index 40115ad..49e9a8d 100644 --- a/tests/Unit/StsCredentialTest.php +++ b/tests/Unit/StsCredentialTest.php @@ -5,6 +5,7 @@ use AlibabaCloud\Credentials\Signature\ShaHmac1Signature; use AlibabaCloud\Credentials\StsCredential; use PHPUnit\Framework\TestCase; +use InvalidArgumentException; class StsCredentialTest extends TestCase { @@ -42,6 +43,9 @@ public function testAccessKeyIdEmpty() $accessKeySecret = 'accessKeySecret'; $securityToken = 'securityToken'; + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('access_key_id cannot be empty'); + new StsCredential($accessKeyId, $accessKeySecret, $securityToken); } @@ -56,6 +60,9 @@ public function testAccessKeyIdFormat() $accessKeySecret = 'accessKeySecret'; $securityToken = 'securityToken'; + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('access_key_id must be a string'); + new StsCredential($accessKeyId, $accessKeySecret, $securityToken); } @@ -70,6 +77,9 @@ public function testAccessKeySecretEmpty() $accessKeySecret = ''; $securityToken = 'securityToken'; + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('access_key_secret cannot be empty'); + new StsCredential($accessKeyId, $accessKeySecret, $securityToken); } @@ -84,6 +94,10 @@ public function testAccessKeySecretFormat() $accessKeySecret = null; $securityToken = 'securityToken'; + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionCode(0); + $this->expectExceptionMessage('access_key_secret must be a string'); + new StsCredential($accessKeyId, $accessKeySecret, $securityToken); } }