PluginProbe
Media Cloud Sync / 1.3.11
Media Cloud Sync v1.3.11
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 1.3.0 All 34 releases
media-cloud-sync / includes / sdk / s3 / Aws / Token / TokenProvider.php

TokenProvider.php in Media Cloud Sync 1.3.11, at includes/sdk/s3/Aws/Token/TokenProvider.php

211 lines 7.8 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\Token;
4
5 use Dudlewebs\WPMCS\s3\Aws;
6 use Dudlewebs\WPMCS\s3\Aws\CacheInterface;
7 use Dudlewebs\WPMCS\s3\Aws\Exception\TokenException;
8 use Dudlewebs\WPMCS\s3\GuzzleHttp\Promise;
9 /**
10 * Token providers are functions that accept no arguments and return a
11 * promise that is fulfilled with an {@see \Aws\Token\TokenInterface}
12 * or rejected with an {@see \Aws\Exception\TokenException}.
13 *
14 * <code>
15 * use Aws\Token\TokenProvider;
16 * $provider = TokenProvider::defaultProvider();
17 * // Returns a TokenInterface or throws.
18 * $token = $provider()->wait();
19 * </code>
20 *
21 * Token providers can be composed to create a token using conditional
22 * logic that can create different tokens in different environments. You
23 * can compose multiple providers into a single provider using
24 * {@see Aws\Token\TokenProvider::chain}. This function accepts
25 * providers as variadic arguments and returns a new function that will invoke
26 * each provider until a token is successfully returned.
27 */
28 class TokenProvider
29 {
30 const ENV_PROFILE = 'AWS_PROFILE';
31 use ParsesIniTrait;
32 /**
33 * Create a default token provider tha checks for cached a SSO token from
34 * the CLI
35 *
36 * This provider is automatically wrapped in a memoize function that caches
37 * previously provided tokens.
38 *
39 * @param array $config Optional array of token provider options.
40 *
41 * @return callable
42 */
43 public static function defaultProvider(array $config = [])
44 {
45 $cacheable = ['sso'];
46 $defaultChain = [];
47 if (!isset($config['use_aws_shared_config_files']) || $config['use_aws_shared_config_files'] !== \false) {
48 $profileName = \getenv(self::ENV_PROFILE) ?: 'default';
49 $defaultChain['sso'] = self::sso($profileName, self::getHomeDir() . '/.aws/config', $config);
50 }
51 if (isset($config['token']) && $config['token'] instanceof CacheInterface) {
52 foreach ($cacheable as $provider) {
53 if (isset($defaultChain[$provider])) {
54 $defaultChain[$provider] = self::cache($defaultChain[$provider], $config['token'], 'aws_cached_' . $provider . '_token');
55 }
56 }
57 }
58 return self::memoize(\call_user_func_array([__CLASS__, 'chain'], \array_values($defaultChain)));
59 }
60 /**
61 * Create a token provider function from a static token.
62 *
63 * @param TokenInterface $token
64 *
65 * @return callable
66 */
67 public static function fromToken(TokenInterface $token)
68 {
69 $promise = Promise\Create::promiseFor($token);
70 return static function () use($promise) {
71 return $promise;
72 };
73 }
74 /**
75 * Creates an aggregate token provider that invokes the provided
76 * variadic providers one after the other until a provider returns
77 * a token.
78 *
79 * @return callable
80 */
81 public static function chain()
82 {
83 $links = \func_get_args();
84 //Common use case for when aws_shared_config_files is false
85 if (empty($links)) {
86 return static function () {
87 return Promise\Create::promiseFor(\false);
88 };
89 }
90 return static function () use($links) {
91 /** @var callable $parent */
92 $parent = \array_shift($links);
93 $promise = $parent();
94 while ($next = \array_shift($links)) {
95 $promise = $promise->otherwise($next);
96 }
97 return $promise;
98 };
99 }
100 /**
101 * Wraps a token provider and caches a previously provided token.
102 * Ensures that cached tokens are refreshed when they expire.
103 *
104 * @param callable $provider Token provider function to wrap.
105 * @return callable
106 */
107 public static function memoize(callable $provider)
108 {
109 return static function () use($provider) {
110 static $result;
111 static $isConstant;
112 // Constant tokens will be returned constantly.
113 if ($isConstant) {
114 return $result;
115 }
116 // Create the initial promise that will be used as the cached value
117 // until it expires.
118 if (null === $result) {
119 $result = $provider();
120 }
121 // Return a token that could expire and refresh when needed.
122 return $result->then(function (TokenInterface $token) use($provider, &$isConstant, &$result) {
123 // Determine if the token is constant.
124 if (!$token->getExpiration()) {
125 $isConstant = \true;
126 return $token;
127 }
128 if (!$token->isExpired()) {
129 return $token;
130 }
131 return $result = $provider();
132 })->otherwise(function ($reason) use(&$result) {
133 // Cleanup rejected promise.
134 $result = null;
135 return Promise\Create::promiseFor(null);
136 });
137 };
138 }
139 /**
140 * Wraps a token provider and saves provided token in an
141 * instance of Aws\CacheInterface. Forwards calls when no token found
142 * in cache and updates cache with the results.
143 *
144 * @param callable $provider Token provider function to wrap
145 * @param CacheInterface $cache Cache to store the token
146 * @param string|null $cacheKey (optional) Cache key to use
147 *
148 * @return callable
149 */
150 public static function cache(callable $provider, CacheInterface $cache, $cacheKey = null)
151 {
152 $cacheKey = $cacheKey ?: 'aws_cached_token';
153 return static function () use($provider, $cache, $cacheKey) {
154 $found = $cache->get($cacheKey);
155 if (\is_array($found) && isset($found['token'])) {
156 $foundToken = $found['token'];
157 if ($foundToken instanceof TokenInterface) {
158 if (!$foundToken->isExpired()) {
159 return Promise\Create::promiseFor($foundToken);
160 }
161 if (isset($found['refreshMethod']) && \is_callable($found['refreshMethod'])) {
162 return Promise\Create::promiseFor($found['refreshMethod']());
163 }
164 }
165 }
166 return $provider()->then(function (TokenInterface $token) use($cache, $cacheKey) {
167 $cache->set($cacheKey, ['token' => $token], null === $token->getExpiration() ? 0 : $token->getExpiration() - \time());
168 return $token;
169 });
170 };
171 }
172 /**
173 * Gets profiles from the ~/.aws/config ini file
174 */
175 private static function loadDefaultProfiles()
176 {
177 $profiles = [];
178 $configFile = self::getHomeDir() . '/.aws/config';
179 if (\file_exists($configFile)) {
180 $configProfileData = \Dudlewebs\WPMCS\s3\Aws\parse_ini_file($configFile, \true, \INI_SCANNER_RAW);
181 foreach ($configProfileData as $name => $profile) {
182 // standardize config profile names
183 $name = \str_replace('profile ', '', $name);
184 if (!isset($profiles[$name])) {
185 $profiles[$name] = $profile;
186 }
187 }
188 }
189 return $profiles;
190 }
191 private static function reject($msg)
192 {
193 return new Promise\RejectedPromise(new TokenException($msg));
194 }
195 /**
196 * Token provider that creates a token from cached sso credentials
197 *
198 * @param string $profileName the name of the ini profile name
199 * @param string $filename the location of the ini file
200 * @param array $config configuration options
201 *
202 * @return SsoTokenProvider
203 * @see Aws\Token\SsoTokenProvider for $config details.
204 */
205 public static function sso($profileName, $filename, $config = [])
206 {
207 $ssoClient = $config['ssoClient'] ?? null;
208 return new SsoTokenProvider($profileName, $filename, $ssoClient);
209 }
210 }
211