Skip to content

Commit

Permalink
Merge pull request aws#572 from aws/v2-creds-fix
Browse files Browse the repository at this point in the history
Better failover for INI credentials.
  • Loading branch information
jeremeamia committed May 12, 2015
2 parents a269950 + 6d4884b commit 2ee4e27
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 23 deletions.
25 changes: 12 additions & 13 deletions src/Aws/Common/Credentials/Credentials.php
Expand Up @@ -143,11 +143,11 @@ public static function fromIni($profile = null, $filename = null)
$profile = self::getEnvVar(self::ENV_PROFILE) ?: 'default';
}

if (!file_exists($filename) || !($data = parse_ini_file($filename, true))) {
if (!is_readable($filename) || ($data = parse_ini_file($filename, true)) === false) {
throw new \RuntimeException("Invalid AWS credentials file: {$filename}.");
}

if (empty($data[$profile])) {
if (!isset($data[$profile]['aws_access_key_id']) || !isset($data[$profile]['aws_secret_access_key'])) {
throw new \RuntimeException("Invalid AWS credentials profile {$profile} in {$filename}.");
}

Expand Down Expand Up @@ -262,7 +262,7 @@ private static function createFromEnvironment($config)
// Get key and secret from ENV variables
$envKey = self::getEnvVar(self::ENV_KEY);
if (!($envSecret = self::getEnvVar(self::ENV_SECRET))) {
// Use AWS_SECRET_ACCESS_KEY if AWS_SECRET_KEY was not set.
// Use AWS_SECRET_ACCESS_KEY if AWS_SECRET_KEY was not set
$envSecret = self::getEnvVar(self::ENV_SECRET_ACCESS_KEY);
}

Expand All @@ -271,17 +271,16 @@ private static function createFromEnvironment($config)
return new static($envKey, $envSecret);
}

// Use credentials from the ini file in HOME directory if available
$home = self::getHomeDir();
if ($home && file_exists("{$home}/.aws/credentials")) {
return self::fromIni($config[Options::PROFILE], "{$home}/.aws/credentials");
try {
// Use credentials from the INI file in HOME directory if available
return self::fromIni($config[Options::PROFILE]);
} catch (\RuntimeException $e) {
// Otherwise, try using instance profile credentials (available on EC2 instances)
return new RefreshableInstanceProfileCredentials(
new static('', '', '', 1),
$config[Options::CREDENTIALS_CLIENT]
);
}

// Use instance profile credentials (available on EC2 instances)
return new RefreshableInstanceProfileCredentials(
new static('', '', '', 1),
$config[Options::CREDENTIALS_CLIENT]
);
}

private static function createCache(CredentialsInterface $credentials, $cache, $cacheKey)
Expand Down
3 changes: 2 additions & 1 deletion tests/Aws/Tests/Common/Credentials/.aws/credentials
Expand Up @@ -3,4 +3,5 @@ aws_access_key_id=foo
aws_secret_access_key=bar
[test]
aws_access_key_id=fizz
aws_secret_access_key=buzz
aws_secret_access_key=buzz
[other]
81 changes: 72 additions & 9 deletions tests/Aws/Tests/Common/Credentials/CredentialsTest.php
Expand Up @@ -147,6 +147,19 @@ public function testFactoryCreatesInstanceProfileWhenNoKeysAreProvided()
$this->assertInstanceOf('Aws\Common\Credentials\RefreshableInstanceProfileCredentials', $credentials);
}

/**
* @covers Aws\Common\Credentials\Credentials::factory
* @covers Aws\Common\Credentials\Credentials::createFromEnvironment
*/
public function testFallsbackToInstanceProfileWhenCredentialsFileFails()
{
unset($_SERVER[Credentials::ENV_KEY], $_SERVER[Credentials::ENV_SECRET]);
putenv('AWS_ACCESS_KEY_ID=');
putenv('AWS_SECRET_KEY=');
$credentials = Credentials::factory(array('profile' => 'other'));
$this->assertInstanceOf('Aws\Common\Credentials\RefreshableInstanceProfileCredentials', $credentials);
}

/**
* @covers Aws\Common\Credentials\Credentials::factory
* @covers Aws\Common\Credentials\Credentials::createFromEnvironment
Expand Down Expand Up @@ -215,16 +228,20 @@ public function testFactoryBailsWhenCacheCannotBeDetermined()
*/
public function testFactoryCreatesCredentialsFromCredentialFile(
array $envVars = array(),
$profile = null,
$expKey = null,
$expSecret = null,
$profile = null
$expExMessage = null
) {
foreach ($envVars as $key => $value) {
$_SERVER[$key] = $value;
putenv("{$key}=");
}

if (!$expKey && !$expSecret) {
$this->setExpectedException('RuntimeException');
if ($expExMessage) {
$this->setExpectedExceptionRegExp(
'RuntimeException', "/Invalid AWS credentials {$expExMessage}/"
);
}
$credentials = Credentials::fromIni($profile);

Expand All @@ -235,12 +252,58 @@ public function testFactoryCreatesCredentialsFromCredentialFile(
public function getDataForCredentialFileTest()
{
return array(
array(array('HOME' => __DIR__), 'foo', 'bar'),
array(array('HOMEDRIVE' => '/', 'HOMEPATH' => __DIR__), 'foo', 'bar'),
array(),
array(array('HOME' => __DIR__), null, null, 'invalid'),
array(array('HOME' => __DIR__), 'fizz', 'buzz', 'test'),
array(array('HOME' => __DIR__, Credentials::ENV_PROFILE => 'test'), 'fizz', 'buzz'),
array(
array('HOME' => __DIR__),
null,
'foo',
'bar',
),
array(
array('HOMEDRIVE' => '/', 'HOMEPATH' => __DIR__),
null,
'foo',
'bar',
),
array(
array(),
null,
null,
null,
'file'
),
array(
array('HOME' => __DIR__),
'invalid',
null,
null,
'profile',
),
array(
array('HOME' => __DIR__),
'test',
'fizz',
'buzz',
),
array(
array('HOME' => __DIR__, Credentials::ENV_PROFILE => 'test'),
null,
'fizz',
'buzz'
),
array(
array('HOME' => __DIR__),
'other',
null,
null,
'profile'
),
array(
array('HOME' => __DIR__ . '/invalid'),
'other',
null,
null,
'file'
),
);
}
}

0 comments on commit 2ee4e27

Please sign in to comment.