4343 */
4444class CredentialProvider
4545{
46- const ENV_ARN = 'AWS_ROLE_ARN ' ;
47- const ENV_KEY = 'AWS_ACCESS_KEY_ID ' ;
48- const ENV_PROFILE = 'AWS_PROFILE ' ;
49- const ENV_ROLE_SESSION_NAME = 'AWS_ROLE_SESSION_NAME ' ;
50- const ENV_SECRET = 'AWS_SECRET_ACCESS_KEY ' ;
51- const ENV_ACCOUNT_ID = 'AWS_ACCOUNT_ID ' ;
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 ' ;
46+ public const ENV_ARN = 'AWS_ROLE_ARN ' ;
47+ public const ENV_KEY = 'AWS_ACCESS_KEY_ID ' ;
48+ public const ENV_PROFILE = 'AWS_PROFILE ' ;
49+ public const ENV_ROLE_SESSION_NAME = 'AWS_ROLE_SESSION_NAME ' ;
50+ public const ENV_SECRET = 'AWS_SECRET_ACCESS_KEY ' ;
51+ public const ENV_ACCOUNT_ID = 'AWS_ACCOUNT_ID ' ;
52+ public const ENV_SESSION = 'AWS_SESSION_TOKEN ' ;
53+ public const ENV_TOKEN_FILE = 'AWS_WEB_IDENTITY_TOKEN_FILE ' ;
54+ public const ENV_SHARED_CREDENTIALS_FILE = 'AWS_SHARED_CREDENTIALS_FILE ' ;
55+ public const ENV_CONFIG_FILE = 'AWS_CONFIG_FILE ' ;
5556 public const ENV_REGION = 'AWS_REGION ' ;
5657 public const FALLBACK_REGION = 'us-east-1 ' ;
5758 public const REFRESH_WINDOW = 60 ;
@@ -82,6 +83,7 @@ public static function defaultProvider(array $config = [])
8283 $ cacheable = [
8384 'web_identity ' ,
8485 'sso ' ,
86+ 'login ' ,
8587 'process_credentials ' ,
8688 'process_config ' ,
8789 'ecs ' ,
@@ -94,24 +96,24 @@ public static function defaultProvider(array $config = [])
9496 'env ' => self ::env (),
9597 'web_identity ' => self ::assumeRoleWithWebIdentityCredentialProvider ($ config ),
9698 ];
97- if (
98- !isset ($ config ['use_aws_shared_config_files ' ])
99+ if (!isset ($ config ['use_aws_shared_config_files ' ])
99100 || $ config ['use_aws_shared_config_files ' ] !== false
100101 ) {
101102 $ defaultChain ['sso ' ] = self ::sso (
102103 $ profileName ,
103- self ::getHomeDir () . ' /.aws/config ' ,
104+ self ::getConfigFileName () ,
104105 $ config
105106 );
107+ $ defaultChain ['login ' ] = self ::login ($ profileName , $ config );
106108 $ defaultChain ['process_credentials ' ] = self ::process ();
107109 $ defaultChain ['ini ' ] = self ::ini (null , null , $ config );
108110 $ defaultChain ['process_config ' ] = self ::process (
109111 'profile ' . $ profileName ,
110- self ::getHomeDir () . ' /.aws/config '
112+ self ::getConfigFileName ()
111113 );
112114 $ defaultChain ['ini_config ' ] = self ::ini (
113115 'profile ' . $ profileName ,
114- self ::getHomeDir () . ' /.aws/config '
116+ self ::getConfigFileName ()
115117 );
116118 }
117119
@@ -339,11 +341,12 @@ public static function instanceProfile(array $config = [])
339341 *
340342 * @return callable
341343 */
342- public static function sso ($ ssoProfileName = 'default ' ,
343- $ filename = null ,
344- $ config = []
344+ public static function sso (
345+ $ ssoProfileName = 'default ' ,
346+ $ filename = null ,
347+ $ config = []
345348 ) {
346- $ filename = $ filename ?: ( self ::getHomeDir () . ' /.aws/config ' );
349+ $ filename = $ filename ?? self ::getConfigFileName ( );
347350
348351 return function () use ($ ssoProfileName , $ filename , $ config ) {
349352 if (!@is_readable ($ filename )) {
@@ -489,17 +492,13 @@ public static function assumeRoleWithWebIdentityCredentialProvider(array $config
489492 */
490493 public static function ini ($ profile = null , $ filename = null , array $ config = [])
491494 {
492- $ filename = self ::getFileName ($ filename );
495+ $ filename = self ::getCredentialsFileName ($ filename );
493496 $ profile = $ profile ?: (getenv (self ::ENV_PROFILE ) ?: 'default ' );
494497
495498 return function () use ($ profile , $ filename , $ config ) {
496- $ preferStaticCredentials = isset ($ config ['preferStaticCredentials ' ])
497- ? $ config ['preferStaticCredentials ' ]
498- : false ;
499- $ disableAssumeRole = isset ($ config ['disableAssumeRole ' ])
500- ? $ config ['disableAssumeRole ' ]
501- : false ;
502- $ stsClient = isset ($ config ['stsClient ' ]) ? $ config ['stsClient ' ] : null ;
499+ $ preferStaticCredentials = $ config ['preferStaticCredentials ' ] ?? false ;
500+ $ disableAssumeRole = $ config ['disableAssumeRole ' ] ?? false ;
501+ $ stsClient = $ config ['stsClient ' ] ?? null ;
503502
504503 if (!@is_readable ($ filename )) {
505504 return self ::reject ("Cannot read credentials from $ filename " );
@@ -583,7 +582,7 @@ public static function ini($profile = null, $filename = null, array $config = []
583582 */
584583 public static function process ($ profile = null , $ filename = null )
585584 {
586- $ filename = self ::getFileName ($ filename );
585+ $ filename = self ::getCredentialsFileName ($ filename );
587586 $ profile = $ profile ?: (getenv (self ::ENV_PROFILE ) ?: 'default ' );
588587
589588 return function () use ($ profile , $ filename ) {
@@ -659,6 +658,41 @@ public static function process($profile = null, $filename = null)
659658 };
660659 }
661660
661+ /**
662+ * Login credential provider for AWS local development using console credentials
663+ *
664+ * @param string|null $profileName profile containing your console login session information
665+ * @param array $config region used for refresh requests.
666+ * pass `'region' => <your_region>` to configure a region,
667+ * otherwise, provider construction falls back to AWS_REGION,
668+ * then the profile specified for `login`
669+ *
670+ * @return callable
671+ */
672+ public static function login (
673+ ?string $ profileName = null ,
674+ array $ config = [],
675+ ): callable
676+ {
677+ $ resolvedProfile = $ profileName ?? getenv (self ::ENV_PROFILE ) ?: 'default ' ;
678+
679+ return static function () use ($ resolvedProfile , $ config ) {
680+ try {
681+ $ provider = new LoginCredentialProvider (
682+ $ resolvedProfile ,
683+ $ config ['region ' ] ?? null
684+ );
685+ } catch (\Exception $ e ) {
686+ return self ::reject (
687+ "Failed to initialize login credential provider for profile ' {$ resolvedProfile }': "
688+ . $ e ->getMessage ()
689+ );
690+ }
691+
692+ return $ provider ();
693+ };
694+ }
695+
662696 /**
663697 * Assumes role for profile that includes role_arn
664698 *
@@ -672,13 +706,11 @@ private static function loadRoleProfile(
672706 $ config = []
673707 ) {
674708 $ roleProfile = $ profiles [$ profileName ];
675- $ roleArn = isset ($ roleProfile ['role_arn ' ]) ? $ roleProfile ['role_arn ' ] : '' ;
676- $ roleSessionName = isset ($ roleProfile ['role_session_name ' ])
677- ? $ roleProfile ['role_session_name ' ]
678- : 'aws-sdk-php- ' . round (microtime (true ) * 1000 );
709+ $ roleArn = $ roleProfile ['role_arn ' ] ?? '' ;
710+ $ roleSessionName = $ roleProfile ['role_session_name ' ]
711+ ?? 'aws-sdk-php- ' . round (microtime (true ) * 1000 );
679712
680- if (
681- empty ($ roleProfile ['source_profile ' ])
713+ if (empty ($ roleProfile ['source_profile ' ])
682714 == empty ($ roleProfile ['credential_source ' ])
683715 ) {
684716 return self ::reject ("Either source_profile or credential_source must be set " .
@@ -748,7 +780,7 @@ private static function loadRoleProfile(
748780 *
749781 * @return null|string
750782 */
751- private static function getHomeDir ()
783+ public static function getHomeDir ()
752784 {
753785 // On Linux/Unix-like systems, use the HOME environment variable
754786 if ($ homeDir = getenv ('HOME ' )) {
@@ -765,15 +797,15 @@ private static function getHomeDir()
765797 /**
766798 * Gets profiles from specified $filename, or default ini files.
767799 */
768- private static function loadProfiles ($ filename )
800+ public static function loadProfiles ($ filename )
769801 {
770802 $ profileData = \Aws \parse_ini_file ($ filename , true , INI_SCANNER_RAW );
771803
772804 // If loading .aws/credentials, also load .aws/config when AWS_SDK_LOAD_NONDEFAULT_CONFIG is set
773805 if ($ filename === self ::getHomeDir () . '/.aws/credentials '
774806 && getenv ('AWS_SDK_LOAD_NONDEFAULT_CONFIG ' )
775807 ) {
776- $ configFilename = self ::getHomeDir () . ' /.aws/config ' ;
808+ $ configFilename = self ::getConfigFileName () ;
777809 $ configProfileData = \Aws \parse_ini_file ($ configFilename , true , INI_SCANNER_RAW );
778810 foreach ($ configProfileData as $ name => $ profile ) {
779811 // standardize config profile names
@@ -790,7 +822,8 @@ private static function loadProfiles($filename)
790822 /**
791823 * Gets profiles from ~/.aws/credentials and ~/.aws/config ini files
792824 */
793- private static function loadDefaultProfiles () {
825+ private static function loadDefaultProfiles ()
826+ {
794827 $ profiles = [];
795828 $ credFile = self ::getHomeDir () . '/.aws/credentials ' ;
796829 $ configFile = self ::getHomeDir () . '/.aws/config ' ;
@@ -861,15 +894,32 @@ private static function reject($msg)
861894 }
862895
863896 /**
897+ * Locates shared configuration file by first checking for AWS_CONFIG,
898+ * then falling back to the default location. Returns the path of the
899+ * resolved configuration file.
900+ *
901+ * @return string
902+ */
903+ public static function getConfigFileName (): string
904+ {
905+ return getenv (self ::ENV_CONFIG_FILE ) ?: self ::getHomeDir () . '/.aws/config ' ;
906+ }
907+
908+ /**
909+ * Locates credentials file by first checking for AWS_SHARED_CREDENTIALS_FILE,
910+ * then falling back to the default location. Returns the path of the
911+ * resolved credentials file.
912+ *
864913 * @param $filename
865914 * @return string
866915 */
867- private static function getFileName ($ filename )
916+ public static function getCredentialsFileName ($ filename ): string
868917 {
869918 if (!isset ($ filename )) {
870919 $ filename = getenv (self ::ENV_SHARED_CREDENTIALS_FILE ) ?:
871920 (self ::getHomeDir () . '/.aws/credentials ' );
872921 }
922+
873923 return $ filename ;
874924 }
875925
0 commit comments