我们使用机器学习技术将英文博客翻译为简体中文。您可以点击导航栏中的“中文(简体)”切换到英文版本。
使用 S3 服务器访问日志和 亚马逊云科技 CloudTrail 中的信息禁用现有 Amazon S3 工作负载的 ACL
访问控制列表 (ACL) 是权限集,用于定义用户访问权限以及用户可以对特定资源执行的操作。
2021 年,我们推出了
为了帮助您禁用 ACL,我们
解决方案演练
以下是我们将在此博客文章中介绍的内容的简要概述:
- 为您的存储桶启用日志记录
- 使用 Amazon Athena 查询日志并识别依赖于 ACL 的 S3 请求
- 将 ACL 权限迁移到存储桶策略权限
- 验证您是否准备好禁用 ACL
- 禁用 ACL
我们将使用 亚马逊云科技 CloudTrail 演示步骤 1 和步骤 2,但您也可以启用和查询 S3 服务器访问日志,然后在这篇博客文章中继续执行步骤 3-5。
步骤 1:为您的存储桶启用日志记录
首先,您必须为存储桶启用 亚马逊云科技 CloudTrail 数据事件并创建亚马逊 Athena 表。如果您已经为存储桶启用了 CloudTrail 并创建了 Athena 表,则可以继续执行 步骤 2:使用 Amazon Athena 查询 日志。 否则,请完成以下步骤:
-
启用 亚马逊云科技 CloudTrail 数据事件 -
创建亚马逊 Athena 桌子
在继续执行以下步骤之前,您需要等待一段时间,具体取决于您的工作负载,以便记录您为 CloudTrail 配置的 S3 存储桶的数据事件。例如,如果您每天和每周都有工作负载访问存储桶中的数据,则可能需要等待至少一周才能收集所有访问模式。
如果您使用的是 S3 服务器访问日志,请参阅
第 2 步:使用 Amazon Athena 查询日志并识别依赖于 ACL 的 S3 请求
在本步骤中,我们将介绍如何在 亚马逊云科技 Cloudtrail 中记录与 ACL 相关的请求,以及如何使用 Amazon Athena 查询日志。
如何在 亚马逊云科技 CloudTrail 中记录依赖于 ACL 的请求
Amazon S3 服务器访问日志和 亚马逊云科技 CloudTrail 中新增的 ACL
Require d 字段为您提供了每个 S3 请求的信息,以表明该请求是否需要 ACL 才能获得授权。在 亚马逊云科技 CloudTrail 中,它的值要么是 “是”,要么不是。此字段的目的是向您显示哪些请求需要修改存储桶策略或请求,然后才能禁用 ACL。以下是一些示例:
示例 1: 账户 222 向 111 拥有的对象发出的跨账户请求,其中存在允许访问 222 的 ACL。
如果没有允许访问账户 222 的存储桶策略声明,则请求将取决于 ACL 才能成功, ACL
Required 为 “ 是”
。 以下是此示例的 亚马逊云科技 CloudTrail 日志示例。
"userIdentity": {
"accountId": "222",
},
"eventTime": "2022-11-17T19:46:01Z",
"eventName": "GetObject",
"resources": [
{
"type": "AWS::S3::Object",
"ARN": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/example-object"
},
{
"accountId": "111",
"type": "AWS::S3::Bucket",
"ARN": "arn:aws:s3:::DOC-EXAMPLE-BUCKET"
}
],
...
"additionalEventData": {
"aclRequired": "Yes"
}
如果存储桶策略确实允许访问账户 222,则删除 ACL 不会中断访问,并且 ACLrequired 不存在。
示例 2: 同账户请求(对象所有者和调用者位于同一 亚马逊云科技 账户中)
对于同账户读取操作(例如 Get、List),不使用 ACL 进行授权,因此没有 ACL
Required。以下是此示例的 亚马逊云科技 CloudTrail 日志示例。
"userIdentity": {
"accountId": "111",
},
"eventTime": "2022-11-17T19:46:01Z",
"eventName": "GetObject",
"resources": [
{
"type": "AWS::S3::Object",
"ARN": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/example-object"
},
{
"accountId": "111",
"type": "AWS::S3::Bucket",
"ARN": "arn:aws:s3:::DOC-EXAMPLE-BUCKET"
}
],
...
示例 3: 在对象上设置 ACL 的 同账户请求
对于未设置 ACL 或未设置存储桶所有者完全控制 ACL 的同账户 PUT,则不存在 ACLRequired。
在对象上设置 ACL 的所有其他 PUT 请求(例如 putobjectACL)都将显示
以下是此示例的 亚马逊云科技 CloudTrail 日志示例。 acl
Required 为 “是”。
"userIdentity": {
"accountId": "222",
},
"eventTime": "2022-11-17T19:46:01Z",
"eventName": "PutObjectACL",
"requestParameters": {
"ObjectCannedACL": "BucketOwnerFullControl",
},
"resources": [
{
"type": "AWS::S3::Object",
"ARN": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/example-object"
},
{
"accountId": "222",
"type": "AWS::S3::Bucket",
"ARN": "arn:aws:s3:::DOC-EXAMPLE-BUCKET"
}
],
...
"additionalEventData": {
"aclRequired": "Yes"
}
此字段中标有 “是” 的请求表示在禁用 ACL 之前您需要在哪里采取其他操作。接下来,我们将展示如何查询日志以识别这些请求。要更详细地了解操作与 CloudTrail 或服务器访问日志中的预期 ACL
Required 值之间的映射,请参阅
使用雅典娜查询 CloudTrail 日志
等待 CloudTrail 中记录数据事件后,您可以运行以下查询,查找您选择的时间段内所有与 ACL 相关的 S3 请求。如果您经常访问数据,我们建议您首先选择较短的时间段(例如几个小时)来测试此查询,以获取样本。在以下示例中,我们使用了 3 天的时间段,但您应该修改查询以适应至少一次将应用程序的所有工作负载捕获到存储桶的时间范围。此查询生成相关信息,例如事件名称、事件数量、请求者账户 ID 和存储桶名称。它仅检索从您启用存储桶登录时起以及在所有区域启动 ACL
Require d 字段之后的信息(23 年 2 月 15 日)。
SELECT
eventName,
COUNT(*) AS eventCount,
userIdentity.accountId,
json_extract_scalar(requestParameters, '$.bucketName') as bucketName
FROM cloudtrail_table
WHERE
json_extract_scalar(additionalEventData, '$.aclRequired') = 'Yes'
AND eventTime > to_iso8601(current_date - interval '3' day)
AND errorCode IS NULL
GROUP BY
userIdentity.accountId,
eventName,
json_extract_scalar(requestParameters, '$.bucketName')
ORDER BY userIdentity.accountId;
如果您想查看特定时间段内的 S3 请求,可以使用以下示例查询。
SELECT
eventName,
COUNT(*) AS eventCount,
userIdentity.accountId,
json_extract_scalar(requestParameters, '$.bucketName') as bucketName
FROM cloudtrail_table
WHERE
json_extract_scalar(additionalEventData, '$.aclRequired') = 'Yes'
AND eventTime > '2023-02-15T00:00:00Z' AND eventTime < '2023-02-18T00:00:00Z'
AND errorCode IS NULL
GROUP BY
userIdentity.accountId,
eventname,
json_extract_scalar(requestParameters, '$.bucketName')
ORDER BY userIdentity.accountId;
以下是此查询的示例输出:
此查询的输出表明,来自账户 111122223333 的 putObject、getObject 和 ListBucket 请求依赖于 ACL 才能成功。为了能够遵循禁用 ACL 这一安全最佳实践,我们需要在存储桶策略中允许这些用户访问权限,并验证不再对请求设置 ACL,我们将在 步骤 3:将 ACL 权限迁移到存储桶策略 和 步骤 4:验证您是否准备好禁用 ACL 中会这样做。
你可能会从这个查询中得到一个空结果。这意味着,在这段时间内,如果禁用 ACL,任何请求都不会被拒绝。如果您的查询为空,则可以在不同的时间段内验证这是真的,或者继续执行 步骤 5:禁用 ACL。
使用 Athena 查询 S3 服务器访问日志
如果您已为存储桶启用服务器访问日志,请参阅
步骤 3:将 ACL 权限迁移到存储桶策略
使用 Athena 查询的输出,我们现在可以编写存储桶策略声明,使这些 ACL 不再需要授权。
在步骤 2 中,我们确定了账户 111122223333 对存储桶 “DOC-EXAMPLE-BUCKET” 进行的三项操作 putObject、getObject 和 ListBucket。 这些操作必须转换为存储桶策略的 操作 元素中的操作,并指定相应的
资源
, 如以下存储桶策略所示:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "111122223333"
},
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*",
"arn:aws:s3:::DOC-EXAMPLE-BUCKET"
]
}
]
}
为了编写此政策,我们将查询结果中的每项操作映射到相应的 IAM 操作和资源。下表列出了一些常见的 S3 操作及其等效的存储桶策略操作和资源类型。要更详细地了解操作与存储桶策略操作和资源之间的映射,请参阅有关
Operation name in 亚马逊云科技 CloudTrail | Operation name in Amazon S3 server access logs | Bucket policy action | Bucket policy resource type |
GetObject | REST.GET.OBJECT | s3:GetObject | Object |
PutObject | REST.PUT.OBJECT | s3:PutObject or n/a | Object or n/a |
ListObjects | REST.GET.BUCKET | s3:ListBucket | Bucket |
DeleteObject | REST.DELETE.OBJECT | s3:DeleteObject | Object |
PutObjectACL | REST.PUT.ACL | n/a | n/a |
PutBucketACL | REST.PUT.ACL | n/a | n/a |
注意:具有 n/a 存储桶策略操作的操作必须停止设置 ACL。参见步骤 4。
通过此存储桶策略,我们向账户 111122223333 授予了对存储桶中所有对象的访问权限。虽然这涵盖了我们已知的访问模式,但如果你知道账户 111122223333 实际上只需要访问 样本前缀/*
下的数据,你可以写一份更具体的政策声明 ,只允许访问特定的前缀。有关上述
步骤 4:验证您是否准备好禁用 ACL
禁用 ACL 后,所有 PutBucketAcl 和 PutObjectACL 以及设置的访问控制权限不是存储桶所有者完全控制 ACL 的 API 都将失败并出现 400 个错误。为了解决这个问题,必须删除所有 PutBucketACL 和 PutobJectACL 请求,所有其他指定 ACL 的 API 都应从请求中删除 ACL 参数。以下是这些更改的示例。
// Removing custom ACL from PutObject Request
final PutObjectRequest putObjectRequest = PutObjectRequest.builder()
.bucket(bucketName)
.key(objectName)
.grantRead(aclString)
.build();
// Removing canned ACL from PutObject Request
final PutObjectRequest putObjectRequest = PutObjectRequest.builder()
.bucket(bucketName)
.key(objectName)
.acl(aclString)
.build();
验证是否不再需要 ACL
对存储桶策略以及需要时对客户端应用程序进行了必要的更改后,您应该等待一段时间以允许记录后续请求。就像 步骤 1:为存储桶启用日志记录 一样 ,等待此分析的适当时间可能是几天或几周,具体取决于您的工作负载。接下来,您可以使用查询来重新评估日志,例如下面的查询,该查询自更新以来会查询日志,以确保您现在没有依赖于 ACL 的工作负载。如果查询从应用存储桶策略之日起返回零结果,则可以在不中断现有工作负载的情况下禁用 ACL。
SELECT
eventName,
COUNT(*) AS eventCount,
userIdentity.accountId,
json_extract_scalar(requestParameters, '$.bucketName') as bucketName
FROM cloudtrail_table
WHERE
json_extract_scalar(additionalEventData, '$.aclRequired') = 'Yes'
AND eventTime > '2023-02-15T00:00:00Z'
GROUP BY
userIdentity.accountId,
eventName,
json_extract_scalar(requestParameters, '$.bucketName')
ORDER BY userIdentity.accountId;
putObject、getObject 和 ListObjects 操作不再出现在查询结果中,这验证了存储桶策略是否允许这些权限,请求未设置 ACL。如果您看到任何结果,则必须添加存储桶策略未考虑的其他与 ACL 相关的请求,否则仍在设置 ACL。如果是这种情况,请重复 步骤 3:将 ACL 权限迁移到存储桶策略 和 步骤 4:验证您是否准备好禁用 ACL 。
步骤 5:禁用 ACL
现在,依赖于 ACL 的权限已添加到您的存储桶策略中,并且您的日志中不再有表明需要 ACL 的请求,您可以放心地在 S3 存储桶上禁用 ACL,确保不会中断现有工作负载。
要禁用存储桶及其中的对象的 ACL,您首先需要删除所有现有的存储桶 ACL。您可以通过在 S3 控制台中转到存储桶的详细信息页面来执行此操作。在 权限 选项卡中,编辑 访问控制列表 (ACL) 以删除除您自己(存储桶所有者)之外的所有被授权者的存储桶 ACL。请勿更改对象 ACL。
删除所有存储桶 ACL 后(保留在 “ 权限 ” 选项卡中),您可以通过编辑 对象所有权 并将其设置为禁用 ACL 来禁用存储分区上的 AC L。 此步骤是可逆的,因此,如果您出于任何原因需要重新启用 ACL,则会立即恢复之前使用的对象 ACL。
现在,您已成功将依赖于 ACL 的请求的权限迁移到存储桶策略,并在存储桶上禁用了 ACL!展望未来,对数据的访问将基于策略,包括 S3 存储桶策略和 IAM 策略。
正在清理
总结一下,在清理过程中完成以下可选步骤:
- 禁用 亚马逊云科技 CloudTrail 数据事件和/或 Amazon S3 服务器访问日志。如果您不需要登录存储桶,则建议使用此方法。
- 删除相应的 Amazon Athena 表,除非您想将其保留以备将来参考。
大多数客户可以在这里停下来。如果出于任何原因您不想禁用 ACL,例如您只是在运行测试,则可以完成以下步骤来重新启用 ACL:
- 通过将 对象所有权 编辑为 启用的 ACL 并恢复存储桶策略的删除 ,恢复在存储桶的 权限 选项卡中所做的更改。
- 恢复对设置 ACL 的 API 的删除。
- 恢复对存储桶策略所做的更改。
结论
在这篇博客中,我们演示了如何使用 Amazon S3 服务器访问日志和 亚马逊云科技 CloudTrail 中的新 ACLRequired 字段来识别依赖 ACL 来访问数据的现有应用程序或访问模式。这篇文章中介绍的方法将允许您放心地将这些依赖于 ACL 的权限迁移到等效的存储桶策略,从而允许您禁用 ACL。
我们推荐的另一种最佳做法是启用 “阻止公共访问”。此功能允许您限制对 S3 存储桶的公共访问。有关 BPA 的更多信息,请参阅
感谢您阅读这篇博客文章。如果您有任何意见或疑问,请随时在评论部分发表评论。
其他资源
-
注意:Amazon S3 安全变更将于 2023 年 4 月发布 (默认启用 S3 区块公共访问权限,默认情况下,新 存储桶禁用 ACL) -
新增 — 简化 Amazon S3 中存储数据的访问管理 (S3 对象所有权可禁用 ACL)
*前述特定亚马逊云科技生成式人工智能相关的服务仅在亚马逊云科技海外区域可用,亚马逊云科技中国仅为帮助您发展海外业务和/或了解行业前沿技术选择推荐该服务。