# 审计系统配置指南

> **重要**: 本文档说明审计系统的所有配置项，生产环境部署前必须完成配置

---

## 🔐 环境变量配置

### 必需配置

在根目录 `.env` 文件中添加以下配置（本项目使用统一的环境变量管理）：

```bash
# =====================================================
# 审计系统配置
# =====================================================

# HMAC 签名密钥（生产环境必须修改）
AUDIT_HMAC_SECRET=your-secure-hmac-secret-key-min-32-chars

# 区域标识（cn/us/eu/ap）
AUDIT_DEFAULT_REGION=cn

# 租户ID（多租户场景）
AUDIT_DEFAULT_TENANT_ID=default
```

### 可选配置

```bash
# 完整性检查间隔（毫秒，默认: 每小时）
AUDIT_INTEGRITY_CHECK_INTERVAL=3600000

# 告警邮件接收人（逗号分隔）
AUDIT_ALERT_RECIPIENTS=auditor@company.com,security@company.com

# 是否启用实时告警（默认: true）
AUDIT_ENABLE_REALTIME_ALERTS=true

# 批量告警检查间隔（毫秒，默认: 每小时）
AUDIT_BATCH_ALERT_INTERVAL=3600000

# 最大查询时间跨度（天，默认: 90天）
AUDIT_MAX_QUERY_DAYS=90

# 财务日志最大查询跨度（天，默认: 365天）
AUDIT_MAX_FINANCIAL_QUERY_DAYS=365

# 最大导出记录数（默认: 100000）
AUDIT_MAX_EXPORT_COUNT=100000
```

---

## 🔑 HMAC 密钥生成

### 生成强密钥

生产环境必须使用安全的随机密钥（至少32字符）：

```bash
# 方法 1: 使用 OpenSSL
openssl rand -base64 32

# 方法 2: 使用 Node.js
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"

# 方法 3: 使用 UUID
node -e "console.log(require('uuid').v4() + require('uuid').v4())"
```

### 密钥管理

⚠️ **安全注意事项**：

- ❌ **不要** 将密钥提交到 Git 仓库
- ❌ **不要** 在代码中硬编码密钥
- ✅ **必须** 使用环境变量
- ✅ **必须** 在生产环境使用强密钥
- ✅ **建议** 定期轮换密钥（每年）
- ✅ **建议** 使用密钥管理服务（AWS KMS、Azure Key Vault）

### 密钥轮换

如果需要更新 HMAC 密钥：

1. **生成新密钥**
2. **同时支持新旧密钥验证**（过渡期）
3. **重新签名旧日志**（可选）
4. **移除旧密钥**

```typescript
// 示例：支持多个密钥验证
const secrets = [
  process.env.AUDIT_HMAC_SECRET,      // 当前密钥
  process.env.AUDIT_HMAC_SECRET_OLD,  // 旧密钥（过渡期）
];

// 验证时尝试所有密钥
for (const secret of secrets) {
  if (verifyWithSecret(data, signature, secret)) {
    return true;
  }
}
```

---

## 🗄️ 数据库配置

### 1. 应用迁移

审计系统包含以下数据库迁移：

```bash
cd backend

# 查看待应用的迁移
npx prisma migrate status

# 应用迁移
npx prisma migrate deploy
```

**关键迁移**：
- `20251215223244_baseline` - 基础 Schema
- `20251219113015_protect_audit_logs` - **保护触发器（防止修改/删除）**

### 2. 验证触发器

迁移后，验证触发器是否正确创建：

```sql
-- 连接到数据库
psql -d ffoa

-- 查看触发器
\dS platform_audit.audit_log

-- 应该看到：
-- prevent_audit_log_delete
-- allow_audit_log_archiving
-- prevent_audit_db_change_update
-- prevent_audit_db_change_delete
-- prevent_audit_sensitive_update
-- prevent_audit_sensitive_delete
```

### 3. 测试保护机制

```sql
-- 尝试更新（应该失败）
UPDATE platform_audit.audit_log SET who = 'test' WHERE id = '...';
-- ❌ ERROR: Audit logs are immutable and cannot be modified

-- 尝试删除（应该失败）
DELETE FROM platform_audit.audit_log WHERE id = '...';
-- ❌ ERROR: Audit logs are immutable and cannot be deleted

-- 归档操作（应该成功）
UPDATE platform_audit.audit_log SET archived_at = NOW() WHERE id = '...';
-- ✅ SUCCESS: Only archivedAt can be updated
```

---

## 📊 权限配置

### 审计相关权限点

在权限系统中添加以下权限：

```sql
-- 基础审计权限
INSERT INTO platform_iam.permissions (code, name, description, resource, action) VALUES
('audit:read', '查看审计日志', '查看普通审计日志', 'audit', 'read'),
('audit:read:financial', '查看财务审计日志', '查看财务相关审计日志', 'audit', 'read'),
('audit:read:sensitive', '查看敏感审计日志', '查看敏感操作审计日志', 'audit', 'read'),
('audit:trace', '追踪请求链路', '按 traceId 追踪完整请求链路', 'audit', 'read'),
('audit:statistics', '查看审计统计', '查看审计统计和分析', 'audit', 'read'),
('audit:verify', '验证数据完整性', '验证审计日志完整性', 'audit', 'verify'),
('audit:export', '导出审计日志', '导出审计日志到文件', 'audit', 'export'),
('audit:admin', '审计管理', '完整性检查、系统配置等管理操作', 'audit', 'admin');

-- 报表权限
INSERT INTO platform_iam.permissions (code, name, description, resource, action) VALUES
('audit:report:sox', '生成 SOX 报表', '生成 SOX 合规审计报表', 'audit', 'report'),
('audit:report:gdpr', '生成 GDPR 报表', '生成 GDPR 数据访问报表', 'audit', 'report'),
('audit:report:anomaly', '生成异常报告', '生成异常操作检测报告', 'audit', 'report');
```

### 角色分配建议

| 角色 | 权限 | 说明 |
|------|------|------|
| **Auditor（审计员）** | `audit:read`, `audit:statistics`, `audit:trace` | 日常审计查看 |
| **Senior Auditor（高级审计员）** | 上述 + `audit:read:financial`, `audit:read:sensitive` | 财务和敏感日志查看 |
| **Compliance Officer（合规官）** | 上述 + `audit:report:*` | 生成合规报表 |
| **Security Admin（安全管理员）** | 上述 + `audit:admin`, `audit:verify`, `audit:export` | 完整管理权限 |

---

## ⚙️ 应用配置

### 注册全局拦截器

确保在 `app.module.ts` 中注册审计拦截器：

```typescript
// backend/src/app.module.ts
import { APP_INTERCEPTOR } from '@nestjs/core';
import { AuditLogInterceptor } from './audit/interceptors/audit-log.interceptor';

@Module({
  providers: [
    {
      provide: APP_INTERCEPTOR,
      useClass: AuditLogInterceptor,
    },
  ],
})
export class AppModule {}
```

---

## ⏰ 定时任务配置

### 完整性检查任务

建议配置以下定时任务：

```typescript
// 每天凌晨 2:00 执行完整性检查
@Cron('0 2 * * *')
async dailyIntegrityCheck() {
  await this.integrityService.performScheduledCheck('DAILY');
}

// 每周日凌晨 3:00 执行完整检查
@Cron('0 3 * * 0')
async weeklyIntegrityCheck() {
  await this.integrityService.performScheduledCheck('WEEKLY');
}

// 每小时执行批量告警检查
@Cron('0 * * * *')
async hourlyAlertCheck() {
  await this.alertService.batchCheckAlerts(region, tenantId);
}
```

### 数据归档任务

```typescript
// 每月 1 号凌晨 4:00 归档旧日志
@Cron('0 4 1 * *')
async monthlyArchive() {
  // 归档 90 天前的日志
  await this.auditService.archiveOldLogs(90);
}
```

---

## 🚨 告警配置

### 告警规则

告警规则在 `alert.service.ts` 中配置：

```typescript
private readonly alertRules = {
  // 高风险操作立即告警
  highRiskActions: [
    AuditAction.DELETE,
    AuditAction.BULK_DELETE,
    AuditAction.ROLE_CHANGE,
    AuditAction.PERMISSION_CHANGE,
    AuditAction.PASSWORD_RESET,
    AuditAction.CONFIG_CHANGE,
    AuditAction.FINANCIAL_CLOSE,
  ],

  // 连续失败告警阈值
  failureThreshold: {
    LOGIN_FAILED: 5,      // 5次登录失败
    CREATE: 10,
    DELETE: 3,
  },

  // 批量操作告警阈值
  bulkOperationThreshold: 100,
};
```

### 告警接收人配置

可以通过以下方式配置告警接收人：

**方式 1: 环境变量**
```bash
AUDIT_ALERT_RECIPIENTS=auditor@company.com,security@company.com,admin@company.com
```

**方式 2: 数据库配置表**
```sql
CREATE TABLE platform_audit.alert_recipients (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  email VARCHAR(255) NOT NULL,
  alert_type VARCHAR(50) NOT NULL,  -- 'FINANCIAL', 'SENSITIVE', 'ALL'
  is_active BOOLEAN DEFAULT true,
  created_at TIMESTAMPTZ DEFAULT NOW()
);
```

---

## 📈 性能配置

### 异步写入优化

```typescript
// 使用队列异步写入（高并发场景）
@Injectable()
export class AuditService {
  private auditQueue: AuditLog[] = [];
  
  async log(dto: CreateAuditLogDto) {
    // 添加到队列
    this.auditQueue.push(dto);
    
    // 批量写入（每100条或每秒）
    if (this.auditQueue.length >= 100) {
      await this.flushQueue();
    }
  }
}
```

### 数据库索引

关键索引已在 Prisma Schema 中定义：

```prisma
@@index([region, tenantId, when])        // 最常用
@@index([tenantId, userId, when])        // 用户历史
@@index([tenantId, entityType, entityId, when])  // 实体历史
@@index([tenantId, isFinancial, when])   // 财务日志
@@index([tenantId, isSensitive, when])   // 敏感日志
```

### 表分区（可选，大数据量场景）

```sql
-- 按月分区（超过 1000 万条记录时考虑）
CREATE TABLE platform_audit.audit_log_2025_01 PARTITION OF platform_audit.audit_log
FOR VALUES FROM ('2025-01-01') TO ('2025-02-01');

CREATE TABLE platform_audit.audit_log_2025_02 PARTITION OF platform_audit.audit_log
FOR VALUES FROM ('2025-02-01') TO ('2025-03-01');
```

---

## 🔄 监控与维护

### 监控指标

建议监控以下指标：

```typescript
// Prometheus 指标
audit_logs_total{region, tenantId, module, action, status}
audit_logs_duration_seconds{module, action}
audit_integrity_checks_total{status}
audit_alerts_total{severity}
audit_log_write_errors_total
```

### 健康检查

审计系统健康检查包含在：

```bash
GET /health/detailed
```

检查项：
- ✅ 审计日志表可访问
- ✅ 最近 24 小时有审计日志写入
- ✅ 最近一次完整性检查通过
- ✅ HMAC 密钥已配置

---

## 📝 配置检查清单

部署前请确认：

### 环境变量
- [ ] `AUDIT_HMAC_SECRET` 已设置为强密钥（≥32字符）
- [ ] `AUDIT_DEFAULT_REGION` 已设置正确
- [ ] `AUDIT_ALERT_RECIPIENTS` 已配置

### 数据库
- [ ] 所有迁移已应用 (`prisma migrate deploy`)
- [ ] 触发器已创建并测试
- [ ] 索引已创建
- [ ] 数据库权限已配置（应用账号只有 INSERT/SELECT）

### 应用
- [ ] `AuditLogInterceptor` 已注册为全局拦截器
- [ ] 关键模块已添加 `@Auditable()` 装饰器
- [ ] 敏感操作已标记 `@Sensitive()`
- [ ] 财务操作已标记 `@Financial()`

### 权限
- [ ] 审计权限点已创建
- [ ] 审计员角色已创建并分配权限
- [ ] 合规官角色已创建（如需要）

### 监控
- [ ] 审计日志写入监控已配置
- [ ] 完整性检查告警已配置
- [ ] 定时任务已启用

---

## 🧪 验证

### 1. 功能验证

```bash
# 1. 执行一个写操作
curl -X POST http://localhost:3001/api/v1/users \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username":"test","email":"test@example.com"}'

# 2. 查看审计日志
curl http://localhost:3001/api/v1/audit/logs?limit=1 \
  -H "Authorization: Bearer $TOKEN"

# 3. 验证完整性
curl -X POST http://localhost:3001/api/v1/audit/verify-integrity \
  -H "Authorization: Bearer $TOKEN"

# 4. 生成 SOX 报表
curl -X POST http://localhost:3001/api/v1/audit/reports/sox \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"startDate":"2025-01-01","endDate":"2025-12-31"}'
```

### 2. 触发器验证

```sql
-- 连接到数据库
psql -d ffoa

-- 尝试修改审计日志（应该失败）
UPDATE platform_audit.audit_log SET who = 'hacker' LIMIT 1;
-- 预期: ERROR: Audit logs are immutable

-- 尝试删除审计日志（应该失败）
DELETE FROM platform_audit.audit_log LIMIT 1;
-- 预期: ERROR: Audit logs are immutable

-- 尝试归档（应该成功）
UPDATE platform_audit.audit_log 
SET archived_at = NOW() 
WHERE when < NOW() - INTERVAL '90 days' 
LIMIT 10;
-- 预期: ✅ 成功更新
```

### 3. 签名验证

```bash
# 验证最近的审计日志签名
curl -X POST http://localhost:3001/api/v1/audit/verify-integrity \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"startDate":"2025-12-19"}'
```

应该返回：
```json
{
  "verified": true,
  "totalRecords": 234,
  "passCount": 234,
  "failCount": 0,
  "failures": []
}
```

---

## 🔧 故障排查

### 问题 1: HMAC 签名验证失败

**症状**: 完整性检查报告 `SIGNATURE_INVALID` 错误

**原因**: 
- HMAC 密钥不一致
- 数据被篡改
- 签名算法版本不匹配

**解决方案**:
```bash
# 1. 检查环境变量
echo $AUDIT_HMAC_SECRET

# 2. 检查日志中是否有密钥警告
grep "default HMAC secret" backend/logs/*.log

# 3. 确保所有实例使用相同密钥
```

### 问题 2: 触发器未生效

**症状**: 仍然可以修改/删除审计日志

**原因**: 迁移未应用或触发器创建失败

**解决方案**:
```bash
# 1. 检查迁移状态
cd backend && npx prisma migrate status

# 2. 应用迁移
npx prisma migrate deploy

# 3. 手动检查触发器
psql -d ffoa -c "\dS platform_audit.audit_log"
```

---

## 🔗 相关文档

- [PRD.md](PRD.md) - 功能需求和合规要求
- [ARCHITECTURE.md](ARCHITECTURE.md) - 架构设计
- [API.md](API.md) - API 接口文档
- [TROUBLESHOOTING.md](TROUBLESHOOTING.md) - 故障排查

---

**最后更新**: 2025-12-19  
**维护者**: FFOA 开发团队
