Aqua Security is a cloud-native security platform that provides vulnerability scanning, runtime protection, and compliance assurance for applications, including Java-based workloads.
1. Aqua Vulnerability Scanning for Java
Aqua Trivy Integration for Java
Maven Plugin Configuration (pom.xml):
<build> <plugins> <!-- Aqua Trivy Vulnerability Scanner --> <plugin> <groupId>org.cyclonedx</groupId> <artifactId>cyclonedx-maven-plugin</artifactId> <version>2.7.9</version> <configuration> <projectType>library</projectType> <schemaVersion>1.4</schemaVersion> <includeBomSerialNumber>true</includeBomSerialNumber> <includeCompileScope>true</includeCompileScope> <includeRuntimeScope>true</includeRuntimeScope> <includeSystemScope>true</includeSystemScope> <includeTestScope>false</includeTestScope> <includeLicenseText>false</includeLicenseText> <outputFormat>json</outputFormat> <outputName>sbom</outputName> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>makeAggregateBom</goal> </goals> </execution> </executions> </plugin> <!-- JAR Vulnerability Check --> <plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> <version>8.2.1</version> <executions> <execution> <goals> <goal>check</goal> </goals> </execution> </executions> <configuration> <format>HTML</format> <failBuildOnAnyVulnerability>true</failBuildOnAnyVulnerability> <suppressionFile>dependency-check-suppressions.xml</suppressionFile> </configuration> </plugin> </plugins> </build>
Gradle Configuration (build.gradle)
plugins { id 'org.cyclonedx.bom' version '1.7.4' id 'org.owasp.dependencycheck' version '8.2.1' } cyclonedxBom { projectType = "library" schemaVersion = "1.4" includeBomSerialNumber = true includeCompileScope = true includeRuntimeScope = true includeSystemScope = true includeTestScope = false outputName = "sbom" outputFormat = "json" } dependencyCheck { format = 'HTML' failBuildOnAnyVulnerability = true suppressionFile = 'dependency-check-suppressions.xml' analyzers { assemblyEnabled = false } } Dockerfile with Aqua Security Scanning
# Multi-stage build for security FROM eclipse-temurin:17-jdk-jammy as builder WORKDIR /app COPY . . RUN ./mvnw clean package -DskipTests # Runtime stage FROM eclipse-temurin:17-jre-jammy RUN addgroup --system --gid 1000 javauser && \ adduser --system --uid 1000 --gid 1000 javauser WORKDIR /app # Copy application JAR COPY --from=builder /app/target/*.jar app.jar # Security hardening RUN apt-get update && \ apt-get install -y --no-install-recommends \ ca-certificates && \ rm -rf /var/lib/apt/lists/* # Non-root user USER javauser # Security-focused JVM options ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -Djava.security.egd=file:/dev/./urandom" EXPOSE 8080 ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
Aqua Security Pipeline Integration
GitHub Actions Workflow (.github/workflows/aqua-scan.yml):
name: Aqua Security Scan on: push: branches: [ main, develop ] pull_request: branches: [ main ] jobs: security-scan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up JDK 17 uses: actions/setup-java@v3 with: java-version: '17' distribution: 'temurin' cache: maven - name: Build and generate SBOM run: mvn clean package cyclonedx:makeAggregateBom -DskipTests - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: scan-type: 'fs' scan-ref: '.' format: 'sarif' output: 'trivy-results.sarif' - name: Upload Trivy scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@v2 with: sarif_file: 'trivy-results.sarif' - name: Docker build run: docker build -t my-java-app:${{ github.sha }} . - name: Scan Docker image with Trivy run: | trivy image \ --format template \ --template "@contrib/gitlab.tpl" \ --output gl-dependency-scanning-report.json \ my-java-app:${{ github.sha }} - name: Check for critical vulnerabilities run: | trivy image \ --severity CRITICAL \ --exit-code 1 \ my-java-app:${{ github.sha }} 2. Aqua Runtime Security for Java
Aqua Enforcer Configuration
Kubernetes Deployment with Aqua Security:
apiVersion: apps/v1 kind: Deployment metadata: name: java-app labels: app: java-app spec: replicas: 3 selector: matchLabels: app: java-app template: metadata: labels: app: java-app annotations: aquasec.com/enforcer: "true" aquasec.com/image: "registry.company.com/java-app:1.0.0" spec: serviceAccountName: java-app-sa containers: - name: java-app image: registry.company.com/java-app:1.0.0 ports: - containerPort: 8080 env: - name: JAVA_OPTS value: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -Djava.security.egd=file:/dev/./urandom" resources: requests: memory: "512Mi" cpu: "250m" limits: memory: "1Gi" cpu: "500m" securityContext: runAsNonRoot: true runAsUser: 1000 allowPrivilegeEscalation: false capabilities: drop: - ALL livenessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 15 periodSeconds: 5 --- apiVersion: v1 kind: ServiceAccount metadata: name: java-app-sa annotations: aquasec.com/enforcer: "true"
Java Application Security Configuration
Spring Security with Aqua Integration:
@Configuration @EnableWebSecurity public class AquaSecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authz -> authz .requestMatchers("/actuator/aqua/**").hasRole("AQUA_MONITOR") .requestMatchers("/public/**").permitAll() .anyRequest().authenticated() ) .oauth2ResourceServer(oauth2 -> oauth2 .jwt(Customizer.withDefaults()) ) .csrf(csrf -> csrf .ignoringRequestMatchers("/actuator/aqua/**") ); return http.build(); } @Bean public AquaRuntimeMonitor aquaRuntimeMonitor() { return new AquaRuntimeMonitor(); } } Aqua Runtime Monitoring Component:
@Component public class AquaRuntimeMonitor { private static final Logger logger = LoggerFactory.getLogger(AquaRuntimeMonitor.class); private final Map<String, SecurityEvent> securityEvents = new ConcurrentHashMap<>(); @EventListener public void handleAuthenticationFailure(AuthenticationFailureBadCredentialsEvent event) { SecurityEvent securityEvent = new SecurityEvent( "AUTH_FAILURE", "Authentication failure for user: " + event.getAuthentication().getName(), Instant.now(), SecurityEvent.Severity.MEDIUM ); logSecurityEvent(securityEvent); reportToAqua(securityEvent); } @EventListener public void handleAccessDenied(AccessDeniedEvent event) { SecurityEvent securityEvent = new SecurityEvent( "ACCESS_DENIED", "Access denied for user: " + event.getAuthentication().getName() + " to resource: " + event.getSource(), Instant.now(), SecurityEvent.Severity.HIGH ); logSecurityEvent(securityEvent); reportToAqua(securityEvent); } public void monitorFileSystemAccess(String path, String operation) { if (isSensitivePath(path)) { SecurityEvent securityEvent = new SecurityEvent( "SENSITIVE_FILE_ACCESS", String.format("Access to sensitive path: %s, operation: %s", path, operation), Instant.now(), SecurityEvent.Severity.HIGH ); logSecurityEvent(securityEvent); reportToAqua(securityEvent); } } private boolean isSensitivePath(String path) { return path.contains("/etc/passwd") || path.contains("/etc/shadow") || path.contains("/proc/") || path.contains("/sys/"); } private void logSecurityEvent(SecurityEvent event) { logger.warn("Security Event - Type: {}, Message: {}, Severity: {}", event.getType(), event.getMessage(), event.getSeverity()); securityEvents.put(event.getId(), event); } private void reportToAqua(SecurityEvent event) { // Integrate with Aqua API to report runtime security events // This would typically send events to Aqua CSP (Cloud Security Platform) } @RestController @RequestMapping("/actuator/aqua") public static class AquaMonitorEndpoint { private final AquaRuntimeMonitor monitor; public AquaMonitorEndpoint(AquaRuntimeMonitor monitor) { this.monitor = monitor; } @GetMapping("/events") public List<SecurityEvent> getSecurityEvents() { return new ArrayList<>(monitor.securityEvents.values()); } @PostMapping("/scan") public ResponseEntity<String> triggerRuntimeScan() { // Trigger runtime security scan return ResponseEntity.ok("Runtime scan initiated"); } } } // Security Event DTO class SecurityEvent { private String id; private String type; private String message; private Instant timestamp; private Severity severity; public SecurityEvent(String type, String message, Instant timestamp, Severity severity) { this.id = UUID.randomUUID().toString(); this.type = type; this.message = message; this.timestamp = timestamp; this.severity = severity; } // Getters public String getId() { return id; } public String getType() { return type; } public String getMessage() { return message; } public Instant getTimestamp() { return timestamp; } public Severity getSeverity() { return severity; } public enum Severity { LOW, MEDIUM, HIGH, CRITICAL } } 3. Aqua CSP (Cloud Security Platform) Integration
Application-Specific Policies
Aqua CSP Policy Definition (YAML):
# aqua-policy.yaml apiVersion: aquasec.com/v1 kind: ApplicationPolicy metadata: name: java-app-security-policy spec: application: java-order-service rules: - name: block-critical-vulnerabilities description: Block deployment if critical vulnerabilities found condition: severity: CRITICAL maxAllowed: 0 action: BLOCK - name: warn-high-vulnerabilities description: Warn on high severity vulnerabilities condition: severity: HIGH maxAllowed: 3 action: WARN - name: require-non-root-user description: Require containers to run as non-root user condition: container: runAsRoot: false action: BLOCK - name: block-privileged-containers description: Block privileged containers condition: container: privileged: false action: BLOCK - name: require-readonly-filesystem description: Require read-only root filesystem condition: container: readOnlyRootFilesystem: true action: WARN - name: block-dangerous-capabilities description: Block containers with dangerous capabilities condition: container: capabilities: - NET_RAW - SYS_ADMIN - SYS_MODULE action: BLOCK - name: runtime-threat-detection description: Enable runtime threat detection condition: runtime: threatDetection: true action: ENFORCE
Kubernetes Security Policies
Aqua Admission Controller Configuration:
apiVersion: aquasec.com/v1 kind: ClusterAdmissionRule metadata: name: java-app-admission spec: match: - namespace: "production" policies: - name: java-app-security-policy actions: - audit - deny settings: enabled: true blockUnauthorizedImages: true
4. Aqua Security in CI/CD Pipeline
Jenkins Pipeline with Aqua Security
pipeline { agent any environment { AQUA_URL = 'https://aqua.company.com' AQUA_USERNAME = credentials('aqua-username') AQUA_PASSWORD = credentials('aqua-password') } stages { stage('Checkout') { steps { git branch: 'main', url: 'https://github.com/company/java-app.git' } } stage('Build') { steps { sh 'mvn clean compile -DskipTests' } } stage('Dependency Scan') { steps { sh 'mvn org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom' aquaMicroscanner imageName: 'java-app:latest' } } stage('Test') { steps { sh 'mvn test' } } stage('Build Docker Image') { steps { sh 'docker build -t java-app:${GIT_COMMIT} .' } } stage('Aqua Security Scan') { steps { script { def scanner = aquaScanner( image: 'java-app:${GIT_COMMIT}', aquaServer: AQUA_URL, aquaUsername: AQUA_USERNAME, aquaPassword: AQUA_PASSWORD, failBuild: true ) if (scanner.hasVulnerabilities()) { error "Aqua Security scan found vulnerabilities" } } } } stage('Deploy to Staging') { when { expression { env.BRANCH_NAME == 'main' } } steps { kubernetesDeploy( kubeconfigId: 'k8s-cluster', configs: 'k8s/staging-deployment.yaml' ) } } } post { always { aquaPublishResults( aquaServer: AQUA_URL, aquaUsername: AQUA_USERNAME, aquaPassword: AQUA_PASSWORD ) } } } 5. Aqua Runtime Security Monitoring
Custom Java Security Agent
@Component public class AquaSecurityAgent { private final Runtime runtime = Runtime.getRuntime(); private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); @PostConstruct public void init() { // Monitor system properties for security violations scheduler.scheduleAtFixedRate(this::monitorSecurity, 0, 30, TimeUnit.SECONDS); } private void monitorSecurity() { monitorSystemProperties(); monitorEnvironmentVariables(); monitorFileSystemAccess(); monitorNetworkConnections(); } private void monitorSystemProperties() { Properties props = System.getProperties(); // Check for suspicious system properties String suspiciousProps = props.stringPropertyNames().stream() .filter(this::isSuspiciousProperty) .collect(Collectors.joining(", ")); if (!suspiciousProps.isEmpty()) { reportSecurityEvent("SUSPICIOUS_SYSTEM_PROPERTIES", "Found suspicious system properties: " + suspiciousProps); } } private boolean isSuspiciousProperty(String propertyName) { return propertyName.contains("jndi") || propertyName.contains("ldap") || propertyName.contains("rmi") || propertyName.contains("codebase"); } private void monitorEnvironmentVariables() { Map<String, String> env = System.getenv(); // Check for sensitive environment variables exposure env.forEach((key, value) -> { if (key.toUpperCase().contains("PASSWORD") || key.toUpperCase().contains("SECRET") || key.toUpperCase().contains("KEY")) { reportSecurityEvent("SENSITIVE_ENV_VAR_EXPOSED", "Sensitive environment variable detected: " + key); } }); } private void monitorFileSystemAccess() { // Monitor file system access patterns // This would integrate with Java Security Manager or custom file system watcher } private void monitorNetworkConnections() { try { // Monitor outbound network connections Process process = runtime.exec("netstat -an"); try (BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { if (line.contains("ESTABLISHED")) { // Analyze established connections analyzeNetworkConnection(line); } } } } catch (IOException e) { logger.error("Failed to monitor network connections", e); } } private void analyzeNetworkConnection(String connectionInfo) { // Analyze if connection is to suspicious destinations if (connectionInfo.contains(":1337") || connectionInfo.contains(":4444") || connectionInfo.contains(".onion")) { reportSecurityEvent("SUSPICIOUS_NETWORK_CONNECTION", "Suspicious network connection detected: " + connectionInfo); } } private void reportSecurityEvent(String type, String message) { // Report to Aqua CSP logger.warn("Security Event - {}: {}", type, message); // Integration with Aqua API would go here // aquaClient.reportSecurityEvent(type, message, getContext()); } @PreDestroy public void cleanup() { scheduler.shutdown(); } } 6. Aqua Compliance and Governance
Compliance Check Configuration
# compliance-policy.yaml apiVersion: aquasec.com/v1 kind: CompliancePolicy metadata: name: java-app-pci-dss spec: standards: - name: PCI-DSS version: "3.2.1" rules: - id: "java-app-encryption" description: "Java app must use TLS 1.2 or higher" check: type: "configuration" path: "app.security.tls.version" expected: ">=1.2" - id: "java-app-logging" description: "Java app must implement audit logging" check: type: "file" path: "/app/logs/audit.log" exists: true - id: "java-app-authentication" description: "Java app must use strong authentication" check: type: "configuration" path: "app.security.auth.strength" expected: "high"
Aqua Security Dashboard Integration
Custom Security Metrics Exporter:
@Component public class AquaSecurityMetrics { private final MeterRegistry meterRegistry; private final Counter securityViolations; private final Gauge vulnerabilityCount; public AquaSecurityMetrics(MeterRegistry meterRegistry) { this.meterRegistry = meterRegistry; this.securityViolations = Counter.builder("aqua.security.violations") .description("Number of security policy violations") .tag("application", "java-app") .register(meterRegistry); this.vulnerabilityCount = Gauge.builder("aqua.security.vulnerabilities") .description("Number of known vulnerabilities") .tag("application", "java-app") .register(meterRegistry); } public void recordViolation(String policy, String severity) { securityViolations.increment(); // Additional metrics recording Counter.builder("aqua.security.violations.by.policy") .tag("policy", policy) .tag("severity", severity) .register(meterRegistry) .increment(); } public void updateVulnerabilityCount(int count) { vulnerabilityCount.set(count); } } This comprehensive guide shows how to integrate Aqua Security throughout the Java application lifecycle, from development to runtime, ensuring security compliance and vulnerability management at every stage.