简体   繁体   English

从某些 IP 地址访问公共 S3 存储桶被拒绝

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

I have tried to make a completely public S3 bucket and access using PHP SDK.我尝试使用 PHP SDK 制作一个完全公共的 S3 存储桶并进行访问。 This works when I run the access code below from my local machine:当我从本地计算机运行以下访问代码时,此方法有效:

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;
}

However, as soon as I run it from the test server (an AWS EC2) I get the below error:但是,一旦我从测试服务器(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=

I have already implemented the following to make the bucket public:我已经实现了以下内容来公开存储桶:

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

Why is this still not working when run from my EC2 server?为什么从我的 EC2 服务器运行时这仍然不起作用?

This is not to do with the S3 bucket - the hint here is that it works from your local machine, meaning that the S3 bucket isn't to blame but the instance.这与 S3 存储桶无关 - 这里的提示是它可以在您的本地机器上工作,这意味着 S3 存储桶不应归咎于实例。

It's to do with the role that your EC2 instance is assuming (or not assuming) - create & assign an IAM role that has access to perform PutObject on mybucketname .这与您的 EC2 实例承担(或不承担)的角色有关 - 创建并分配有权在mybucketname上执行PutObject的 IAM 角色。

One quick way to test this would be to use a role with the AWS-managed policy AmazonS3FullAccess attached which provides full access to all S3 buckets.测试这一点的一种快速方法是使用附加了 AWS 托管策略AmazonS3FullAccess的角色,该策略提供对所有 S3 存储桶的完全访问权限。

Your EC2 instance will then have access to the S3 bucket.然后,您的 EC2 实例将有权访问 S3 存储桶。

for HTTP 403 Forbidden error debug these below steps.对于 HTTP 403 禁止错误调试以下步骤。

  1. Missing permissions to s3:PutObject or s3:PutObjectAcl缺少对 s3:PutObject 或 s3:PutObjectAcl 的权限
  2. Missing permissions to use an AWS Key Management Service (AWS KMS) key缺少使用 AWS Key Management Service (AWS KMS) 密钥的权限
  3. Explicit deny statement in the bucket policy存储桶策略中的显式拒绝语句
  4. Bucket access control list (ACL) doesn't allow the AWS account root user to write objects存储桶访问控制列表 (ACL) 不允许 AWS 账户根用户写入对象

could you please check this command from your ec2 instance您能否从您的 ec2 实例中检查此命令

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

If this command is successful, then the credentials or role specified in your application code are causing the "Access Denied" error.如果此命令成功,则应用程序代码中指定的凭据或角色会导致“拒绝访问”错误。 Be sure that the instance profile role has the required read and write permissions for the S3 buckets.确保实例配置文件角色具有 S3 存储桶所需的读取和写入权限。 For example, the S3 actions in the following IAM policy provides the required read and write access to the S3 bucket.例如,以下 IAM 策略中的 S3 操作提供对 S3 存储桶的所需读写访问权限。

Your problem is that the PHP web-server running on your EC2 instance uses AWS PHP SDK and does NOT have an IAM principal , because there's neither an instance profile (AWS role) attached to your EC2, nor a default profile (AWS user) configured with aws configure .您的问题是在您的 EC2 实例上运行的 PHP 网络服务器使用 AWS PHP SDK 并且没有配置文件( IAM 角色主体,AWS),因为您的 EC2 用户既没有附加实例,也没有配置默认角色(AWS)使用aws configure

In other words your AWS API calls are not authenticated, let alone authorized to perform any actions against S3.换句话说,您的 AWS API 调用未经过身份验证,更不用说授权对 S3 执行任何操作了。 Even if you allow s3:* for all Principals in the Bucket policy.即使您在 Bucket 策略中允许所有 Principals 使用s3:* Remember: the Bucket policy expects an AWS principal, but your request is not authenticated (AWS API can't figure out who is calling).请记住:存储桶策略需要 AWS 委托人,但您的请求未经过身份验证(AWS API 无法确定谁在调用)。 Hence AccessDenied .因此AccessDenied

There are several solutions to your problem.您的问题有几种解决方案。 But all of them can be boiled down to:但所有这些都可以归结为:

  • Using IAM policy (recommended)使用 IAM 政策(推荐)

  • Using S3 bucket policy使用 S3 存储桶策略

You can check out this AWS blog post as to which approach to follow, but for your particular problem I would go with IAM policies.您可以查看此 AWS 博客文章以了解要遵循的方法,但对于您的特定问题,我会使用 IAM 策略 go。


Using S3 bucket policy使用 S3 存储桶策略

Let me start with the second solution first.让我先从第二种解决方案开始。

  1. Create a bucket.创建一个存储桶。 Disable all public access to it.禁用对它的所有公共访问。
  2. Attach the following S3 bucket policy:附加以下 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. Create a new IAM role named ec2-instance-role .创建一个名为ec2-instance-role的新 IAM 角色。 You do NOT need any IAM policies attached to it.不需要附加任何 IAM 策略。 Leave it blank.留空。

  2. Go to your EC2 instance, click Actions -> Security -> Modify IAM role and select the role created in step 3. Go 到您的 EC2 实例,单击Actions -> Security -> Modify IAM role和 select 在步骤 3 中创建的角色。

  3. No need to restart the instance.无需重启实例。 To verify everything works as expected I am using AWS CLI, but it should work with any SDK (eg PHP) as well.为了验证一切都按预期工作,我正在使用 AWS CLI,但它也应该适用于任何 SDK(例如 PHP)。 Execute from your EC2 instance:从您的 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

Using IAM policies使用 IAM 策略

Here, everything stays the same with the exception that you do not need any Bucket policy, but you attach the policy directly to the IAM instance profile (role).在这里,除了您不需要任何存储桶策略之外,一切都保持不变,但您将策略直接附加到 IAM 实例配置文件(角色)。

  1. Create a bucket.创建一个存储桶。 Disable all public access to it.禁用对它的所有公共访问。 Disable ACL.禁用 ACL。

  2. Create a new IAM role named ec2-instance-role with the following policy:使用以下策略创建一个名为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 to your EC2 instance, click Actions -> Security -> Modify IAM role and select the role created in the previous step. Go 到您的 EC2 实例,单击Actions -> Security -> Modify IAM role和 select 在上一步中创建的角色。

  2. To verify everything works as expected I am using AWS CLI, but it should work with any SDK (eg PHP) as well.为了验证一切都按预期工作,我正在使用 AWS CLI,但它也应该适用于任何 SDK(例如 PHP)。 Execute from your EC2 instance:从您的 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

Last but not least for both approaches: do not use ACLs (configure your bucket with ACLs disabled ) since ACLs exist for backward compatibility in favor of Bucket policies, see details in the same blog post :最后但并非最不重要的两种方法:不要使用 ACL(配置您的存储桶ACLs disabled ),因为 ACL 的存在是为了向后兼容以支持存储桶策略,请参阅同一篇博文中的详细信息:

As a general rule, AWS recommends using S3 bucket policies or IAM policies for access control.作为一般规则,AWS 建议使用 S3 存储桶策略或 IAM 策略进行访问控制。 S3 ACLs is a legacy access control mechanism that predates IAM. S3 ACL 是早于 IAM 的传统访问控制机制。


In the above snippets:在上面的片段中:

  • xxxxxxxxxxx is your AWS account number, eg 561262107623 xxxxxxxxxxx是您的 AWS 帐号,例如561262107623
  • yyyyyyyyyyy is your bucket name, eg mybucket yyyyyyyyyyy是您的存储桶名称,例如mybucket

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM