PluginProbe
Media Cloud Sync / 1.1.1
Media Cloud Sync v1.1.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 / CredentialProvider.php

CredentialProvider.php in Media Cloud Sync 1.1.1, at includes/sdk/s3/Aws/Credentials/CredentialProvider.php

639 lines 30.3 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;
6 use Dudlewebs\WPMCS\s3\Aws\Api\DateTimeResult;
7 use Dudlewebs\WPMCS\s3\Aws\CacheInterface;
8 use Dudlewebs\WPMCS\s3\Aws\Exception\CredentialsException;
9 use Dudlewebs\WPMCS\s3\Aws\Sts\StsClient;
10 use Dudlewebs\WPMCS\s3\GuzzleHttp\Promise;
11 /**
12 * Credential providers are functions that accept no arguments and return a
13 * promise that is fulfilled with an {@see \Aws\Credentials\CredentialsInterface}
14 * or rejected with an {@see \Aws\Exception\CredentialsException}.
15 *
16 * <code>
17 * use Aws\Credentials\CredentialProvider;
18 * $provider = CredentialProvider::defaultProvider();
19 * // Returns a CredentialsInterface or throws.
20 * $creds = $provider()->wait();
21 * </code>
22 *
23 * Credential providers can be composed to create credentials using conditional
24 * logic that can create different credentials in different environments. You
25 * can compose multiple providers into a single provider using
26 * {@see Aws\Credentials\CredentialProvider::chain}. This function accepts
27 * providers as variadic arguments and returns a new function that will invoke
28 * each provider until a successful set of credentials is returned.
29 *
30 * <code>
31 * // First try an INI file at this location.
32 * $a = CredentialProvider::ini(null, '/path/to/file.ini');
33 * // Then try an INI file at this location.
34 * $b = CredentialProvider::ini(null, '/path/to/other-file.ini');
35 * // Then try loading from environment variables.
36 * $c = CredentialProvider::env();
37 * // Combine the three providers together.
38 * $composed = CredentialProvider::chain($a, $b, $c);
39 * // Returns a promise that is fulfilled with credentials or throws.
40 * $promise = $composed();
41 * // Wait on the credentials to resolve.
42 * $creds = $promise->wait();
43 * </code>
44 */
45 class CredentialProvider
46 {
47 const ENV_ARN = 'AWS_ROLE_ARN';
48 const ENV_KEY = 'AWS_ACCESS_KEY_ID';
49 const ENV_PROFILE = 'AWS_PROFILE';
50 const ENV_ROLE_SESSION_NAME = 'AWS_ROLE_SESSION_NAME';
51 const ENV_SECRET = 'AWS_SECRET_ACCESS_KEY';
52 const ENV_SESSION = 'AWS_SESSION_TOKEN';
53 const ENV_TOKEN_FILE = 'AWS_WEB_IDENTITY_TOKEN_FILE';
54 const ENV_SHARED_CREDENTIALS_FILE = 'AWS_SHARED_CREDENTIALS_FILE';
55 /**
56 * Create a default credential provider that
57 * first checks for environment variables,
58 * then checks for assumed role via web identity,
59 * then checks for cached SSO credentials from the CLI,
60 * then check for credential_process in the "default" profile in ~/.aws/credentials,
61 * then checks for the "default" profile in ~/.aws/credentials,
62 * then for credential_process in the "default profile" profile in ~/.aws/config,
63 * then checks for "profile default" profile in ~/.aws/config (which is
64 * the default profile of AWS CLI),
65 * then tries to make a GET Request to fetch credentials if ECS environment variable is presented,
66 * finally checks for EC2 instance profile credentials.
67 *
68 * This provider is automatically wrapped in a memoize function that caches
69 * previously provided credentials.
70 *
71 * @param array $config Optional array of ecs/instance profile credentials
72 * provider options.
73 *
74 * @return callable
75 */
76 public static function defaultProvider(array $config = [])
77 {
78 $cacheable = ['web_identity', 'sso', 'process_credentials', 'process_config', 'ecs', 'instance'];
79 $profileName = \getenv(self::ENV_PROFILE) ?: 'default';
80 $defaultChain = ['env' => self::env(), 'web_identity' => self::assumeRoleWithWebIdentityCredentialProvider($config)];
81 if (!isset($config['use_aws_shared_config_files']) || $config['use_aws_shared_config_files'] !== \false) {
82 $defaultChain['sso'] = self::sso('profile ' . $profileName, self::getHomeDir() . '/.aws/config', $config);
83 $defaultChain['process_credentials'] = self::process();
84 $defaultChain['ini'] = self::ini();
85 $defaultChain['process_config'] = self::process('profile ' . $profileName, self::getHomeDir() . '/.aws/config');
86 $defaultChain['ini_config'] = self::ini('profile ' . $profileName, self::getHomeDir() . '/.aws/config');
87 }
88 if (self::shouldUseEcs()) {
89 $defaultChain['ecs'] = self::ecsCredentials($config);
90 } else {
91 $defaultChain['instance'] = self::instanceProfile($config);
92 }
93 if (isset($config['credentials']) && $config['credentials'] instanceof CacheInterface) {
94 foreach ($cacheable as $provider) {
95 if (isset($defaultChain[$provider])) {
96 $defaultChain[$provider] = self::cache($defaultChain[$provider], $config['credentials'], 'aws_cached_' . $provider . '_credentials');
97 }
98 }
99 }
100 return self::memoize(\call_user_func_array([CredentialProvider::class, 'chain'], \array_values($defaultChain)));
101 }
102 /**
103 * Create a credential provider function from a set of static credentials.
104 *
105 * @param CredentialsInterface $creds
106 *
107 * @return callable
108 */
109 public static function fromCredentials(CredentialsInterface $creds)
110 {
111 $promise = Promise\Create::promiseFor($creds);
112 return function () use($promise) {
113 return $promise;
114 };
115 }
116 /**
117 * Creates an aggregate credentials provider that invokes the provided
118 * variadic providers one after the other until a provider returns
119 * credentials.
120 *
121 * @return callable
122 */
123 public static function chain()
124 {
125 $links = \func_get_args();
126 if (empty($links)) {
127 throw new \InvalidArgumentException('No providers in chain');
128 }
129 return function ($previousCreds = null) use($links) {
130 /** @var callable $parent */
131 $parent = \array_shift($links);
132 $promise = $parent();
133 while ($next = \array_shift($links)) {
134 if ($next instanceof InstanceProfileProvider && $previousCreds instanceof Credentials) {
135 $promise = $promise->otherwise(function () use($next, $previousCreds) {
136 return $next($previousCreds);
137 });
138 } else {
139 $promise = $promise->otherwise($next);
140 }
141 }
142 return $promise;
143 };
144 }
145 /**
146 * Wraps a credential provider and caches previously provided credentials.
147 *
148 * Ensures that cached credentials are refreshed when they expire.
149 *
150 * @param callable $provider Credentials provider function to wrap.
151 *
152 * @return callable
153 */
154 public static function memoize(callable $provider)
155 {
156 return function () use($provider) {
157 static $result;
158 static $isConstant;
159 // Constant credentials will be returned constantly.
160 if ($isConstant) {
161 return $result;
162 }
163 // Create the initial promise that will be used as the cached value
164 // until it expires.
165 if (null === $result) {
166 $result = $provider();
167 }
168 // Return credentials that could expire and refresh when needed.
169 return $result->then(function (CredentialsInterface $creds) use($provider, &$isConstant, &$result) {
170 // Determine if these are constant credentials.
171 if (!$creds->getExpiration()) {
172 $isConstant = \true;
173 return $creds;
174 }
175 // Refresh expired credentials.
176 if (!$creds->isExpired()) {
177 return $creds;
178 }
179 // Refresh the result and forward the promise.
180 return $result = $provider($creds);
181 })->otherwise(function ($reason) use(&$result) {
182 // Cleanup rejected promise.
183 $result = null;
184 return new Promise\RejectedPromise($reason);
185 });
186 };
187 }
188 /**
189 * Wraps a credential provider and saves provided credentials in an
190 * instance of Aws\CacheInterface. Forwards calls when no credentials found
191 * in cache and updates cache with the results.
192 *
193 * @param callable $provider Credentials provider function to wrap
194 * @param CacheInterface $cache Cache to store credentials
195 * @param string|null $cacheKey (optional) Cache key to use
196 *
197 * @return callable
198 */
199 public static function cache(callable $provider, CacheInterface $cache, $cacheKey = null)
200 {
201 $cacheKey = $cacheKey ?: 'aws_cached_credentials';
202 return function () use($provider, $cache, $cacheKey) {
203 $found = $cache->get($cacheKey);
204 if ($found instanceof CredentialsInterface && !$found->isExpired()) {
205 return Promise\Create::promiseFor($found);
206 }
207 return $provider()->then(function (CredentialsInterface $creds) use($cache, $cacheKey) {
208 $cache->set($cacheKey, $creds, null === $creds->getExpiration() ? 0 : $creds->getExpiration() - \time());
209 return $creds;
210 });
211 };
212 }
213 /**
214 * Provider that creates credentials from environment variables
215 * AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN.
216 *
217 * @return callable
218 */
219 public static function env()
220 {
221 return function () {
222 // Use credentials from environment variables, if available
223 $key = \getenv(self::ENV_KEY);
224 $secret = \getenv(self::ENV_SECRET);
225 if ($key && $secret) {
226 return Promise\Create::promiseFor(new Credentials($key, $secret, \getenv(self::ENV_SESSION) ?: NULL));
227 }
228 return self::reject('Could not find environment variable ' . 'credentials in ' . self::ENV_KEY . '/' . self::ENV_SECRET);
229 };
230 }
231 /**
232 * Credential provider that creates credentials using instance profile
233 * credentials.
234 *
235 * @param array $config Array of configuration data.
236 *
237 * @return InstanceProfileProvider
238 * @see Aws\Credentials\InstanceProfileProvider for $config details.
239 */
240 public static function instanceProfile(array $config = [])
241 {
242 return new InstanceProfileProvider($config);
243 }
244 /**
245 * Credential provider that retrieves cached SSO credentials from the CLI
246 *
247 * @return callable
248 */
249 public static function sso($ssoProfileName, $filename = null, $config = [])
250 {
251 $filename = $filename ?: self::getHomeDir() . '/.aws/config';
252 return function () use($ssoProfileName, $filename, $config) {
253 if (!@\is_readable($filename)) {
254 return self::reject("Cannot read credentials from {$filename}");
255 }
256 $profiles = self::loadProfiles($filename);
257 if (!isset($profiles[$ssoProfileName])) {
258 return self::reject("Profile {$ssoProfileName} does not exist in {$filename}.");
259 }
260 $ssoProfile = $profiles[$ssoProfileName];
261 if (empty($ssoProfile['sso_start_url']) || empty($ssoProfile['sso_region']) || empty($ssoProfile['sso_account_id']) || empty($ssoProfile['sso_role_name'])) {
262 return self::reject("Profile {$ssoProfileName} in {$filename} must contain the following keys: " . "sso_start_url, sso_region, sso_account_id, and sso_role_name.");
263 }
264 $tokenLocation = self::getHomeDir() . '/.aws/sso/cache/' . \utf8_encode(\sha1($ssoProfile['sso_start_url'])) . ".json";
265 if (!@\is_readable($tokenLocation)) {
266 return self::reject("Unable to read token file at {$tokenLocation}");
267 }
268 $tokenData = \json_decode(\file_get_contents($tokenLocation), \true);
269 if (empty($tokenData['accessToken']) || empty($tokenData['expiresAt'])) {
270 return self::reject("Token file at {$tokenLocation} must contain an access token and an expiration");
271 }
272 try {
273 $expiration = (new DateTimeResult($tokenData['expiresAt']))->getTimestamp();
274 } catch (\Exception $e) {
275 return self::reject("Cached SSO credentials returned an invalid expiration");
276 }
277 $now = \time();
278 if ($expiration < $now) {
279 return self::reject("Cached SSO credentials returned expired credentials");
280 }
281 $ssoClient = null;
282 if (empty($config['ssoClient'])) {
283 $ssoClient = new Aws\SSO\SSOClient(['region' => $ssoProfile['sso_region'], 'version' => '2019-06-10', 'credentials' => \false]);
284 } else {
285 $ssoClient = $config['ssoClient'];
286 }
287 $ssoResponse = $ssoClient->getRoleCredentials(['accessToken' => $tokenData['accessToken'], 'accountId' => $ssoProfile['sso_account_id'], 'roleName' => $ssoProfile['sso_role_name']]);
288 $ssoCredentials = $ssoResponse['roleCredentials'];
289 return Promise\Create::promiseFor(new Credentials($ssoCredentials['accessKeyId'], $ssoCredentials['secretAccessKey'], $ssoCredentials['sessionToken'], $expiration));
290 };
291 }
292 /**
293 * Credential provider that creates credentials using
294 * ecs credentials by a GET request, whose uri is specified
295 * by environment variable
296 *
297 * @param array $config Array of configuration data.
298 *
299 * @return EcsCredentialProvider
300 * @see Aws\Credentials\EcsCredentialProvider for $config details.
301 */
302 public static function ecsCredentials(array $config = [])
303 {
304 return new EcsCredentialProvider($config);
305 }
306 /**
307 * Credential provider that creates credentials using assume role
308 *
309 * @param array $config Array of configuration data
310 * @return callable
311 * @see Aws\Credentials\AssumeRoleCredentialProvider for $config details.
312 */
313 public static function assumeRole(array $config = [])
314 {
315 return new AssumeRoleCredentialProvider($config);
316 }
317 /**
318 * Credential provider that creates credentials by assuming role from a
319 * Web Identity Token
320 *
321 * @param array $config Array of configuration data
322 * @return callable
323 * @see Aws\Credentials\AssumeRoleWithWebIdentityCredentialProvider for
324 * $config details.
325 */
326 public static function assumeRoleWithWebIdentityCredentialProvider(array $config = [])
327 {
328 return function () use($config) {
329 $arnFromEnv = \getenv(self::ENV_ARN);
330 $tokenFromEnv = \getenv(self::ENV_TOKEN_FILE);
331 $stsClient = isset($config['stsClient']) ? $config['stsClient'] : null;
332 $region = isset($config['region']) ? $config['region'] : null;
333 if ($tokenFromEnv && $arnFromEnv) {
334 $sessionName = \getenv(self::ENV_ROLE_SESSION_NAME) ? \getenv(self::ENV_ROLE_SESSION_NAME) : null;
335 $provider = new AssumeRoleWithWebIdentityCredentialProvider(['RoleArn' => $arnFromEnv, 'WebIdentityTokenFile' => $tokenFromEnv, 'SessionName' => $sessionName, 'client' => $stsClient, 'region' => $region]);
336 return $provider();
337 }
338 $profileName = \getenv(self::ENV_PROFILE) ?: 'default';
339 if (isset($config['filename'])) {
340 $profiles = self::loadProfiles($config['filename']);
341 } else {
342 $profiles = self::loadDefaultProfiles();
343 }
344 if (isset($profiles[$profileName])) {
345 $profile = $profiles[$profileName];
346 if (isset($profile['region'])) {
347 $region = $profile['region'];
348 }
349 if (isset($profile['web_identity_token_file']) && isset($profile['role_arn'])) {
350 $sessionName = isset($profile['role_session_name']) ? $profile['role_session_name'] : null;
351 $provider = new AssumeRoleWithWebIdentityCredentialProvider(['RoleArn' => $profile['role_arn'], 'WebIdentityTokenFile' => $profile['web_identity_token_file'], 'SessionName' => $sessionName, 'client' => $stsClient, 'region' => $region]);
352 return $provider();
353 }
354 } else {
355 return self::reject("Unknown profile: {$profileName}");
356 }
357 return self::reject("No RoleArn or WebIdentityTokenFile specified");
358 };
359 }
360 /**
361 * Credentials provider that creates credentials using an ini file stored
362 * in the current user's home directory. A source can be provided
363 * in this file for assuming a role using the credential_source config option.
364 *
365 * @param string|null $profile Profile to use. If not specified will use
366 * the "default" profile in "~/.aws/credentials".
367 * @param string|null $filename If provided, uses a custom filename rather
368 * than looking in the home directory.
369 * @param array|null $config If provided, may contain the following:
370 * preferStaticCredentials: If true, prefer static
371 * credentials to role_arn if both are present
372 * disableAssumeRole: If true, disable support for
373 * roles that assume an IAM role. If true and role profile
374 * is selected, an error is raised.
375 * stsClient: StsClient used to assume role specified in profile
376 *
377 * @return callable
378 */
379 public static function ini($profile = null, $filename = null, array $config = [])
380 {
381 $filename = self::getFileName($filename);
382 $profile = $profile ?: (\getenv(self::ENV_PROFILE) ?: 'default');
383 return function () use($profile, $filename, $config) {
384 $preferStaticCredentials = isset($config['preferStaticCredentials']) ? $config['preferStaticCredentials'] : \false;
385 $disableAssumeRole = isset($config['disableAssumeRole']) ? $config['disableAssumeRole'] : \false;
386 $stsClient = isset($config['stsClient']) ? $config['stsClient'] : null;
387 if (!@\is_readable($filename)) {
388 return self::reject("Cannot read credentials from {$filename}");
389 }
390 $data = self::loadProfiles($filename);
391 if ($data === \false) {
392 return self::reject("Invalid credentials file: {$filename}");
393 }
394 if (!isset($data[$profile])) {
395 return self::reject("'{$profile}' not found in credentials file");
396 }
397 /*
398 In the CLI, the presence of both a role_arn and static credentials have
399 different meanings depending on how many profiles have been visited. For
400 the first profile processed, role_arn takes precedence over any static
401 credentials, but for all subsequent profiles, static credentials are
402 used if present, and only in their absence will the profile's
403 source_profile and role_arn keys be used to load another set of
404 credentials. This bool is intended to yield compatible behaviour in this
405 sdk.
406 */
407 $preferStaticCredentialsToRoleArn = $preferStaticCredentials && isset($data[$profile]['aws_access_key_id']) && isset($data[$profile]['aws_secret_access_key']);
408 if (isset($data[$profile]['role_arn']) && !$preferStaticCredentialsToRoleArn) {
409 if ($disableAssumeRole) {
410 return self::reject("Role assumption profiles are disabled. " . "Failed to load profile " . $profile);
411 }
412 return self::loadRoleProfile($data, $profile, $filename, $stsClient, $config);
413 }
414 if (!isset($data[$profile]['aws_access_key_id']) || !isset($data[$profile]['aws_secret_access_key'])) {
415 return self::reject("No credentials present in INI profile " . "'{$profile}' ({$filename})");
416 }
417 if (empty($data[$profile]['aws_session_token'])) {
418 $data[$profile]['aws_session_token'] = isset($data[$profile]['aws_security_token']) ? $data[$profile]['aws_security_token'] : null;
419 }
420 return Promise\Create::promiseFor(new Credentials($data[$profile]['aws_access_key_id'], $data[$profile]['aws_secret_access_key'], $data[$profile]['aws_session_token']));
421 };
422 }
423 /**
424 * Credentials provider that creates credentials using a process configured in
425 * ini file stored in the current user's home directory.
426 *
427 * @param string|null $profile Profile to use. If not specified will use
428 * the "default" profile in "~/.aws/credentials".
429 * @param string|null $filename If provided, uses a custom filename rather
430 * than looking in the home directory.
431 *
432 * @return callable
433 */
434 public static function process($profile = null, $filename = null)
435 {
436 $filename = self::getFileName($filename);
437 $profile = $profile ?: (\getenv(self::ENV_PROFILE) ?: 'default');
438 return function () use($profile, $filename) {
439 if (!@\is_readable($filename)) {
440 return self::reject("Cannot read process credentials from {$filename}");
441 }
442 $data = \Dudlewebs\WPMCS\s3\Aws\parse_ini_file($filename, \true, \INI_SCANNER_RAW);
443 if ($data === \false) {
444 return self::reject("Invalid credentials file: {$filename}");
445 }
446 if (!isset($data[$profile])) {
447 return self::reject("'{$profile}' not found in credentials file");
448 }
449 if (!isset($data[$profile]['credential_process'])) {
450 return self::reject("No credential_process present in INI profile " . "'{$profile}' ({$filename})");
451 }
452 $credentialProcess = $data[$profile]['credential_process'];
453 $json = \shell_exec($credentialProcess);
454 $processData = \json_decode($json, \true);
455 // Only support version 1
456 if (isset($processData['Version'])) {
457 if ($processData['Version'] !== 1) {
458 return self::reject("credential_process does not return Version == 1");
459 }
460 }
461 if (!isset($processData['AccessKeyId']) || !isset($processData['SecretAccessKey'])) {
462 return self::reject("credential_process does not return valid credentials");
463 }
464 if (isset($processData['Expiration'])) {
465 try {
466 $expiration = new DateTimeResult($processData['Expiration']);
467 } catch (\Exception $e) {
468 return self::reject("credential_process returned invalid expiration");
469 }
470 $now = new DateTimeResult();
471 if ($expiration < $now) {
472 return self::reject("credential_process returned expired credentials");
473 }
474 $expires = $expiration->getTimestamp();
475 } else {
476 $expires = null;
477 }
478 if (empty($processData['SessionToken'])) {
479 $processData['SessionToken'] = null;
480 }
481 return Promise\Create::promiseFor(new Credentials($processData['AccessKeyId'], $processData['SecretAccessKey'], $processData['SessionToken'], $expires));
482 };
483 }
484 /**
485 * Assumes role for profile that includes role_arn
486 *
487 * @return callable
488 */
489 private static function loadRoleProfile($profiles, $profileName, $filename, $stsClient, $config = [])
490 {
491 $roleProfile = $profiles[$profileName];
492 $roleArn = isset($roleProfile['role_arn']) ? $roleProfile['role_arn'] : '';
493 $roleSessionName = isset($roleProfile['role_session_name']) ? $roleProfile['role_session_name'] : 'aws-sdk-php-' . \round(\microtime(\true) * 1000);
494 if (empty($roleProfile['source_profile']) == empty($roleProfile['credential_source'])) {
495 return self::reject("Either source_profile or credential_source must be set " . "using profile " . $profileName . ", but not both.");
496 }
497 $sourceProfileName = "";
498 if (!empty($roleProfile['source_profile'])) {
499 $sourceProfileName = $roleProfile['source_profile'];
500 if (!isset($profiles[$sourceProfileName])) {
501 return self::reject("source_profile " . $sourceProfileName . " using profile " . $profileName . " does not exist");
502 }
503 if (isset($config['visited_profiles']) && \in_array($roleProfile['source_profile'], $config['visited_profiles'])) {
504 return self::reject("Circular source_profile reference found.");
505 }
506 $config['visited_profiles'][] = $roleProfile['source_profile'];
507 } else {
508 if (empty($roleArn)) {
509 return self::reject("A role_arn must be provided with credential_source in " . "file {$filename} under profile {$profileName} ");
510 }
511 }
512 if (empty($stsClient)) {
513 $sourceRegion = isset($profiles[$sourceProfileName]['region']) ? $profiles[$sourceProfileName]['region'] : 'us-east-1';
514 $config['preferStaticCredentials'] = \true;
515 $sourceCredentials = null;
516 if (!empty($roleProfile['source_profile'])) {
517 $sourceCredentials = \call_user_func(CredentialProvider::ini($sourceProfileName, $filename, $config))->wait();
518 } else {
519 $sourceCredentials = self::getCredentialsFromSource($profileName, $filename);
520 }
521 $stsClient = new StsClient(['credentials' => $sourceCredentials, 'region' => $sourceRegion, 'version' => '2011-06-15']);
522 }
523 $result = $stsClient->assumeRole(['RoleArn' => $roleArn, 'RoleSessionName' => $roleSessionName]);
524 $credentials = $stsClient->createCredentials($result);
525 return Promise\Create::promiseFor($credentials);
526 }
527 /**
528 * Gets the environment's HOME directory if available.
529 *
530 * @return null|string
531 */
532 private static function getHomeDir()
533 {
534 // On Linux/Unix-like systems, use the HOME environment variable
535 if ($homeDir = \getenv('HOME')) {
536 return $homeDir;
537 }
538 // Get the HOMEDRIVE and HOMEPATH values for Windows hosts
539 $homeDrive = \getenv('HOMEDRIVE');
540 $homePath = \getenv('HOMEPATH');
541 return $homeDrive && $homePath ? $homeDrive . $homePath : null;
542 }
543 /**
544 * Gets profiles from specified $filename, or default ini files.
545 */
546 private static function loadProfiles($filename)
547 {
548 $profileData = \Dudlewebs\WPMCS\s3\Aws\parse_ini_file($filename, \true, \INI_SCANNER_RAW);
549 // If loading .aws/credentials, also load .aws/config when AWS_SDK_LOAD_NONDEFAULT_CONFIG is set
550 if ($filename === self::getHomeDir() . '/.aws/credentials' && \getenv('AWS_SDK_LOAD_NONDEFAULT_CONFIG')) {
551 $configFilename = self::getHomeDir() . '/.aws/config';
552 $configProfileData = \Dudlewebs\WPMCS\s3\Aws\parse_ini_file($configFilename, \true, \INI_SCANNER_RAW);
553 foreach ($configProfileData as $name => $profile) {
554 // standardize config profile names
555 $name = \str_replace('profile ', '', $name);
556 if (!isset($profileData[$name])) {
557 $profileData[$name] = $profile;
558 }
559 }
560 }
561 return $profileData;
562 }
563 /**
564 * Gets profiles from ~/.aws/credentials and ~/.aws/config ini files
565 */
566 private static function loadDefaultProfiles()
567 {
568 $profiles = [];
569 $credFile = self::getHomeDir() . '/.aws/credentials';
570 $configFile = self::getHomeDir() . '/.aws/config';
571 if (\file_exists($credFile)) {
572 $profiles = \Dudlewebs\WPMCS\s3\Aws\parse_ini_file($credFile, \true, \INI_SCANNER_RAW);
573 }
574 if (\file_exists($configFile)) {
575 $configProfileData = \Dudlewebs\WPMCS\s3\Aws\parse_ini_file($configFile, \true, \INI_SCANNER_RAW);
576 foreach ($configProfileData as $name => $profile) {
577 // standardize config profile names
578 $name = \str_replace('profile ', '', $name);
579 if (!isset($profiles[$name])) {
580 $profiles[$name] = $profile;
581 }
582 }
583 }
584 return $profiles;
585 }
586 public static function getCredentialsFromSource($profileName = '', $filename = '', $config = [])
587 {
588 $data = self::loadProfiles($filename);
589 $credentialSource = !empty($data[$profileName]['credential_source']) ? $data[$profileName]['credential_source'] : null;
590 $credentialsPromise = null;
591 switch ($credentialSource) {
592 case 'Environment':
593 $credentialsPromise = self::env();
594 break;
595 case 'Ec2InstanceMetadata':
596 $credentialsPromise = self::instanceProfile($config);
597 break;
598 case 'EcsContainer':
599 $credentialsPromise = self::ecsCredentials($config);
600 break;
601 default:
602 throw new CredentialsException("Invalid credential_source found in config file: {$credentialSource}. Valid inputs " . "include Environment, Ec2InstanceMetadata, and EcsContainer.");
603 }
604 $credentialsResult = null;
605 try {
606 $credentialsResult = $credentialsPromise()->wait();
607 } catch (\Exception $reason) {
608 return self::reject("Unable to successfully retrieve credentials from the source specified in the" . " credentials file: {$credentialSource}; failure message was: " . $reason->getMessage());
609 }
610 return function () use($credentialsResult) {
611 return Promise\Create::promiseFor($credentialsResult);
612 };
613 }
614 private static function reject($msg)
615 {
616 return new Promise\RejectedPromise(new CredentialsException($msg));
617 }
618 /**
619 * @param $filename
620 * @return string
621 */
622 private static function getFileName($filename)
623 {
624 if (!isset($filename)) {
625 $filename = \getenv(self::ENV_SHARED_CREDENTIALS_FILE) ?: self::getHomeDir() . '/.aws/credentials';
626 }
627 return $filename;
628 }
629 /**
630 * @return boolean
631 */
632 public static function shouldUseEcs()
633 {
634 //Check for relative uri. if not, then full uri.
635 //fall back to server for each as getenv is not thread-safe.
636 return !empty(\getenv(EcsCredentialProvider::ENV_URI)) || !empty($_SERVER[EcsCredentialProvider::ENV_URI]) || !empty(\getenv(EcsCredentialProvider::ENV_FULL_URI)) || !empty($_SERVER[EcsCredentialProvider::ENV_FULL_URI]);
637 }
638 }
639