DefaultCredentialsProvider.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. <?php
  2. namespace AlibabaCloud\Credentials\Providers;
  3. use AlibabaCloud\Credentials\Utils\Filter;
  4. use AlibabaCloud\Credentials\Utils\Helper;
  5. use InvalidArgumentException;
  6. use RuntimeException;
  7. use Exception;
  8. /**
  9. * @internal This class is intended for internal use within the package.
  10. * Class DefaultCredentialsProvider
  11. *
  12. * @package AlibabaCloud\Credentials\Providers
  13. */
  14. class DefaultCredentialsProvider implements CredentialsProvider
  15. {
  16. /**
  17. * @var array
  18. */
  19. private static $defaultProviders = [];
  20. /**
  21. * @var bool
  22. */
  23. private $reuseLastProviderEnabled;
  24. /**
  25. * @var CredentialsProvider
  26. */
  27. private $lastUsedCredentialsProvider;
  28. /**
  29. * @var array
  30. */
  31. private static $customChain = [];
  32. /**
  33. * DefaultCredentialsProvider constructor.
  34. * @param array $params
  35. */
  36. public function __construct(array $params = [])
  37. {
  38. $this->filterReuseLastProviderEnabled($params);
  39. $this->createDefaultChain();
  40. Filter::reuseLastProviderEnabled($this->reuseLastProviderEnabled);
  41. }
  42. private function filterReuseLastProviderEnabled(array $params)
  43. {
  44. $this->reuseLastProviderEnabled = true;
  45. if (isset($params['reuseLastProviderEnabled'])) {
  46. $this->reuseLastProviderEnabled = $params['reuseLastProviderEnabled'];
  47. }
  48. }
  49. private function createDefaultChain()
  50. {
  51. self::$defaultProviders = [
  52. new EnvironmentVariableCredentialsProvider(),
  53. ];
  54. if (
  55. Helper::envNotEmpty('ALIBABA_CLOUD_ROLE_ARN')
  56. && Helper::envNotEmpty('ALIBABA_CLOUD_OIDC_PROVIDER_ARN')
  57. && Helper::envNotEmpty('ALIBABA_CLOUD_OIDC_TOKEN_FILE')
  58. ) {
  59. array_push(
  60. self::$defaultProviders,
  61. new OIDCRoleArnCredentialsProvider()
  62. );
  63. }
  64. array_push(
  65. self::$defaultProviders,
  66. new CLIProfileCredentialsProvider()
  67. );
  68. array_push(
  69. self::$defaultProviders,
  70. new ProfileCredentialsProvider()
  71. );
  72. if (Helper::envNotEmpty('ALIBABA_CLOUD_ECS_METADATA')) {
  73. array_push(
  74. self::$defaultProviders,
  75. new EcsRamRoleCredentialsProvider()
  76. );
  77. }
  78. if (Helper::envNotEmpty('ALIBABA_CLOUD_CREDENTIALS_URI')) {
  79. array_push(
  80. self::$defaultProviders,
  81. new URLCredentialsProvider()
  82. );
  83. }
  84. }
  85. /**
  86. * @param CredentialsProvider ...$providers
  87. */
  88. public static function set(...$providers)
  89. {
  90. if (empty($providers)) {
  91. throw new InvalidArgumentException('No providers in chain');
  92. }
  93. foreach ($providers as $provider) {
  94. if (!$provider instanceof CredentialsProvider) {
  95. throw new InvalidArgumentException('Providers must all be CredentialsProvider');
  96. }
  97. }
  98. self::$customChain = $providers;
  99. }
  100. /**
  101. * @return bool
  102. */
  103. public static function hasCustomChain()
  104. {
  105. return (bool) self::$customChain;
  106. }
  107. public static function flush()
  108. {
  109. self::$customChain = [];
  110. }
  111. /**
  112. * Get credential.
  113. *
  114. * @return Credentials
  115. * @throws RuntimeException
  116. */
  117. public function getCredentials()
  118. {
  119. if ($this->reuseLastProviderEnabled && !is_null($this->lastUsedCredentialsProvider)) {
  120. $credentials = $this->lastUsedCredentialsProvider->getCredentials();
  121. return new Credentials([
  122. 'accessKeyId' => $credentials->getAccessKeyId(),
  123. 'accessKeySecret' => $credentials->getAccessKeySecret(),
  124. 'securityToken' => $credentials->getSecurityToken(),
  125. 'providerName' => $this->getProviderName() . '/' . $this->lastUsedCredentialsProvider->getProviderName(),
  126. ]);
  127. }
  128. $providerChain = array_merge(
  129. self::$customChain,
  130. self::$defaultProviders
  131. );
  132. $exceptionMessages = [];
  133. foreach ($providerChain as $provider) {
  134. try {
  135. $credentials = $provider->getCredentials();
  136. $this->lastUsedCredentialsProvider = $provider;
  137. return new Credentials([
  138. 'accessKeyId' => $credentials->getAccessKeyId(),
  139. 'accessKeySecret' => $credentials->getAccessKeySecret(),
  140. 'securityToken' => $credentials->getSecurityToken(),
  141. 'providerName' => $this->getProviderName() . '/' . $provider->getProviderName(),
  142. ]);
  143. } catch (Exception $exception) {
  144. array_push($exceptionMessages, basename(str_replace('\\', '/', get_class($provider))) . ': ' . $exception->getMessage());
  145. }
  146. }
  147. throw new RuntimeException('Unable to load credentials from any of the providers in the chain: ' . implode(', ', $exceptionMessages));
  148. }
  149. /**
  150. * @inheritDoc
  151. */
  152. public function getProviderName()
  153. {
  154. return "default";
  155. }
  156. }