

# 使用 CloudTrail 识别 Amazon S3 请求
<a name="cloudtrail-request-identification"></a>

在 Amazon S3 中，可以使用 AWS CloudTrail 事件日志识别请求。AWS CloudTrail 是识别 Amazon S3 请求的首选方法，但是如果您使用的是 Amazon S3 服务器访问日志，请参阅[使用 Amazon S3 服务器访问日志来确定请求](using-s3-access-logs-to-identify-requests.md)。

**Topics**
+ [识别 CloudTrail 日志中向 Amazon S3 发出的请求](#identify-S3-requests-using-in-CTlog)
+ [使用 CloudTrail 识别 Amazon S3 签名版本 2 请求](#cloudtrail-identification-sigv2-requests)
+ [使用 CloudTrail 识别对 S3 对象的访问权限](#cloudtrail-identification-object-access)

## 识别 CloudTrail 日志中向 Amazon S3 发出的请求
<a name="identify-S3-requests-using-in-CTlog"></a>

在设置 CloudTrail 以将事件传输到存储桶后，您应开始看到对象进入您在 Amazon S3 控制台上的目标存储桶。其格式如下所示：

`s3://amzn-s3-demo-bucket1/AWSLogs/111122223333/CloudTrail/Region/yyyy/mm/dd` 

由 CloudTrail 记录的事件作为使用 gzipped 进行压缩的 JSON 对象存储在您的 S3 存储桶中。要高效地查找请求，您应使用 Amazon Athena 等服务来为 CloudTrail 日志建立索引并查询。

有关 CloudTrail 和 Athena 的更多信息，请参阅《Amazon Athena 用户指南》**中的[使用分区投影在 Athena 中创建 AWS CloudTrail 日志表](https://docs.aws.amazon.com/athena/latest/ug/cloudtrail-logs.html#create-cloudtrail-table-partition-projection)。

## 使用 CloudTrail 识别 Amazon S3 签名版本 2 请求
<a name="cloudtrail-identification-sigv2-requests"></a>

您可以使用 CloudTrail 事件日志来确定已用于在 Amazon S3 中签署请求的 API 签名版本。此功能非常重要，因为对 Signature Version 2 的支持将会关闭（弃用）。之后，Amazon S3 将不再接受使用 Signature Version 2 的请求，并且所有请求必须使用 *Signature Version 4* 进行签署。

我们*强烈*建议您使用 CloudTrail 来帮助确定您的任何工作流是否正在使用 Signature Version 2 进行签署。请通过将您的库和代码升级为使用 Signature Version 4 进行纠正，以防对您的业务产生任何影响。

有关更多信息，请参阅 AWS re:Post 中的[公告：适用于 Amazon S3 的 AWS CloudTrail 为增强安全性审计添加了新字段](https://forums.aws.amazon.com/ann.jspa?annID=6551)。

**注意**  
Amazon S3 的 CloudTrail 事件在请求详细信息中的键名称“`additionalEventData`”之下包含签名版本。要针对为 Amazon S3 中的对象发出的请求（如 `GET`、`PUT` 和 `DELETE` 请求）查找签名版本，您必须启用 CloudTrail 数据事件。（默认情况下，此特征处于关闭状态。）

AWS CloudTrail 是确定签名版本 2 请求的首选方法。如果您使用的是 Amazon S3 服务器访问日志，请参阅[使用 Amazon S3 访问日志确定签名版本 2 请求](using-s3-access-logs-to-identify-requests.md#using-s3-access-logs-to-identify-sigv2-requests)。

**Topics**
+ [用于识别 Amazon S3 签名版本 2 请求的 Athena 查询示例](#ct-examples-identify-sigv2-requests)
+ [对签名版本 2 数据进行分区](#partitioning-sigv2-data)

### 用于识别 Amazon S3 签名版本 2 请求的 Athena 查询示例
<a name="ct-examples-identify-sigv2-requests"></a>

**Example — 选择所有签名版本 2 事件，并仅打印 `EventTime`、`S3_Action`、`Request_Parameters`、`Region`、`SourceIP` 和 `UserAgent`**  
在以下 Athena 查询中，将 *`s3_cloudtrail_events_db.cloudtrail_table`* 替换为您的 Athena 详细信息，并根据需要增加或删除限制。  

```
SELECT EventTime, EventName as S3_Action, requestParameters as Request_Parameters, awsregion as AWS_Region, sourceipaddress as Source_IP, useragent as User_Agent
FROM s3_cloudtrail_events_db.cloudtrail_table
WHERE eventsource='s3.amazonaws.com'
AND json_extract_scalar(additionalEventData, '$.SignatureVersion')='SigV2'
LIMIT 10;
```

**Example — 选择发送签名版本 2 流量的所有请求者**  
   

```
SELECT useridentity.arn, Count(requestid) as RequestCount
FROM s3_cloudtrail_events_db.cloudtrail_table
WHERE eventsource='s3.amazonaws.com'
    and json_extract_scalar(additionalEventData, '$.SignatureVersion')='SigV2'
Group by useridentity.arn
```

### 对签名版本 2 数据进行分区
<a name="partitioning-sigv2-data"></a>

如果您有大量要查询的数据，则可以通过创建分区表来减少 Athena 的成本和运行时间。

为此，创建一个包含分区的新表，如下所示。

```
   CREATE EXTERNAL TABLE s3_cloudtrail_events_db.cloudtrail_table_partitioned(
        eventversion STRING,
        userIdentity STRUCT<
            type:STRING,
            principalid:STRING,
            arn:STRING,
            accountid:STRING,
            invokedby:STRING,
            accesskeyid:STRING,
            userName:STRING,
         sessioncontext:STRUCT<
                    attributes:STRUCT< 
                    mfaauthenticated:STRING,
                    creationdate:STRING>,
                    sessionIssuer:STRUCT<
                    type:STRING,
                    principalId:STRING,
                    arn:STRING,
                    accountId:STRING,
                    userName:STRING>
                >
             >,
        eventTime STRING,
        eventSource STRING,
        eventName STRING,
        awsRegion STRING,
        sourceIpAddress STRING,
        userAgent STRING,
        errorCode STRING,
        errorMessage STRING,
        requestParameters STRING,
        responseElements STRING,
        additionalEventData STRING,
        requestId STRING,
        eventId STRING,
        resources ARRAY<STRUCT<ARN:STRING,accountId: STRING,type:STRING>>, 
        eventType STRING,
        apiVersion STRING,
        readOnly STRING,
        recipientAccountId STRING,
        serviceEventDetails STRING,
        sharedEventID STRING,
        vpcEndpointId STRING
    )   
    PARTITIONED BY (region string, year string, month string, day string)
    ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.orc.OrcSerde' 
    STORED AS INPUTFORMAT 'org.apache.hadoop.hive.ql.io.SymlinkTextInputFormat'
    OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
    LOCATION 's3://amzn-s3-demo-bucket1/AWSLogs/111122223333/';
```

然后，单独创建分区。您无法从尚未创建的日期获取结果。

```
ALTER TABLE s3_cloudtrail_events_db.cloudtrail_table_partitioned ADD
    PARTITION (region= 'us-east-1', year= '2019', month= '02', day= '19') LOCATION 's3://amzn-s3-demo-bucket1/AWSLogs/111122223333/CloudTrail/us-east-1/2019/02/19/'
    PARTITION (region= 'us-west-1', year= '2019', month= '02', day= '19') LOCATION 's3://amzn-s3-demo-bucket1/AWSLogs/111122223333/CloudTrail/us-west-1/2019/02/19/'
    PARTITION (region= 'us-west-2', year= '2019', month= '02', day= '19') LOCATION 's3://amzn-s3-demo-bucket1/AWSLogs/111122223333/CloudTrail/us-west-2/2019/02/19/'
    PARTITION (region= 'ap-southeast-1', year= '2019', month= '02', day= '19') LOCATION 's3://amzn-s3-demo-bucket1/AWSLogs/111122223333/CloudTrail/ap-southeast-1/2019/02/19/'
    PARTITION (region= 'ap-southeast-2', year= '2019', month= '02', day= '19') LOCATION 's3://amzn-s3-demo-bucket1/AWSLogs/111122223333/CloudTrail/ap-southeast-2/2019/02/19/'
    PARTITION (region= 'ap-northeast-1', year= '2019', month= '02', day= '19') LOCATION 's3://amzn-s3-demo-bucket1/AWSLogs/111122223333/CloudTrail/ap-northeast-1/2019/02/19/'
    PARTITION (region= 'eu-west-1', year= '2019', month= '02', day= '19') LOCATION 's3://amzn-s3-demo-bucket1/AWSLogs/111122223333/CloudTrail/eu-west-1/2019/02/19/'
    PARTITION (region= 'sa-east-1', year= '2019', month= '02', day= '19') LOCATION 's3://amzn-s3-demo-bucket1/AWSLogs/111122223333/CloudTrail/sa-east-1/2019/02/19/';
```

然后，您可以根据这些分区发出请求，并且无需加载完整的存储桶。

```
SELECT useridentity.arn,
Count(requestid) AS RequestCount
FROM s3_cloudtrail_events_db.cloudtrail_table_partitioned
WHERE eventsource='s3.amazonaws.com'
AND json_extract_scalar(additionalEventData, '$.SignatureVersion')='SigV2'
AND region='us-east-1'
AND year='2019'
AND month='02'
AND day='19'
Group by useridentity.arn
```

## 使用 CloudTrail 识别对 S3 对象的访问权限
<a name="cloudtrail-identification-object-access"></a>

您可以使用 AWS CloudTrail 事件日志确定对于诸如 `GetObject`、`DeleteObject` 和 `PutObject` 等数据事件的 Amazon S3 对象访问请求，并发现有关这些请求的进一步信息。

**注意**  
如果您使用 AWS CloudTrail 记录数据活动，则 Amazon S3 `DeleteObjects` 数据事件的事件记录同时包括 `DeleteObjects` 事件和作为该操作的一部分删除的每个对象的 `DeleteObject` 事件。您可以从事件记录中排除有关已删除对象的额外可见性。有关更多信息，请参阅《AWS CloudTrail User Guide》**中的 [AWS CLI examples for filtering data events](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/filtering-data-events.html#filtering-data-events-deleteobjects)。

以下示例说明如何从 AWS CloudTrail 事件日志获取对于 Amazon S3 的所有 `PUT` 对象请求。

**Topics**
+ [用于识别 Amazon S3 对象访问请求的 Athena 查询示例](#ct-examples-identify-object-access-requests)

### 用于识别 Amazon S3 对象访问请求的 Athena 查询示例
<a name="ct-examples-identify-object-access-requests"></a>

在以下 Athena 查询示例中，将 *`s3_cloudtrail_events_db.cloudtrail_table`* 替换为您的 Athena 详细信息，并根据需要修改日期范围。

**Example — 选择所有具有 `PUT` 对象访问请求的事件，并仅打印 `EventTime`、`EventSource`、`SourceIP`、`UserAgent`、`BucketName`、`object` 和 `UserARN`**  

```
SELECT
  eventTime, 
  eventName, 
  eventSource, 
  sourceIpAddress, 
  userAgent, 
  json_extract_scalar(requestParameters, '$.bucketName') as bucketName, 
  json_extract_scalar(requestParameters, '$.key') as object,
  userIdentity.arn as userArn
FROM
  s3_cloudtrail_events_db.cloudtrail_table
WHERE
  eventName = 'PutObject'
  AND eventTime BETWEEN '2019-07-05T00:00:00Z' and '2019-07-06T00:00:00Z'
```

**Example — 选择所有具有 `GET` 对象访问请求的事件，并仅打印 `EventTime`、`EventSource`、`SourceIP`、`UserAgent`、`BucketName`、`object` 和 `UserARN`**  

```
SELECT
  eventTime, 
  eventName, 
  eventSource, 
  sourceIpAddress, 
  userAgent, 
  json_extract_scalar(requestParameters, '$.bucketName') as bucketName, 
  json_extract_scalar(requestParameters, '$.key') as object,
  userIdentity.arn as userArn
FROM
  s3_cloudtrail_events_db.cloudtrail_table
WHERE
  eventName = 'GetObject'
  AND eventTime BETWEEN '2019-07-05T00:00:00Z' and '2019-07-06T00:00:00Z'
```

**Example — 选择特定时段内向存储桶发送的所有匿名请求者事件，并仅打印 `EventTime`、`EventName`、`EventSource`、`SourceIP`、`UserAgent`、`BucketName`、`UserARN` 和 `AccountID`**  

```
SELECT
  eventTime, 
  eventName, 
  eventSource, 
  sourceIpAddress, 
  userAgent, 
  json_extract_scalar(requestParameters, '$.bucketName') as bucketName, 
  userIdentity.arn as userArn,
  userIdentity.accountId
FROM
  s3_cloudtrail_events_db.cloudtrail_table
WHERE
  userIdentity.accountId = 'anonymous'
  AND eventTime BETWEEN '2019-07-05T00:00:00Z' and '2019-07-06T00:00:00Z'
```

**Example — 识别所有需要 ACL 进行授权的请求**  
 以下 Amazon Athena 查询示例说明如何识别向 S3 存储桶发出的所有请求，这些请求需要访问控制列表（ACL）进行授权。如果请求需要 ACL 进行授权，则 `additionalEventData` 中的 `aclRequired` 值为 `Yes`。如果不需要 ACL，则 `aclRequired` 不存在。您可以使用此信息将这些 ACL 权限迁移到相应的存储桶策略。创建这些存储桶策略后，您可以对这些存储桶禁用 ACL。有关禁用 ACL 的更多信息，请参阅[禁用 ACL 的先决条件](object-ownership-migrating-acls-prerequisites.md)。  

```
SELECT
  eventTime, 
  eventName, 
  eventSource, 
  sourceIpAddress, 
  userAgent, 
  userIdentity.arn as userArn,
  json_extract_scalar(requestParameters, '$.bucketName') as bucketName,
  json_extract_scalar(requestParameters, '$.key') as object,
  json_extract_scalar(additionalEventData, '$.aclRequired') as aclRequired
FROM 
  s3_cloudtrail_events_db.cloudtrail_table
WHERE
  json_extract_scalar(additionalEventData, '$.aclRequired') = 'Yes'
  AND eventTime BETWEEN '2022-05-10T00:00:00Z' and '2022-08-10T00:00:00Z'
```

**注意**  
也可以使用这些查询示例进行安全监控。您可以查看意外或未经授权的 IP 地址或请求者发出的 `PutObject` 或 `GetObject` 调用的结果，以及确定向存储桶发出的任何匿名请求。
 此查询仅从启用了日志记录的时间检索信息。

如果您使用的是 Amazon S3 服务器访问日志，请参阅 [使用 Amazon S3 访问日志确定对象访问请求](using-s3-access-logs-to-identify-requests.md#using-s3-access-logs-to-identify-objects-access)。