Files
wwjcloud-nest-v1/wwjcloud-nest-v1/wwjcloud/libs/wwjcloud-ai/src/safe/services/ai-audit.service.ts

800 lines
20 KiB
TypeScript
Raw Normal View History

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;
}