Sysdig Secure for Containers in Java

Introduction

Sysdig Secure is a container security platform that provides runtime security, vulnerability management, and compliance for containerized applications. It uses eBPF technology to provide deep visibility and security for Java applications running in containers.

Architecture Overview

Sysdig Secure Architecture for Java Containers

┌─────────────────────────────────────────────────────────────┐
│                    Java Application Container               │
├─────────────────────────────────────────────────────────────┤
│               Sysdig Agent (eBPF-based)                     │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  │
│  │  System     │  │  Network    │  │   Security          │  │
│  │   Calls     │  │  Activity   │  │   Policies          │  │
│  └─────────────┘  └─────────────┘  └─────────────────────┘  │
├─────────────────────────────────────────────────────────────┤
│                    Container Runtime                        │
└─────────────────────────────────────────────────────────────┘

Installation and Setup

1. Sysdig Agent Installation

Kubernetes Deployment

# k8s/sysdig-agent.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: sysdig-agent-config
data:
dragent.yaml: |
sysdig:
access_key: ${ACCESS_KEY}
url: https://us2.app.sysdig.com
security:
enabled: true
falco_rules_filename: ["falco_rules.yaml", "java_rules.yaml"]
new_k8s: true
k8s_cluster_name: production-cluster
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: sysdig-agent
labels:
app: sysdig-agent
spec:
selector:
matchLabels:
app: sysdig-agent
template:
metadata:
labels:
app: sysdig-agent
spec:
hostNetwork: true
hostPID: true
containers:
- name: sysdig-agent
image: sysdig/agent:latest
imagePullPolicy: Always
env:
- name: ACCESS_KEY
valueFrom:
secretKeyRef:
name: sysdig-access-key
key: access-key
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
securityContext:
privileged: true
volumeMounts:
- mountPath: /host/var/run/docker.sock
name: docker-sock
- mountPath: /host/dev
name: dev-vol
- mountPath: /host/proc
name: proc-vol
readOnly: true
- mountPath: /host/boot
name: boot-vol
readOnly: true
- mountPath: /host/lib/modules
name: lib-modules-vol
readOnly: true
- mountPath: /host/usr
name: usr-vol
readOnly: true
- mountPath: /etc/sysdig
name: sysdig-agent-config
volumes:
- name: docker-sock
hostPath:
path: /var/run/docker.sock
- name: dev-vol
hostPath:
path: /dev
- name: proc-vol
hostPath:
path: /proc
- name: boot-vol
hostPath:
path: /boot
- name: lib-modules-vol
hostPath:
path: /lib/modules
- name: usr-vol
hostPath:
path: /usr
- name: sysdig-agent-config
configMap:
name: sysdig-agent-config
tolerations:
- effect: NoSchedule
operator: Exists

Installation Script

#!/bin/bash
# install-sysdig-agent.sh
set -euo pipefail
CLUSTER_NAME="production-cluster"
ACCESS_KEY="${SYSFIG_ACCESS_KEY}"
# Create namespace
kubectl create namespace sysdig-agent
# Create secret
kubectl create secret generic sysdig-access-key \
--from-literal=access-key=$ACCESS_KEY \
-n sysdig-agent
# Deploy agent
kubectl apply -f k8s/sysdig-agent.yaml
# Verify installation
kubectl get pods -n sysdig-agent
kubectl logs -f daemonset/sysdig-agent -n sysdig-agent

Java Application Security

2. Secure Java Container Configuration

Security-Hardened Dockerfile

# Dockerfile for Secure Java Application
FROM eclipse-temurin:17-jre-jammy as runtime
# Security: Use non-root user
RUN groupadd -r javaapp && useradd -r -g javaapp javaapp
# Security: Create app directory with proper permissions
RUN mkdir -p /app && chown javaapp:javaapp /app
WORKDIR /app
# Security: Copy application with correct ownership
COPY --chown=javaapp:javaapp target/*.jar app.jar
# Security: Use signed base images only
# Security: Minimal base image with no shell
# Security: Read-only root filesystem
RUN chmod 755 /app && \
chmod 644 app.jar
# Security: Drop capabilities
# Security: No new privileges
# Security: Read-only root filesystem
# Security: Disable ptrace
# Switch to non-root user
USER javaapp
# Security: Use secure JVM options
ENV JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom \
-Djava.awt.headless=true \
-Dspring.profiles.active=production \
-Dlog4j2.formatMsgNoLookups=true"
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
CMD curl -f http://localhost:8080/actuator/health || exit 1
# Security: Expose non-privileged port
EXPOSE 8080
# Security: Use exec form for proper signal handling
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

Security Context in Kubernetes

# k8s/secure-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
labels:
app: user-service
spec:
replicas: 3
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
annotations:
# Sysdig annotations for enhanced monitoring
sysdig.com/monitoring: "true"
sysdig.com/secure: "enabled"
spec:
securityContext:
# Pod security context
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault
containers:
- name: user-service
image: company/user-service:1.0.0
securityContext:
# Container security context
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 1000
privileged: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
ports:
- containerPort: 8080
env:
- name: JAVA_OPTS
value: "-Djava.security.egd=file:/dev/./urandom -Xmx512m -Xms256m"
- name: SYSFIG_CAPTURE_ENABLED
value: "true"
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
volumeMounts:
- name: tmp
mountPath: /tmp
- name: logs
mountPath: /app/logs
volumes:
- name: tmp
emptyDir: {}
- name: logs
emptyDir: {}

3. Custom Security Rules for Java Applications

Java-Specific Falco Rules

# java-security-rules.yaml
- rule: Java Process Spawned Shell
desc: Detect Java process spawning shell commands
condition: >
proc.name = "java" and 
(spawned_process and 
(proc.name in (bash, sh, zsh, ksh, csh, tcsh)))
output: >
Java process spawned shell (user=%user.name command=%proc.cmdline 
container=%container.info shell=%proc.name parent=%proc.pname)
priority: WARNING
tags: [java, process, container]
- rule: Java File System Write in Sensitive Location
desc: Detect Java writing to sensitive file system locations
condition: >
proc.name = "java" and 
(write and 
(fd.name startswith /etc or 
fd.name startswith /bin or 
fd.name startswith /sbin or 
fd.name startswith /usr/bin))
output: >
Java process wrote to sensitive location (user=%user.name 
command=%proc.cmdline container=%container.info file=%fd.name)
priority: CRITICAL
tags: [java, filesystem, container]
- rule: Java Network Connection to Suspicious Ports
desc: Detect Java making network connections to suspicious ports
condition: >
proc.name = "java" and 
(evt.type = connect and 
(server_port < 1024 and server_port != 80 and server_port != 443 and 
server_port != 8080 and server_port != 8443))
output: >
Java process connected to suspicious port (user=%user.name 
command=%proc.cmdline container=%container.info port=%server_port)
priority: WARNING
tags: [java, network, container]
- rule: Java Process Memory Execution
desc: Detect Java process executing from memory
condition: >
proc.name = "java" and 
(evt.type = execve and evt.dir=> and 
(proc.exe != /usr/lib/jvm/java-17-openjdk/bin/java))
output: >
Java process executed from memory (user=%user.name 
command=%proc.cmdline container=%container.info)
priority: CRITICAL
tags: [java, process, container]
- rule: Java Deserialization Attack Detection
desc: Detect potential Java deserialization attacks
condition: >
proc.name = "java" and 
(evt.type in (open, openat) and 
(fd.name contains ".ser" or fd.name contains ".serialized"))
output: >
Java process accessed serialized file (user=%user.name 
command=%proc.cmdline container=%container.info file=%fd.name)
priority: WARNING
tags: [java, deserialization, container]
- rule: Java Classpath Manipulation
desc: Detect Java process modifying classpath or loading external classes
condition: >
proc.name = "java" and 
(evt.type in (open, openat, execve) and 
(proc.cmdline contains "-cp" or proc.cmdline contains "-classpath" or
proc.cmdline contains "javaagent:"))
output: >
Java process with classpath manipulation (user=%user.name 
command=%proc.cmdline container=%container.info)
priority: WARNING
tags: [java, classpath, container]

Runtime Security Monitoring

4. Java Application Security Integration

Security Event Monitoring Service

@Service
public class SecurityEventMonitor {
private static final Logger logger = LoggerFactory.getLogger(SecurityEventMonitor.class);
private final MeterRegistry meterRegistry;
private final Counter securityEventCounter;
public SecurityEventMonitor(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
this.securityEventCounter = Counter.builder("security_events")
.description("Security events detected in the application")
.register(meterRegistry);
}
@EventListener
public void handleSecurityEvent(SecurityEvent event) {
logger.warn("Security event detected: {}", event.getDescription());
securityEventCounter.increment();
// Tag the event with severity and type
Tags tags = Tags.of(
Tag.of("severity", event.getSeverity().name()),
Tag.of("type", event.getType()),
Tag.of("source", event.getSource())
);
meterRegistry.counter("security_events_detailed", tags).increment();
// Log to security audit log
auditSecurityEvent(event);
}
public void monitorSuspiciousActivity(String activity, String details) {
logger.warn("Suspicious activity detected: {} - {}", activity, details);
Tags tags = Tags.of(
Tag.of("activity", activity),
Tag.of("details", details)
);
meterRegistry.counter("suspicious_activities", tags).increment();
}
public void monitorFileAccess(String filePath, String operation) {
if (isSensitiveFile(filePath)) {
logger.warn("Sensitive file accessed: {} - {}", filePath, operation);
Tags tags = Tags.of(
Tag.of("file", filePath),
Tag.of("operation", operation)
);
meterRegistry.counter("sensitive_file_access", tags).increment();
}
}
public void monitorNetworkConnection(String host, int port, String protocol) {
if (isSuspiciousDestination(host, port)) {
logger.warn("Suspicious network connection: {}:{} via {}", host, port, protocol);
Tags tags = Tags.of(
Tag.of("host", host),
Tag.of("port", String.valueOf(port)),
Tag.of("protocol", protocol)
);
meterRegistry.counter("suspicious_connections", tags).increment();
}
}
private boolean isSensitiveFile(String filePath) {
return filePath.contains("/etc/") || 
filePath.contains("/bin/") || 
filePath.contains("/sys/") ||
filePath.contains("/proc/") ||
filePath.endsWith(".key") ||
filePath.endsWith(".pem") ||
filePath.endsWith(".jks");
}
private boolean isSuspiciousDestination(String host, int port) {
// Define suspicious destinations
return port < 1024 && port != 80 && port != 443 && port != 8080 && port != 8443;
}
private void auditSecurityEvent(SecurityEvent event) {
// Send to security information and event management (SIEM) system
// Integrate with Sysdig Secure API
logger.info("SECURITY_AUDIT: {}", event);
}
}
// Security Event Classes
@Data
class SecurityEvent {
private final String type;
private final String description;
private final Severity severity;
private final String source;
private final Instant timestamp;
private final Map<String, Object> details;
public SecurityEvent(String type, String description, Severity severity, String source) {
this.type = type;
this.description = description;
this.severity = severity;
this.source = source;
this.timestamp = Instant.now();
this.details = new HashMap<>();
}
public SecurityEvent withDetail(String key, Object value) {
this.details.put(key, value);
return this;
}
}
enum Severity {
LOW, MEDIUM, HIGH, CRITICAL
}

5. Security Aspect for Method Monitoring

@Aspect
@Component
public class SecurityMonitoringAspect {
private final SecurityEventMonitor securityMonitor;
public SecurityMonitoringAspect(SecurityEventMonitor securityMonitor) {
this.securityMonitor = securityMonitor;
}
@Around("execution(* com.company..*(..)) && " +
"@annotation(monitorSecurity)")
public Object monitorSecuritySensitiveMethods(ProceedingJoinPoint joinPoint, 
MonitorSecurity monitorSecurity) throws Throwable {
String methodName = joinPoint.getSignature().getName();
String className = joinPoint.getTarget().getClass().getSimpleName();
long startTime = System.currentTimeMillis();
try {
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() - startTime;
// Log successful execution
if (monitorSecurity.logSuccess()) {
logger.debug("Security-sensitive method executed: {}.{} in {}ms", 
className, methodName, duration);
}
return result;
} catch (Exception e) {
long duration = System.currentTimeMillis() - startTime;
// Create security event for exceptions in security-sensitive methods
SecurityEvent event = new SecurityEvent(
"METHOD_EXCEPTION",
String.format("Exception in security-sensitive method %s.%s: %s", 
className, methodName, e.getMessage()),
Severity.MEDIUM,
"SecurityAspect"
).withDetail("method", methodName)
.withDetail("class", className)
.withDetail("exception", e.getClass().getSimpleName())
.withDetail("duration", duration);
securityMonitor.handleSecurityEvent(event);
throw e;
}
}
@AfterReturning(pointcut = "execution(* java.io.*.*(..)) || " +
"execution(* java.nio.file.*.*(..))", 
returning = "result")
public void monitorFileOperations(JoinPoint joinPoint, Object result) {
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
// Monitor file operations
for (Object arg : args) {
if (arg instanceof String) {
String path = (String) arg;
securityMonitor.monitorFileAccess(path, methodName);
} else if (arg instanceof Path) {
Path path = (Path) arg;
securityMonitor.monitorFileAccess(path.toString(), methodName);
}
}
}
}
// Annotation for security-sensitive methods
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MonitorSecurity {
boolean logSuccess() default false;
Severity severity() default Severity.MEDIUM;
}

Vulnerability Management

6. Vulnerability Scanning Integration

Pre-commit Security Scanning

@Component
public class VulnerabilityScanner {
private final RestTemplate restTemplate;
private final SysdigSecureClient sysdigClient;
public VulnerabilityScanner(RestTemplate restTemplate, 
SysdigSecureClient sysdigClient) {
this.restTemplate = restTemplate;
this.sysdigClient = sysdigClient;
}
public VulnerabilityReport scanImage(String imageName, String imageTag) {
try {
// Trigger Sysdig Secure vulnerability scan
ScanRequest request = new ScanRequest(imageName, imageTag);
ScanResponse response = sysdigClient.scanImage(request);
return analyzeVulnerabilities(response);
} catch (Exception e) {
logger.error("Failed to scan image {}:{}", imageName, imageTag, e);
throw new SecurityScanException("Vulnerability scan failed", e);
}
}
public ComplianceReport checkCompliance(String imageName, String imageTag) {
try {
// Check compliance against standards
ComplianceRequest request = new ComplianceRequest(imageName, imageTag);
ComplianceResponse response = sysdigClient.checkCompliance(request);
return analyzeCompliance(response);
} catch (Exception e) {
logger.error("Failed to check compliance for {}:{}", imageName, imageTag, e);
throw new SecurityScanException("Compliance check failed", e);
}
}
public boolean isImageApproved(String imageName, String imageTag) {
VulnerabilityReport vulnerabilityReport = scanImage(imageName, imageTag);
ComplianceReport complianceReport = checkCompliance(imageName, imageTag);
return vulnerabilityReport.isApproved() && complianceReport.isCompliant();
}
private VulnerabilityReport analyzeVulnerabilities(ScanResponse response) {
List<Vulnerability> criticalVulns = response.getVulnerabilities().stream()
.filter(v -> v.getSeverity() == Severity.CRITICAL)
.collect(Collectors.toList());
List<Vulnerability> highVulns = response.getVulnerabilities().stream()
.filter(v -> v.getSeverity() == Severity.HIGH)
.collect(Collectors.toList());
boolean approved = criticalVulns.isEmpty() && highVulns.size() <= 3;
return new VulnerabilityReport(response.getVulnerabilities(), approved);
}
private ComplianceReport analyzeCompliance(ComplianceResponse response) {
List<ComplianceCheck> failedChecks = response.getChecks().stream()
.filter(check -> !check.isPassed())
.collect(Collectors.toList());
boolean compliant = failedChecks.size() <= response.getAllowedFailures();
return new ComplianceReport(response.getChecks(), compliant);
}
}
// Report Classes
@Data
class VulnerabilityReport {
private final List<Vulnerability> vulnerabilities;
private final boolean approved;
private final Instant scanTime;
public VulnerabilityReport(List<Vulnerability> vulnerabilities, boolean approved) {
this.vulnerabilities = vulnerabilities;
this.approved = approved;
this.scanTime = Instant.now();
}
public long getCriticalCount() {
return vulnerabilities.stream()
.filter(v -> v.getSeverity() == Severity.CRITICAL)
.count();
}
public long getHighCount() {
return vulnerabilities.stream()
.filter(v -> v.getSeverity() == Severity.HIGH)
.count();
}
}
@Data
class ComplianceReport {
private final List<ComplianceCheck> checks;
private final boolean compliant;
private final Instant checkTime;
public ComplianceReport(List<ComplianceCheck> checks, boolean compliant) {
this.checks = checks;
this.compliant = compliant;
this.checkTime = Instant.now();
}
public List<ComplianceCheck> getFailedChecks() {
return checks.stream()
.filter(check -> !check.isPassed())
.collect(Collectors.toList());
}
}

7. Admission Controller for Security

Kubernetes Validating Webhook

@RestController
@RequestMapping("/admission")
public class SecurityAdmissionController {
private final VulnerabilityScanner vulnerabilityScanner;
private final ObjectMapper objectMapper;
public SecurityAdmissionController(VulnerabilityScanner vulnerabilityScanner) {
this.vulnerabilityScanner = vulnerabilityScanner;
this.objectMapper = new ObjectMapper();
}
@PostMapping("/validate")
public AdmissionReview validateDeployment(@RequestBody AdmissionReview review) {
try {
AdmissionRequest request = review.getRequest();
// Extract deployment information
DeploymentInfo deploymentInfo = extractDeploymentInfo(request);
// Check image security
boolean approved = validateImageSecurity(deploymentInfo);
// Create response
AdmissionResponse response = new AdmissionResponse();
response.setUid(request.getUid());
response.setAllowed(approved);
if (!approved) {
response.setStatus(new AdmissionResponseStatus("Failure", 
"Image security validation failed. Check vulnerabilities and compliance."));
}
return new AdmissionReview(response);
} catch (Exception e) {
logger.error("Admission validation failed", e);
return createErrorResponse(review.getRequest().getUid(), 
"Admission validation error: " + e.getMessage());
}
}
private DeploymentInfo extractDeploymentInfo(AdmissionRequest request) {
try {
String deploymentJson = objectMapper.writeValueAsString(request.getObject());
JsonNode deploymentNode = objectMapper.readTree(deploymentJson);
String image = deploymentNode.path("spec")
.path("template")
.path("spec")
.path("containers")
.get(0)
.path("image")
.asText();
String[] imageParts = image.split(":");
String imageName = imageParts[0];
String imageTag = imageParts.length > 1 ? imageParts[1] : "latest";
return new DeploymentInfo(imageName, imageTag, request.getNamespace());
} catch (Exception e) {
throw new AdmissionException("Failed to extract deployment info", e);
}
}
private boolean validateImageSecurity(DeploymentInfo deploymentInfo) {
try {
// Check if image is approved
boolean imageApproved = vulnerabilityScanner.isImageApproved(
deploymentInfo.getImageName(), 
deploymentInfo.getImageTag());
if (!imageApproved) {
logger.warn("Image security validation failed for {}:{} in namespace {}", 
deploymentInfo.getImageName(), deploymentInfo.getImageTag(),
deploymentInfo.getNamespace());
return false;
}
// Additional security checks
boolean securityContextValid = validateSecurityContext(deploymentInfo);
return securityContextValid;
} catch (Exception e) {
logger.error("Image security validation error for {}:{}", 
deploymentInfo.getImageName(), deploymentInfo.getImageTag(), e);
return false;
}
}
private boolean validateSecurityContext(DeploymentInfo deploymentInfo) {
// Validate security context requirements
// - Non-root user
// - Read-only root filesystem
// - No privilege escalation
// - etc.
return true; // Simplified for example
}
private AdmissionReview createErrorResponse(String uid, String message) {
AdmissionResponse response = new AdmissionResponse();
response.setUid(uid);
response.setAllowed(false);
response.setStatus(new AdmissionResponseStatus("Failure", message));
return new AdmissionReview(response);
}
}
@Data
class DeploymentInfo {
private final String imageName;
private final String imageTag;
private final String namespace;
}

Runtime Policy Enforcement

8. Security Policy Configuration

Sysdig Secure Policies

# java-security-policies.yaml
apiVersion: security.sysdig.com/v1
kind: Policy
metadata:
name: java-container-security
spec:
rules:
- name: "Java Container Security"
description: "Security policies for Java containers"
scope:
- container:
image: "company/*"
actions:
- containerExec: block
- containerTerminal: block
- networkDetection: alert
condition:
and:
- proc.name = java
- not:
k8s.pod.label.app in (user-service, profile-service, api-gateway)
---
apiVersion: security.sysdig.com/v1
kind: Policy
metadata:
name: java-file-integrity
spec:
rules:
- name: "Java File Integrity Monitoring"
description: "Monitor file system changes in Java containers"
scope:
- container:
image: "company/java-*"
actions:
- fileModification: alert
condition:
and:
- proc.name = java
- fd.name contains "/app/"
- not:
fd.name endswith ".log"
---
apiVersion: security.sysdig.com/v1
kind: Policy
metadata:
name: java-network-policy
spec:
rules:
- name: "Java Network Policy"
description: "Network security policies for Java applications"
scope:
- container:
image: "company/*"
actions:
- networkConnection: alert
condition:
and:
- proc.name = java
- server_port not in (80, 443, 8080, 8443, 9092, 5432)

9. Real-time Security Monitoring

Security Dashboard Integration

@Service
public class SecurityDashboardService {
private final SysdigSecureClient sysdigClient;
private final MeterRegistry meterRegistry;
public SecurityDashboardService(SysdigSecureClient sysdigClient,
MeterRegistry meterRegistry) {
this.sysdigClient = sysdigClient;
this.meterRegistry = meterRegistry;
}
@Scheduled(fixedRate = 30000) // Every 30 seconds
public void updateSecurityMetrics() {
try {
SecurityMetrics metrics = sysdigClient.getSecurityMetrics();
updateMetrics(metrics);
} catch (Exception e) {
logger.error("Failed to update security metrics", e);
}
}
@Scheduled(fixedRate = 60000) // Every minute
public void checkRuntimeThreats() {
try {
List<SecurityEvent> threats = sysdigClient.getRecentThreats();
processThreats(threats);
} catch (Exception e) {
logger.error("Failed to check runtime threats", e);
}
}
public SecurityStatus getSecurityStatus() {
try {
RuntimeSecurityStatus status = sysdigClient.getRuntimeSecurityStatus();
return mapToSecurityStatus(status);
} catch (Exception e) {
logger.error("Failed to get security status", e);
return SecurityStatus.ERROR;
}
}
private void updateMetrics(SecurityMetrics metrics) {
// Update Micrometer metrics
Gauge.builder("security.vulnerabilities.critical")
.description("Critical vulnerabilities count")
.register(meterRegistry, metrics::getCriticalVulnerabilities);
Gauge.builder("security.vulnerabilities.high")
.description("High vulnerabilities count")
.register(meterRegistry, metrics::getHighVulnerabilities);
Gauge.builder("security.runtime.threats")
.description("Active runtime threats")
.register(meterRegistry, metrics::getActiveThreats);
Gauge.builder("security.compliance.score")
.description("Compliance score percentage")
.register(meterRegistry, metrics::getComplianceScore);
}
private void processThreats(List<SecurityEvent> threats) {
for (SecurityEvent threat : threats) {
logger.warn("Runtime threat detected: {}", threat.getDescription());
// Alert based on severity
if (threat.getSeverity() == Severity.CRITICAL) {
sendCriticalAlert(threat);
}
}
}
private void sendCriticalAlert(SecurityEvent threat) {
// Integrate with alerting system (PagerDuty, Slack, etc.)
logger.error("CRITICAL SECURITY ALERT: {}", threat);
}
private SecurityStatus mapToSecurityStatus(RuntimeSecurityStatus status) {
if (status.getCriticalThreats() > 0) {
return SecurityStatus.CRITICAL;
} else if (status.getHighThreats() > 5) {
return SecurityStatus.WARNING;
} else {
return SecurityStatus.HEALTHY;
}
}
}
enum SecurityStatus {
HEALTHY, WARNING, CRITICAL, ERROR
}

Incident Response

10. Automated Incident Response

Security Incident Handler

@Service
public class SecurityIncidentHandler {
private final SecurityEventMonitor securityMonitor;
private final KubernetesClient kubernetesClient;
private final SysdigSecureClient sysdigClient;
public SecurityIncidentHandler(SecurityEventMonitor securityMonitor,
KubernetesClient kubernetesClient,
SysdigSecureClient sysdigClient) {
this.securityMonitor = securityMonitor;
this.kubernetesClient = kubernetesClient;
this.sysdigClient = sysdigClient;
}
@EventListener
public void handleCriticalSecurityEvent(SecurityEvent event) {
if (event.getSeverity() == Severity.CRITICAL) {
logger.error("Handling critical security event: {}", event.getDescription());
// Automated response actions
switch (event.getType()) {
case "CONTAINER_BREACH":
handleContainerBreach(event);
break;
case "MALICIOUS_PROCESS":
handleMaliciousProcess(event);
break;
case "UNAUTHORIZED_ACCESS":
handleUnauthorizedAccess(event);
break;
default:
logger.warn("No specific handler for event type: {}", event.getType());
}
}
}
private void handleContainerBreach(SecurityEvent event) {
String containerId = (String) event.getDetails().get("containerId");
String podName = (String) event.getDetails().get("podName");
String namespace = (String) event.getDetails().get("namespace");
logger.warn("Container breach detected in pod {}/{}", namespace, podName);
try {
// Isolate the pod by adding network policies
isolatePod(podName, namespace);
// Capture forensic data
captureForensicData(podName, namespace);
// Scale down the deployment
scaleDownDeployment(podName, namespace);
// Notify security team
notifySecurityTeam(event);
} catch (Exception e) {
logger.error("Failed to handle container breach for pod {}/{}", 
namespace, podName, e);
}
}
private void handleMaliciousProcess(SecurityEvent event) {
String containerId = (String) event.getDetails().get("containerId");
String processName = (String) event.getDetails().get("processName");
logger.warn("Malicious process detected: {} in container {}", 
processName, containerId);
// Kill the malicious process
killProcess(containerId, processName);
// Create security policy to block similar processes
createBlockingPolicy(processName);
}
private void handleUnauthorizedAccess(SecurityEvent event) {
String sourceIp = (String) event.getDetails().get("sourceIp");
String user = (String) event.getDetails().get("user");
logger.warn("Unauthorized access detected from IP: {} by user: {}", 
sourceIp, user);
// Block the source IP
blockSourceIp(sourceIp);
// Revoke user access if applicable
revokeUserAccess(user);
}
private void isolatePod(String podName, String namespace) {
// Create network policy to isolate the pod
NetworkPolicy policy = new NetworkPolicyBuilder()
.withNewMetadata()
.withName("isolate-" + podName)
.withNamespace(namespace)
.endMetadata()
.withNewSpec()
.withNewPodSelector()
.addToMatchLabels("pod-name", podName)
.endPodSelector()
.withPolicyTypes("Ingress", "Egress")
.withNewIngress()
.addNewFrom()
.withNewPodSelector()
.addToMatchLabels("app", "security-scanner")
.endPodSelector()
.endFrom()
.endIngress()
.endSpec()
.build();
kubernetesClient.network().networkPolicies()
.inNamespace(namespace)
.createOrReplace(policy);
}
private void captureForensicData(String podName, String namespace) {
// Use Sysdig Secure to capture forensic data
sysdigClient.captureContainerData(podName, namespace);
}
private void scaleDownDeployment(String podName, String namespace) {
// Find deployment for the pod and scale to 0
kubernetesClient.apps().deployments()
.inNamespace(namespace)
.withName(getDeploymentName(podName))
.scale(0);
}
private void killProcess(String containerId, String processName) {
// Use Sysdig Secure to kill the process
sysdigClient.killProcess(containerId, processName);
}
private String getDeploymentName(String podName) {
// Extract deployment name from pod name
return podName.substring(0, podName.lastIndexOf('-'));
}
}

Best Practices and Compliance

11. Security Compliance Reporting

Compliance Service

@Service
public class ComplianceService {
private final SysdigSecureClient sysdigClient;
private final VulnerabilityScanner vulnerabilityScanner;
public ComplianceService(SysdigSecureClient sysdigClient,
VulnerabilityScanner vulnerabilityScanner) {
this.sysdigClient = sysdigClient;
this.vulnerabilityScanner = vulnerabilityScanner;
}
public ComplianceReport generateComplianceReport(String namespace) {
try {
List<PodSecurityReport> podReports = getPodSecurityReports(namespace);
List<ImageSecurityReport> imageReports = getImageSecurityReports(namespace);
RuntimeSecurityReport runtimeReport = getRuntimeSecurityReport(namespace);
return compileComplianceReport(podReports, imageReports, runtimeReport);
} catch (Exception e) {
logger.error("Failed to generate compliance report for namespace {}", 
namespace, e);
throw new ComplianceException("Compliance report generation failed", e);
}
}
public boolean checkCISCompliance(String namespace) {
try {
CISComplianceReport cisReport = sysdigClient.getCISCompliance(namespace);
return cisReport.isCompliant() && cisReport.getScore() >= 90;
} catch (Exception e) {
logger.error("Failed to check CIS compliance for namespace {}", namespace, e);
return false;
}
}
public void enforceCompliancePolicies(String namespace) {
List<ComplianceViolation> violations = 
sysdigClient.getComplianceViolations(namespace);
for (ComplianceViolation violation : violations) {
if (violation.getSeverity() == Severity.CRITICAL) {
enforceCriticalViolation(violation);
}
}
}
private List<PodSecurityReport> getPodSecurityReports(String namespace) {
// Get pod security context compliance
return kubernetesClient.pods()
.inNamespace(namespace)
.list()
.getItems()
.stream()
.map(this::analyzePodSecurity)
.collect(Collectors.toList());
}
private PodSecurityReport analyzePodSecurity(Pod pod) {
PodSecurityReport report = new PodSecurityReport(pod.getMetadata().getName());
// Check security context
if (pod.getSpec().getSecurityContext() == null) {
report.addViolation("Missing pod security context");
}
// Check container security contexts
pod.getSpec().getContainers().forEach(container -> {
if (container.getSecurityContext() == null) {
report.addViolation(
String.format("Container %s missing security context", 
container.getName()));
} else {
checkContainerSecurityContext(container, report);
}
});
return report;
}
private void checkContainerSecurityContext(Container container, 
PodSecurityReport report) {
SecurityContext sc = container.getSecurityContext();
if (sc.getRunAsNonRoot() == null || !sc.getRunAsNonRoot()) {
report.addViolation(
String.format("Container %s not running as non-root", 
container.getName()));
}
if (sc.getReadOnlyRootFilesystem() == null || !sc.getReadOnlyRootFilesystem()) {
report.addViolation(
String.format("Container %s has writable root filesystem", 
container.getName()));
}
if (sc.getAllowPrivilegeEscalation() != null && 
sc.getAllowPrivilegeEscalation()) {
report.addViolation(
String.format("Container %s allows privilege escalation", 
container.getName()));
}
}
}

Conclusion

Sysdig Secure provides comprehensive security for Java containerized applications:

  1. Runtime Security: Real-time threat detection using eBPF
  2. Vulnerability Management: Container image scanning and compliance
  3. Network Security: Micro-segmentation and network policies
  4. Compliance: CIS benchmarks and custom compliance checks
  5. Incident Response: Automated response to security events

Key benefits for Java applications:

  • Deep Visibility: System call monitoring for Java processes
  • Zero Configuration: Automatic detection of Java applications
  • Performance: eBPF-based monitoring with minimal overhead
  • Integration: Seamless integration with Java ecosystem and frameworks
  • Compliance: Out-of-the-box compliance for Java containers

By implementing Sysdig Secure with these patterns, organizations can achieve enterprise-grade security for their Java microservices while maintaining development velocity and operational efficiency.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper