簡體   English   中英

從某些 IP 地址訪問公共 S3 存儲桶被拒絕

[英]Access Denied to Public S3 Bucket from certain IP addresses

我嘗試使用 PHP SDK 制作一個完全公共的 S3 存儲桶並進行訪問。 當我從本地計算機運行以下訪問代碼時,此方法有效:

require 'vendor/autoload.php';

use Aws\S3\S3Client;
use Aws\S3\Exception\S3Exception;

$s3 = new S3Client([
    'version' => 'latest',
    'region'  => 'eu-west-2',
    'credentials' => [
        'key'    => "my correct key",
        'secret' => "my correct secret"
        ]
]);

// //publictest2
$bucket = 'mybucketname';
$keyname = 'test_file.txt';

// Upload an object
try {
    // Upload data.
    $result = $s3->putObject([
        'Bucket' => $bucket,
        'Key'    => $keyname,
        'Body'   => 'Hello',
        'ACL'    => 'public-read'
    ]);

    // Print the URL to the object.
    echo $result['ObjectURL'] . PHP_EOL;
} catch (S3Exception $e) {
    echo $e->getMessage() . PHP_EOL;
}

但是,一旦我從測試服務器(AWS EC2)運行它,我就會收到以下錯誤:

Error executing "PutObject" on "mybucketname"; AWS HTTP error: Client error: `PUT https://mybucketname/test_file.txt` resulted in a `403 Forbidden` response: AccessDeniedAccess DeniedVTJX7V (truncated...) AccessDenied (client): Access Denied - AccessDeniedAccess DeniedVTJX7V4CCKZYG7CRTz+dPA7fsZQnFxTERKxxbP+IpTtMIIsS1uu23fvTruHH3w8KxwGIduCntRBM5u6tIfHdusbCoPw=

我已經實現了以下內容來公開存儲桶:

    {
    "Version": "2012-10-17",
    "Id": "S3BukcetPolicyIPAccess",
    "Statement": [
        {
            "Sid": "DenyIfNotFromAllowedVPC",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "mybucketarn",
                "mybucketarn/*"
            ]
        }
    ]
}

為什么從我的 EC2 服務器運行時這仍然不起作用?

這與 S3 存儲桶無關 - 這里的提示是它可以在您的本地機器上工作,這意味着 S3 存儲桶不應歸咎於實例。

這與您的 EC2 實例承擔(或不承擔)的角色有關 - 創建並分配有權在mybucketname上執行PutObject的 IAM 角色。

測試這一點的一種快速方法是使用附加了 AWS 托管策略AmazonS3FullAccess的角色,該策略提供對所有 S3 存儲桶的完全訪問權限。

然后,您的 EC2 實例將有權訪問 S3 存儲桶。

對於 HTTP 403 禁止錯誤調試以下步驟。

  1. 缺少對 s3:PutObject 或 s3:PutObjectAcl 的權限
  2. 缺少使用 AWS Key Management Service (AWS KMS) 密鑰的權限
  3. 存儲桶策略中的顯式拒絕語句
  4. 存儲桶訪問控制列表 (ACL) 不允許 AWS 賬戶根用戶寫入對象

您能否從您的 ec2 實例中檢查此命令

“aws s3 ls s3://doc-example-bucket/abc/”

如果此命令成功,則應用程序代碼中指定的憑據或角色會導致“拒絕訪問”錯誤。 確保實例配置文件角色具有 S3 存儲桶所需的讀取和寫入權限。 例如,以下 IAM 策略中的 S3 操作提供對 S3 存儲桶的所需讀寫訪問權限。

您的問題是在您的 EC2 實例上運行的 PHP 網絡服務器使用 AWS PHP SDK 並且沒有配置文件( IAM 角色主體,AWS),因為您的 EC2 用戶既沒有附加實例,也沒有配置默認角色(AWS)使用aws configure

換句話說,您的 AWS API 調用未經過身份驗證,更不用說授權對 S3 執行任何操作了。 即使您在 Bucket 策略中允許所有 Principals 使用s3:* 請記住:存儲桶策略需要 AWS 委托人,但您的請求未經過身份驗證(AWS API 無法確定誰在調用)。 因此AccessDenied

您的問題有幾種解決方案。 但所有這些都可以歸結為:

  • 使用 IAM 政策(推薦)

  • 使用 S3 存儲桶策略

您可以查看此 AWS 博客文章以了解要遵循的方法,但對於您的特定問題,我會使用 IAM 策略 go。


使用 S3 存儲桶策略

讓我先從第二種解決方案開始。

  1. 創建一個存儲桶。 禁用對它的所有公共訪問。
  2. 附加以下 S3 存儲桶策略:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Statement1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::xxxxxxxxxxx:role/ec2-instance-role"
            },
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::yyyyyyyyyyy",
                "arn:aws:s3:::yyyyyyyyyyy/*"
            ]
        }
    ]
}
  1. 創建一個名為ec2-instance-role的新 IAM 角色。 不需要附加任何 IAM 策略。 留空。

  2. Go 到您的 EC2 實例,單擊Actions -> Security -> Modify IAM role和 select 在步驟 3 中創建的角色。

  3. 無需重啟實例。 為了驗證一切都按預期工作,我正在使用 AWS CLI,但它也應該適用於任何 SDK(例如 PHP)。 從您的 EC2 實例執行:

# Make sure the correct role is assumed
$ aws sts get-caller-identity
{
    "Account": "xxxxxxxxxxx",
    "UserId": "AROAYGJILC6K4AJRGLZTS:i-0aa422c12359ac00e",
    "Arn": "arn:aws:sts::xxxxxxxxxxx:assumed-role/ec2-instance-role/i-0aa422c12359ac00e"
}

# Upload a test file and check the bucket
$ touch test.txt
$ aws s3 cp test.txt s3://yyyyyyyyyyy/test.txt
upload: ./test.txt to s3://yyyyyyyyyyy/test.txt
$ aws s3 ls s3://yyyyyyyyyyy
2021-12-12 11:01:51        0 test.txt

使用 IAM 策略

在這里,除了您不需要任何存儲桶策略之外,一切都保持不變,但您將策略直接附加到 IAM 實例配置文件(角色)。

  1. 創建一個存儲桶。 禁用對它的所有公共訪問。 禁用 ACL。

  2. 使用以下策略創建一個名為ec2-instance-role的新 IAM 角色:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Statement1",
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::yyyyyyyyyyy",
                "arn:aws:s3:::yyyyyyyyyyy/*"
            ]
        }
    ]
}
  1. Go 到您的 EC2 實例,單擊Actions -> Security -> Modify IAM role和 select 在上一步中創建的角色。

  2. 為了驗證一切都按預期工作,我正在使用 AWS CLI,但它也應該適用於任何 SDK(例如 PHP)。 從您的 EC2 實例執行:

# Make sure the correct role is assumed
$ aws sts get-caller-identity
{
    "Account": "xxxxxxxxxxx",
    "UserId": "AROAYGJILC6K4AJRGLZTS:i-0aa422c12359ac00e",
    "Arn": "arn:aws:sts::xxxxxxxxxxx:assumed-role/ec2-instance-role/i-0aa422c12359ac00e"
}

# Upload a test file and check the bucket
$ touch test.txt
$ aws s3 cp test.txt s3://yyyyyyyyyyy/test.txt
upload: ./test.txt to s3://yyyyyyyyyyy/test.txt
$ aws s3 ls s3://yyyyyyyyyyy
2021-12-12 11:01:51        0 test.txt

最后但並非最不重要的兩種方法:不要使用 ACL(配置您的存儲桶ACLs disabled ),因為 ACL 的存在是為了向后兼容以支持存儲桶策略,請參閱同一篇博文中的詳細信息:

作為一般規則,AWS 建議使用 S3 存儲桶策略或 IAM 策略進行訪問控制。 S3 ACL 是早於 IAM 的傳統訪問控制機制。


在上面的片段中:

  • xxxxxxxxxxx是您的 AWS 帳號,例如561262107623
  • yyyyyyyyyyy是您的存儲桶名稱,例如mybucket

暫無
暫無

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

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