PluginProbe
Media Cloud Sync / 1.4.1
Media Cloud Sync v1.4.1
1.4.1 1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 All 35 releases
media-cloud-sync / includes / sdk / s3 / Aws / Credentials / AssumeRoleWithWebIdentityCredentialProvider.php

AssumeRoleWithWebIdentityCredentialProvider.php in Media Cloud Sync 1.4.1, at includes/sdk/s3/Aws/Credentials/AssumeRoleWithWebIdentityCredentialProvider.php

139 lines 6.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Dudlewebs\WPMCS\s3\Aws\Credentials;
4
5 use Dudlewebs\WPMCS\s3\Aws\Exception\AwsException;
6 use Dudlewebs\WPMCS\s3\Aws\Exception\CredentialsException;
7 use Dudlewebs\WPMCS\s3\Aws\Result;
8 use Dudlewebs\WPMCS\s3\Aws\Sts\StsClient;
9 use Dudlewebs\WPMCS\s3\GuzzleHttp\Promise;
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 /** @var string */
19 private $tokenFile;
20 /** @var string */
21 private $arn;
22 /** @var string */
23 private $session;
24 /** @var StsClient */
25 private $client;
26 /** @var integer */
27 private $retries;
28 /** @var integer */
29 private $authenticationAttempts;
30 /** @var integer */
31 private $tokenFileReadAttempts;
32 /** @var string */
33 private $source;
34 /**
35 * The constructor attempts to load config from environment variables.
36 * If not set, the following config options are used:
37 * - WebIdentityTokenFile: full path of token filename
38 * - RoleArn: arn of role to be assumed
39 * - SessionName: (optional) set by SDK if not provided
40 * - source: To identify if the provider was sourced by a profile or
41 * from environment definition. Default will be `sts_web_id_token`.
42 *
43 * @param array $config Configuration options
44 * @throws \InvalidArgumentException
45 */
46 public function __construct(array $config = [])
47 {
48 if (!isset($config['RoleArn'])) {
49 throw new \InvalidArgumentException(self::ERROR_MSG . "'RoleArn'.");
50 }
51 $this->arn = $config['RoleArn'];
52 if (!isset($config['WebIdentityTokenFile'])) {
53 throw new \InvalidArgumentException(self::ERROR_MSG . "'WebIdentityTokenFile'.");
54 }
55 $this->tokenFile = $config['WebIdentityTokenFile'];
56 if (!\preg_match("/^\\w\\:|^\\/|^\\\\/", $this->tokenFile)) {
57 throw new \InvalidArgumentException("'WebIdentityTokenFile' must be an absolute path.");
58 }
59 $this->retries = (int) \getenv(self::ENV_RETRIES) ?: (isset($config['retries']) ? $config['retries'] : 3);
60 $this->authenticationAttempts = 0;
61 $this->tokenFileReadAttempts = 0;
62 $this->session = $config['SessionName'] ?? 'aws-sdk-php-' . \round(\microtime(\true) * 1000);
63 if (isset($config['client'])) {
64 $this->client = $config['client'];
65 } else {
66 $region = $config['region'] ?? \getEnv(CredentialProvider::ENV_REGION) ?: null;
67 $this->client = $this->createDefaultStsClient($region);
68 }
69 $this->source = $config['source'] ?? CredentialSources::STS_WEB_ID_TOKEN;
70 }
71 /**
72 * Loads assume role with web identity credentials.
73 *
74 * @return Promise\PromiseInterface
75 */
76 public function __invoke()
77 {
78 return Promise\Coroutine::of(function () {
79 $client = $this->client;
80 $result = null;
81 while ($result == null) {
82 try {
83 $token = @\file_get_contents($this->tokenFile);
84 if (\false === $token) {
85 \clearstatcache(\true, \dirname($this->tokenFile) . "/" . \readlink($this->tokenFile));
86 \clearstatcache(\true, \dirname($this->tokenFile) . "/" . \dirname(\readlink($this->tokenFile)));
87 \clearstatcache(\true, $this->tokenFile);
88 if (!@\is_readable($this->tokenFile)) {
89 throw new CredentialsException("Unreadable tokenfile at location {$this->tokenFile}");
90 }
91 $token = @\file_get_contents($this->tokenFile);
92 }
93 if (empty($token)) {
94 if ($this->tokenFileReadAttempts < $this->retries) {
95 \sleep((int) \pow(1.2, $this->tokenFileReadAttempts));
96 $this->tokenFileReadAttempts++;
97 continue;
98 }
99 throw new CredentialsException("InvalidIdentityToken from file: {$this->tokenFile}");
100 }
101 } catch (\Exception $exception) {
102 throw new CredentialsException("Error reading WebIdentityTokenFile from " . $this->tokenFile, 0, $exception);
103 }
104 $assumeParams = ['RoleArn' => $this->arn, 'RoleSessionName' => $this->session, 'WebIdentityToken' => $token];
105 try {
106 $result = $client->assumeRoleWithWebIdentity($assumeParams);
107 } catch (AwsException $e) {
108 if ($e->getAwsErrorCode() == 'InvalidIdentityToken') {
109 if ($this->authenticationAttempts < $this->retries) {
110 \sleep((int) \pow(1.2, $this->authenticationAttempts));
111 } else {
112 throw new CredentialsException("InvalidIdentityToken, retries exhausted");
113 }
114 } else {
115 throw new CredentialsException("Error assuming role from web identity credentials", 0, $e);
116 }
117 } catch (\Exception $e) {
118 throw new CredentialsException("Error retrieving web identity credentials: " . $e->getMessage() . " (" . $e->getCode() . ")");
119 }
120 $this->authenticationAttempts++;
121 }
122 (yield $this->client->createCredentials($result, $this->source));
123 });
124 }
125 /**
126 * @param string|null $region
127 *
128 * @return StsClient
129 */
130 private function createDefaultStsClient(?string $region) : StsClient
131 {
132 if (empty($region)) {
133 $region = CredentialProvider::FALLBACK_REGION;
134 \trigger_error('NOTICE: STS client created without explicit `region` configuration.' . \PHP_EOL . "Defaulting to {$region}. This fallback behavior may be removed." . \PHP_EOL . 'To avoid potential disruptions, configure a region using one of the following methods:' . \PHP_EOL . '(1) Pass `region` in the `$config` array when calling the provider,' . \PHP_EOL . '(2) Set the `AWS_REGION` environment variable.' . \PHP_EOL . 'OR provide an STS client in the `$config` array when creating the provider as `client`.' . \PHP_EOL . 'See: https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/assume-role-with-web-identity-provider.html' . \PHP_EOL, \E_USER_NOTICE);
135 }
136 return new StsClient(['credentials' => \false, 'region' => $region]);
137 }
138 }
139