IniFileLoader.php 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. <?php
  2. declare(strict_types=1);
  3. namespace AsyncAws\Core\Credentials;
  4. use AsyncAws\Core\EnvVar;
  5. use Psr\Log\LoggerInterface;
  6. use Psr\Log\NullLogger;
  7. /**
  8. * Load and parse AWS iniFile.
  9. *
  10. * @author Jérémy Derussé <jeremy@derusse.com>
  11. */
  12. final class IniFileLoader
  13. {
  14. public const KEY_REGION = 'region';
  15. public const KEY_ACCESS_KEY_ID = 'aws_access_key_id';
  16. public const KEY_SECRET_ACCESS_KEY = 'aws_secret_access_key';
  17. public const KEY_SESSION_TOKEN = 'aws_session_token';
  18. public const KEY_ROLE_ARN = 'role_arn';
  19. public const KEY_ROLE_SESSION_NAME = 'role_session_name';
  20. public const KEY_SOURCE_PROFILE = 'source_profile';
  21. public const KEY_WEB_IDENTITY_TOKEN_FILE = 'web_identity_token_file';
  22. private $logger;
  23. public function __construct(?LoggerInterface $logger = null)
  24. {
  25. $this->logger = $logger ?? new NullLogger();
  26. }
  27. /**
  28. * @param string[] $filepaths
  29. *
  30. * @return string[][]
  31. */
  32. public function loadProfiles(array $filepaths): array
  33. {
  34. $profilesData = [];
  35. $homeDir = null;
  36. foreach ($filepaths as $filepath) {
  37. if ('' === $filepath) {
  38. continue;
  39. }
  40. if ('~' === $filepath[0]) {
  41. $homeDir = $homeDir ?? $this->getHomeDir();
  42. $filepath = $homeDir . substr($filepath, 1);
  43. }
  44. if (!is_readable($filepath) || !is_file($filepath)) {
  45. continue;
  46. }
  47. foreach ($this->parseIniFile($filepath) as $name => $profile) {
  48. $name = preg_replace('/^profile /', '', (string) $name);
  49. if (!isset($profilesData[$name])) {
  50. $profilesData[$name] = array_map('trim', $profile);
  51. } else {
  52. foreach ($profile as $k => $v) {
  53. if (!isset($profilesData[$name][$k])) {
  54. $profilesData[$name][$k] = trim($v);
  55. }
  56. }
  57. }
  58. }
  59. }
  60. return $profilesData;
  61. }
  62. private function getHomeDir(): string
  63. {
  64. // On Linux/Unix-like systems, use the HOME environment variable
  65. if (null !== $homeDir = EnvVar::get('HOME')) {
  66. return $homeDir;
  67. }
  68. // Get the HOMEDRIVE and HOMEPATH values for Windows hosts
  69. $homeDrive = EnvVar::get('HOMEDRIVE');
  70. $homePath = EnvVar::get('HOMEPATH');
  71. return ($homeDrive && $homePath) ? $homeDrive . $homePath : '/';
  72. }
  73. private function parseIniFile(string $filepath): array
  74. {
  75. if (false === $data = parse_ini_string(
  76. preg_replace('/^#/m', ';', file_get_contents($filepath)),
  77. true,
  78. \INI_SCANNER_RAW
  79. )) {
  80. $this->logger->warning('The ini file {path} is invalid.', ['path' => $filepath]);
  81. return [];
  82. }
  83. return $data;
  84. }
  85. }