AWS:如何在 EC2 实例上使用 PHP 来读取 Secrets Manager 密钥?

Dor*_*bre 5 php amazon-ec2 amazon-web-services amazon-iam aws-secrets-manager

我已经设置了一个运行 PHP 的 EC2 实例。仅用于测试,该实例位于公有子网中,其安全组允许所有流量通过0.0.0.0/0。路由表具有到10.0.0.0/16(VPC 的 CIDR 块)的默认本地路由以及到位于 的 Internet 网关的路由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"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

我已在实例上的名为 的子文件夹中安装了适用于 PHP 的 AWS 开发工具包sdks,最后创建了一个“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,
    ]);
?>
Run Code Online (Sandbox Code Playgroud)

一旦包含该$result = $client->getSecretValue([...代码块,我就会收到 HTTP ERROR 500 错误消息,尽管没有它它也能正常工作。我aws secretsmanager get-secret-value --secret-id MySecret-xxxxx --region eu-west-2在 CLI 上运行并正确返回了秘密详细信息。

Dor*_*bre 10

终于弄清楚了 - 尽管我已经在/home/ec2-user/.awsEC2 实例上的文件夹中创建了凭证文件,但我仍然必须通过 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>' );
Run Code Online (Sandbox Code Playgroud)