访问受限于 VPC 端点的 S3 网站从 VPC 内部获取 403
S3 website with access restricted to VPC endpoint is getting 403 from inside the VPC
我想创建一个配置为用作网站的 S3 存储桶,并且我想将对 S3 网站的访问限制为来自特定 VPC 内部的请求 而已。
我正在使用 Cloudformation 设置存储桶和存储桶策略。
存储桶 CF 已启用 WebsiteConfiguration
并将 AccessControl
设置为 PublicRead
。
ContentStorageBucket:
Type: AWS::S3::Bucket
Properties:
AccessControl: PublicRead
BucketName: "bucket-name"
WebsiteConfiguration:
IndexDocument: index.html
ErrorDocument: error.html
存储桶策略包括两个条件:一个条件授予在办公室 IP 上访问存储桶的完全访问权限,另一个条件授予通过 VPC 端点的访问权限。代码如下:
ContentStorageBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref ContentStorageBucket
PolicyDocument:
Id: BucketPolicy
Version: '2012-10-17'
Statement:
- Sid: FullAccessFromParticularIP
Action:
- s3:*
Effect: "Allow"
Resource:
- !GetAtt [ ContentStorageBucket, Arn ]
- Fn::Join:
- '/'
- - !GetAtt [ ContentStorageBucket, Arn ]
- '*'
Principal: "*"
Condition:
IpAddress:
aws:SourceIp: "x.x.x.x"
- Sid: FullAccessFromInsideVpcEndpoint
Action:
- s3:*
Effect: "Allow"
Resource:
- !GetAtt [ ContentStorageBucket, Arn ]
- Fn::Join:
- '/'
- - !GetAtt [ ContentStorageBucket, Arn ]
- '*'
Principal: "*"
Condition:
StringEquals:
aws:sourceVpce: "vpce-xxxx"
为了测试上述政策条件,我做了以下工作:
- 我已将名为
json.json
的文件添加到 S3 存储桶;
- 我已经创建了一个 EC2 实例并将其放置在存储桶中引用的 VPC 中。
- 我从列入白名单的 IP 地址向文件端点
http://bucket-name.s3-website-us-east-1.amazonaws.com/json.json
发出了 curl 请求,请求成功;
- 我从 EC2 实例(放置在 VPC 中)向文件端点 发出了 curl 请求,请求失败并显示 403 访问被拒绝
备注:
- 我已确保 EC2 实例位于正确的 VPC 中。
aws:sourceVpce
不是使用VPC ID的值,而是使用对应VPC的Endpoint ID的值。
- 我还使用了
aws:sourceVpc
和 VPC ID,而不是使用 aws:sourceVpce
和端点 ID,但这产生了与上述相同的结果。
鉴于此,我目前不确定如何进一步调试它。您对可能出现的问题有什么建议吗?如果问题不清楚或有任何需要澄清的地方,请告诉我。感谢您的帮助!
为了让资源使用 S3 的 VPC 端点,VPC 路由器必须将发往 S3 的所有流量指向 VPC 端点。 AWS 允许您使用 BGP 前缀列表,而不是自行维护所有特定于 S3 的 CIDR 块的列表,这是 AWS 中的第一个 class 资源。
要查找 S3 运行 的前缀列表,请执行以下命令(您的输出应该与我的匹配,因为这应该是跨所有帐户的相同区域范围,但最好检查一下)。使用您的 VPC 的区域。
aws ec2 describe-prefix-lists --region us-east-1
我得到以下输出:
{
"PrefixLists": [
{
"Cidrs": [
"54.231.0.0/17",
"52.216.0.0/15"
],
"PrefixListId": "pl-63a5400a",
"PrefixListName": "com.amazonaws.us-east-1.s3"
},
{
"Cidrs": [
"52.94.0.0/22",
"52.119.224.0/20"
],
"PrefixListId": "pl-02cd2c6b",
"PrefixListName": "com.amazonaws.us-east-1.dynamodb"
}
]
}
对于com.amazonaws.us-east-1.s3,前缀列表id为pl-63a5400a,
这样您就可以在 table 为相关子网提供服务的任何路由中创建一个路由。目的地应该是前缀列表 (pl-63a5400a),目标应该是 VPC 端点 ID (vpce-XXXXXXXX)(您可以通过 aws ec2 describe-vpc-endpoints
找到它)。
这在控制台上是微不足道的。我不记得如何从命令行执行此操作,我想你必须发送一个 cli-input-json 以及类似下面的内容,但我还没有测试过。这留作 reader 的练习。
{
"DestinationPrefixListId": "pl-63a5400a",
"GatewayId": "vpce-12345678",
"RouteTableid": "rt-90123456"
}
我想创建一个配置为用作网站的 S3 存储桶,并且我想将对 S3 网站的访问限制为来自特定 VPC 内部的请求 而已。
我正在使用 Cloudformation 设置存储桶和存储桶策略。
存储桶 CF 已启用 WebsiteConfiguration
并将 AccessControl
设置为 PublicRead
。
ContentStorageBucket:
Type: AWS::S3::Bucket
Properties:
AccessControl: PublicRead
BucketName: "bucket-name"
WebsiteConfiguration:
IndexDocument: index.html
ErrorDocument: error.html
存储桶策略包括两个条件:一个条件授予在办公室 IP 上访问存储桶的完全访问权限,另一个条件授予通过 VPC 端点的访问权限。代码如下:
ContentStorageBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref ContentStorageBucket
PolicyDocument:
Id: BucketPolicy
Version: '2012-10-17'
Statement:
- Sid: FullAccessFromParticularIP
Action:
- s3:*
Effect: "Allow"
Resource:
- !GetAtt [ ContentStorageBucket, Arn ]
- Fn::Join:
- '/'
- - !GetAtt [ ContentStorageBucket, Arn ]
- '*'
Principal: "*"
Condition:
IpAddress:
aws:SourceIp: "x.x.x.x"
- Sid: FullAccessFromInsideVpcEndpoint
Action:
- s3:*
Effect: "Allow"
Resource:
- !GetAtt [ ContentStorageBucket, Arn ]
- Fn::Join:
- '/'
- - !GetAtt [ ContentStorageBucket, Arn ]
- '*'
Principal: "*"
Condition:
StringEquals:
aws:sourceVpce: "vpce-xxxx"
为了测试上述政策条件,我做了以下工作:
- 我已将名为
json.json
的文件添加到 S3 存储桶; - 我已经创建了一个 EC2 实例并将其放置在存储桶中引用的 VPC 中。
- 我从列入白名单的 IP 地址向文件端点
http://bucket-name.s3-website-us-east-1.amazonaws.com/json.json
发出了 curl 请求,请求成功; - 我从 EC2 实例(放置在 VPC 中)向文件端点 发出了 curl 请求,请求失败并显示 403 访问被拒绝
备注:
- 我已确保 EC2 实例位于正确的 VPC 中。
aws:sourceVpce
不是使用VPC ID的值,而是使用对应VPC的Endpoint ID的值。- 我还使用了
aws:sourceVpc
和 VPC ID,而不是使用aws:sourceVpce
和端点 ID,但这产生了与上述相同的结果。
鉴于此,我目前不确定如何进一步调试它。您对可能出现的问题有什么建议吗?如果问题不清楚或有任何需要澄清的地方,请告诉我。感谢您的帮助!
为了让资源使用 S3 的 VPC 端点,VPC 路由器必须将发往 S3 的所有流量指向 VPC 端点。 AWS 允许您使用 BGP 前缀列表,而不是自行维护所有特定于 S3 的 CIDR 块的列表,这是 AWS 中的第一个 class 资源。
要查找 S3 运行 的前缀列表,请执行以下命令(您的输出应该与我的匹配,因为这应该是跨所有帐户的相同区域范围,但最好检查一下)。使用您的 VPC 的区域。
aws ec2 describe-prefix-lists --region us-east-1
我得到以下输出:
{
"PrefixLists": [
{
"Cidrs": [
"54.231.0.0/17",
"52.216.0.0/15"
],
"PrefixListId": "pl-63a5400a",
"PrefixListName": "com.amazonaws.us-east-1.s3"
},
{
"Cidrs": [
"52.94.0.0/22",
"52.119.224.0/20"
],
"PrefixListId": "pl-02cd2c6b",
"PrefixListName": "com.amazonaws.us-east-1.dynamodb"
}
]
}
对于com.amazonaws.us-east-1.s3,前缀列表id为pl-63a5400a,
这样您就可以在 table 为相关子网提供服务的任何路由中创建一个路由。目的地应该是前缀列表 (pl-63a5400a),目标应该是 VPC 端点 ID (vpce-XXXXXXXX)(您可以通过 aws ec2 describe-vpc-endpoints
找到它)。
这在控制台上是微不足道的。我不记得如何从命令行执行此操作,我想你必须发送一个 cli-input-json 以及类似下面的内容,但我还没有测试过。这留作 reader 的练习。
{
"DestinationPrefixListId": "pl-63a5400a",
"GatewayId": "vpce-12345678",
"RouteTableid": "rt-90123456"
}