我正在使用PHP在AWS Elastic Beanstalk上运行Web应用程序。
该应用程序使用RDS MySQL数据库。我想通过AWS Secrets Manager存储数据库凭证。
我成功创建了秘密。
通过作曲家,我安装了AWS PHP SDK版本3.129。我运行了compatibility.test php文件来验证我的开发环境。一切都是绿色的(警告是出于性能原因请勿使用Xdebug)。
使用AWS文档,我编写了一个PHP类来获取秘密值。我为该课程写了单元测试。单元测试通过了,我能够使用RDS的用户名,密码等显示秘密值。
为了提供本地开发环境的凭据,我使用了存储在.aws目录中的凭据文件。在此文件中,我存储了:
我在本地apache网络服务器上运行了应用程序,它能够从AWS Secrets Manager成功检索RDS凭证,并对RDS数据库进行MySQL调用。
我的最后一步是通过我的Elastic Beanstalk平台在AWS中运行该应用程序(该平台已经运行了几个月,并使用了硬编码的RDS凭证,我想停止使用它)。
我查看了解释"Credentials for the AWS SDK for PHP Version 3的AWS文档。该文档描述了“默认凭证提供者链”。
在标题为“使用环境变量的凭据”的this AWS document之后,我尝试(未成功)使用链中的第一个链接为环境变量。该文件指出:
如果您将应用程序托管在AWS Elastic Beanstalk上,则可以通过AWS Elastic Beanstalk控制台设置AWS_ACCESS_KEY_ID和AWS_SECRET_KEY环境变量,以便SDK可以自动使用这些凭据。
我通过AWS控制台使用了这些值作为变量:
在测试期间,我尝试了两个访问密钥,并且我知道它们可以工作,因为我将它们用于其他目的,并且IAM控制台显示了这两个的最近使用情况。
运行测试时,我总是在AWS PHP SDK代码中遇到相同的异常,该异常报告“无法从/.aws/credentials读取凭据”。
这向我暗示:
遇到异常时,我会收到“ Whoops”输出,其中显示了AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY环境变量及其输入时的准确值。
PHP SDK代码是正确的,因为它没有将我的凭据文件上传到Elastic Beanstalk,所以它找不到我的凭据文件。这样做对我来说在Elastic Beanstalk中是没有意义的,尽管它对于我的本地环境也很好。
以下是异常回溯中的最后几个调用:
Aws \ Exception \ CredentialsException …/ vendor / aws / aws-sdk-php / src / Credentials / CredentialProvider.php691 21 Aws \ Credentials \ CredentialProvider拒绝 …/ vendor / aws / aws-sdk-php / src / Credentials / CredentialProvider.php424 20 Aws \ Credentials \ CredentialProvider Aws \ Credentials {关闭} …/ vendor / aws / aws-sdk-php / src / Middleware.php121 19 Aws \ Middleware Aws {closure} …/ vendor / aws / aws-sdk-php / src / RetryMiddleware.php269 18岁 Aws \ RetryMiddleware __调用 …/ vendor / aws / aws-sdk-php / src / Middleware.php206 17 Aws \ Middleware Aws {closure} …/ vendor / aws / aws-sdk-php / src / StreamRequestPayloadMiddleware.php83
这是我在“凭据提供拒绝”中输入的代码:
if (!is_readable($filename)) {
return self::reject("Cannot read credentials from $filename");
}
这是我为获取机密而编写的代码(带有一些无关的调试语句,稍后将删除它们):
public function getSecretString(): ?string
{
echo 'In getSecretString' . "\r\n";
$result = null;
$client = new SecretsManagerClient([
'profile' => 'default',
'version' => '2017-10-17',
'region' => 'us-east-2'
]);
echo 'Lets try' . "\r\n";
try {
$result = $client->getSecretValue([
'SecretId' => $this->secretName,
]);
echo 'Got a result' . "\r\n";
} catch (AwsException $e) {
echo 'FAILED!' . "\r\n";
// output error message if fails
echo $e->getMessage();
echo "\n";
}
if ($result !== null) {
echo 'We got our secret string!' . "\r\n" .
$this->secretString = $result['SecretString'];
} else {
echo 'We DID NOT get our secret string!' . "\r\n" .
$this->secretString = null;
}
print_r($this->secretString);
echo "\r\n";
return $this->secretString;
}
从我的调试看来,SDK只是忽略了除凭证文件以外的任何凭证提供方法。我尝试过:
设置我的信誉的这些方法都不起作用。
我还尝试使用旧版本的SDK,以查看是否最近引入了错误,该错误可以追溯到3.76.0。没什么。
以下是修改后的代码,其中显示了上面注释2以及上面注释3的尝试:
public function getSecretString(): ?string
{
echo 'In getSecretString' . "\r\n";
$result = null;
// Only load credentials from environment variables
//$provider = CredentialProvider::env();
$client = new SecretsManagerClient([
'profile' => 'default',
'version' => '2017-10-17',
'region' => 'us-east-2',
//'credentials' => $provider,
'credentials' => [
'key' => 'AKIAVGZKSJ5G76TTG2P4',
'secret' => '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',
],
// 'debug' => true
]);
try {
$result = $client->getSecretValue([
'SecretId' => $this->secretName,
]);
echo 'Got a result' . "\r\n";
} catch (AwsException $e) {
echo 'FAILED!' . "\r\n";
// output error message if fails
echo $e->getMessage();
echo "\n";
}
if ($result !== null) {
echo 'We got our secret string!' . "\r\n" .
$this->secretString = $result['SecretString'];
} else {
echo 'We DID NOT get our secret string!' . "\r\n" .
$this->secretString = null;
}
return $this->secretString;
}
我还尝试了通过默认链获取凭据的第二种方法:承担IAM角色。我尝试遵循文档here,但坦白地发现它令人困惑。在我的Elastic Beanstalk Security配置中,我注意到了两个IAM角色:
我为这两个角色分配了以下策略:
分配这些IAM策略不能解决问题。
我的首选是通过Elastic Beanstalk环境变量解决此问题,因为它看起来非常简单,并且AWS文档明确指出它应该可以工作。另外,如果不需要大量脚本,则希望通过IAM策略解决它。
我该如何解决这个问题?
答案 0 :(得分:0)
(代表问题作者发布了解决方案,以便将其从问题中移出)。
在我的客户端SecretsManagerClient数组中,包含以下行:
PROJECT_ID@appspot.gserviceaccount.com
通过单步执行SDK代码,我观察到该行的存在被解释为“寻找凭据文件并跳过默认的凭据链”。
我删除了这一行,然后SDK处理了在我的环境变量中设置的凭据。