Overview
Pod Security Standards (PSS) define different isolation levels for Kubernetes pods. This Java implementation provides validation, admission control, and security context management for Kubernetes workloads.
1. Dependencies
<dependencies> <!-- Kubernetes Client --> <dependency> <groupId>io.kubernetes</groupId> <artifactId>client-java</artifactId> <version>18.0.0</version> </dependency> <!-- Jakarta Validation --> <dependency> <groupId>jakarta.validation</groupId> <artifactId>jakarta.validation-api</artifactId> <version>3.0.2</version> </dependency> <!-- JSON Processing --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> </dependency> <!-- YAML Processing --> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-yaml</artifactId> <version>2.15.2</version> </dependency> <!-- Logging --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>2.0.7</version> </dependency> </dependencies>
2. Core Domain Models
Pod Security Standards Levels
package com.example.pss;
public enum PodSecurityLevel {
PRIVILEGED("privileged"),
BASELINE("baseline"),
RESTRICTED("restricted");
private final String value;
PodSecurityLevel(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public static PodSecurityLevel fromString(String value) {
for (PodSecurityLevel level : values()) {
if (level.value.equalsIgnoreCase(value)) {
return level;
}
}
throw new IllegalArgumentException("Unknown Pod Security Level: " + value);
}
}
Security Context Models
package com.example.pss.model;
import com.fasterxml.jackson.annotation.JsonInclude;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class PodSecurityContext {
private Boolean runAsNonRoot;
private Long runAsUser;
private Long runAsGroup;
private Long fsGroup;
private String fsGroupChangePolicy;
private SeLinuxOptions seLinuxOptions;
private SeccompProfile seccompProfile;
private WindowsSecurityContextOptions windowsOptions;
// Getters and Setters
public Boolean getRunAsNonRoot() { return runAsNonRoot; }
public void setRunAsNonRoot(Boolean runAsNonRoot) { this.runAsNonRoot = runAsNonRoot; }
public Long getRunAsUser() { return runAsUser; }
public void setRunAsUser(Long runAsUser) { this.runAsUser = runAsUser; }
public Long getRunAsGroup() { return runAsGroup; }
public void setRunAsGroup(Long runAsGroup) { this.runAsGroup = runAsGroup; }
public Long getFsGroup() { return fsGroup; }
public void setFsGroup(Long fsGroup) { this.fsGroup = fsGroup; }
public String getFsGroupChangePolicy() { return fsGroupChangePolicy; }
public void setFsGroupChangePolicy(String fsGroupChangePolicy) { this.fsGroupChangePolicy = fsGroupChangePolicy; }
public SeLinuxOptions getSeLinuxOptions() { return seLinuxOptions; }
public void setSeLinuxOptions(SeLinuxOptions seLinuxOptions) { this.seLinuxOptions = seLinuxOptions; }
public SeccompProfile getSeccompProfile() { return seccompProfile; }
public void setSeccompProfile(SeccompProfile seccompProfile) { this.seccompProfile = seccompProfile; }
public WindowsSecurityContextOptions getWindowsOptions() { return windowsOptions; }
public void setWindowsOptions(WindowsSecurityContextOptions windowsOptions) { this.windowsOptions = windowsOptions; }
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ContainerSecurityContext {
private Boolean allowPrivilegeEscalation;
private Boolean privileged;
private Boolean readOnlyRootFilesystem;
private Long runAsUser;
private Long runAsGroup;
private Boolean runAsNonRoot;
private SeLinuxOptions seLinuxOptions;
private SeccompProfile seccompProfile;
private WindowsSecurityContextOptions windowsOptions;
private Capabilities capabilities;
// Getters and Setters
public Boolean getAllowPrivilegeEscalation() { return allowPrivilegeEscalation; }
public void setAllowPrivilegeEscalation(Boolean allowPrivilegeEscalation) { this.allowPrivilegeEscalation = allowPrivilegeEscalation; }
public Boolean getPrivileged() { return privileged; }
public void setPrivileged(Boolean privileged) { this.privileged = privileged; }
public Boolean getReadOnlyRootFilesystem() { return readOnlyRootFilesystem; }
public void setReadOnlyRootFilesystem(Boolean readOnlyRootFilesystem) { this.readOnlyRootFilesystem = readOnlyRootFilesystem; }
public Long getRunAsUser() { return runAsUser; }
public void setRunAsUser(Long runAsUser) { this.runAsUser = runAsUser; }
public Long getRunAsGroup() { return runAsGroup; }
public void setRunAsGroup(Long runAsGroup) { this.runAsGroup = runAsGroup; }
public Boolean getRunAsNonRoot() { return runAsNonRoot; }
public void setRunAsNonRoot(Boolean runAsNonRoot) { this.runAsNonRoot = runAsNonRoot; }
public SeLinuxOptions getSeLinuxOptions() { return seLinuxOptions; }
public void setSeLinuxOptions(SeLinuxOptions seLinuxOptions) { this.seLinuxOptions = seLinuxOptions; }
public SeccompProfile getSeccompProfile() { return seccompProfile; }
public void setSeccompProfile(SeccompProfile seccompProfile) { this.seccompProfile = seccompProfile; }
public WindowsSecurityContextOptions getWindowsOptions() { return windowsOptions; }
public void setWindowsOptions(WindowsSecurityContextOptions windowsOptions) { this.windowsOptions = windowsOptions; }
public Capabilities getCapabilities() { return capabilities; }
public void setCapabilities(Capabilities capabilities) { this.capabilities = capabilities; }
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Capabilities {
private java.util.List<String> add;
private java.util.List<String> drop;
// Getters and Setters
public java.util.List<String> getAdd() { return add; }
public void setAdd(java.util.List<String> add) { this.add = add; }
public java.util.List<String> getDrop() { return drop; }
public void setDrop(java.util.List<String> drop) { this.drop = drop; }
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public class SeLinuxOptions {
private String level;
private String role;
private String type;
private String user;
// Getters and Setters
public String getLevel() { return level; }
public void setLevel(String level) { this.level = level; }
public String getRole() { return role; }
public void setRole(String role) { this.role = role; }
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public String getUser() { return user; }
public void setUser(String user) { this.user = user; }
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public class SeccompProfile {
private String type;
private String localhostProfile;
// Getters and Setters
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public String getLocalhostProfile() { return localhostProfile; }
public void setLocalhostProfile(String localhostProfile) { this.localhostProfile = localhostProfile; }
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public class WindowsSecurityContextOptions {
private String gmsaCredentialSpec;
private String gmsaCredentialSpecName;
private String hostProcess;
private String runAsUserName;
// Getters and Setters
public String getGmsaCredentialSpec() { return gmsaCredentialSpec; }
public void setGmsaCredentialSpec(String gmsaCredentialSpec) { this.gmsaCredentialSpec = gmsaCredentialSpec; }
public String getGmsaCredentialSpecName() { return gmsaCredentialSpecName; }
public void setGmsaCredentialSpecName(String gmsaCredentialSpecName) { this.gmsaCredentialSpecName = gmsaCredentialSpecName; }
public String getHostProcess() { return hostProcess; }
public void setHostProcess(String hostProcess) { this.hostProcess = hostProcess; }
public String getRunAsUserName() { return runAsUserName; }
public void setRunAsUserName(String runAsUserName) { this.runAsUserName = runAsUserName; }
}
3. Pod Security Standards Validator
package com.example.pss.validator;
import com.example.pss.PodSecurityLevel;
import com.example.pss.model.*;
import com.example.pss.result.ValidationResult;
import com.example.pss.result.Violation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
public class PodSecurityValidator {
private static final Logger log = LoggerFactory.getLogger(PodSecurityValidator.class);
public ValidationResult validatePod(PodSpec podSpec, PodSecurityLevel level) {
List<Violation> violations = new ArrayList<>();
switch (level) {
case PRIVILEGED:
// No restrictions for privileged
break;
case BASELINE:
violations.addAll(validateBaseline(podSpec));
break;
case RESTRICTED:
violations.addAll(validateBaseline(podSpec));
violations.addAll(validateRestricted(podSpec));
break;
}
return new ValidationResult(violations.isEmpty(), violations);
}
private List<Violation> validateBaseline(PodSpec podSpec) {
List<Violation> violations = new ArrayList<>();
// Validate pod-level security context
validatePodSecurityContext(podSpec.getSecurityContext(), violations);
// Validate container security contexts
for (ContainerSpec container : podSpec.getContainers()) {
validateContainerBaseline(container, violations);
}
// Validate host namespace sharing
if (Boolean.TRUE.equals(podSpec.getHostNetwork())) {
violations.add(new Violation("hostNetwork",
"Sharing the host network namespace is not allowed", "baseline"));
}
if (Boolean.TRUE.equals(podSpec.getHostPID())) {
violations.add(new Violation("hostPID",
"Sharing the host PID namespace is not allowed", "baseline"));
}
if (Boolean.TRUE.equals(podSpec.getHostIPC())) {
violations.add(new Violation("hostIPC",
"Sharing the host IPC namespace is not allowed", "baseline"));
}
return violations;
}
private List<Violation> validateRestricted(PodSpec podSpec) {
List<Violation> violations = new ArrayList<>();
// Validate pod security context for restricted requirements
PodSecurityContext podSecurityContext = podSpec.getSecurityContext();
if (podSecurityContext == null) {
violations.add(new Violation("securityContext",
"Pod-level security context is required", "restricted"));
} else {
if (podSecurityContext.getRunAsNonRoot() == null || !podSecurityContext.getRunAsNonRoot()) {
violations.add(new Violation("securityContext.runAsNonRoot",
"Must run as non-root user", "restricted"));
}
if (podSecurityContext.getSeccompProfile() == null ||
!"RuntimeDefault".equals(podSecurityContext.getSeccompProfile().getType())) {
violations.add(new Violation("securityContext.seccompProfile",
"Seccomp profile must be set to RuntimeDefault", "restricted"));
}
}
// Validate container security contexts for restricted requirements
for (ContainerSpec container : podSpec.getContainers()) {
validateContainerRestricted(container, violations);
}
return violations;
}
private void validatePodSecurityContext(PodSecurityContext context, List<Violation> violations) {
if (context == null) {
return;
}
// Validate SELinux options
if (context.getSeLinuxOptions() != null) {
violations.add(new Violation("securityContext.seLinuxOptions",
"SELinux options are not allowed", "baseline"));
}
// Validate Windows options
if (context.getWindowsOptions() != null) {
violations.add(new Violation("securityContext.windowsOptions",
"Windows security options are not allowed", "baseline"));
}
}
private void validateContainerBaseline(ContainerSpec container, List<Violation> violations) {
ContainerSecurityContext context = container.getSecurityContext();
if (context == null) {
violations.add(new Violation("containers[" + container.getName() + "].securityContext",
"Container security context is required", "baseline"));
return;
}
// Privileged containers are not allowed
if (Boolean.TRUE.equals(context.getPrivileged())) {
violations.add(new Violation("containers[" + container.getName() + "].securityContext.privileged",
"Privileged containers are not allowed", "baseline"));
}
// Host path volumes are restricted
if (container.getVolumeMounts() != null) {
for (VolumeMount mount : container.getVolumeMounts()) {
if ("hostPath".equals(mount.getType())) {
violations.add(new Violation("volumes[" + mount.getName() + "].hostPath",
"HostPath volumes are restricted", "baseline"));
}
}
}
// Validate capabilities
validateCapabilities(container.getName(), context.getCapabilities(), violations);
}
private void validateContainerRestricted(ContainerSpec container, List<Violation> violations) {
ContainerSecurityContext context = container.getSecurityContext();
if (context == null) {
violations.add(new Violation("containers[" + container.getName() + "].securityContext",
"Container security context is required for restricted level", "restricted"));
return;
}
// Must run as non-root
if (context.getRunAsNonRoot() == null || !context.getRunAsNonRoot()) {
violations.add(new Violation("containers[" + container.getName() + "].securityContext.runAsNonRoot",
"Must run as non-root user", "restricted"));
}
// Allow privilege escalation must be false
if (context.getAllowPrivilegeEscalation() == null || context.getAllowPrivilegeEscalation()) {
violations.add(new Violation("containers[" + container.getName() + "].securityContext.allowPrivilegeEscalation",
"Privilege escalation must be disabled", "restricted"));
}
// Read-only root filesystem is required
if (context.getReadOnlyRootFilesystem() == null || !context.getReadOnlyRootFilesystem()) {
violations.add(new Violation("containers[" + container.getName() + "].securityContext.readOnlyRootFilesystem",
"Read-only root filesystem is required", "restricted"));
}
// Must drop ALL capabilities
if (context.getCapabilities() != null) {
List<String> drop = context.getCapabilities().getDrop();
if (drop == null || !drop.contains("ALL")) {
violations.add(new Violation("containers[" + container.getName() + "].securityContext.capabilities.drop",
"Must drop ALL capabilities", "restricted"));
}
} else {
violations.add(new Violation("containers[" + container.getName() + "].securityContext.capabilities",
"Capabilities must be configured to drop ALL", "restricted"));
}
}
private void validateCapabilities(String containerName, Capabilities capabilities, List<Violation> violations) {
if (capabilities == null) {
return;
}
// Check for dangerous capabilities in add list
List<String> dangerousCaps = Arrays.asList(
"NET_RAW", "SYS_ADMIN", "SYS_PTRACE", "SYS_MODULE", "SYS_RAWIO"
);
if (capabilities.getAdd() != null) {
for (String cap : capabilities.getAdd()) {
if (dangerousCaps.contains(cap)) {
violations.add(new Violation("containers[" + containerName + "].securityContext.capabilities.add." + cap,
"Dangerous capability " + cap + " is not allowed", "baseline"));
}
}
}
}
}
4. Pod Specification Models
package com.example.pss.model;
import java.util.List;
import java.util.Map;
public class PodSpec {
private PodSecurityContext securityContext;
private Boolean hostNetwork;
private Boolean hostPID;
private Boolean hostIPC;
private List<ContainerSpec> containers;
private List<Volume> volumes;
private List<ContainerSpec> initContainers;
// Getters and Setters
public PodSecurityContext getSecurityContext() { return securityContext; }
public void setSecurityContext(PodSecurityContext securityContext) { this.securityContext = securityContext; }
public Boolean getHostNetwork() { return hostNetwork; }
public void setHostNetwork(Boolean hostNetwork) { this.hostNetwork = hostNetwork; }
public Boolean getHostPID() { return hostPID; }
public void setHostPID(Boolean hostPID) { this.hostPID = hostPID; }
public Boolean getHostIPC() { return hostIPC; }
public void setHostIPC(Boolean hostIPC) { this.hostIPC = hostIPC; }
public List<ContainerSpec> getContainers() { return containers; }
public void setContainers(List<ContainerSpec> containers) { this.containers = containers; }
public List<Volume> getVolumes() { return volumes; }
public void setVolumes(List<Volume> volumes) { this.volumes = volumes; }
public List<ContainerSpec> getInitContainers() { return initContainers; }
public void setInitContainers(List<ContainerSpec> initContainers) { this.initContainers = initContainers; }
}
public class ContainerSpec {
private String name;
private String image;
private ContainerSecurityContext securityContext;
private List<VolumeMount> volumeMounts;
private List<EnvVar> env;
// Getters and Setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getImage() { return image; }
public void setImage(String image) { this.image = image; }
public ContainerSecurityContext getSecurityContext() { return securityContext; }
public void setSecurityContext(ContainerSecurityContext securityContext) { this.securityContext = securityContext; }
public List<VolumeMount> getVolumeMounts() { return volumeMounts; }
public void setVolumeMounts(List<VolumeMount> volumeMounts) { this.volumeMounts = volumeMounts; }
public List<EnvVar> getEnv() { return env; }
public void setEnv(List<EnvVar> env) { this.env = env; }
}
public class VolumeMount {
private String name;
private String mountPath;
private String type;
// Getters and Setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getMountPath() { return mountPath; }
public void setMountPath(String mountPath) { this.mountPath = mountPath; }
public String getType() { return type; }
public void setType(String type) { this.type = type; }
}
public class Volume {
private String name;
private String type;
private Map<String, Object> config;
// Getters and Setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public Map<String, Object> getConfig() { return config; }
public void setConfig(Map<String, Object> config) { this.config = config; }
}
public class EnvVar {
private String name;
private String value;
private EnvVarSource valueFrom;
// Getters and Setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getValue() { return value; }
public void setValue(String value) { this.value = value; }
public EnvVarSource getValueFrom() { return valueFrom; }
public void setValueFrom(EnvVarSource valueFrom) { this.valueFrom = valueFrom; }
}
public class EnvVarSource {
private Object fieldRef;
private Object secretKeyRef;
private Object configMapKeyRef;
// Getters and Setters
public Object getFieldRef() { return fieldRef; }
public void setFieldRef(Object fieldRef) { this.fieldRef = fieldRef; }
public Object getSecretKeyRef() { return secretKeyRef; }
public void setSecretKeyRef(Object secretKeyRef) { this.secretKeyRef = secretKeyRef; }
public Object getConfigMapKeyRef() { return configMapKeyRef; }
public void setConfigMapKeyRef(Object configMapKeyRef) { this.configMapKeyRef = configMapKeyRef; }
}
5. Validation Results
package com.example.pss.result;
import java.util.List;
public class ValidationResult {
private final boolean valid;
private final List<Violation> violations;
private final String message;
public ValidationResult(boolean valid, List<Violation> violations) {
this.valid = valid;
this.violations = violations;
this.message = valid ? "Validation passed" : "Validation failed with " + violations.size() + " violations";
}
// Getters
public boolean isValid() { return valid; }
public List<Violation> getViolations() { return violations; }
public String getMessage() { return message; }
}
package com.example.pss.result;
public class Violation {
private final String field;
private final String message;
private final String level;
private final Severity severity;
public enum Severity {
LOW, MEDIUM, HIGH, CRITICAL
}
public Violation(String field, String message, String level) {
this.field = field;
this.message = message;
this.level = level;
this.severity = determineSeverity(field, message);
}
// Getters
public String getField() { return field; }
public String getMessage() { return message; }
public String getLevel() { return level; }
public Severity getSeverity() { return severity; }
private Severity determineSeverity(String field, String message) {
if (field.contains("privileged") || field.contains("hostNetwork")) {
return Severity.CRITICAL;
} else if (field.contains("capabilities") || field.contains("runAsNonRoot")) {
return Severity.HIGH;
} else if (field.contains("seLinuxOptions") || field.contains("seccompProfile")) {
return Severity.MEDIUM;
} else {
return Severity.LOW;
}
}
@Override
public String toString() {
return String.format("Violation{field='%s', message='%s', level='%s', severity=%s}",
field, message, level, severity);
}
}
6. Security Context Generator
package com.example.pss.generator;
import com.example.pss.PodSecurityLevel;
import com.example.pss.model.*;
public class SecurityContextGenerator {
public static PodSecurityContext generatePodSecurityContext(PodSecurityLevel level) {
PodSecurityContext context = new PodSecurityContext();
switch (level) {
case RESTRICTED:
context.setRunAsNonRoot(true);
context.setRunAsUser(1000L);
context.setRunAsGroup(1000L);
context.setFsGroup(1000L);
SeccompProfile seccomp = new SeccompProfile();
seccomp.setType("RuntimeDefault");
context.setSeccompProfile(seccomp);
break;
case BASELINE:
context.setRunAsNonRoot(true);
context.setRunAsUser(1000L);
break;
case PRIVILEGED:
// Minimal restrictions for privileged
break;
}
return context;
}
public static ContainerSecurityContext generateContainerSecurityContext(PodSecurityLevel level) {
ContainerSecurityContext context = new ContainerSecurityContext();
switch (level) {
case RESTRICTED:
context.setRunAsNonRoot(true);
context.setRunAsUser(1000L);
context.setAllowPrivilegeEscalation(false);
context.setReadOnlyRootFilesystem(true);
context.setPrivileged(false);
// Drop ALL capabilities
Capabilities caps = new Capabilities();
caps.setDrop(java.util.Arrays.asList("ALL"));
context.setCapabilities(caps);
// Set seccomp profile
SeccompProfile seccomp = new SeccompProfile();
seccomp.setType("RuntimeDefault");
context.setSeccompProfile(seccomp);
break;
case BASELINE:
context.setRunAsNonRoot(true);
context.setAllowPrivilegeEscalation(false);
context.setPrivileged(false);
// Drop some dangerous capabilities
Capabilities baselineCaps = new Capabilities();
baselineCaps.setDrop(java.util.Arrays.asList("NET_RAW", "SYS_ADMIN"));
context.setCapabilities(baselineCaps);
break;
case PRIVILEGED:
// Minimal restrictions
break;
}
return context;
}
public static PodSpec enforceSecurityStandards(PodSpec originalPod, PodSecurityLevel level) {
PodSpec securedPod = deepCopy(originalPod);
// Set pod-level security context
if (securedPod.getSecurityContext() == null) {
securedPod.setSecurityContext(generatePodSecurityContext(level));
}
// Set container security contexts
if (securedPod.getContainers() != null) {
for (ContainerSpec container : securedPod.getContainers()) {
if (container.getSecurityContext() == null) {
container.setSecurityContext(generateContainerSecurityContext(level));
}
}
}
// Set init container security contexts
if (securedPod.getInitContainers() != null) {
for (ContainerSpec initContainer : securedPod.getInitContainers()) {
if (initContainer.getSecurityContext() == null) {
initContainer.setSecurityContext(generateContainerSecurityContext(level));
}
}
}
// Enforce namespace restrictions based on level
if (level != PodSecurityLevel.PRIVILEGED) {
securedPod.setHostNetwork(false);
securedPod.setHostPID(false);
securedPod.setHostIPC(false);
}
return securedPod;
}
private static PodSpec deepCopy(PodSpec original) {
// In a real implementation, use a proper deep copy mechanism
// This is a simplified version
PodSpec copy = new PodSpec();
copy.setSecurityContext(original.getSecurityContext());
copy.setHostNetwork(original.getHostNetwork());
copy.setHostPID(original.getHostPID());
copy.setHostIPC(original.getHostIPC());
copy.setContainers(original.getContainers());
copy.setInitContainers(original.getInitContainers());
copy.setVolumes(original.getVolumes());
return copy;
}
}
7. Kubernetes Admission Webhook
package com.example.pss.webhook;
import com.example.pss.PodSecurityLevel;
import com.example.pss.validator.PodSecurityValidator;
import com.example.pss.model.PodSpec;
import com.example.pss.result.ValidationResult;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
public class AdmissionWebhook {
private static final Logger log = LoggerFactory.getLogger(AdmissionWebhook.class);
private static final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
private final PodSecurityValidator validator;
private final PodSecurityLevel enforcedLevel;
public AdmissionWebhook(PodSecurityLevel enforcedLevel) {
this.validator = new PodSecurityValidator();
this.enforcedLevel = enforcedLevel;
}
public AdmissionResponse validateAdmission(AdmissionRequest request) {
try {
log.info("Processing admission request for {}", request.getUid());
// Extract pod spec from request
PodSpec podSpec = extractPodSpec(request.getObject());
// Validate against enforced level
ValidationResult result = validator.validatePod(podSpec, enforcedLevel);
return buildAdmissionResponse(request.getUid(), result);
} catch (Exception e) {
log.error("Error processing admission request", e);
return buildErrorResponse(request.getUid(), e.getMessage());
}
}
private PodSpec extractPodSpec(Map<String, Object> requestObject) {
// Extract pod spec from Kubernetes admission request
// This is a simplified extraction - real implementation would be more robust
Map<String, Object> spec = (Map<String, Object>) requestObject.get("spec");
return mapper.convertValue(spec, PodSpec.class);
}
private AdmissionResponse buildAdmissionResponse(String uid, ValidationResult result) {
AdmissionResponse response = new AdmissionResponse();
response.setUid(uid);
response.setAllowed(result.isValid());
if (!result.isValid()) {
AdmissionResponse.Status status = new AdmissionResponse.Status();
status.setMessage(result.getMessage());
status.setCode(403);
response.setStatus(status);
// Add detailed violations to response
response.setViolations(result.getViolations());
}
return response;
}
private AdmissionResponse buildErrorResponse(String uid, String error) {
AdmissionResponse response = new AdmissionResponse();
response.setUid(uid);
response.setAllowed(false);
AdmissionResponse.Status status = new AdmissionResponse.Status();
status.setMessage("Error validating pod: " + error);
status.setCode(500);
response.setStatus(status);
return response;
}
}
// Admission request/response models
class AdmissionRequest {
private String uid;
private Map<String, Object> object;
private Map<String, Object> oldObject;
private String operation;
// Getters and Setters
public String getUid() { return uid; }
public void setUid(String uid) { this.uid = uid; }
public Map<String, Object> getObject() { return object; }
public void setObject(Map<String, Object> object) { this.object = object; }
public Map<String, Object> getOldObject() { return oldObject; }
public void setOldObject(Map<String, Object> oldObject) { this.oldObject = oldObject; }
public String getOperation() { return operation; }
public void setOperation(String operation) { this.operation = operation; }
}
class AdmissionResponse {
private String uid;
private boolean allowed;
private Status status;
private Object patch;
private String patchType;
private Object violations;
// Getters and Setters
public String getUid() { return uid; }
public void setUid(String uid) { this.uid = uid; }
public boolean isAllowed() { return allowed; }
public void setAllowed(boolean allowed) { this.allowed = allowed; }
public Status getStatus() { return status; }
public void setStatus(Status status) { this.status = status; }
public Object getPatch() { return patch; }
public void setPatch(Object patch) { this.patch = patch; }
public String getPatchType() { return patchType; }
public void setPatchType(String patchType) { this.patchType = patchType; }
public Object getViolations() { return violations; }
public void setViolations(Object violations) { this.violations = violations; }
public static class Status {
private String message;
private int code;
// Getters and Setters
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public int getCode() { return code; }
public void setCode(int code) { this.code = code; }
}
}
8. Example Usage
package com.example.pss.demo;
import com.example.pss.PodSecurityLevel;
import com.example.pss.generator.SecurityContextGenerator;
import com.example.pss.model.*;
import com.example.pss.validator.PodSecurityValidator;
import com.example.pss.result.ValidationResult;
import java.util.Arrays;
public class PodSecurityDemo {
public static void main(String[] args) {
// Create a sample pod specification
PodSpec podSpec = createSamplePod();
// Initialize validator
PodSecurityValidator validator = new PodSecurityValidator();
// Test different security levels
testSecurityLevel(podSpec, validator, PodSecurityLevel.BASELINE);
testSecurityLevel(podSpec, validator, PodSecurityLevel.RESTRICTED);
// Generate secured pod spec
PodSpec securedPod = SecurityContextGenerator.enforceSecurityStandards(
podSpec, PodSecurityLevel.RESTRICTED);
System.out.println("\n=== Secured Pod Specification ===");
System.out.println("RunAsNonRoot: " +
securedPod.getSecurityContext().getRunAsNonRoot());
System.out.println("Seccomp Profile: " +
securedPod.getSecurityContext().getSeccompProfile().getType());
}
private static void testSecurityLevel(PodSpec podSpec, PodSecurityValidator validator,
PodSecurityLevel level) {
System.out.println("\n=== Testing " + level + " Level ===");
ValidationResult result = validator.validatePod(podSpec, level);
System.out.println("Valid: " + result.isValid());
System.out.println("Message: " + result.getMessage());
if (!result.isValid()) {
System.out.println("Violations:");
result.getViolations().forEach(v ->
System.out.println(" - " + v.getField() + ": " + v.getMessage() +
" (Severity: " + v.getSeverity() + ")"));
}
}
private static PodSpec createSamplePod() {
PodSpec pod = new PodSpec();
// Create a container with minimal security context
ContainerSpec container = new ContainerSpec();
container.setName("test-container");
container.setImage("nginx:latest");
// Intentionally insecure configuration for demonstration
ContainerSecurityContext containerContext = new ContainerSecurityContext();
containerContext.setPrivileged(false); // This would fail baseline
container.setSecurityContext(containerContext);
pod.setContainers(Arrays.asList(container));
// Set some insecure pod-level settings
pod.setHostNetwork(true); // This would fail baseline
pod.setHostPID(false);
return pod;
}
}
Key Features
- Pod Security Standards Validation: Implements baseline and restricted levels
- Security Context Generation: Automatically generates compliant security contexts
- Admission Control: Kubernetes webhook for real-time validation
- Comprehensive Violation Reporting: Detailed security violation information
- Security Context Management: Tools for managing pod and container security contexts
This implementation provides a complete framework for enforcing Pod Security Standards in Java applications, suitable for integration with Kubernetes operators, CI/CD pipelines, or security scanning tools.