[英]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 禁止错误调试以下步骤。
您能否从您的 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 存储桶策略
让我先从第二种解决方案开始。
{
"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/*"
]
}
]
}
创建一个名为ec2-instance-role
的新 IAM 角色。 您不需要附加任何 IAM 策略。 留空。
Go 到您的 EC2 实例,单击Actions -> Security -> Modify IAM role
和 select 在步骤 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 实例配置文件(角色)。
创建一个存储桶。 禁用对它的所有公共访问。 禁用 ACL。
使用以下策略创建一个名为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 到您的 EC2 实例,单击Actions -> Security -> Modify IAM role
和 select 在上一步中创建的角色。
为了验证一切都按预期工作,我正在使用 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.