800 lines
20 KiB
TypeScript
800 lines
20 KiB
TypeScript
|
|
import { Injectable, Logger } from '@nestjs/common';
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* AI Audit Service - AI 审计服务
|
|||
|
|
*
|
|||
|
|
* 职责:
|
|||
|
|
* - 记录和跟踪安全事件
|
|||
|
|
* - 生成审计报告
|
|||
|
|
* - 合规性检查
|
|||
|
|
* - 安全日志管理
|
|||
|
|
*/
|
|||
|
|
@Injectable()
|
|||
|
|
export class AiAuditService {
|
|||
|
|
private readonly logger = new Logger(AiAuditService.name);
|
|||
|
|
private readonly auditLogs: AuditLog[] = [];
|
|||
|
|
private readonly complianceRules: ComplianceRule[] = [];
|
|||
|
|
|
|||
|
|
constructor() {
|
|||
|
|
this.initializeComplianceRules();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 记录审计事件
|
|||
|
|
*/
|
|||
|
|
async logAuditEvent(event: AuditEvent): Promise<void> {
|
|||
|
|
this.logger.debug(`Logging audit event: ${event.type}`);
|
|||
|
|
|
|||
|
|
const auditLog: AuditLog = {
|
|||
|
|
id: this.generateAuditId(),
|
|||
|
|
timestamp: Date.now(),
|
|||
|
|
event,
|
|||
|
|
severity: this.determineSeverity(event),
|
|||
|
|
category: this.categorizeEvent(event),
|
|||
|
|
compliance: await this.checkCompliance(event),
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
this.auditLogs.push(auditLog);
|
|||
|
|
|
|||
|
|
// 保持最近 10000 条审计日志
|
|||
|
|
if (this.auditLogs.length > 10000) {
|
|||
|
|
this.auditLogs.splice(0, this.auditLogs.length - 10000);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果是高严重性事件,立即处理
|
|||
|
|
if (auditLog.severity === 'high' || auditLog.severity === 'critical') {
|
|||
|
|
await this.handleHighSeverityEvent(auditLog);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 生成审计报告
|
|||
|
|
*/
|
|||
|
|
async generateAuditReport(options: AuditReportOptions): Promise<AuditReport> {
|
|||
|
|
this.logger.log('Generating audit report');
|
|||
|
|
|
|||
|
|
const startTime =
|
|||
|
|
options.startTime || Date.now() - 30 * 24 * 60 * 60 * 1000; // 默认30天
|
|||
|
|
const endTime = options.endTime || Date.now();
|
|||
|
|
|
|||
|
|
// 过滤指定时间范围内的日志
|
|||
|
|
const filteredLogs = this.auditLogs.filter(
|
|||
|
|
(log) => log.timestamp >= startTime && log.timestamp <= endTime,
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
// 按类型分组统计
|
|||
|
|
const eventsByType = this.groupEventsByType(filteredLogs);
|
|||
|
|
const eventsBySeverity = this.groupEventsBySeverity(filteredLogs);
|
|||
|
|
const eventsByCategory = this.groupEventsByCategory(filteredLogs);
|
|||
|
|
|
|||
|
|
// 合规性分析
|
|||
|
|
const complianceAnalysis = await this.analyzeCompliance(filteredLogs);
|
|||
|
|
|
|||
|
|
// 安全趋势分析
|
|||
|
|
const securityTrends = this.analyzeSecurityTrends(filteredLogs);
|
|||
|
|
|
|||
|
|
// 异常检测
|
|||
|
|
const anomalies = this.detectAnomalies(filteredLogs);
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
id: this.generateReportId(),
|
|||
|
|
timestamp: Date.now(),
|
|||
|
|
period: { startTime, endTime },
|
|||
|
|
summary: {
|
|||
|
|
totalEvents: filteredLogs.length,
|
|||
|
|
criticalEvents: eventsBySeverity.critical || 0,
|
|||
|
|
highSeverityEvents: eventsBySeverity.high || 0,
|
|||
|
|
complianceScore: complianceAnalysis.overallScore,
|
|||
|
|
},
|
|||
|
|
statistics: {
|
|||
|
|
eventsByType,
|
|||
|
|
eventsBySeverity,
|
|||
|
|
eventsByCategory,
|
|||
|
|
},
|
|||
|
|
complianceAnalysis,
|
|||
|
|
securityTrends,
|
|||
|
|
anomalies,
|
|||
|
|
recommendations: this.generateRecommendations(
|
|||
|
|
filteredLogs,
|
|||
|
|
complianceAnalysis,
|
|||
|
|
),
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 执行合规性检查
|
|||
|
|
*/
|
|||
|
|
async performComplianceCheck(): Promise<ComplianceCheckResult> {
|
|||
|
|
this.logger.log('Performing compliance check');
|
|||
|
|
|
|||
|
|
const results: ComplianceRuleResult[] = [];
|
|||
|
|
|
|||
|
|
for (const rule of this.complianceRules) {
|
|||
|
|
const result = await this.evaluateComplianceRule(rule);
|
|||
|
|
results.push(result);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const overallScore = this.calculateComplianceScore(results);
|
|||
|
|
const violations = results.filter((r) => !r.compliant);
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
timestamp: Date.now(),
|
|||
|
|
overallScore,
|
|||
|
|
status: this.determineComplianceStatus(overallScore),
|
|||
|
|
results,
|
|||
|
|
violations,
|
|||
|
|
recommendations: this.generateComplianceRecommendations(violations),
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 搜索审计日志
|
|||
|
|
*/
|
|||
|
|
async searchAuditLogs(
|
|||
|
|
criteria: AuditSearchCriteria,
|
|||
|
|
): Promise<AuditSearchResult> {
|
|||
|
|
this.logger.debug('Searching audit logs', criteria);
|
|||
|
|
|
|||
|
|
let filteredLogs = [...this.auditLogs];
|
|||
|
|
|
|||
|
|
// 按时间范围过滤
|
|||
|
|
if (criteria.startTime) {
|
|||
|
|
filteredLogs = filteredLogs.filter(
|
|||
|
|
(log) => log.timestamp >= criteria.startTime!,
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
if (criteria.endTime) {
|
|||
|
|
filteredLogs = filteredLogs.filter(
|
|||
|
|
(log) => log.timestamp <= criteria.endTime!,
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 按事件类型过滤
|
|||
|
|
if (criteria.eventType) {
|
|||
|
|
filteredLogs = filteredLogs.filter(
|
|||
|
|
(log) => log.event.type === criteria.eventType,
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 按严重性过滤
|
|||
|
|
if (criteria.severity) {
|
|||
|
|
filteredLogs = filteredLogs.filter(
|
|||
|
|
(log) => log.severity === criteria.severity,
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 按用户过滤
|
|||
|
|
if (criteria.userId) {
|
|||
|
|
filteredLogs = filteredLogs.filter(
|
|||
|
|
(log) => log.event.userId === criteria.userId,
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 按关键词搜索
|
|||
|
|
if (criteria.keyword) {
|
|||
|
|
const keyword = criteria.keyword.toLowerCase();
|
|||
|
|
filteredLogs = filteredLogs.filter(
|
|||
|
|
(log) =>
|
|||
|
|
log.event.description.toLowerCase().includes(keyword) ||
|
|||
|
|
log.event.type.toLowerCase().includes(keyword),
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 分页
|
|||
|
|
const total = filteredLogs.length;
|
|||
|
|
const page = criteria.page || 1;
|
|||
|
|
const limit = criteria.limit || 50;
|
|||
|
|
const offset = (page - 1) * limit;
|
|||
|
|
const paginatedLogs = filteredLogs.slice(offset, offset + limit);
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
logs: paginatedLogs,
|
|||
|
|
pagination: {
|
|||
|
|
total,
|
|||
|
|
page,
|
|||
|
|
limit,
|
|||
|
|
totalPages: Math.ceil(total / limit),
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 导出审计数据
|
|||
|
|
*/
|
|||
|
|
async exportAuditData(
|
|||
|
|
format: 'json' | 'csv' | 'xml',
|
|||
|
|
options: ExportOptions,
|
|||
|
|
): Promise<string> {
|
|||
|
|
this.logger.log(`Exporting audit data in ${format} format`);
|
|||
|
|
|
|||
|
|
const startTime =
|
|||
|
|
options.startTime || Date.now() - 30 * 24 * 60 * 60 * 1000;
|
|||
|
|
const endTime = options.endTime || Date.now();
|
|||
|
|
|
|||
|
|
const filteredLogs = this.auditLogs.filter(
|
|||
|
|
(log) => log.timestamp >= startTime && log.timestamp <= endTime,
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
switch (format) {
|
|||
|
|
case 'json':
|
|||
|
|
return JSON.stringify(filteredLogs, null, 2);
|
|||
|
|
case 'csv':
|
|||
|
|
return this.convertToCsv(filteredLogs);
|
|||
|
|
case 'xml':
|
|||
|
|
return this.convertToXml(filteredLogs);
|
|||
|
|
default:
|
|||
|
|
throw new Error(`Unsupported export format: ${format}`);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 初始化合规性规则
|
|||
|
|
*/
|
|||
|
|
private initializeComplianceRules(): void {
|
|||
|
|
this.complianceRules.push(
|
|||
|
|
{
|
|||
|
|
id: 'GDPR_DATA_ACCESS',
|
|||
|
|
name: 'GDPR Data Access Logging',
|
|||
|
|
description: 'All personal data access must be logged',
|
|||
|
|
category: 'data_protection',
|
|||
|
|
severity: 'high',
|
|||
|
|
evaluator: this.evaluateDataAccessLogging.bind(this),
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: 'SOX_FINANCIAL_ACCESS',
|
|||
|
|
name: 'SOX Financial Data Access Control',
|
|||
|
|
description:
|
|||
|
|
'Financial data access must be properly controlled and audited',
|
|||
|
|
category: 'financial_compliance',
|
|||
|
|
severity: 'critical',
|
|||
|
|
evaluator: this.evaluateFinancialAccessControl.bind(this),
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: 'ISO27001_INCIDENT_RESPONSE',
|
|||
|
|
name: 'ISO 27001 Incident Response',
|
|||
|
|
description:
|
|||
|
|
'Security incidents must be properly documented and responded to',
|
|||
|
|
category: 'security_management',
|
|||
|
|
severity: 'high',
|
|||
|
|
evaluator: this.evaluateIncidentResponse.bind(this),
|
|||
|
|
},
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 生成审计ID
|
|||
|
|
*/
|
|||
|
|
private generateAuditId(): string {
|
|||
|
|
return `AUDIT_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 生成报告ID
|
|||
|
|
*/
|
|||
|
|
private generateReportId(): string {
|
|||
|
|
return `REPORT_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 确定事件严重性
|
|||
|
|
*/
|
|||
|
|
private determineSeverity(
|
|||
|
|
event: AuditEvent,
|
|||
|
|
): 'low' | 'medium' | 'high' | 'critical' {
|
|||
|
|
const severityMap: Record<string, 'low' | 'medium' | 'high' | 'critical'> =
|
|||
|
|
{
|
|||
|
|
LOGIN_SUCCESS: 'low',
|
|||
|
|
LOGIN_FAILURE: 'medium',
|
|||
|
|
PERMISSION_DENIED: 'medium',
|
|||
|
|
DATA_ACCESS: 'medium',
|
|||
|
|
DATA_MODIFICATION: 'high',
|
|||
|
|
SECURITY_VIOLATION: 'high',
|
|||
|
|
SYSTEM_BREACH: 'critical',
|
|||
|
|
DATA_BREACH: 'critical',
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return severityMap[event.type] || 'medium';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 事件分类
|
|||
|
|
*/
|
|||
|
|
private categorizeEvent(event: AuditEvent): string {
|
|||
|
|
const categoryMap: Record<string, string> = {
|
|||
|
|
LOGIN_SUCCESS: 'authentication',
|
|||
|
|
LOGIN_FAILURE: 'authentication',
|
|||
|
|
PERMISSION_DENIED: 'authorization',
|
|||
|
|
DATA_ACCESS: 'data_access',
|
|||
|
|
DATA_MODIFICATION: 'data_modification',
|
|||
|
|
SECURITY_VIOLATION: 'security',
|
|||
|
|
SYSTEM_BREACH: 'security',
|
|||
|
|
DATA_BREACH: 'security',
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return categoryMap[event.type] || 'general';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 检查合规性
|
|||
|
|
*/
|
|||
|
|
private async checkCompliance(event: AuditEvent): Promise<ComplianceStatus> {
|
|||
|
|
// 简化的合规性检查
|
|||
|
|
const requiredFields = ['userId', 'timestamp', 'type', 'description'];
|
|||
|
|
const hasRequiredFields = requiredFields.every(
|
|||
|
|
(field) => event[field as keyof AuditEvent],
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
compliant: hasRequiredFields,
|
|||
|
|
violations: hasRequiredFields ? [] : ['Missing required fields'],
|
|||
|
|
rules: ['BASIC_AUDIT_REQUIREMENTS'],
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 处理高严重性事件
|
|||
|
|
*/
|
|||
|
|
private async handleHighSeverityEvent(auditLog: AuditLog): Promise<void> {
|
|||
|
|
this.logger.warn(`High severity audit event detected`, auditLog);
|
|||
|
|
|
|||
|
|
// 这里应该实现高严重性事件的处理逻辑
|
|||
|
|
// 例如:发送告警、通知管理员、触发自动响应等
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 按类型分组事件
|
|||
|
|
*/
|
|||
|
|
private groupEventsByType(logs: AuditLog[]): Record<string, number> {
|
|||
|
|
const groups: Record<string, number> = {};
|
|||
|
|
|
|||
|
|
logs.forEach((log) => {
|
|||
|
|
groups[log.event.type] = (groups[log.event.type] || 0) + 1;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return groups;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 按严重性分组事件
|
|||
|
|
*/
|
|||
|
|
private groupEventsBySeverity(logs: AuditLog[]): Record<string, number> {
|
|||
|
|
const groups: Record<string, number> = {};
|
|||
|
|
|
|||
|
|
logs.forEach((log) => {
|
|||
|
|
groups[log.severity] = (groups[log.severity] || 0) + 1;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return groups;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 按类别分组事件
|
|||
|
|
*/
|
|||
|
|
private groupEventsByCategory(logs: AuditLog[]): Record<string, number> {
|
|||
|
|
const groups: Record<string, number> = {};
|
|||
|
|
|
|||
|
|
logs.forEach((log) => {
|
|||
|
|
groups[log.category] = (groups[log.category] || 0) + 1;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return groups;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 分析合规性
|
|||
|
|
*/
|
|||
|
|
private async analyzeCompliance(
|
|||
|
|
logs: AuditLog[],
|
|||
|
|
): Promise<ComplianceAnalysis> {
|
|||
|
|
const compliantLogs = logs.filter((log) => log.compliance.compliant);
|
|||
|
|
const violationLogs = logs.filter((log) => !log.compliance.compliant);
|
|||
|
|
|
|||
|
|
const overallScore =
|
|||
|
|
logs.length > 0 ? (compliantLogs.length / logs.length) * 100 : 100;
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
overallScore: Math.round(overallScore),
|
|||
|
|
compliantEvents: compliantLogs.length,
|
|||
|
|
violationEvents: violationLogs.length,
|
|||
|
|
violationsByRule: this.groupViolationsByRule(violationLogs),
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 按规则分组违规
|
|||
|
|
*/
|
|||
|
|
private groupViolationsByRule(logs: AuditLog[]): Record<string, number> {
|
|||
|
|
const groups: Record<string, number> = {};
|
|||
|
|
|
|||
|
|
logs.forEach((log) => {
|
|||
|
|
log.compliance.violations.forEach((violation) => {
|
|||
|
|
groups[violation] = (groups[violation] || 0) + 1;
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return groups;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 分析安全趋势
|
|||
|
|
*/
|
|||
|
|
private analyzeSecurityTrends(logs: AuditLog[]): SecurityTrend[] {
|
|||
|
|
// 简化的趋势分析
|
|||
|
|
const dailyStats = this.groupLogsByDay(logs);
|
|||
|
|
|
|||
|
|
return [
|
|||
|
|
{
|
|||
|
|
metric: 'daily_events',
|
|||
|
|
values: Object.entries(dailyStats).map(([date, count]) => ({
|
|||
|
|
timestamp: new Date(date).getTime(),
|
|||
|
|
value: count,
|
|||
|
|
})),
|
|||
|
|
trend: 'stable',
|
|||
|
|
},
|
|||
|
|
];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 按天分组日志
|
|||
|
|
*/
|
|||
|
|
private groupLogsByDay(logs: AuditLog[]): Record<string, number> {
|
|||
|
|
const groups: Record<string, number> = {};
|
|||
|
|
|
|||
|
|
logs.forEach((log) => {
|
|||
|
|
const date = new Date(log.timestamp).toISOString().split('T')[0];
|
|||
|
|
groups[date] = (groups[date] || 0) + 1;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return groups;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 检测异常
|
|||
|
|
*/
|
|||
|
|
private detectAnomalies(logs: AuditLog[]): AuditAnomaly[] {
|
|||
|
|
const anomalies: AuditAnomaly[] = [];
|
|||
|
|
|
|||
|
|
// 检测异常高频事件
|
|||
|
|
const eventCounts = this.groupEventsByType(logs);
|
|||
|
|
const avgCount =
|
|||
|
|
Object.values(eventCounts).reduce((sum, count) => sum + count, 0) /
|
|||
|
|
Object.keys(eventCounts).length;
|
|||
|
|
|
|||
|
|
Object.entries(eventCounts).forEach(([type, count]) => {
|
|||
|
|
if (count > avgCount * 3) {
|
|||
|
|
// 超过平均值3倍
|
|||
|
|
anomalies.push({
|
|||
|
|
type: 'high_frequency_event',
|
|||
|
|
description: `Unusually high frequency of ${type} events: ${count}`,
|
|||
|
|
severity: 'medium',
|
|||
|
|
timestamp: Date.now(),
|
|||
|
|
metadata: { eventType: type, count },
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return anomalies;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 生成建议
|
|||
|
|
*/
|
|||
|
|
private generateRecommendations(
|
|||
|
|
logs: AuditLog[],
|
|||
|
|
complianceAnalysis: ComplianceAnalysis,
|
|||
|
|
): string[] {
|
|||
|
|
const recommendations: string[] = [];
|
|||
|
|
|
|||
|
|
if (complianceAnalysis.overallScore < 90) {
|
|||
|
|
recommendations.push(
|
|||
|
|
'Improve compliance by addressing identified violations',
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (complianceAnalysis.violationEvents > 0) {
|
|||
|
|
recommendations.push(
|
|||
|
|
'Review and update security policies to prevent violations',
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const criticalEvents = logs.filter(
|
|||
|
|
(log) => log.severity === 'critical',
|
|||
|
|
).length;
|
|||
|
|
if (criticalEvents > 0) {
|
|||
|
|
recommendations.push(
|
|||
|
|
'Investigate and address critical security events immediately',
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return recommendations;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 评估合规性规则
|
|||
|
|
*/
|
|||
|
|
private async evaluateComplianceRule(
|
|||
|
|
rule: ComplianceRule,
|
|||
|
|
): Promise<ComplianceRuleResult> {
|
|||
|
|
try {
|
|||
|
|
const result = await rule.evaluator();
|
|||
|
|
return {
|
|||
|
|
ruleId: rule.id,
|
|||
|
|
ruleName: rule.name,
|
|||
|
|
compliant: result.compliant,
|
|||
|
|
score: result.score || (result.compliant ? 100 : 0),
|
|||
|
|
violations: result.violations || [],
|
|||
|
|
recommendations: result.recommendations || [],
|
|||
|
|
};
|
|||
|
|
} catch (error) {
|
|||
|
|
this.logger.error(`Failed to evaluate compliance rule ${rule.id}`, error);
|
|||
|
|
return {
|
|||
|
|
ruleId: rule.id,
|
|||
|
|
ruleName: rule.name,
|
|||
|
|
compliant: false,
|
|||
|
|
score: 0,
|
|||
|
|
violations: ['Rule evaluation failed'],
|
|||
|
|
recommendations: ['Review rule implementation'],
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 计算合规性评分
|
|||
|
|
*/
|
|||
|
|
private calculateComplianceScore(results: ComplianceRuleResult[]): number {
|
|||
|
|
if (results.length === 0) return 100;
|
|||
|
|
|
|||
|
|
const totalScore = results.reduce((sum, result) => sum + result.score, 0);
|
|||
|
|
return Math.round(totalScore / results.length);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 确定合规性状态
|
|||
|
|
*/
|
|||
|
|
private determineComplianceStatus(
|
|||
|
|
score: number,
|
|||
|
|
): 'compliant' | 'warning' | 'non_compliant' {
|
|||
|
|
if (score >= 90) return 'compliant';
|
|||
|
|
if (score >= 70) return 'warning';
|
|||
|
|
return 'non_compliant';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 生成合规性建议
|
|||
|
|
*/
|
|||
|
|
private generateComplianceRecommendations(
|
|||
|
|
violations: ComplianceRuleResult[],
|
|||
|
|
): string[] {
|
|||
|
|
const recommendations: string[] = [];
|
|||
|
|
|
|||
|
|
violations.forEach((violation) => {
|
|||
|
|
recommendations.push(...violation.recommendations);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return [...new Set(recommendations)]; // 去重
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 转换为CSV格式
|
|||
|
|
*/
|
|||
|
|
private convertToCsv(logs: AuditLog[]): string {
|
|||
|
|
const headers = [
|
|||
|
|
'ID',
|
|||
|
|
'Timestamp',
|
|||
|
|
'Event Type',
|
|||
|
|
'User ID',
|
|||
|
|
'Description',
|
|||
|
|
'Severity',
|
|||
|
|
'Category',
|
|||
|
|
];
|
|||
|
|
const rows = logs.map((log) => [
|
|||
|
|
log.id,
|
|||
|
|
new Date(log.timestamp).toISOString(),
|
|||
|
|
log.event.type,
|
|||
|
|
log.event.userId || '',
|
|||
|
|
log.event.description,
|
|||
|
|
log.severity,
|
|||
|
|
log.category,
|
|||
|
|
]);
|
|||
|
|
|
|||
|
|
return [headers, ...rows].map((row) => row.join(',')).join('\n');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 转换为XML格式
|
|||
|
|
*/
|
|||
|
|
private convertToXml(logs: AuditLog[]): string {
|
|||
|
|
const xmlLogs = logs
|
|||
|
|
.map(
|
|||
|
|
(log) => `
|
|||
|
|
<log>
|
|||
|
|
<id>${log.id}</id>
|
|||
|
|
<timestamp>${new Date(log.timestamp).toISOString()}</timestamp>
|
|||
|
|
<event>
|
|||
|
|
<type>${log.event.type}</type>
|
|||
|
|
<userId>${log.event.userId || ''}</userId>
|
|||
|
|
<description>${log.event.description}</description>
|
|||
|
|
</event>
|
|||
|
|
<severity>${log.severity}</severity>
|
|||
|
|
<category>${log.category}</category>
|
|||
|
|
</log>
|
|||
|
|
`,
|
|||
|
|
)
|
|||
|
|
.join('');
|
|||
|
|
|
|||
|
|
return `<?xml version="1.0" encoding="UTF-8"?><auditLogs>${xmlLogs}</auditLogs>`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 评估数据访问日志记录
|
|||
|
|
*/
|
|||
|
|
private async evaluateDataAccessLogging(): Promise<ComplianceEvaluationResult> {
|
|||
|
|
// 模拟评估逻辑
|
|||
|
|
return {
|
|||
|
|
compliant: true,
|
|||
|
|
score: 95,
|
|||
|
|
violations: [],
|
|||
|
|
recommendations: [],
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 评估财务访问控制
|
|||
|
|
*/
|
|||
|
|
private async evaluateFinancialAccessControl(): Promise<ComplianceEvaluationResult> {
|
|||
|
|
// 模拟评估逻辑
|
|||
|
|
return {
|
|||
|
|
compliant: true,
|
|||
|
|
score: 90,
|
|||
|
|
violations: [],
|
|||
|
|
recommendations: [],
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 评估事件响应
|
|||
|
|
*/
|
|||
|
|
private async evaluateIncidentResponse(): Promise<ComplianceEvaluationResult> {
|
|||
|
|
// 模拟评估逻辑
|
|||
|
|
return {
|
|||
|
|
compliant: false,
|
|||
|
|
score: 70,
|
|||
|
|
violations: ['Incident response time exceeds policy requirements'],
|
|||
|
|
recommendations: ['Implement automated incident response procedures'],
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 类型定义
|
|||
|
|
export interface AuditEvent {
|
|||
|
|
type: string;
|
|||
|
|
userId?: string;
|
|||
|
|
timestamp: number;
|
|||
|
|
description: string;
|
|||
|
|
metadata?: Record<string, any>;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface AuditLog {
|
|||
|
|
id: string;
|
|||
|
|
timestamp: number;
|
|||
|
|
event: AuditEvent;
|
|||
|
|
severity: 'low' | 'medium' | 'high' | 'critical';
|
|||
|
|
category: string;
|
|||
|
|
compliance: ComplianceStatus;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface ComplianceStatus {
|
|||
|
|
compliant: boolean;
|
|||
|
|
violations: string[];
|
|||
|
|
rules: string[];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface AuditReportOptions {
|
|||
|
|
startTime?: number;
|
|||
|
|
endTime?: number;
|
|||
|
|
includeDetails?: boolean;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface AuditReport {
|
|||
|
|
id: string;
|
|||
|
|
timestamp: number;
|
|||
|
|
period: { startTime: number; endTime: number };
|
|||
|
|
summary: {
|
|||
|
|
totalEvents: number;
|
|||
|
|
criticalEvents: number;
|
|||
|
|
highSeverityEvents: number;
|
|||
|
|
complianceScore: number;
|
|||
|
|
};
|
|||
|
|
statistics: {
|
|||
|
|
eventsByType: Record<string, number>;
|
|||
|
|
eventsBySeverity: Record<string, number>;
|
|||
|
|
eventsByCategory: Record<string, number>;
|
|||
|
|
};
|
|||
|
|
complianceAnalysis: ComplianceAnalysis;
|
|||
|
|
securityTrends: SecurityTrend[];
|
|||
|
|
anomalies: AuditAnomaly[];
|
|||
|
|
recommendations: string[];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface ComplianceAnalysis {
|
|||
|
|
overallScore: number;
|
|||
|
|
compliantEvents: number;
|
|||
|
|
violationEvents: number;
|
|||
|
|
violationsByRule: Record<string, number>;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface SecurityTrend {
|
|||
|
|
metric: string;
|
|||
|
|
values: { timestamp: number; value: number }[];
|
|||
|
|
trend: 'increasing' | 'decreasing' | 'stable';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface AuditAnomaly {
|
|||
|
|
type: string;
|
|||
|
|
description: string;
|
|||
|
|
severity: 'low' | 'medium' | 'high' | 'critical';
|
|||
|
|
timestamp: number;
|
|||
|
|
metadata?: Record<string, any>;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface ComplianceRule {
|
|||
|
|
id: string;
|
|||
|
|
name: string;
|
|||
|
|
description: string;
|
|||
|
|
category: string;
|
|||
|
|
severity: 'low' | 'medium' | 'high' | 'critical';
|
|||
|
|
evaluator: () => Promise<ComplianceEvaluationResult>;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface ComplianceEvaluationResult {
|
|||
|
|
compliant: boolean;
|
|||
|
|
score?: number;
|
|||
|
|
violations?: string[];
|
|||
|
|
recommendations?: string[];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface ComplianceCheckResult {
|
|||
|
|
timestamp: number;
|
|||
|
|
overallScore: number;
|
|||
|
|
status: 'compliant' | 'warning' | 'non_compliant';
|
|||
|
|
results: ComplianceRuleResult[];
|
|||
|
|
violations: ComplianceRuleResult[];
|
|||
|
|
recommendations: string[];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface ComplianceRuleResult {
|
|||
|
|
ruleId: string;
|
|||
|
|
ruleName: string;
|
|||
|
|
compliant: boolean;
|
|||
|
|
score: number;
|
|||
|
|
violations: string[];
|
|||
|
|
recommendations: string[];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface AuditSearchCriteria {
|
|||
|
|
startTime?: number;
|
|||
|
|
endTime?: number;
|
|||
|
|
eventType?: string;
|
|||
|
|
severity?: 'low' | 'medium' | 'high' | 'critical';
|
|||
|
|
userId?: string;
|
|||
|
|
keyword?: string;
|
|||
|
|
page?: number;
|
|||
|
|
limit?: number;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface AuditSearchResult {
|
|||
|
|
logs: AuditLog[];
|
|||
|
|
pagination: {
|
|||
|
|
total: number;
|
|||
|
|
page: number;
|
|||
|
|
limit: number;
|
|||
|
|
totalPages: number;
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface ExportOptions {
|
|||
|
|
startTime?: number;
|
|||
|
|
endTime?: number;
|
|||
|
|
includeMetadata?: boolean;
|
|||
|
|
}
|