AI changes to reporting
This commit is contained in:
@@ -60,6 +60,10 @@ dependencies {
|
||||
// Email dependancy for SMTP
|
||||
implementation 'org.springframework.boot:spring-boot-starter-mail'
|
||||
|
||||
// Caching with Caffeine
|
||||
implementation 'org.springframework.boot:spring-boot-starter-cache'
|
||||
implementation 'com.github.ben-manes.caffeine:caffeine'
|
||||
|
||||
// Lombok (optional for reducing boilerplate)
|
||||
compileOnly 'org.projectlombok:lombok'
|
||||
annotationProcessor 'org.projectlombok:lombok'
|
||||
|
||||
88751
scripts/cve-sync.log
88751
scripts/cve-sync.log
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
||||
package com.psg.dlsysinfo.dl_sysinfo_server.config;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.caffeine.CaffeineCacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
public class CacheConfig {
|
||||
|
||||
@Bean
|
||||
public CacheManager cacheManager() {
|
||||
CaffeineCacheManager cacheManager = new CaffeineCacheManager(
|
||||
"complianceSummary",
|
||||
"topVulnerabilities",
|
||||
"vulnerableSoftware"
|
||||
);
|
||||
|
||||
cacheManager.setCaffeine(Caffeine.newBuilder()
|
||||
.maximumSize(1000)
|
||||
.expireAfterWrite(15, TimeUnit.MINUTES));
|
||||
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Caffeine<Object, Object> caffeineConfig() {
|
||||
return Caffeine.newBuilder()
|
||||
.maximumSize(1000)
|
||||
.expireAfterWrite(15, TimeUnit.MINUTES);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.psg.dlsysinfo.dl_sysinfo_server.controller;
|
||||
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.dto.ComplianceSummaryDTO;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.dto.TopVulnerabilityDTO;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.dto.VulnerableSoftwareDTO;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.repository.ClientRepository;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.security.CurrentUser;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.service.ReportingService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/reporting")
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class ReportingController {
|
||||
|
||||
private final ReportingService reportingService;
|
||||
private final ClientRepository clientRepository;
|
||||
|
||||
/**
|
||||
* GET /api/reporting/compliance-summary
|
||||
* Provides high-level security compliance metrics for executive dashboard
|
||||
*/
|
||||
@PreAuthorize("isAuthenticated()")
|
||||
@GetMapping("/compliance-summary")
|
||||
public ResponseEntity<?> getComplianceSummary(@AuthenticationPrincipal CurrentUser user) {
|
||||
try {
|
||||
var client = clientRepository.findByClientIdentifier(user.getClientIdentifier())
|
||||
.orElseThrow(() -> new RuntimeException("Client not found"));
|
||||
|
||||
ComplianceSummaryDTO summary = reportingService.getComplianceSummary(client.getClientId());
|
||||
return ResponseEntity.ok(summary);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to generate compliance summary", e);
|
||||
return ResponseEntity.internalServerError()
|
||||
.body(Map.of("error", "Failed to generate compliance report", "code", 500));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/reporting/top-vulnerabilities
|
||||
* Provides list of most critical vulnerabilities for detailed reporting
|
||||
*/
|
||||
@PreAuthorize("isAuthenticated()")
|
||||
@GetMapping("/top-vulnerabilities")
|
||||
public ResponseEntity<?> getTopVulnerabilities(@AuthenticationPrincipal CurrentUser user) {
|
||||
try {
|
||||
var client = clientRepository.findByClientIdentifier(user.getClientIdentifier())
|
||||
.orElseThrow(() -> new RuntimeException("Client not found"));
|
||||
|
||||
List<TopVulnerabilityDTO> vulnerabilities = reportingService.getTopVulnerabilities(client.getClientId());
|
||||
return ResponseEntity.ok(vulnerabilities);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to fetch top vulnerabilities", e);
|
||||
return ResponseEntity.internalServerError()
|
||||
.body(Map.of("error", "Failed to generate compliance report", "code", 500));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/reporting/vulnerable-software
|
||||
* Identifies software packages posing highest security risk
|
||||
*/
|
||||
@PreAuthorize("isAuthenticated()")
|
||||
@GetMapping("/vulnerable-software")
|
||||
public ResponseEntity<?> getVulnerableSoftware(@AuthenticationPrincipal CurrentUser user) {
|
||||
try {
|
||||
var client = clientRepository.findByClientIdentifier(user.getClientIdentifier())
|
||||
.orElseThrow(() -> new RuntimeException("Client not found"));
|
||||
|
||||
List<VulnerableSoftwareDTO> software = reportingService.getVulnerableSoftware(client.getClientId());
|
||||
return ResponseEntity.ok(software);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to fetch vulnerable software", e);
|
||||
return ResponseEntity.internalServerError()
|
||||
.body(Map.of("error", "Failed to generate compliance report", "code", 500));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.psg.dlsysinfo.dl_sysinfo_server.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ComplianceSummaryDTO {
|
||||
private Long totalDevices;
|
||||
private Long vulnerableDevices;
|
||||
private Long totalVulnerabilities;
|
||||
private Long criticalVulns;
|
||||
private Long highVulns;
|
||||
private Long mediumVulns;
|
||||
private Long lowVulns;
|
||||
private Long totalSoftware;
|
||||
private Long vulnerableSoftware;
|
||||
private LocalDateTime lastUpdated;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.psg.dlsysinfo.dl_sysinfo_server.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TopVulnerabilityDTO {
|
||||
private String cveId;
|
||||
private String title;
|
||||
private String severity;
|
||||
private Double score;
|
||||
private Long affectedDevices;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.psg.dlsysinfo.dl_sysinfo_server.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class VulnerableSoftwareDTO {
|
||||
private String softwareName;
|
||||
private Long totalInstances;
|
||||
private Long vulnerableInstances;
|
||||
private Long totalCves;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.psg.dlsysinfo.dl_sysinfo_server.repository;
|
||||
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.dto.TopVulnerabilityDTO;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.dto.VulnerableSoftwareDTO;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface ReportingRepository extends JpaRepository<com.psg.dlsysinfo.dl_sysinfo_server.entity.Devices, Long> {
|
||||
|
||||
// Compliance Summary Queries
|
||||
|
||||
@Query("SELECT COUNT(DISTINCT d.deviceId) FROM Devices d WHERE d.client.clientId = :clientId")
|
||||
Long countTotalDevices(@Param("clientId") Long clientId);
|
||||
|
||||
@Query("SELECT COUNT(DISTINCT cdv.deviceId) FROM CachedDeviceVuln cdv " +
|
||||
"WHERE cdv.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId)")
|
||||
Long countVulnerableDevices(@Param("clientId") Long clientId);
|
||||
|
||||
@Query("SELECT COUNT(cdv) FROM CachedDeviceVuln cdv " +
|
||||
"WHERE cdv.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId)")
|
||||
Long countTotalVulnerabilities(@Param("clientId") Long clientId);
|
||||
|
||||
@Query("SELECT COUNT(cdv) FROM CachedDeviceVuln cdv " +
|
||||
"WHERE cdv.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId) " +
|
||||
"AND UPPER(cdv.severity) = 'CRITICAL'")
|
||||
Long countCriticalVulnerabilities(@Param("clientId") Long clientId);
|
||||
|
||||
@Query("SELECT COUNT(cdv) FROM CachedDeviceVuln cdv " +
|
||||
"WHERE cdv.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId) " +
|
||||
"AND UPPER(cdv.severity) = 'HIGH'")
|
||||
Long countHighVulnerabilities(@Param("clientId") Long clientId);
|
||||
|
||||
@Query("SELECT COUNT(cdv) FROM CachedDeviceVuln cdv " +
|
||||
"WHERE cdv.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId) " +
|
||||
"AND UPPER(cdv.severity) = 'MEDIUM'")
|
||||
Long countMediumVulnerabilities(@Param("clientId") Long clientId);
|
||||
|
||||
@Query("SELECT COUNT(cdv) FROM CachedDeviceVuln cdv " +
|
||||
"WHERE cdv.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId) " +
|
||||
"AND UPPER(cdv.severity) = 'LOW'")
|
||||
Long countLowVulnerabilities(@Param("clientId") Long clientId);
|
||||
|
||||
@Query("SELECT COUNT(DISTINCT cis.softwareName) FROM CachedInstalledSoftware cis " +
|
||||
"WHERE cis.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId)")
|
||||
Long countTotalSoftware(@Param("clientId") Long clientId);
|
||||
|
||||
@Query("SELECT COUNT(DISTINCT cis.softwareName) FROM CachedInstalledSoftware cis " +
|
||||
"WHERE cis.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId) " +
|
||||
"AND cis.totalCves > 0")
|
||||
Long countVulnerableSoftware(@Param("clientId") Long clientId);
|
||||
|
||||
@Query("SELECT MAX(cdv.lastUpdated) FROM CachedDeviceVuln cdv " +
|
||||
"WHERE cdv.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId)")
|
||||
LocalDateTime findLastVulnerabilityScanDate(@Param("clientId") Long clientId);
|
||||
|
||||
// Top Vulnerabilities Query
|
||||
|
||||
@Query("SELECT new com.psg.dlsysinfo.dl_sysinfo_server.dto.TopVulnerabilityDTO(" +
|
||||
"cdv.cveId, " +
|
||||
"cdv.description, " +
|
||||
"cdv.severity, " +
|
||||
"cdv.score, " +
|
||||
"COUNT(DISTINCT cdv.deviceId)) " +
|
||||
"FROM CachedDeviceVuln cdv " +
|
||||
"WHERE cdv.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId) " +
|
||||
"GROUP BY cdv.cveId, cdv.description, cdv.severity, cdv.score " +
|
||||
"ORDER BY " +
|
||||
"CASE WHEN UPPER(cdv.severity) = 'CRITICAL' THEN 0 " +
|
||||
" WHEN UPPER(cdv.severity) = 'HIGH' THEN 1 " +
|
||||
" WHEN UPPER(cdv.severity) = 'MEDIUM' THEN 2 " +
|
||||
" WHEN UPPER(cdv.severity) = 'LOW' THEN 3 " +
|
||||
" ELSE 4 END, " +
|
||||
"COUNT(DISTINCT cdv.deviceId) DESC")
|
||||
List<TopVulnerabilityDTO> findTopVulnerabilities(@Param("clientId") Long clientId,
|
||||
@Param("limit") int limit);
|
||||
|
||||
// Vulnerable Software Query
|
||||
|
||||
@Query("SELECT new com.psg.dlsysinfo.dl_sysinfo_server.dto.VulnerableSoftwareDTO(" +
|
||||
"cis.softwareName, " +
|
||||
"COUNT(cis.id), " +
|
||||
"SUM(CASE WHEN cis.totalCves > 0 THEN 1 ELSE 0 END), " +
|
||||
"MAX(COALESCE(cis.totalCves, 0))) " +
|
||||
"FROM CachedInstalledSoftware cis " +
|
||||
"WHERE cis.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId) " +
|
||||
"GROUP BY cis.softwareName " +
|
||||
"ORDER BY (SUM(CASE WHEN cis.totalCves > 0 THEN 1 ELSE 0 END) * 1.0 / COUNT(cis.id) * MAX(COALESCE(cis.totalCves, 0))) DESC")
|
||||
List<VulnerableSoftwareDTO> findVulnerableSoftware(@Param("clientId") Long clientId,
|
||||
@Param("limit") int limit);
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.psg.dlsysinfo.dl_sysinfo_server.service;
|
||||
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.dto.ComplianceSummaryDTO;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.dto.TopVulnerabilityDTO;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.dto.VulnerableSoftwareDTO;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.repository.ReportingRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class ReportingService {
|
||||
|
||||
private final ReportingRepository reportingRepository;
|
||||
|
||||
/**
|
||||
* Get compliance summary with high-level security metrics
|
||||
* Cached for 15 minutes due to high computation cost
|
||||
*/
|
||||
@Cacheable(value = "complianceSummary", key = "#clientId")
|
||||
@Transactional(readOnly = true)
|
||||
public ComplianceSummaryDTO getComplianceSummary(Long clientId) {
|
||||
log.info("Generating compliance summary for client: {}", clientId);
|
||||
|
||||
Long totalDevices = reportingRepository.countTotalDevices(clientId);
|
||||
Long vulnerableDevices = reportingRepository.countVulnerableDevices(clientId);
|
||||
Long totalVulnerabilities = reportingRepository.countTotalVulnerabilities(clientId);
|
||||
Long criticalVulns = reportingRepository.countCriticalVulnerabilities(clientId);
|
||||
Long highVulns = reportingRepository.countHighVulnerabilities(clientId);
|
||||
Long mediumVulns = reportingRepository.countMediumVulnerabilities(clientId);
|
||||
Long lowVulns = reportingRepository.countLowVulnerabilities(clientId);
|
||||
Long totalSoftware = reportingRepository.countTotalSoftware(clientId);
|
||||
Long vulnerableSoftware = reportingRepository.countVulnerableSoftware(clientId);
|
||||
LocalDateTime lastUpdated = reportingRepository.findLastVulnerabilityScanDate(clientId);
|
||||
|
||||
return ComplianceSummaryDTO.builder()
|
||||
.totalDevices(totalDevices != null ? totalDevices : 0L)
|
||||
.vulnerableDevices(vulnerableDevices != null ? vulnerableDevices : 0L)
|
||||
.totalVulnerabilities(totalVulnerabilities != null ? totalVulnerabilities : 0L)
|
||||
.criticalVulns(criticalVulns != null ? criticalVulns : 0L)
|
||||
.highVulns(highVulns != null ? highVulns : 0L)
|
||||
.mediumVulns(mediumVulns != null ? mediumVulns : 0L)
|
||||
.lowVulns(lowVulns != null ? lowVulns : 0L)
|
||||
.totalSoftware(totalSoftware != null ? totalSoftware : 0L)
|
||||
.vulnerableSoftware(vulnerableSoftware != null ? vulnerableSoftware : 0L)
|
||||
.lastUpdated(lastUpdated != null ? lastUpdated : LocalDateTime.now())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get top vulnerabilities by severity and affected device count
|
||||
* Cached for 30 minutes due to moderate update frequency
|
||||
*/
|
||||
@Cacheable(value = "topVulnerabilities", key = "#clientId")
|
||||
@Transactional(readOnly = true)
|
||||
public List<TopVulnerabilityDTO> getTopVulnerabilities(Long clientId) {
|
||||
log.info("Fetching top vulnerabilities for client: {}", clientId);
|
||||
return reportingRepository.findTopVulnerabilities(clientId, 20);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get vulnerable software packages by risk score
|
||||
* Cached for 1 hour due to less frequent changes
|
||||
*/
|
||||
@Cacheable(value = "vulnerableSoftware", key = "#clientId")
|
||||
@Transactional(readOnly = true)
|
||||
public List<VulnerableSoftwareDTO> getVulnerableSoftware(Long clientId) {
|
||||
log.info("Fetching vulnerable software for client: {}", clientId);
|
||||
return reportingRepository.findVulnerableSoftware(clientId, 20);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user