繁体   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