Skip to content

Commit

Permalink
Updates credential chain so that it fails over to instance profile cr…
Browse files Browse the repository at this point in the history
…edentials when ini credentials are invalid.
  • Loading branch information
jeremeamia committed May 11, 2015
1 parent a269950 commit 6d4884b
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 6d4884b

Please sign in to comment.