transferito
/
vendor
/
aws
/
aws-sdk-php
/
src
/
Credentials
/
AssumeRoleWithWebIdentityCredentialProvider.php
AssumeRoleCredentialProvider.php
11 months ago
AssumeRoleWithWebIdentityCredentialProvider.php
11 months ago
CredentialProvider.php
11 months ago
Credentials.php
11 months ago
CredentialsInterface.php
11 months ago
EcsCredentialProvider.php
11 months ago
InstanceProfileProvider.php
11 months ago
AssumeRoleWithWebIdentityCredentialProvider.php
167 lines
| 1 | <?php |
| 2 | namespace Aws\Credentials; |
| 3 | |
| 4 | use Aws\Exception\AwsException; |
| 5 | use Aws\Exception\CredentialsException; |
| 6 | use Aws\Result; |
| 7 | use Aws\Sts\StsClient; |
| 8 | use GuzzleHttp\Promise; |
| 9 | |
| 10 | /** |
| 11 | * Credential provider that provides credentials via assuming a role with a web identity |
| 12 | * More Information, see: https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-sts-2011-06-15.html#assumerolewithwebidentity |
| 13 | */ |
| 14 | class AssumeRoleWithWebIdentityCredentialProvider |
| 15 | { |
| 16 | const ERROR_MSG = "Missing required 'AssumeRoleWithWebIdentityCredentialProvider' configuration option: "; |
| 17 | const ENV_RETRIES = 'AWS_METADATA_SERVICE_NUM_ATTEMPTS'; |
| 18 | |
| 19 | /** @var string */ |
| 20 | private $tokenFile; |
| 21 | |
| 22 | /** @var string */ |
| 23 | private $arn; |
| 24 | |
| 25 | /** @var string */ |
| 26 | private $session; |
| 27 | |
| 28 | /** @var StsClient */ |
| 29 | private $client; |
| 30 | |
| 31 | /** @var integer */ |
| 32 | private $retries; |
| 33 | |
| 34 | /** @var integer */ |
| 35 | private $authenticationAttempts; |
| 36 | |
| 37 | /** @var integer */ |
| 38 | private $tokenFileReadAttempts; |
| 39 | |
| 40 | /** |
| 41 | * The constructor attempts to load config from environment variables. |
| 42 | * If not set, the following config options are used: |
| 43 | * - WebIdentityTokenFile: full path of token filename |
| 44 | * - RoleArn: arn of role to be assumed |
| 45 | * - SessionName: (optional) set by SDK if not provided |
| 46 | * |
| 47 | * @param array $config Configuration options |
| 48 | * @throws \InvalidArgumentException |
| 49 | */ |
| 50 | public function __construct(array $config = []) |
| 51 | { |
| 52 | if (!isset($config['RoleArn'])) { |
| 53 | throw new \InvalidArgumentException(self::ERROR_MSG . "'RoleArn'."); |
| 54 | } |
| 55 | $this->arn = $config['RoleArn']; |
| 56 | |
| 57 | if (!isset($config['WebIdentityTokenFile'])) { |
| 58 | throw new \InvalidArgumentException(self::ERROR_MSG . "'WebIdentityTokenFile'."); |
| 59 | } |
| 60 | $this->tokenFile = $config['WebIdentityTokenFile']; |
| 61 | |
| 62 | if (!preg_match("/^\w\:|^\/|^\\\/", $this->tokenFile)) { |
| 63 | throw new \InvalidArgumentException("'WebIdentityTokenFile' must be an absolute path."); |
| 64 | } |
| 65 | |
| 66 | $this->retries = (int) getenv(self::ENV_RETRIES) ?: (isset($config['retries']) ? $config['retries'] : 3); |
| 67 | $this->authenticationAttempts = 0; |
| 68 | $this->tokenFileReadAttempts = 0; |
| 69 | |
| 70 | $this->session = isset($config['SessionName']) |
| 71 | ? $config['SessionName'] |
| 72 | : 'aws-sdk-php-' . round(microtime(true) * 1000); |
| 73 | |
| 74 | $region = isset($config['region']) |
| 75 | ? $config['region'] |
| 76 | : 'us-east-1'; |
| 77 | |
| 78 | if (isset($config['client'])) { |
| 79 | $this->client = $config['client']; |
| 80 | } else { |
| 81 | $this->client = new StsClient([ |
| 82 | 'credentials' => false, |
| 83 | 'region' => $region, |
| 84 | 'version' => 'latest' |
| 85 | ]); |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | /** |
| 90 | * Loads assume role with web identity credentials. |
| 91 | * |
| 92 | * @return Promise\PromiseInterface |
| 93 | */ |
| 94 | public function __invoke() |
| 95 | { |
| 96 | return Promise\Coroutine::of(function () { |
| 97 | $client = $this->client; |
| 98 | $result = null; |
| 99 | while ($result == null) { |
| 100 | try { |
| 101 | $token = @file_get_contents($this->tokenFile); |
| 102 | if (false === $token) { |
| 103 | clearstatcache(true, dirname($this->tokenFile) . "/" . readlink($this->tokenFile)); |
| 104 | clearstatcache(true, dirname($this->tokenFile) . "/" . dirname(readlink($this->tokenFile))); |
| 105 | clearstatcache(true, $this->tokenFile); |
| 106 | if (!@is_readable($this->tokenFile)) { |
| 107 | throw new CredentialsException( |
| 108 | "Unreadable tokenfile at location {$this->tokenFile}" |
| 109 | ); |
| 110 | } |
| 111 | |
| 112 | $token = @file_get_contents($this->tokenFile); |
| 113 | } |
| 114 | if (empty($token)) { |
| 115 | if ($this->tokenFileReadAttempts < $this->retries) { |
| 116 | sleep((int) pow(1.2, $this->tokenFileReadAttempts)); |
| 117 | $this->tokenFileReadAttempts++; |
| 118 | continue; |
| 119 | } |
| 120 | throw new CredentialsException("InvalidIdentityToken from file: {$this->tokenFile}"); |
| 121 | } |
| 122 | } catch (\Exception $exception) { |
| 123 | throw new CredentialsException( |
| 124 | "Error reading WebIdentityTokenFile from " . $this->tokenFile, |
| 125 | 0, |
| 126 | $exception |
| 127 | ); |
| 128 | } |
| 129 | |
| 130 | $assumeParams = [ |
| 131 | 'RoleArn' => $this->arn, |
| 132 | 'RoleSessionName' => $this->session, |
| 133 | 'WebIdentityToken' => $token |
| 134 | ]; |
| 135 | |
| 136 | try { |
| 137 | $result = $client->assumeRoleWithWebIdentity($assumeParams); |
| 138 | } catch (AwsException $e) { |
| 139 | if ($e->getAwsErrorCode() == 'InvalidIdentityToken') { |
| 140 | if ($this->authenticationAttempts < $this->retries) { |
| 141 | sleep((int) pow(1.2, $this->authenticationAttempts)); |
| 142 | } else { |
| 143 | throw new CredentialsException( |
| 144 | "InvalidIdentityToken, retries exhausted" |
| 145 | ); |
| 146 | } |
| 147 | } else { |
| 148 | throw new CredentialsException( |
| 149 | "Error assuming role from web identity credentials", |
| 150 | 0, |
| 151 | $e |
| 152 | ); |
| 153 | } |
| 154 | } catch (\Exception $e) { |
| 155 | throw new CredentialsException( |
| 156 | "Error retrieving web identity credentials: " . $e->getMessage() |
| 157 | . " (" . $e->getCode() . ")" |
| 158 | ); |
| 159 | } |
| 160 | $this->authenticationAttempts++; |
| 161 | } |
| 162 | |
| 163 | yield $this->client->createCredentials($result); |
| 164 | }); |
| 165 | } |
| 166 | } |
| 167 |