# 审计日志

Alluxio 审计日志是安全与合规的关键组件，它提供了系统内执行操作的详细、结构化记录。它可以帮助您监控敏感数据访问、跟踪管理命令并满足法规要求。

审计日志以结构化的 **JSON** 格式生成，便于解析并与 Splunk 或 ELK Stack 等分析工具集成。日志记录涵盖两大类操作：

1. **管理操作**：用于管理任务的 API 请求，例如加载数据或管理挂载点。
2. **数据访问**：通过各种接口（包括 **S3、HDFS、FUSE 和 Python SDK**）执行的读写操作。

本指南介绍了如何为这两类操作启用和配置审计日志记录。

## 启用和配置审计日志记录

审计日志记录是分别为管理操作和数据访问接口配置的。

### 步骤 1：启用管理操作审计日志记录

此配置记录所有管理 API 请求。此功能**默认启用**。

审计日志存储在 Gateway 主机的 `/mnt/alluxio/logs/gateway/audit/` 目录中，并存储在 Gateway pod 的 `/opt/alluxio/logs/audit/` 目录中。要修改日志位置或其他设置，您可以更新 `alluxio-cluster.yaml` 文件中的 `gateway` 部分：

```yaml
spec:
  gateway:
    enabled: true
    log:
      level: info
      type: hostPath
      hostPath: /mnt/alluxio/logs/gateway
      size: 1Gi
      storageClass: standard
    auditLog:
      enabled: true
```

### 步骤 2：启用数据访问审计日志记录

此配置记录来自使用 S3、HDFS 和 FUSE 接口的客户端的数据访问操作。

要启用它，请将以下属性添加到您的 `alluxio-cluster.yaml` 文件中：

```yaml
spec:
  properties:
    alluxio.audit.logging.enabled: "true"
    alluxio.audit.logging.poll.interval: "5s"
```

* 默认情况下，数据访问审计日志存储在 `${audit.logs.dir}` 目录中。您可以通过修改 `conf/log4j2.xml` 文件中的 `*_AUDIT_LOG` appender 来自定义此位置。
* 对于 3.3.3 及以后的 operator 版本，所需的审计日志 appender 默认包含在 `log4j2.xml` 中。对于更早的版本，您必须手动将日志记录器配置添加到 `alluxio-configmap` 的 `log4j2.xml` 部分。

| 属性                                    | 描述                           | 默认值     |
| ------------------------------------- | ---------------------------- | ------- |
| `alluxio.audit.logging.enabled`       | 设置为 `true` 以启用数据访问操作的审计日志记录。 | `false` |
| `alluxio.audit.logging.poll.interval` | 将审计日志写入文件的间隔。                | `5s`    |

## 通过 REST API 和 CLI 进行动态配置

审计日志和访问日志均支持通过 REST API 或 User CLI 进行动态配置。修改在集群范围内生效，并在集群重启后保持不变。

{% hint style="info" %}
如需启用审计日志或访问日志，请先与售后支持讨论日志保留策略。
{% endhint %}

### REST API

使用 `LogConfigEntity` 同时控制两种日志。

创建 `LogConfigEntity.json` 文件：

```json
{
  "accessLogEnabled": false,
  "auditLogEnabled": false,
  "bfRefreshInterval": "6000s",
  "logPollInterval": "5s"
}
```

| 字段                  | 描述                              | 默认值     |
| ------------------- | ------------------------------- | ------- |
| `accessLogEnabled`  | 是否启用访问日志。                       | `false` |
| `auditLogEnabled`   | 是否启用审计日志。                       | `false` |
| `bfRefreshInterval` | 访问日志的布隆过滤器刷新周期。推荐设置为 100 分钟。    | —       |
| `logPollInterval`   | 访问日志和审计日志从内存写入磁盘的时间间隔。推荐设置为 5s。 | —       |

应用配置：

```shell
jq -n --rawfile conf ./LogConfigEntity.json '{key: "LogConfigEntity", conf: $conf}' | curl -sS 'http://<coordinator_host>:19999/api/v1/conf' -X PUT -H 'Content-Type: application/json' --data @-
```

验证配置：

```shell
curl -sS 'http://<coordinator_host>:19999/api/v1/conf?key=LogConfigEntity' | jq
```

### User CLI

`alluxio log` 命令组用于管理审计日志和访问日志的动态配置。

#### log access

管理访问日志的开启状态以及布隆过滤器的刷新间隔。

```shell
bin/alluxio log access [--enable <true|false>] [--bfRefreshInterval <duration>]
```

* `--enable`：启用或禁用访问日志。可选值为 `true` 或 `false`。
* `--bfRefreshInterval`：布隆过滤器的刷新时间间隔。支持带单位的时间格式，例如 `30s`、`10min`、`1h`。推荐设置为 100 分钟。

示例：

```shell
# 启用访问日志，并设置刷新间隔为 30 分钟
bin/alluxio log access --enable=true --bfRefreshInterval=30min

# 禁用访问日志
bin/alluxio log access --enable=false
```

#### log audit

管理审计日志的开启状态。

```shell
bin/alluxio log audit [--enable <true|false>]
```

* `--enable`：启用或禁用审计日志。可选值为 `true` 或 `false`。

示例：

```shell
# 启用审计日志
bin/alluxio log audit --enable=true

# 禁用审计日志
bin/alluxio log audit --enable=false
```

#### log status

展示当前集群中审计日志和访问日志的所有相关配置状态。该命令不接受任何参数。

```shell
bin/alluxio log status
```

示例输出：

```console
Access Log Enabled: true
Audit Log Enabled: false
Bloom Filter Refresh Interval: 3600000ms
Log Poll Interval: 5000ms
```

{% hint style="info" %}

* **持久化**：通过 `log access` 和 `log audit` 所做的修改在集群重启后依然有效。
* **生效范围**：配置修改后，相关进程会通过动态配置机制感知并应用新设置。
  {% endhint %}

## 理解审计日志格式

每个审计日志条目都是一个结构化的 JSON 对象，具有一致的模式，便于处理和分析。

### 审计日志模式

| 字段               | 类型            | 描述                                                                                            |
| ---------------- | ------------- | --------------------------------------------------------------------------------------------- |
| `timestamp`      | 字符串           | ISO 8601 格式的操作时间戳，带时区（例如，`2025-08-02T09:12:30.123456+08:00[Asia/Singapore]`）。                 |
| `user`           | JSON 对象       | 有关执行操作的用户的信息，包含 `name`（用户标识符）、`group`（组列表）和 `role`（角色列表）。                                     |
| `interface`      | 字符串           | 使用的访问接口。可能的值：`S3`、`FUSE`、`HADOOP_FS` 和 `GATEWAY`。`GATEWAY` 代表管理操作。                            |
| `operation`      | 字符串 / JSON 对象 | 具体的操作或 API 名称。对于数据访问接口，这是一个字符串（例如，`GetObject`）。对于 Gateway，这是一个包含 `method` 和 `path` 的 JSON 对象。 |
| `resource`       | JSON 对象 / 字符串 | 涉及的资源。内容因接口而异。例如，S3 操作包括 `bucket` 和 `object`，而 HDFS 操作包括 `path`。                              |
| `status`         | 字符串           | 操作的结果，例如 `SUCCESS`、`FAILURE`、`FORBIDDEN`、`ALLOWED` 或 `UNAUTHORIZED`。                          |
| `errorMessage`   | 字符串           | 如果操作失败，此字段包含错误消息。                                                                             |
| `clientIp`       | 字符串           | 发起请求的客户端的 IP 地址。                                                                              |
| `clientPort`     | 字符串           | 客户端连接的源端口号。                                                                                   |
| `reqContentLen`  | 字符串           | 请求的内容长度（如果适用）。                                                                                |
| `respContentLen` | 字符串           | 响应的内容长度（如果适用）。                                                                                |
| `requestId`      | 字符串           | 请求的唯一标识符，主要由 Gateway 使用。                                                                      |

### 日志示例

#### 示例 1：管理操作

用户通过 API 列出所有挂载点。

```json
{
    "timestamp": "2025-07-29T15:21:21.846416+08:00",
    "user": {
        "name": "super-user",
        "group": ["Storage"],
        "role": ["SuperAdmin"]
    },
    "interface": "GATEWAY",
    "operation": {
        "method": "GET",
        "path": "/api/v1/mount"
    },
    "resource": {
        "parameters": {},
        "body": {}
    },
    "status": "SUCCESS",
    "errorMessage": "",
    "clientIp": "192.168.124.21",
    "requestId": "b3c9efe4-35aa-42d0-8690-ab044126452c"
}
```

#### 示例 2：S3 API 数据访问

用户使用 S3 客户端获取一个对象。

```json
{
    "timestamp": "2025-07-24T14:45:59.911358+08:00[Asia/Shanghai]",
    "user": {
        "name": "search-admin@alluxio.com",
        "group": ["Search"],
        "role": ["GroupAdmin"]
    },
    "interface": "S3",
    "operation": "GetObject",
    "resource": {
        "bucket": "testbucket",
        "object": "hosts3",
        "sourcePath": null,
        "prefix": null,
        "path": null
    },
    "status": "SUCCESS",
    "errorMessage": null,
    "clientIp": "127.0.0.1",
    "clientPort": "60304",
    "reqContentLen": "None",
    "respContentLen": "268",
    "requestId": null
}
```

#### 示例 3：HDFS API 数据访问

用户使用 Hadoop 客户端打开一个文件。

```json
{
    "timestamp": "2025-07-24T16:37:28.71468+08:00[Asia/Shanghai]",
    "user": {
        "name": "search-admin@alluxio.com",
        "group": ["Search"],
        "role": ["GroupAdmin"]
    },
    "interface": "HADOOP_FS",
    "operation": "HadoopFs.Open",
    "resource": {
        "path": "/testbucket/hosts3"
    },
    "status": "ALLOWED",
    "clientIp": "192.168.1.104"
}
```

#### 示例 4：FUSE 数据访问

匿名用户从 FUSE 挂载点读取文件（`cat testbucket/hosts`）。

```json
{
    "timestamp": "2025-07-24T14:48:14.566555+08:00[Asia/Shanghai]",
    "user": {
        "name": "anonymous",
        "group": null,
        "role": null
    },
    "interface": "FUSE",
    "operation": "Fuse.Open",
    "resource": {
        "path": "/testbucket/hosts"
    },
    "status": "SUCCESS",
    "errorMessage": null,
    "clientIp": null,
    "clientPort": null,
    "reqContentLen": null,
    "respContentLen": null,
    "requestId": null
}
{
    "timestamp": "2025-07-24T14:48:14.650128+08:00[Asia/Shanghai]",
    "user": {
        "name": "anonymous",
        "group": null,
        "role": null
    },
    "interface": "FUSE",
    "operation": "Fuse.Read",
    "resource": {
        "fd": 3,
        "path": "/testbucket/hosts"
    },
    "status": "SUCCESS",
    "errorMessage": null,
    "clientIp": null,
    "clientPort": null,
    "reqContentLen": null,
    "respContentLen": "268",
    "requestId": null
}
{
    "timestamp": "2025-07-24T14:48:14.650381+08:00[Asia/Shanghai]",
    "user": {
        "name": "anonymous",
        "group": null,
        "role": null
    },
    "interface": "FUSE",
    "operation": "Fuse.Release",
    "resource": {
        "path": "/testbucket/hosts"
    },
    "status": "SUCCESS",
    "errorMessage": null,
    "clientIp": null,
    "clientPort": null,
    "reqContentLen": null,
    "respContentLen": null,
    "requestId": null
}
```

#### 示例 5：Python SDK 数据访问

用户通过 Python SDK 删除文件。

```json
{
    "timestamp": "2025-07-24T15:42:59.002146+08:00[Asia/Shanghai]",
    "user": {
        "name": "anonymous",
        "group": null,
        "role": null
    },
    "interface": "HTTP",
    "operation": "HttpServer.Rm",
    "resource": {
        "path": null,
        "srcPath": null,
        "dstPath": null,
        "ufsFullPath": "/testbucket/test.txt"
    },
    "status": "SUCCESS",
    "errorMessage": null,
    "clientIp": "0:0:0:0:0:0:0:1",
    "clientPort": "48304",
    "reqContentLen": null,
    "respContentLen": "38",
    "requestId": null
}
```

## 附录：按接口审计的操作

### 管理操作

所有管理 API 调用都会被审计。

### S3 API

所有 S3 API 调用都会被审计。对于像 `DeleteObjects` 这样的批量操作，会为每个子操作生成一个单独的日志条目。

### Hadoop 文件系统 (HDFS) API

以下 Hadoop 文件系统 API 操作会被审计：

* `HadoopFs.Authenticate`
* `HadoopFs.Create`
* `HadoopFs.Append`
* `HadoopFs.Delete`
* `HadoopFs.GetFileStatus`
* `HadoopFs.GetFileBlockLocations`
* `HadoopFs.ListStatus`
* `HadoopFs.Mkdirs`
* `HadoopFs.Open`
* `HadoopFs.Rename`
* `HadoopFs.SetOwner`
* `HadoopFs.SetPermission`

**关于 `clientIp` 的说明**：对于 Hadoop 文件系统接口，会获取一个 IPv4 地址。如果机器有多个网卡，可能无法确定哪个网卡用于该操作。建议依赖 `user` 来识别操作者。

### FUSE API

以下 FUSE 操作会被审计：

* `Fuse.Create`
* `Fuse.Open`
* `Fuse.Opendir`
* `Fuse.Release`
* `Fuse.Mkdir`
* `Fuse.Rmdir`
* `Fuse.Unlink`
* `Fuse.Rename`
* `Fuse.Chown`
* `Fuse.Chmod`
* `Fuse.Truncate`
* `Fuse.Symlink`
* `Fuse.Link`

**关于 FUSE 日志记录的说明**：典型的文件访问序列包括 `Fuse.Open`，然后是 `read` 或 `write` 操作，最后是 `Fuse.Release`。为了避免生成过多的日志，单个的 `read` 和 `write` 调用不会被审计。相反，关于是否发生读或写的信息会作为 `Fuse.Release` 事件的一部分被记录下来。

### HTTP Server（由 Python SDK 使用）

以下 HTTP server 操作会被审计：

* `HttpServer.GetFile`
* `HttpServer.WriteFile`
* `HttpServer.FilterParquetFile`
* `HttpServer.FilterParquetFileRaw`
* `HttpServer.Mkdir`
* `HttpServer.Touch`
* `HttpServer.Mv`
* `HttpServer.Rm`
* `HttpServer.Copy`
* `HttpServer.ListFiles`
* `HttpServer.GetFileStatus`
* `HttpServer.Load`
* `HttpServer.Tail`
* `HttpServer.Head`
* `HttpServer.GetRange`

像 `HealthCheck`、`GetCache`、`PostCache` 这样的操作不会被审计。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://documentation.alluxio.io/ee-ai-cn/administration/audit-access-logs/audit-log.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
