NeuVector is a container security platform that provides vulnerability scanning, runtime protection, and network security. This implementation demonstrates how to integrate NeuVector's scanning capabilities into Java applications.
NeuVector Scanner Overview
NeuVector provides:
- Container image vulnerability scanning
- Runtime security monitoring
- Network policy enforcement
- Compliance checking
- CI/CD pipeline integration
Dependencies and Setup
Maven Configuration:
<dependencies> <!-- HTTP Client --> <dependency> <groupId>org.apache.httpcomponents.client5</groupId> <artifactId>httpclient5</artifactId> <version>5.2.1</version> </dependency> <!-- JSON Processing --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> </dependency> <!-- Docker Java API --> <dependency> <groupId>com.github.docker-java</groupId> <artifactId>docker-java</artifactId> <version>3.3.0</version> </dependency> <!-- Kubernetes Client --> <dependency> <groupId>io.kubernetes</groupId> <artifactId>client-java</artifactId> <version>18.0.0</version> </dependency> <!-- Spring Boot --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Logging --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>2.0.7</version> </dependency> </dependencies>
Configuration Management
NeuVectorConfig.java:
@Configuration @ConfigurationProperties(prefix = "neuvector") @Data public class NeuVectorConfig { private ScannerConfig scanner = new ScannerConfig(); private ControllerConfig controller = new ControllerConfig(); private RegistryConfig registry = new RegistryConfig(); private SecurityConfig security = new SecurityConfig(); @Data public static class ScannerConfig { private String url = "https://neuvector-scanner:8080"; private String username; private String password; private int timeout = 30000; private int maxRetries = 3; private boolean sslVerify = true; private String caCertPath; } @Data public static class ControllerConfig { private String url = "https://neuvector-controller:8443"; private String username; private String password; private String apiVersion = "v1"; } @Data public static class RegistryConfig { private String url; private String username; private String password; private String registryType = "docker"; private boolean scanLayers = true; private List<String> excludedRepositories = new ArrayList<>(); } @Data public static class SecurityConfig { private String jwtSecret; private String encryptionKey; private boolean enableTLS = true; private List<String> allowedCidrs = Arrays.asList("0.0.0.0/0"); } public String getScannerAuthHeader() { String auth = username + ":" + password; return "Basic " + Base64.getEncoder().encodeToString(auth.getBytes()); } public String getControllerAuthHeader() { String auth = controller.getUsername() + ":" + controller.getPassword(); return "Basic " + Base64.getEncoder().encodeToString(auth.getBytes()); } } NeuVector API Client
NeuVectorApiClient.java:
@Service @Slf4j public class NeuVectorApiClient { private final NeuVectorConfig config; private final RestTemplate restTemplate; private final ObjectMapper objectMapper; public NeuVectorApiClient(NeuVectorConfig config) { this.config = config; this.restTemplate = createRestTemplate(); this.objectMapper = new ObjectMapper(); } public ScanResult scanImage(ScanRequest request) { try { String url = config.getScanner().getUrl() + "/scan"; HttpHeaders headers = createScannerHeaders(); HttpEntity<ScanRequest> entity = new HttpEntity<>(request, headers); ResponseEntity<ScanResponse> response = restTemplate.exchange( url, HttpMethod.POST, entity, ScanResponse.class); return processScanResponse(response.getBody()); } catch (Exception e) { throw new NeuVectorException("Image scan failed: " + e.getMessage(), e); } } public ScanStatus getScanStatus(String scanId) { try { String url = config.getScanner().getUrl() + "/scan/" + scanId + "/status"; HttpHeaders headers = createScannerHeaders(); HttpEntity<String> entity = new HttpEntity<>(headers); ResponseEntity<ScanStatus> response = restTemplate.exchange( url, HttpMethod.GET, entity, ScanStatus.class); return response.getBody(); } catch (Exception e) { throw new NeuVectorException("Failed to get scan status: " + e.getMessage(), e); } } public List<Vulnerability> getVulnerabilities(String imageId) { try { String url = config.getController().getUrl() + "/" + config.getController().getApiVersion() + "/scan/image/" + imageId; HttpHeaders headers = createControllerHeaders(); HttpEntity<String> entity = new HttpEntity<>(headers); ResponseEntity<VulnerabilityResponse> response = restTemplate.exchange( url, HttpMethod.GET, entity, VulnerabilityResponse.class); return response.getBody().getVulnerabilities(); } catch (Exception e) { throw new NeuVectorException("Failed to get vulnerabilities: " + e.getMessage(), e); } } public ComplianceReport getComplianceReport(String namespace) { try { String url = config.getController().getUrl() + "/" + config.getController().getApiVersion() + "/compliance/" + namespace; HttpHeaders headers = createControllerHeaders(); HttpEntity<String> entity = new HttpEntity<>(headers); ResponseEntity<ComplianceReport> response = restTemplate.exchange( url, HttpMethod.GET, entity, ComplianceReport.class); return response.getBody(); } catch (Exception e) { throw new NeuVectorException("Failed to get compliance report: " + e.getMessage(), e); } } public List<SecurityEvent> getSecurityEvents(String namespace, Duration timeRange) { try { Instant endTime = Instant.now(); Instant startTime = endTime.minus(timeRange); String url = config.getController().getUrl() + "/" + config.getController().getApiVersion() + "/events/security" + "?start=" + startTime.getEpochSecond() + "&end=" + endTime.getEpochSecond() + "&namespace=" + namespace; HttpHeaders headers = createControllerHeaders(); HttpEntity<String> entity = new HttpEntity<>(headers); ResponseEntity<SecurityEventResponse> response = restTemplate.exchange( url, HttpMethod.GET, entity, SecurityEventResponse.class); return response.getBody().getEvents(); } catch (Exception e) { throw new NeuVectorException("Failed to get security events: " + e.getMessage(), e); } } public boolean createNetworkPolicy(NetworkPolicy policy) { try { String url = config.getController().getUrl() + "/" + config.getController().getApiVersion() + "/policy/network"; HttpHeaders headers = createControllerHeaders(); HttpEntity<NetworkPolicy> entity = new HttpEntity<>(policy, headers); ResponseEntity<Void> response = restTemplate.exchange( url, HttpMethod.POST, entity, Void.class); return response.getStatusCode().is2xxSuccessful(); } catch (Exception e) { throw new NeuVectorException("Failed to create network policy: " + e.getMessage(), e); } } private HttpHeaders createScannerHeaders() { HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", config.getScannerAuthHeader()); headers.setContentType(MediaType.APPLICATION_JSON); return headers; } private HttpHeaders createControllerHeaders() { HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", config.getControllerAuthHeader()); headers.setContentType(MediaType.APPLICATION_JSON); return headers; } private RestTemplate createRestTemplate() { RestTemplate template = new RestTemplate(); // Configure SSL if (!config.getScanner().isSslVerify() && config.getScanner().getCaCertPath() != null) { template.setRequestFactory(createSslFactory()); } // Configure timeout SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); factory.setConnectTimeout(config.getScanner().getTimeout()); factory.setReadTimeout(config.getScanner().getTimeout()); template.setRequestFactory(factory); return template; } private ClientHttpRequestFactory createSslFactory() { try { SSLContext sslContext = SSLContexts.custom() .loadTrustMaterial(new File(config.getScanner().getCaCertPath()), (chain, authType) -> true) .build(); SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( sslContext, NoopHostnameVerifier.INSTANCE); HttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create() .setSSLSocketFactory(socketFactory) .build(); HttpClient httpClient = HttpClients.custom() .setConnectionManager(connectionManager) .build(); return new HttpComponentsClientHttpRequestFactory(httpClient); } catch (Exception e) { throw new NeuVectorException("SSL configuration failed", e); } } private ScanResult processScanResponse(ScanResponse response) { return ScanResult.builder() .scanId(response.getScanId()) .status(response.getStatus()) .vulnerabilities(response.getVulnerabilities()) .summary(createSummary(response.getVulnerabilities())) .scanDate(Instant.now()) .build(); } private VulnerabilitySummary createSummary(List<Vulnerability> vulnerabilities) { Map<String, Long> severityCount = vulnerabilities.stream() .collect(Collectors.groupingBy(Vulnerability::getSeverity, Collectors.counting())); return VulnerabilitySummary.builder() .total(vulnerabilities.size()) .critical(severityCount.getOrDefault("Critical", 0L)) .high(severityCount.getOrDefault("High", 0L)) .medium(severityCount.getOrDefault("Medium", 0L)) .low(severityCount.getOrDefault("Low", 0L)) .build(); } } Data Models
ScanRequest.java:
@Data @Builder @JsonInclude(JsonInclude.Include.NON_NULL) public class ScanRequest { private String image; private String registry; private String username; private String password; private String tag; private ScanConfig scanConfig; private Boolean scanLayers; private Map<String, String> labels; @Data @Builder public static class ScanConfig { private Boolean scanSecrets; private Boolean scanMalware; private Boolean scanSetuidSetgid; private List<String> excludedPaths; private Integer timeout; } } ScanResult.java:
@Data @Builder public class ScanResult { private String scanId; private String status; private List<Vulnerability> vulnerabilities; private VulnerabilitySummary summary; private Instant scanDate; private String imageDigest; private List<ComplianceIssue> complianceIssues; private ScanMetadata metadata; public boolean hasCriticalVulnerabilities() { return summary != null && summary.getCritical() > 0; } public boolean hasHighVulnerabilities() { return summary != null && summary.getHigh() > 0; } public boolean isCompliant() { return complianceIssues == null || complianceIssues.isEmpty(); } } Vulnerability.java:
@Data @Builder @JsonIgnoreProperties(ignoreUnknown = true) public class Vulnerability { private String name; private String severity; private String packageName; private String packageVersion; private String fixedVersion; private String description; private String link; private List<String> cves; private Double score; private Vector vector; private List<String> layers; private Instant publishedDate; private Instant discoveredDate; @Data @Builder public static class Vector { private String attackVector; private String attackComplexity; private String privilegesRequired; private String userInteraction; private String scope; private String confidentialityImpact; private String integrityImpact; private String availabilityImpact; } } ComplianceIssue.java:
@Data @Builder public class ComplianceIssue { private String id; private String type; private String level; private String description; private String standard; private String message; private List<String> affectedResources; private Remediation remediation; @Data @Builder public static class Remediation { private String description; private List<String> commands; private List<String> resources; } } Vulnerability Scanner Service
VulnerabilityScannerService.java:
@Service @Slf4j public class VulnerabilityScannerService { private final NeuVectorApiClient apiClient; private final DockerService dockerService; private final KubernetesService kubernetesService; public VulnerabilityScannerService(NeuVectorApiClient apiClient, DockerService dockerService, KubernetesService kubernetesService) { this.apiClient = apiClient; this.dockerService = dockerService; this.kubernetesService = kubernetesService; } public ScanResult scanImage(String imageName) { try { log.info("Starting vulnerability scan for image: {}", imageName); ScanRequest request = ScanRequest.builder() .image(imageName) .scanConfig(ScanRequest.ScanConfig.builder() .scanSecrets(true) .scanMalware(true) .scanSetuidSetgid(true) .build()) .build(); ScanResult result = apiClient.scanImage(request); log.info("Scan completed for image: {} - {} vulnerabilities found", imageName, result.getSummary().getTotal()); return result; } catch (Exception e) { log.error("Vulnerability scan failed for image: {}", imageName, e); throw new ScanException("Scan failed for image: " + imageName, e); } } public ScanResult scanImageWithRetry(String imageName, int maxRetries) { for (int attempt = 1; attempt <= maxRetries; attempt++) { try { return scanImage(imageName); } catch (Exception e) { if (attempt == maxRetries) { throw e; } log.warn("Scan attempt {} failed for image: {}, retrying...", attempt, imageName); sleepExponentialBackoff(attempt); } } throw new ScanException("All scan attempts failed for image: " + imageName); } public List<ScanResult> scanImages(List<String> images) { return images.parallelStream() .map(this::scanImage) .collect(Collectors.toList()); } public ScanReport scanNamespace(String namespace) { try { log.info("Starting comprehensive scan for namespace: {}", namespace); // Get all pods in namespace List<Pod> pods = kubernetesService.getPodsInNamespace(namespace); // Extract unique images Set<String> images = pods.stream() .flatMap(pod -> pod.getContainers().stream()) .map(Container::getImage) .collect(Collectors.toSet()); // Scan all images List<ScanResult> scanResults = scanImages(new ArrayList<>(images)); // Get compliance report ComplianceReport complianceReport = apiClient.getComplianceReport(namespace); // Get security events List<SecurityEvent> securityEvents = apiClient.getSecurityEvents(namespace, Duration.ofHours(24)); return ScanReport.builder() .namespace(namespace) .scanDate(Instant.now()) .scanResults(scanResults) .complianceReport(complianceReport) .securityEvents(securityEvents) .summary(createNamespaceSummary(scanResults, complianceReport, securityEvents)) .build(); } catch (Exception e) { throw new ScanException("Namespace scan failed: " + namespace, e); } } public ComplianceCheckResult checkCompliance(String namespace, ComplianceStandard standard) { try { ComplianceReport report = apiClient.getComplianceReport(namespace); List<ComplianceIssue> relevantIssues = report.getIssues().stream() .filter(issue -> standard.getName().equals(issue.getStandard())) .collect(Collectors.toList()); boolean compliant = relevantIssues.stream() .noneMatch(issue -> "HIGH".equals(issue.getLevel()) || "CRITICAL".equals(issue.getLevel())); return ComplianceCheckResult.builder() .namespace(namespace) .standard(standard) .compliant(compliant) .issues(relevantIssues) .checkDate(Instant.now()) .build(); } catch (Exception e) { throw new ComplianceException("Compliance check failed", e); } } public VulnerabilityTrend analyzeVulnerabilityTrend(String image, Duration period) { try { Instant endDate = Instant.now(); Instant startDate = endDate.minus(period); // This would typically query historical scan data List<ScanResult> historicalScans = getHistoricalScans(image, startDate, endDate); return VulnerabilityTrend.builder() .image(image) .period(period) .trendData(calculateTrend(historicalScans)) .recommendations(generateRecommendations(historicalScans)) .build(); } catch (Exception e) { throw new AnalysisException("Vulnerability trend analysis failed", e); } } public boolean isImageApproved(String image, ApprovalPolicy policy) { ScanResult scanResult = scanImage(image); return evaluateApprovalPolicy(scanResult, policy); } public ImageRiskAssessment assessImageRisk(String image) { ScanResult scanResult = scanImage(image); double riskScore = calculateRiskScore(scanResult); RiskLevel riskLevel = determineRiskLevel(riskScore); return ImageRiskAssessment.builder() .image(image) .riskScore(riskScore) .riskLevel(riskLevel) .scanResult(scanResult) .assessmentDate(Instant.now()) .recommendations(generateRiskRecommendations(scanResult, riskLevel)) .build(); } private NamespaceScanSummary createNamespaceSummary(List<ScanResult> scanResults, ComplianceReport complianceReport, List<SecurityEvent> securityEvents) { VulnerabilitySummary vulnSummary = scanResults.stream() .map(ScanResult::getSummary) .reduce(new VulnerabilitySummary(0, 0L, 0L, 0L, 0L), (s1, s2) -> new VulnerabilitySummary( s1.getTotal() + s2.getTotal(), s1.getCritical() + s2.getCritical(), s1.getHigh() + s2.getHigh(), s1.getMedium() + s2.getMedium(), s1.getLow() + s2.getLow() )); return NamespaceScanSummary.builder() .totalImages(scanResults.size()) .vulnerabilitySummary(vulnSummary) .complianceIssues(complianceReport.getIssues().size()) .securityEvents(securityEvents.size()) .overallStatus(calculateOverallStatus(vulnSummary, complianceReport)) .build(); } private String calculateOverallStatus(VulnerabilitySummary vulnSummary, ComplianceReport complianceReport) { if (vulnSummary.getCritical() > 0) { return "CRITICAL"; } else if (vulnSummary.getHigh() > 0) { return "HIGH"; } else if (!complianceReport.getIssues().isEmpty()) { return "WARNING"; } else { return "PASS"; } } private boolean evaluateApprovalPolicy(ScanResult scanResult, ApprovalPolicy policy) { if (policy.isBlockCritical() && scanResult.getSummary().getCritical() > 0) { return false; } if (policy.isBlockHigh() && scanResult.getSummary().getHigh() > 0) { return false; } if (policy.getMaxTotalVulnerabilities() > 0 && scanResult.getSummary().getTotal() > policy.getMaxTotalVulnerabilities()) { return false; } return true; } private double calculateRiskScore(ScanResult scanResult) { VulnerabilitySummary summary = scanResult.getSummary(); double score = summary.getCritical() * 10.0 + summary.getHigh() * 5.0 + summary.getMedium() * 2.0 + summary.getLow() * 0.5; return Math.min(score, 100.0); } private RiskLevel determineRiskLevel(double riskScore) { if (riskScore >= 80) return RiskLevel.CRITICAL; if (riskScore >= 60) return RiskLevel.HIGH; if (riskScore >= 40) return RiskLevel.MEDIUM; if (riskScore >= 20) return RiskLevel.LOW; return RiskLevel.NONE; } private void sleepExponentialBackoff(int attempt) { try { long delay = Math.min(1000 * (long) Math.pow(2, attempt), 30000); Thread.sleep(delay); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new ScanException("Scan interrupted", e); } } } Docker Integration Service
DockerService.java:
@Service @Slf4j public class DockerService { private final DockerClient dockerClient; public DockerService() { this.dockerClient = createDockerClient(); } public List<Image> getLocalImages() { try { return dockerClient.listImagesCmd().exec().stream() .map(this::convertToImage) .collect(Collectors.toList()); } catch (Exception e) { throw new DockerException("Failed to list local images", e); } } public ImageInfo inspectImage(String imageName) { try { InspectImageResponse response = dockerClient.inspectImageCmd(imageName).exec(); return convertToImageInfo(response); } catch (Exception e) { throw new DockerException("Failed to inspect image: " + imageName, e); } } public void pullImage(String imageName) { try { dockerClient.pullImageCmd(imageName) .exec(new PullImageResultCallback()) .awaitCompletion(300, TimeUnit.SECONDS); } catch (Exception e) { throw new DockerException("Failed to pull image: " + imageName, e); } } public List<Container> getRunningContainers() { try { return dockerClient.listContainersCmd() .withShowAll(false) .exec().stream() .map(this::convertToContainer) .collect(Collectors.toList()); } catch (Exception e) { throw new DockerException("Failed to list running containers", e); } } public ImageHistory getImageHistory(String imageName) { try { List<ImageHistory> history = dockerClient.inspectImageCmd(imageName) .exec() .getRepoDigests(); return ImageHistory.builder() .image(imageName) .layers(extractLayers(history)) .build(); } catch (Exception e) { throw new DockerException("Failed to get image history: " + imageName, e); } } private DockerClient createDockerClient() { return DockerClientBuilder.getInstance().build(); } private Image convertToImage(com.github.dockerjava.api.model.Image dockerImage) { return Image.builder() .id(dockerImage.getId()) .repository(dockerImage.getRepoTags() != null ? dockerImage.getRepoTags()[0] : "unknown") .size(dockerImage.getSize()) .created(dockerImage.getCreated()) .build(); } private ImageInfo convertToImageInfo(InspectImageResponse response) { return ImageInfo.builder() .id(response.getId()) .architecture(response.getArch()) .os(response.getOs()) .created(response.getCreated()) .size(response.getSize()) .layers(response.getRootFS().getLayers()) .environment(response.getConfig().getEnv()) .labels(response.getConfig().getLabels()) .build(); } private Container convertToContainer(com.github.dockerjava.api.model.Container dockerContainer) { return Container.builder() .id(dockerContainer.getId()) .name(dockerContainer.getNames()[0]) .image(dockerContainer.getImage()) .status(dockerContainer.getStatus()) .created(dockerContainer.getCreated()) .build(); } private List<ImageLayer> extractLayers(List<ImageHistory> history) { return history.stream() .map(h -> ImageLayer.builder() .digest(h.getId()) .created(h.getCreated()) .size(h.getSize()) .build()) .collect(Collectors.toList()); } } Kubernetes Integration Service
KubernetesService.java:
@Service @Slf4j public class KubernetesService { private final ApiClient apiClient; private final CoreV1Api coreApi; private final AppsV1Api appsApi; public KubernetesService() { this.apiClient = createApiClient(); this.coreApi = new CoreV1Api(apiClient); this.appsApi = new AppsV1Api(apiClient); } public List<Pod> getPodsInNamespace(String namespace) { try { V1PodList podList = coreApi.listNamespacedPod(namespace) .execute(); return podList.getItems().stream() .map(this::convertToPod) .collect(Collectors.toList()); } catch (ApiException e) { throw new KubernetesException("Failed to get pods in namespace: " + namespace, e); } } public List<Deployment> getDeploymentsInNamespace(String namespace) { try { V1DeploymentList deploymentList = appsApi.listNamespacedDeployment(namespace) .execute(); return deploymentList.getItems().stream() .map(this::convertToDeployment) .collect(Collectors.toList()); } catch (ApiException e) { throw new KubernetesException("Failed to get deployments in namespace: " + namespace, e); } } public NamespaceInfo getNamespaceInfo(String namespace) { try { V1Namespace ns = coreApi.readNamespace(namespace).execute(); return NamespaceInfo.builder() .name(namespace) .labels(ns.getMetadata().getLabels()) .annotations(ns.getMetadata().getAnnotations()) .creationTimestamp(ns.getMetadata().getCreationTimestamp()) .status(ns.getStatus().getPhase()) .build(); } catch (ApiException e) { throw new KubernetesException("Failed to get namespace info: " + namespace, e); } } public boolean createNetworkPolicy(NetworkPolicy policy) { try { V1NetworkPolicy v1Policy = convertToV1NetworkPolicy(policy); coreApi.createNamespacedNetworkPolicy(policy.getNamespace(), v1Policy) .execute(); return true; } catch (ApiException e) { throw new KubernetesException("Failed to create network policy", e); } } public ClusterSecurityReport getClusterSecurityReport() { try { List<Pod> allPods = getAllPods(); List<NamespaceInfo> namespaces = getAllNamespaces(); return ClusterSecurityReport.builder() .totalPods(allPods.size()) .totalNamespaces(namespaces.size()) .namespaces(namespaces.stream() .map(ns -> getNamespaceInfo(ns.getName())) .collect(Collectors.toList())) .generatedAt(Instant.now()) .build(); } catch (Exception e) { throw new KubernetesException("Failed to generate cluster security report", e); } } private ApiClient createApiClient() { try { // Try in-cluster config first, then fallback to kubeconfig if (isRunningInCluster()) { return Config.fromCluster(); } else { return Config.defaultClient(); } } catch (Exception e) { throw new KubernetesException("Failed to create Kubernetes client", e); } } private boolean isRunningInCluster() { return Files.exists(Paths.get("/var/run/secrets/kubernetes.io/serviceaccount/token")); } private Pod convertToPod(V1Pod v1Pod) { return Pod.builder() .name(v1Pod.getMetadata().getName()) .namespace(v1Pod.getMetadata().getNamespace()) .containers(v1Pod.getSpec().getContainers().stream() .map(this::convertToContainer) .collect(Collectors.toList())) .labels(v1Pod.getMetadata().getLabels()) .status(v1Pod.getStatus().getPhase()) .created(v1Pod.getMetadata().getCreationTimestamp()) .build(); } private Container convertToContainer(V1Container v1Container) { return Container.builder() .name(v1Container.getName()) .image(v1Container.getImage()) .resources(v1Container.getResources()) .build(); } private Deployment convertToDeployment(V1Deployment v1Deployment) { return Deployment.builder() .name(v1Deployment.getMetadata().getName()) .namespace(v1Deployment.getMetadata().getNamespace()) .replicas(v1Deployment.getSpec().getReplicas()) .containers(v1Deployment.getSpec().getTemplate().getSpec().getContainers().stream() .map(this::convertToContainer) .collect(Collectors.toList())) .labels(v1Deployment.getMetadata().getLabels()) .build(); } private V1NetworkPolicy convertToV1NetworkPolicy(NetworkPolicy policy) { V1NetworkPolicy v1Policy = new V1NetworkPolicy(); V1ObjectMeta metadata = new V1ObjectMeta(); metadata.setName(policy.getName()); metadata.setNamespace(policy.getNamespace()); v1Policy.setMetadata(metadata); V1NetworkPolicySpec spec = new V1NetworkPolicySpec(); spec.setPodSelector(new V1LabelSelector() .matchLabels(policy.getPodSelector())); // Convert policy rules if (policy.getIngressRules() != null) { spec.setIngress(policy.getIngressRules().stream() .map(this::convertToV1NetworkPolicyIngressRule) .collect(Collectors.toList())); } if (policy.getEgressRules() != null) { spec.setEgress(policy.getEgressRules().stream() .map(this::convertToV1NetworkPolicyEgressRule) .collect(Collectors.toList())); } v1Policy.setSpec(spec); return v1Policy; } private List<Pod> getAllPods() { try { V1PodList podList = coreApi.listPodForAllNamespaces().execute(); return podList.getItems().stream() .map(this::convertToPod) .collect(Collectors.toList()); } catch (ApiException e) { throw new KubernetesException("Failed to get all pods", e); } } private List<NamespaceInfo> getAllNamespaces() { try { V1NamespaceList namespaceList = coreApi.listNamespace().execute(); return namespaceList.getItems().stream() .map(ns -> NamespaceInfo.builder() .name(ns.getMetadata().getName()) .labels(ns.getMetadata().getLabels()) .build()) .collect(Collectors.toList()); } catch (ApiException e) { throw new KubernetesException("Failed to get all namespaces", e); } } } Security Policy Manager
SecurityPolicyManager.java:
@Service @Slf4j public class SecurityPolicyManager { private final NeuVectorApiClient apiClient; private final KubernetesService kubernetesService; public SecurityPolicyManager(NeuVectorApiClient apiClient, KubernetesService kubernetesService) { this.apiClient = apiClient; this.kubernetesService = kubernetesService; } public PolicyValidationResult validateImagePolicy(String image, ImagePolicy policy) { try { ScanResult scanResult = apiClient.scanImage(ScanRequest.builder() .image(image) .build()); return PolicyValidationResult.builder() .image(image) .policy(policy) .compliant(isCompliantWithPolicy(scanResult, policy)) .violations(findPolicyViolations(scanResult, policy)) .scanResult(scanResult) .validatedAt(Instant.now()) .build(); } catch (Exception e) { throw new PolicyException("Image policy validation failed", e); } } public RuntimePolicy createRuntimePolicy(RuntimePolicy policy) { try { // Create NeuVector runtime policy boolean success = apiClient.createRuntimePolicy(policy); if (success) { log.info("Runtime policy created: {}", policy.getName()); return policy; } else { throw new PolicyException("Failed to create runtime policy: " + policy.getName()); } } catch (Exception e) { throw new PolicyException("Runtime policy creation failed", e); } } public NetworkPolicy createNetworkPolicy(NetworkPolicy policy) { try { // Create Kubernetes network policy boolean success = kubernetesService.createNetworkPolicy(policy); if (success) { log.info("Network policy created: {}", policy.getName()); return policy; } else { throw new PolicyException("Failed to create network policy: " + policy.getName()); } } catch (Exception e) { throw new PolicyException("Network policy creation failed", e); } } public ComplianceReport checkNamespaceCompliance(String namespace, ComplianceStandard standard) { try { return apiClient.getComplianceReport(namespace); } catch (Exception e) { throw new ComplianceException("Compliance check failed for namespace: " + namespace, e); } } public List<SecurityEvent> monitorSecurityEvents(String namespace, Duration timeRange) { try { return apiClient.getSecurityEvents(namespace, timeRange); } catch (Exception e) { throw new MonitoringException("Security event monitoring failed", e); } } public SecurityDashboard getSecurityDashboard(String namespace) { try { List<ScanResult> scanResults = scanNamespaceImages(namespace); ComplianceReport complianceReport = apiClient.getComplianceReport(namespace); List<SecurityEvent> securityEvents = apiClient.getSecurityEvents(namespace, Duration.ofHours(24)); return SecurityDashboard.builder() .namespace(namespace) .timestamp(Instant.now()) .vulnerabilitySummary(createVulnerabilitySummary(scanResults)) .complianceStatus(createComplianceStatus(complianceReport)) .securityEvents(securityEvents) .riskScore(calculateRiskScore(scanResults, complianceReport, securityEvents)) .recommendations(generateRecommendations(scanResults, complianceReport, securityEvents)) .build(); } catch (Exception e) { throw new DashboardException("Security dashboard generation failed", e); } } private boolean isCompliantWithPolicy(ScanResult scanResult, ImagePolicy policy) { VulnerabilitySummary summary = scanResult.getSummary(); if (policy.getMaxCriticalSeverity() > 0 && summary.getCritical() > policy.getMaxCriticalSeverity()) { return false; } if (policy.getMaxHighSeverity() > 0 && summary.getHigh() > policy.getMaxHighSeverity()) { return false; } if (policy.getMaxTotalVulnerabilities() > 0 && summary.getTotal() > policy.getMaxTotalVulnerabilities()) { return false; } return true; } private List<PolicyViolation> findPolicyViolations(ScanResult scanResult, ImagePolicy policy) { List<PolicyViolation> violations = new ArrayList<>(); VulnerabilitySummary summary = scanResult.getSummary(); if (policy.getMaxCriticalSeverity() > 0 && summary.getCritical() > policy.getMaxCriticalSeverity()) { violations.add(PolicyViolation.builder() .type("CRITICAL_VULNERABILITIES") .message("Exceeded maximum critical vulnerabilities: " + summary.getCritical()) .severity("HIGH") .build()); } // Add other violation checks... return violations; } private List<ScanResult> scanNamespaceImages(String namespace) { List<Pod> pods = kubernetesService.getPodsInNamespace(namespace); Set<String> images = pods.stream() .flatMap(pod -> pod.getContainers().stream()) .map(Container::getImage) .collect(Collectors.toSet()); VulnerabilityScannerService scanner = new VulnerabilityScannerService( apiClient, new DockerService(), kubernetesService); return scanner.scanImages(new ArrayList<>(images)); } private VulnerabilitySummary createVulnerabilitySummary(List<ScanResult> scanResults) { return scanResults.stream() .map(ScanResult::getSummary) .reduce(new VulnerabilitySummary(0, 0L, 0L, 0L, 0L), (s1, s2) -> new VulnerabilitySummary( s1.getTotal() + s2.getTotal(), s1.getCritical() + s2.getCritical(), s1.getHigh() + s2.getHigh(), s1.getMedium() + s2.getMedium(), s1.getLow() + s2.getLow() )); } private ComplianceStatus createComplianceStatus(ComplianceReport report) { long criticalIssues = report.getIssues().stream() .filter(issue -> "CRITICAL".equals(issue.getLevel())) .count(); long highIssues = report.getIssues().stream() .filter(issue -> "HIGH".equals(issue.getLevel())) .count(); return ComplianceStatus.builder() .totalIssues(report.getIssues().size()) .criticalIssues(criticalIssues) .highIssues(highIssues) .compliant(criticalIssues == 0 && highIssues == 0) .build(); } private double calculateRiskScore(List<ScanResult> scanResults, ComplianceReport complianceReport, List<SecurityEvent> securityEvents) { // Implement risk scoring logic double vulnScore = scanResults.stream() .mapToDouble(result -> result.getSummary().getCritical() * 10 + result.getSummary().getHigh() * 5) .sum(); double complianceScore = complianceReport.getIssues().size() * 2; double eventScore = securityEvents.size() * 3; return Math.min((vulnScore + complianceScore + eventScore) / 100.0, 1.0) * 100; } private List<String> generateRecommendations(List<ScanResult> scanResults, ComplianceReport complianceReport, List<SecurityEvent> securityEvents) { List<String> recommendations = new ArrayList<>(); // Generate recommendations based on scan results, compliance issues, and security events if (scanResults.stream().anyMatch(ScanResult::hasCriticalVulnerabilities)) { recommendations.add("Upgrade images with critical vulnerabilities immediately"); } if (!complianceReport.getIssues().isEmpty()) { recommendations.add("Address compliance issues to meet security standards"); } if (!securityEvents.isEmpty()) { recommendations.add("Investigate recent security events for potential threats"); } return recommendations; } } REST API Controller
NeuVectorController.java:
@RestController @RequestMapping("/api/neuvector") @Slf4j public class NeuVectorController { private final VulnerabilityScannerService scannerService; private final SecurityPolicyManager policyManager; private final NeuVectorApiClient apiClient; public NeuVectorController(VulnerabilityScannerService scannerService, SecurityPolicyManager policyManager, NeuVectorApiClient apiClient) { this.scannerService = scannerService; this.policyManager = policyManager; this.apiClient = apiClient; } @PostMapping("/scan/image") public ResponseEntity<ScanResult> scanImage(@RequestBody ScanImageRequest request) { try { ScanResult result = scannerService.scanImage(request.getImageName()); return ResponseEntity.ok(result); } catch (Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body(null); } } @PostMapping("/scan/namespace") public ResponseEntity<ScanReport> scanNamespace(@RequestBody ScanNamespaceRequest request) { try { ScanReport report = scannerService.scanNamespace(request.getNamespace()); return ResponseEntity.ok(report); } catch (Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body(null); } } @PostMapping("/policy/validate") public ResponseEntity<PolicyValidationResult> validatePolicy( @RequestBody PolicyValidationRequest request) { try { PolicyValidationResult result = policyManager.validateImagePolicy( request.getImage(), request.getPolicy()); return ResponseEntity.ok(result); } catch (Exception e) { return ResponseEntity.status(HttpStatus.BAD_REQUEST) .body(null); } } @GetMapping("/dashboard/{namespace}") public ResponseEntity<SecurityDashboard> getSecurityDashboard( @PathVariable String namespace) { try { SecurityDashboard dashboard = policyManager.getSecurityDashboard(namespace); return ResponseEntity.ok(dashboard); } catch (Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body(null); } } @GetMapping("/compliance/{namespace}") public ResponseEntity<ComplianceReport> getComplianceReport( @PathVariable String namespace) { try { ComplianceReport report = apiClient.getComplianceReport(namespace); return ResponseEntity.ok(report); } catch (Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body(null); } } @GetMapping("/events/{namespace}") public ResponseEntity<List<SecurityEvent>> getSecurityEvents( @PathVariable String namespace, @RequestParam(defaultValue = "24h") String duration) { try { Duration timeRange = parseDuration(duration); List<SecurityEvent> events = apiClient.getSecurityEvents(namespace, timeRange); return ResponseEntity.ok(events); } catch (Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body(Collections.emptyList()); } } @PostMapping("/risk/assessment") public ResponseEntity<ImageRiskAssessment> assessImageRisk( @RequestBody RiskAssessmentRequest request) { try { ImageRiskAssessment assessment = scannerService.assessImageRisk(request.getImage()); return ResponseEntity.ok(assessment); } catch (Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body(null); } } // DTO classes @Data public static class ScanImageRequest { private String imageName; } @Data public static class ScanNamespaceRequest { private String namespace; } @Data public static class PolicyValidationRequest { private String image; private ImagePolicy policy; } @Data public static class RiskAssessmentRequest { private String image; } private Duration parseDuration(String duration) { if (duration.endsWith("h")) { long hours = Long.parseLong(duration.substring(0, duration.length() - 1)); return Duration.ofHours(hours); } else if (duration.endsWith("d")) { long days = Long.parseLong(duration.substring(0, duration.length() - 1)); return Duration.ofDays(days); } else { return Duration.ofHours(24); } } } Best Practices
- Implement proper error handling and retry mechanisms
- Use secure authentication with TLS and API keys
- Cache scan results to improve performance
- Monitor API rate limits and implement backoff strategies
- Keep NeuVector components updated for latest vulnerability databases
- Integrate with CI/CD pipelines for automated security scanning
- Set up alerts for critical vulnerabilities and compliance violations
Conclusion
NeuVector Scanner integration in Java provides:
- Comprehensive vulnerability scanning for container images
- Runtime security monitoring and policy enforcement
- Compliance checking against security standards
- Risk assessment and trend analysis
- Kubernetes-native integration for cluster security
- RESTful API for automation and integration
This implementation demonstrates how to build a robust container security scanning solution that can be integrated into development pipelines, runtime environments, and security operations workflows.