[英]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 禁止错误调试以下步骤。
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.让我先从第二种解决方案开始。
{
"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/*"
]
}
]
}
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.
留空。
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 中创建的角色。
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 实例配置文件(角色)。
Create a bucket.创建一个存储桶。 Disable all public access to it.
禁用对它的所有公共访问。 Disable ACL.
禁用 ACL。
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/*"
]
}
]
}
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 在上一步中创建的角色。
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.