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:
- Runtime Security: Real-time threat detection using eBPF
- Vulnerability Management: Container image scanning and compliance
- Network Security: Micro-segmentation and network policies
- Compliance: CIS benchmarks and custom compliance checks
- 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.