AWS:如何在 EC2 实例上获取 PHP 以读取 Secrets Manager 机密?
AWS: How to get PHP on an EC2 instance to read a Secrets Manager secret?
我已经设置了一个 EC2 实例 运行ning PHP。仅用于测试,该实例位于 public 子网中,其安全组允许所有流量流向 0.0.0.0/0
。路由 Table 具有到 10.0.0.0/16
(VPC 的 CIDR 块)的默认本地路由和到 0.0.0.0/0
处的互联网网关的路由。与子网关联的 NACL 允许 0.0.0.0/0
处的所有流量进出。我知道这很开放,但我想确保我遇到的问题与安全组和 NACL 无关。
我创建了一个 Secrets Manager 秘密 MySecret-xxxxx
并使用以下策略将 IAM 角色附加到实例以允许实例访问秘密:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"secretsmanager:GetResourcePolicy",
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret",
"secretsmanager:ListSecretVersionIds"
],
"Resource": "arn:aws:secretsmanager:eu-west-2:xxxxxxxxx:secret:MySecret-xxxxx"
}
]
}
我已经在名为 sdks
的子文件夹中的实例上安装了 PHP 的 AWS SDK,最后创建了一个运行良好的 "Hello World" index.php 文件直到我尝试 运行 getSecretValue
简化版本的 AWS 提供的设置信息。这是 PHP 代码:
<?php
require 'sdks/aws/aws-autoloader.php';
use Aws\SecretsManager\SecretsManagerClient;
use Aws\Exception\AwsException;
$client = new SecretsManagerClient( [
'profile' => 'default',
'version' => 'latest',
'region' => 'eu-west-2'
] );
$secretName = 'MySecret-xxxxx';
echo '<h1>Hello World</h1>';
$result = $client->getSecretValue([
'SecretId' => $secretName,
]);
?>
一旦包含 $result = $client->getSecretValue([...
代码块,我就会收到 HTTP ERROR 500 错误消息,尽管没有它它也能正常工作。我在 CLI 上 运行 aws secretsmanager get-secret-value --secret-id MySecret-xxxxx --region eu-west-2
并正确返回了秘密详细信息。
终于弄明白了 - 虽然我已经在 EC2 实例的 /home/ec2-user/.aws
文件夹中创建了一个凭据文件,但我仍然必须通过 SDK 检索凭据。为什么这被排除在 AWS 提供的 Secrets Manager 示例代码之外,这超出了我的理解范围。完整的工作代码现在看起来像这样:
<?php
require 'vendor/autoload.php';
use Aws\Credentials\CredentialProvider;
use Aws\SecretsManager\SecretsManagerClient;
use Aws\Exception\AwsException;
$provider = CredentialProvider::defaultProvider();
$client = new SecretsManagerClient( [
'credentials' => $provider,
'version' => 'latest',
'region' => 'eu-west-2'
] );
$secretName = 'MySecret-xxxxx';
try {
$result = $client->getSecretValue( [
'SecretId' => $secretName,
] );
} catch ( AwsException $e ) {
$error = $e->getAwsErrorCode();
if ( $error == 'DecryptionFailureException' ) { // Can't decrypt the protected secret text using the provided AWS KMS key.
throw $e;
}
if ( $error == 'InternalServiceErrorException' ) { // An error occurred on the server side.
throw $e;
}
if ( $error == 'InvalidParameterException' ) { // Invalid parameter value.
throw $e;
}
if ( $error == 'InvalidRequestException' ) { // Parameter value is not valid for the current state of the resource.
throw $e;
}
if ( $error == 'ResourceNotFoundException' ) { // Requested resource not found
throw $e;
}
}
// Decrypts secret using the associated KMS CMK, depends on whether the secret is a string or binary.
if ( isset( $result[ 'SecretString' ] ) ) {
$secret = $result[ 'SecretString' ];
} else {
$secret = base64_decode( $result[ 'SecretBinary' ] );
}
// Decode the secret json
$secrets = json_decode( $secret, true );
echo( '<p>hostname/ipaddress: ' . $secrets[ 'host' ] . '</p><p>username: ' . $secrets[ 'username' ] . '</p><p>password: ' . $secrets[ 'password' ] . '</p><p>dbname: ' . $secrets[ 'dbname' ] . '</p>' );
我已经设置了一个 EC2 实例 运行ning PHP。仅用于测试,该实例位于 public 子网中,其安全组允许所有流量流向 0.0.0.0/0
。路由 Table 具有到 10.0.0.0/16
(VPC 的 CIDR 块)的默认本地路由和到 0.0.0.0/0
处的互联网网关的路由。与子网关联的 NACL 允许 0.0.0.0/0
处的所有流量进出。我知道这很开放,但我想确保我遇到的问题与安全组和 NACL 无关。
我创建了一个 Secrets Manager 秘密 MySecret-xxxxx
并使用以下策略将 IAM 角色附加到实例以允许实例访问秘密:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"secretsmanager:GetResourcePolicy",
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret",
"secretsmanager:ListSecretVersionIds"
],
"Resource": "arn:aws:secretsmanager:eu-west-2:xxxxxxxxx:secret:MySecret-xxxxx"
}
]
}
我已经在名为 sdks
的子文件夹中的实例上安装了 PHP 的 AWS SDK,最后创建了一个运行良好的 "Hello World" index.php 文件直到我尝试 运行 getSecretValue
简化版本的 AWS 提供的设置信息。这是 PHP 代码:
<?php
require 'sdks/aws/aws-autoloader.php';
use Aws\SecretsManager\SecretsManagerClient;
use Aws\Exception\AwsException;
$client = new SecretsManagerClient( [
'profile' => 'default',
'version' => 'latest',
'region' => 'eu-west-2'
] );
$secretName = 'MySecret-xxxxx';
echo '<h1>Hello World</h1>';
$result = $client->getSecretValue([
'SecretId' => $secretName,
]);
?>
一旦包含 $result = $client->getSecretValue([...
代码块,我就会收到 HTTP ERROR 500 错误消息,尽管没有它它也能正常工作。我在 CLI 上 运行 aws secretsmanager get-secret-value --secret-id MySecret-xxxxx --region eu-west-2
并正确返回了秘密详细信息。
终于弄明白了 - 虽然我已经在 EC2 实例的 /home/ec2-user/.aws
文件夹中创建了一个凭据文件,但我仍然必须通过 SDK 检索凭据。为什么这被排除在 AWS 提供的 Secrets Manager 示例代码之外,这超出了我的理解范围。完整的工作代码现在看起来像这样:
<?php
require 'vendor/autoload.php';
use Aws\Credentials\CredentialProvider;
use Aws\SecretsManager\SecretsManagerClient;
use Aws\Exception\AwsException;
$provider = CredentialProvider::defaultProvider();
$client = new SecretsManagerClient( [
'credentials' => $provider,
'version' => 'latest',
'region' => 'eu-west-2'
] );
$secretName = 'MySecret-xxxxx';
try {
$result = $client->getSecretValue( [
'SecretId' => $secretName,
] );
} catch ( AwsException $e ) {
$error = $e->getAwsErrorCode();
if ( $error == 'DecryptionFailureException' ) { // Can't decrypt the protected secret text using the provided AWS KMS key.
throw $e;
}
if ( $error == 'InternalServiceErrorException' ) { // An error occurred on the server side.
throw $e;
}
if ( $error == 'InvalidParameterException' ) { // Invalid parameter value.
throw $e;
}
if ( $error == 'InvalidRequestException' ) { // Parameter value is not valid for the current state of the resource.
throw $e;
}
if ( $error == 'ResourceNotFoundException' ) { // Requested resource not found
throw $e;
}
}
// Decrypts secret using the associated KMS CMK, depends on whether the secret is a string or binary.
if ( isset( $result[ 'SecretString' ] ) ) {
$secret = $result[ 'SecretString' ];
} else {
$secret = base64_decode( $result[ 'SecretBinary' ] );
}
// Decode the secret json
$secrets = json_decode( $secret, true );
echo( '<p>hostname/ipaddress: ' . $secrets[ 'host' ] . '</p><p>username: ' . $secrets[ 'username' ] . '</p><p>password: ' . $secrets[ 'password' ] . '</p><p>dbname: ' . $secrets[ 'dbname' ] . '</p>' );