簡體   English   中英

如何讓 AWS PHP SDK 找到我存儲在 Elastic Beanstalk 環境變量中的憑證?

[英]How do I get the AWS PHP SDK to find the credentials I stored in Elastic Beanstalk environment variables?

我正在 AWS Elastic Beanstalk 上使用 PHP 運行 Web 應用程序。

該應用程序使用 RDS MySQL 數據庫。 我想通過 AWS Secrets Manager 存儲數據庫憑證。

我成功創建了秘密。

通過 composer,我安裝了 AWS PHP SDK,版本 3.129。 我運行了compatibility.test php 文件來驗證我的開發環境。 一切都是綠色的(除了出於性能原因不要使用 Xdebug 的警告)。

使用 AWS 文檔,我編寫了一個 PHP 類來獲取秘密值。 我為那個班級寫了一個單元測試。 單元測試通過,我能夠使用我的用戶名、密碼等來顯示 RDS 的秘密值。

為了為我的本地開發環境提供憑據,我使用了存儲在 .aws 目錄中的憑據文件。 在這個文件中,我存儲了:

  • aws_access_key_id
  • aws_secret_access_key

我在本地 apache 網絡服務器上運行我的應用程序,它能夠成功地從 AWS 機密管理器檢索 RDS 憑證,並對 RDS 數據庫進行 MySQL 調用。

我的最后一步是通過我的 Elastic Beanstalk 平台在 AWS 中運行該應用程序(該平台已運行數月,帶有硬編碼的 RDS 憑證,我想停止使用它)。

我查看了 AWS 文檔,其中解釋了“適用於 PHP 版本 3 的 AWS 開發工具包的憑據”。 該文檔描述了“默認憑證提供者鏈”。

我嘗試(未成功)使用鏈中的第一個鏈接,即環境變量,遵循名為“使用環境變量的憑據”的AWS 文檔 該文件指出:

如果您在 AWS Elastic Beanstalk 上托管您的應用程序,您可以通過 AWS Elastic Beanstalk 控制台設置 AWS_ACCESS_KEY_ID 和 AWS_SECRET_KEY 環境變量,以便開發工具包可以自動使用這些憑證。

我通過 AWS 控制台這樣做,將這些值用於我的變量:

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY

在我的測試過程中,我嘗試了我的兩個訪問密鑰,我知道它們有效,因為我將它們用於其他目的,並且 IAM 控制台顯示最近使用了這兩個密鑰。

當我運行測試時,我總是在 AWS PHP SDK 代碼中遇到相同的異常,報告“無法從 /.aws/credentials 讀取憑證”。

這向我表明:

  1. PHP SDK 代碼不是在尋找我的環境變量
  2. 它試圖找到它們但找不到
  3. 它找到了但無法使用它們

當我遇到異常時,我得到了“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{closure} .../vendor/aws/aws-sdk-php/src/Middleware.php121 19 Aws\\Middleware Aws{closure} .../vendor/aws/aws-sdk-php/src /RetryMiddleware.php269 18 Aws\\RetryMiddleware __invoke .../vendor/aws/aws-sdk-php/src/Middleware.php206 17 Aws\\Middleware Aws{closure} .../vendor/aws/aws-sdk-php/src/StreamRequestPayloadMiddle 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 似乎只是忽略了憑據文件以外的任何憑據提供方法。 我試過了:

  1. 運行本地網絡服務器時在本地機器上設置本地環境變量。
  2. 將我的 SDK 客戶端數組設置為僅查看 env() 方法。
  3. 硬編碼我的憑據。

這些設置我的信用的方法都沒有奏效。

我還嘗試使用舊版本的 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 角色。 我試圖按照此處的文檔進行操作,但無可否認地發現它令人困惑。 在我的 Elastic Beanstalk 安全配置中,我注意到兩個 IAM 角色:

  1. aws-elasticbeanstalk-ec2-角色
  2. aws-elasticbeanstalk-服務角色

我為這兩個角色分配了以下策略:

  1. SecretsManager 讀寫
  2. IAMFullAccess(因為我在分配之前的策略時,有一個注釋也分配了這個)

分配這些 IAM 策略並沒有解決問題。

我的首選是通過 Elastic Beanstalk 環境變量解決這個問題,因為它看起來非常簡單,而且 AWS 文檔明確指出它應該可以工作。 或者,如果不需要大量腳本,則通過 IAM 策略解決它是可取的。

我怎么解決這個問題?

(代表問題作者發布解決方案,以便將其從問題中移開)

在我的客戶端 SecretsManagerClient 數組中,我包含了以下行:

            'profile' => 'default',

通過逐步執行 SDK 代碼,我觀察到該行的存在被解釋為“查找憑據文件並跳過默認憑據鏈”。

我刪除了該行,然后 SDK 處理了在我的環境變量中設置的憑據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM