

# 使用 Amazon S3 服务器访问日志来确定请求
<a name="using-s3-access-logs-to-identify-requests"></a>

您可以使用 Amazon S3 服务器访问日志来确定 Amazon S3 请求。

**注意**  
要确定 Amazon S3 请求，建议您使用 AWS CloudTrail 数据事件而不是 Amazon S3 服务器访问日志。CloudTrail 数据事件更易于设置并包含更多信息。有关更多信息，请参阅 [使用 CloudTrail 识别 Amazon S3 请求](cloudtrail-request-identification.md)。
根据您获得的访问请求数量，与使用 CloudTrail 数据事件相比，分析日志使用的资源或时间可能会更多。

**Topics**
+ [使用 Amazon Athena 查询访问日志中的请求](#querying-s3-access-logs-for-requests)
+ [使用 Amazon S3 访问日志确定签名版本 2 请求](#using-s3-access-logs-to-identify-sigv2-requests)
+ [使用 Amazon S3 访问日志确定对象访问请求](#using-s3-access-logs-to-identify-objects-access)

## 使用 Amazon Athena 查询访问日志中的请求
<a name="querying-s3-access-logs-for-requests"></a>

您可以使用 Amazon Athena 查询 Amazon S3 访问日志以确定 Amazon S3 请求。

Amazon S3 将服务器访问日志作为对象存储在 S3 存储桶中。使用可以分析 Amazon S3 中的日志的工具通常会更轻松。Athena 支持分析 S3 对象，并且可用于查询 Amazon S3 访问日志。

**Example**  
以下示例说明了如何在 Amazon Athena 中查询 Amazon S3 服务器访问日志。将以下示例中使用的 `user input placeholders` 替换为您自己的信息。  
要在 Athena 查询中指定 Amazon S3 位置，您必须提供将日志传输到的存储桶的 S3 URI。此 URI 必须包含以下格式的存储桶名称和前缀：`s3://amzn-s3-demo-bucket1-logs/prefix/`

1. 从 [https://console.aws.amazon.com/athena/](https://console.aws.amazon.com/athena/home) 打开 Athena 控制台。

1. 在查询编辑器中，运行类似如下的命令。将 `s3_access_logs_db` 替换为要为数据库指定的名称。

   ```
   CREATE DATABASE s3_access_logs_db
   ```
**注意**  
最佳实践是在与 S3 存储桶所在相同的 AWS 区域中创建数据库。

1. 在查询编辑器中，运行类似如下的命令以便在步骤 2 中创建的数据库中创建一个表架构。将 `s3_access_logs_db.mybucket_logs` 替换为要为表指定的名称。`STRING` 和 `BIGINT` 数据类型值是访问日志属性。您可以在 Athena 中查询这些属性。对于 `LOCATION`，输入之前记下的 S3 存储桶和前缀。

------
#### [ Date-based partitioning ]

   ```
   CREATE EXTERNAL TABLE s3_access_logs_db.mybucket_logs( 
    `bucketowner` STRING, 
    `bucket_name` STRING, 
    `requestdatetime` STRING, 
    `remoteip` STRING, 
    `requester` STRING, 
    `requestid` STRING, 
    `operation` STRING, 
    `key` STRING, 
    `request_uri` STRING, 
    `httpstatus` STRING, 
    `errorcode` STRING, 
    `bytessent` BIGINT, 
    `objectsize` BIGINT, 
    `totaltime` STRING, 
    `turnaroundtime` STRING, 
    `referrer` STRING, 
    `useragent` STRING, 
    `versionid` STRING, 
    `hostid` STRING, 
    `sigv` STRING, 
    `ciphersuite` STRING, 
    `authtype` STRING, 
    `endpoint` STRING, 
    `tlsversion` STRING,
    `accesspointarn` STRING,
    `aclrequired` STRING,
    `sourceregion` STRING)
    PARTITIONED BY (
      `timestamp` string)
   ROW FORMAT SERDE 
    'org.apache.hadoop.hive.serde2.RegexSerDe' 
   WITH SERDEPROPERTIES ( 
    'input.regex'='([^ ]*) ([^ ]*) \\[(.*?)\\] ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) (\"[^\"]*\"|-) (-|[0-9]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) (\"[^\"]*\"|-) ([^ ]*)(?: ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*))?.*$') 
   STORED AS INPUTFORMAT 
    'org.apache.hadoop.mapred.TextInputFormat' 
   OUTPUTFORMAT 
    'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
   LOCATION
    's3://bucket-name/prefix-name/account-id/region/source-bucket-name/'
    TBLPROPERTIES (
     'projection.enabled'='true', 
     'projection.timestamp.format'='yyyy/MM/dd', 
     'projection.timestamp.interval'='1', 
     'projection.timestamp.interval.unit'='DAYS', 
     'projection.timestamp.range'='2024/01/01,NOW', 
     'projection.timestamp.type'='date', 
     'storage.location.template'='s3://bucket-name/prefix-name/account-id/region/source-bucket-name/${timestamp}')
   ```

------
#### [ Non-date-based partitioning ]

   ```
   CREATE EXTERNAL TABLE `s3_access_logs_db.mybucket_logs`(
     `bucketowner` STRING, 
     `bucket_name` STRING, 
     `requestdatetime` STRING, 
     `remoteip` STRING, 
     `requester` STRING, 
     `requestid` STRING, 
     `operation` STRING, 
     `key` STRING, 
     `request_uri` STRING, 
     `httpstatus` STRING, 
     `errorcode` STRING, 
     `bytessent` BIGINT, 
     `objectsize` BIGINT, 
     `totaltime` STRING, 
     `turnaroundtime` STRING, 
     `referrer` STRING, 
     `useragent` STRING, 
     `versionid` STRING, 
     `hostid` STRING, 
     `sigv` STRING, 
     `ciphersuite` STRING, 
     `authtype` STRING, 
     `endpoint` STRING, 
     `tlsversion` STRING,
     `accesspointarn` STRING,
     `aclrequired` STRING,
     `sourceregion` STRING)
   ROW FORMAT SERDE 
     'org.apache.hadoop.hive.serde2.RegexSerDe' 
   WITH SERDEPROPERTIES ( 
     'input.regex'='([^ ]*) ([^ ]*) \\[(.*?)\\] ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) (\"[^\"]*\"|-) (-|[0-9]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) (\"[^\"]*\"|-) ([^ ]*)(?: ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*))?.*$') 
   STORED AS INPUTFORMAT 
     'org.apache.hadoop.mapred.TextInputFormat' 
   OUTPUTFORMAT 
     'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
   LOCATION
     's3://amzn-s3-demo-bucket1-logs/prefix/'
   ```

------

1. 在导航窗格中，在 **Database (数据库)** 下，请选择您的数据库。

1. 在 **Tables (表)** 下，请选择表名称旁边的 **Preview table (预览表)**。

   在 **Results (结果)** 窗格中，您应看到来自服务器访问日志中的数据，如 `bucketowner`、`bucket`、`requestdatetime` 等。这表示您成功创建了 Athena 表。您现在可以查询 Amazon S3 服务器访问日志。

**Example — 显示已删除对象的人员和时间（时间戳、IP 地址和 IAM 用户）**  

```
SELECT requestdatetime, remoteip, requester, key 
FROM s3_access_logs_db.mybucket_logs 
WHERE key = 'images/picture.jpg' AND operation like '%DELETE%';
```

**Example — 显示 IAM 用户执行的所有操作**  

```
SELECT * 
FROM s3_access_logs_db.mybucket_logs 
WHERE requester='arn:aws:iam::123456789123:user/user_name';
```

**Example — 显示在特定时间段内对对象执行的所有操作**  

```
SELECT *
FROM s3_access_logs_db.mybucket_logs
WHERE Key='prefix/images/picture.jpg' 
AND parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2017-02-18:07:00:00','yyyy-MM-dd:HH:mm:ss')
AND parse_datetime('2017-02-18:08:00:00','yyyy-MM-dd:HH:mm:ss');
```

**Example — 显示在特定时间段内传输到特定 IP 地址的数据量**  

```
SELECT coalesce(SUM(bytessent), 0) AS bytessenttotal
FROM s3_access_logs_db.mybucket_logs
WHERE remoteip='192.0.2.1'
AND parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2022-06-01','yyyy-MM-dd')
AND parse_datetime('2022-07-01','yyyy-MM-dd');
```

**Example — 查找特定时间段内 HTTP 5xx 错误的请求 ID**  

```
SELECT requestdatetime, key, httpstatus, errorcode, requestid, hostid 
FROM s3_access_logs_db.mybucket_logs
WHERE httpstatus like '5%' AND timestamp
BETWEEN '2024/01/29'
AND '2024/01/30'
```

**注意**  
要减少保留日志的时间，您可以为服务器访问日志存储桶创建 S3 生命周期配置。创建生命周期配置规则以定期删除日志文件。这样做可以减少 Athena 为每个查询分析的数据量。有关更多信息，请参阅 [在存储桶上设置 S3 生命周期配置](how-to-set-lifecycle-configuration-intro.md)。

## 使用 Amazon S3 访问日志确定签名版本 2 请求
<a name="using-s3-access-logs-to-identify-sigv2-requests"></a>

对 Signature Version 2 的 Amazon S3 支持将会关闭（弃用）。之后，Amazon S3 将不再接受使用 Signature Version 2 的请求，并且所有请求必须使用 Signature Version 4 进行签署。您可以使用 Amazon S3 访问日志确定签名版本 2 访问请求。

**注意**  
要确定签名版本 2 请求，建议您使用 AWS CloudTrail 数据事件而不是 Amazon S3 服务器访问日志。CloudTrail 数据事件更易于设置，并且包含比服务器访问日志更多的信息。有关更多信息，请参阅 [使用 CloudTrail 识别 Amazon S3 签名版本 2 请求](cloudtrail-request-identification.md#cloudtrail-identification-sigv2-requests)。

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

```
SELECT requester, sigv, Count(sigv) as sigcount 
FROM s3_access_logs_db.mybucket_logs
GROUP BY requester, sigv;
```

## 使用 Amazon S3 访问日志确定对象访问请求
<a name="using-s3-access-logs-to-identify-objects-access"></a>

对于诸如 `GET`、`PUT` 和 `DELETE` 等操作，您可以对 Amazon S3 服务访问日志使用查询以确定 Amazon S3 对象访问请求，并发现有关这些请求的进一步信息。

以下 Amazon Athena 查询示例说明如何从服务器访问日志中获取 Amazon S3 的所有 `PUT` 对象请求。

**Example — 显示在特定时段内正在发送 `PUT` 对象请求的所有请求者**  

```
SELECT bucket_name, requester, remoteip, key, httpstatus, errorcode, requestdatetime
FROM s3_access_logs_db.mybucket_logs
WHERE operation='REST.PUT.OBJECT' 
AND parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z') 
BETWEEN parse_datetime('2019-07-01:00:42:42',yyyy-MM-dd:HH:mm:ss')
AND parse_datetime('2019-07-02:00:42:42','yyyy-MM-dd:HH:mm:ss')
```

以下 Amazon Athena 查询示例说明了如何从服务器访问日志中获取 Amazon S3 的所有 `GET` 对象请求。

**Example — 显示在特定时段内正在发送 `GET` 对象请求的所有请求者**  

```
SELECT bucket_name, requester, remoteip, key, httpstatus, errorcode, requestdatetime
FROM s3_access_logs_db.mybucket_logs
WHERE operation='REST.GET.OBJECT' 
AND parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z') 
BETWEEN parse_datetime('2019-07-01:00:42:42','yyyy-MM-dd:HH:mm:ss')
AND parse_datetime('2019-07-02:00:42:42','yyyy-MM-dd:HH:mm:ss')
```

以下 Amazon Athena 查询示例说明了如何从服务器访问日志中获取向 S3 存储桶发出的所有匿名请求。

**Example — 显示在特定时段内向存储桶发出请求的所有匿名请求者**  

```
SELECT bucket_name, requester, remoteip, key, httpstatus, errorcode, requestdatetime
FROM s3_access_logs_db.mybucket_logs
WHERE requester IS NULL 
AND parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z') 
BETWEEN parse_datetime('2019-07-01:00:42:42','yyyy-MM-dd:HH:mm:ss')
AND parse_datetime('2019-07-02:00:42:42','yyyy-MM-dd:HH:mm:ss')
```

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

**Example — 识别所有需要 ACL 进行授权的请求**  

```
SELECT bucket_name, requester, key, operation, aclrequired, requestdatetime
FROM s3_access_logs_db.mybucket_logs
WHERE aclrequired = 'Yes' 
AND parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN parse_datetime('2022-05-10:00:00:00','yyyy-MM-dd:HH:mm:ss')
AND parse_datetime('2022-08-10:00:00:00','yyyy-MM-dd:HH:mm:ss')
```

**注意**  
您可以修改日期范围以满足您的需要。
也可以使用这些查询示例进行安全监控。您可以查看意外或未经授权的 IP 地址或请求者发出的 `PutObject` 或 `GetObject` 调用的结果，以及确定向存储桶发出的任何匿名请求。
此查询仅从启用了日志记录的时间检索信息。
如果您使用 AWS CloudTrail 日志，请参阅 [使用 CloudTrail 识别对 S3 对象的访问权限](cloudtrail-request-identification.md#cloudtrail-identification-object-access)。