Welcome to from-docker-to-kubernetes

Kubernetes Pod Security Standards

Understanding and implementing Pod Security Standards in Kubernetes

Introduction to Pod Security Standards

Pod Security Standards (PSS) in Kubernetes provide a standardized approach to securing pod deployments. These standards define different levels of security restrictions that can be applied to pods, helping organizations implement consistent security policies across their Kubernetes clusters.

Pod Security Standards were introduced in Kubernetes v1.22 to replace the deprecated PodSecurityPolicy (PSP) admission controller, offering a more flexible and maintainable approach to pod security. Unlike PSP, which was an all-or-nothing admission controller that required cluster-wide privileges to manage, PSS can be implemented gradually and at different levels within a cluster, making adoption significantly easier.

The creation of Pod Security Standards addressed several challenges that organizations faced with PodSecurityPolicies:

  1. Complexity: PodSecurityPolicies were difficult to author correctly and understand
  2. Privilege Requirements: Managing PSPs required cluster-admin privileges
  3. Validation Challenges: Testing PSPs was cumbersome before applying them
  4. All-or-Nothing Implementation: PSPs couldn't be rolled out incrementally
  5. Maintenance Burden: PSPs required ongoing updates as Kubernetes evolved

These standards are particularly important because pods are the fundamental building blocks in Kubernetes, and securing them properly is essential for maintaining overall cluster security. By implementing Pod Security Standards, organizations can significantly reduce the attack surface and mitigate the risk of container escapes and privilege escalation attacks.

The Pod Security Standards specification is now an integral part of the Kubernetes project, maintained by the Security Special Interest Group (SIG-Security). This ensures that the standards evolve alongside Kubernetes itself, maintaining compatibility with new features while addressing emerging security concerns in containerized environments.

The Three Security Profiles

Pod Security Standards define three distinct security profiles, each with different levels of restriction:

Privileged Profile

  • Unrestricted policy with minimal security controls
  • Allows privileged operations that could compromise the node
  • Provides the same level of access as the node's root user
  • Suitable for system-level workloads that require extensive permissions
  • Examples: cluster add-ons, node monitoring agents, CNI plugins
  • Used when functionality takes precedence over security restrictions
  • Represents the highest risk level if compromised
  • Permits all privileged escalation paths, including:
    • Running as privileged containers
    • Accessing host namespaces (network, PID, IPC)
    • Using host ports and networking
    • Mounting host paths and sensitive volumes
    • Running as root with unrestricted capabilities
  • Specific use cases include:
    • Container networking plugins requiring host network access
    • Storage drivers requiring direct device access
    • Node problem detectors requiring deep system visibility
    • Monitoring agents requiring comprehensive system metrics
    • Security tooling that enforces policies at the node level

Baseline Profile

  • Minimally restrictive policy that prevents known privilege escalations
  • Allows default (minimally specified) Pod configuration
  • Permits most workloads to run without modification
  • Blocks known privilege escalation vectors
  • Restricts dangerous capabilities and host access
  • Suitable for default security for non-sensitive applications
  • Represents a middle ground between functionality and security
  • Prevents the following high-risk practices:
    • Running privileged containers
    • Sharing host namespaces directly
    • Mounting host directories as writable volumes
    • Running as root with dangerous capabilities
    • Using hostPort to bind to host network interfaces
  • Allows common container behaviors:
    • Running as any user ID, including root
    • Adding and dropping specific capabilities
    • Using the default seccomp profile
    • Using any SELinux context configured by the platform
    • Using any AppArmor profile configured by the platform
    • Mounting persistent volumes, configMaps, and secrets
  • Most suitable for:
    • Legacy applications that haven't been designed for security
    • Applications from third parties without security modifications
    • Internal applications with moderate security requirements
    • Development and testing environments

Restricted Profile

  • Highly restrictive policy enforcing security best practices
  • Follows hardening guidelines for pods
  • Significantly limits the attack surface of containerized applications
  • Suitable for applications handling sensitive data or running in multi-tenant environments
  • Implements principle of least privilege
  • May require modifications to existing workloads to be compliant
  • Represents the most secure configuration for critical workloads
  • Enforces strong security controls including:
    • Mandatory non-root user execution
    • Prevention of privilege escalation completely
    • Removal of ALL Linux capabilities by default
    • Strict use of SecComp profiles (RuntimeDefault or Localhost)
    • Restriction of volume types to secure options only
    • Prohibition of hostPath volumes entirely
    • Restriction of file system groups and supplemental groups
    • Required read-only root filesystems
    • Explicit declaration of security contexts
  • Applications must be specifically designed for:
    • Running with least privilege
    • Operating without root access
    • Using minimal container images
    • Functioning with immutable filesystems
    • Declaring all required permissions explicitly
  • Best suited for:
    • High-security workloads with sensitive data
    • Multi-tenant environments with strong isolation needs
    • Financial, healthcare, and government applications
    • Applications subject to compliance requirements
    • Production environments with critical infrastructure

Key Control Mechanisms

Pod Security Standards enforce various control mechanisms to ensure appropriate security levels:

# Example: Restricted Profile Pod
apiVersion: v1
kind: Pod
metadata:
  name: restricted-pod
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: myapp:1.0
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop: ["ALL"]
      runAsUser: 1000
      runAsGroup: 3000
      readOnlyRootFilesystem: true
    resources:
      limits:
        cpu: "1"
        memory: "512Mi"

The example above demonstrates a pod configured according to the Restricted profile, implementing multiple security controls to minimize the pod's attack surface.

Control Categories in Detail

Implementing Pod Security Standards

Kubernetes offers multiple ways to implement Pod Security Standards:

Pod Security Admission Controller

  • Built-in admission controller in Kubernetes 1.23+
  • Configurable at namespace level
  • Supports three modes: enforce, audit, and warn
  • Labels determine which standards apply to each namespace
  • Three enforcement modes with different behaviors:
    • enforce: Rejects non-compliant pods at admission time
    • audit: Allows non-compliant pods but logs violations as audit events
    • warn: Allows non-compliant pods but returns warnings to the user
  • Can apply different profiles to each mode:
    • Enforce baseline while auditing against restricted
    • Gradually increase enforcement as applications adapt
    • Maintain visibility into compliance status during migration
  • Optional version control through additional labels:
    • pod-security.kubernetes.io/enforce-version: v1.25
    • Ensures stability during Kubernetes upgrades
    • Controls which version of the PSS specification applies
  • Example namespace labels:
    apiVersion: v1
    kind: Namespace
    metadata:
      name: production
      labels:
        pod-security.kubernetes.io/enforce: restricted
        pod-security.kubernetes.io/audit: restricted
        pod-security.kubernetes.io/warn: restricted
    
  • Graduated implementation example:
    apiVersion: v1
    kind: Namespace
    metadata:
      name: transitional-namespace
      labels:
        pod-security.kubernetes.io/enforce: baseline
        pod-security.kubernetes.io/audit: restricted
        pod-security.kubernetes.io/warn: restricted
        pod-security.kubernetes.io/enforce-version: v1.24
    

Webhook-based Solutions

  • Use dynamic admission controllers for fine-grained control
  • Examples include OPA Gatekeeper and Kyverno
  • Allows for custom policies beyond standard PSS
  • Supports advanced validation logic
  • Key advantages over built-in admission controller:
    • More complex conditional logic and exceptions
    • Custom validation rules specific to organization needs
    • Integration with external policy systems
    • Ability to mutate pods to make them compliant
    • Centralized policy management across clusters
    • Integration with audit and compliance systems
    • Support for non-pod resources (Deployments, StatefulSets)
  • Kyverno features:
    • Kubernetes-native policy management
    • No new language to learn (uses YAML)
    • Supports validation, mutation, and generation
    • Can enforce PSS profiles plus additional controls
    • Provides exceptions mechanism for special cases
  • Example Kyverno policy:
    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
      name: restrict-privileged-containers
    spec:
      validationFailureAction: enforce
      rules:
      - name: privileged-containers
        match:
          resources:
            kinds:
            - Pod
        validate:
          message: "Privileged containers are not allowed"
          pattern:
            spec:
              containers:
                - name: "*"
                  securityContext:
                    privileged: false
    
  • Advanced Kyverno policy with exceptions:
    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
      name: restricted-security-context
    spec:
      validationFailureAction: enforce
      background: true
      rules:
      - name: restricted-securitycontext
        match:
          resources:
            kinds:
            - Pod
        exclude:
          resources:
            namespaces:
            - kube-system
            - monitoring
        validate:
          message: "Use of restricted security context settings is not allowed"
          pattern:
            spec:
              containers:
              - name: "*"
                securityContext:
                  allowPrivilegeEscalation: "false"
                  runAsNonRoot: "true"
                  capabilities:
                    drop: ["ALL"]
                  seccompProfile:
                    type: "RuntimeDefault"
    

Policy-as-Code Tools

  • Define security policies as code
  • Integrates with GitOps workflows
  • Examples include Conftest and Checkov
  • Validates manifests before deployment
  • Shift-left security approach:
    • Catches security issues before deployment
    • Integrates into CI/CD pipelines
    • Provides feedback during development
    • Enforces policies at code review time
    • Prevents non-compliant resources from being applied
    • Reduces operational security burden
  • Open Policy Agent (OPA) Conftest:
    • Uses Rego policy language
    • Validates Kubernetes YAML against policies
    • Can be run locally or in CI/CD pipelines
    • Provides detailed policy violation information
    • Supports multiple policy libraries
  • Infrastructure as Code scanning:
    • Checkov analyzes Kubernetes manifests for misconfigurations
    • Detects security issues across multiple resources
    • Provides auto-remediation suggestions
    • Can enforce PSS controls pre-deployment
  • Example Conftest policy:
    package main
    
    # Basic privileged container check
    deny[msg] {
      input.kind == "Pod"
      input.spec.containers[i].securityContext.privileged
      msg = sprintf("Privileged container is not allowed: %v", [input.spec.containers[i].name])
    }
    
    # Comprehensive PSS Restricted profile check
    deny[msg] {
      input.kind == "Pod"
      container := input.spec.containers[i]
      not restricted_security_context(container)
      msg = sprintf("Container %v does not comply with Restricted PSS profile", [container.name])
    }
    
    restricted_security_context(container) {
      # Must run as non-root
      container.securityContext.runAsNonRoot == true
      
      # Must not allow privilege escalation
      container.securityContext.allowPrivilegeEscalation == false
      
      # Must drop all capabilities
      container.securityContext.capabilities.drop[_] == "ALL"
      
      # Must use RuntimeDefault seccomp profile
      container.securityContext.seccompProfile.type == "RuntimeDefault"
    }
    

Security Contexts

  • Apply security settings directly to pods and containers
  • Implement controls without admission controllers
  • Requires discipline from application teams
  • Example pod with security contexts:
    apiVersion: v1
    kind: Pod
    metadata:
      name: security-context-demo
    spec:
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
      containers:
      - name: app
        image: myapp:1.0
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
          readOnlyRootFilesystem: true
    

Migrating from PodSecurityPolicy

If you're transitioning from the deprecated PodSecurityPolicy to Pod Security Standards, follow these steps:

  1. Analyze current PodSecurityPolicies
    • Identify security requirements in existing PSPs
    • Determine appropriate PSS profiles for each workload
    • Example analysis script:
      kubectl get psp -o yaml | grep -E 'privileged:|allowPrivilegeEscalation:|hostNetwork:'
      
  2. Create namespace strategy
    • Decide which PSS profile applies to each namespace
    • Consider gradual implementation with warn mode first
    • Example namespace mapping:
      kube-system: Privileged (system components need high privileges)
      monitoring: Baseline (needs some privileges but can be restricted)
      production: Restricted (business applications with highest security)
      
  3. Test with warn mode
    • Apply audit/warn modes before enforcing
    • Collect and analyze violations
    • Make necessary workload modifications
    • Example labels for testing:
      pod-security.kubernetes.io/enforce: baseline
      pod-security.kubernetes.io/audit: restricted
      pod-security.kubernetes.io/warn: restricted
      
  4. Implement enforce mode gradually
    • Start with low-risk namespaces
    • Monitor for unexpected issues
    • Adjust security profiles as needed
    • Example gradual rollout plan:
      Week 1: All namespaces in warn mode
      Week 2: Dev namespaces enforce baseline
      Week 3: Non-critical production enforce baseline
      Week 4: Critical production enforce restricted
      

Best Practices

PSS in CI/CD Pipelines

Integrating Pod Security Standards into CI/CD pipelines ensures that non-compliant workloads are caught before they reach the cluster:

  1. Pre-deployment validation
    • Validate Kubernetes manifests against PSS during CI
    • Fail the pipeline for non-compliant resources
    • Example using kubeaudit in CI:
      # GitHub Actions workflow example
      name: Kubernetes Security Audit
      on: [push, pull_request]
      jobs:
        kubeaudit:
          runs-on: ubuntu-latest
          steps:
            - uses: actions/checkout@v3
            - name: Run kubeaudit
              run: |
                kubeaudit all -f ./kubernetes/ --format sarif > results.sarif
            - name: Upload SARIF file
              uses: github/codeql-action/upload-sarif@v2
              with:
                sarif_file: results.sarif
      
  2. Policy-as-code in pipelines
    • Implement OPA/Conftest checks in CI
    • Validate against specific PSS profiles
    • Example Conftest in GitLab CI:
      stages:
        - validate
      
      k8s-security:
        stage: validate
        image: openpolicyagent/conftest:latest
        script:
          - conftest test ./k8s-manifests/ -p ./policies/pss.rego
      

Monitoring and Auditing PSS

Continuous monitoring of Pod Security Standards ensures ongoing compliance:

  1. Audit logging
    • Enable audit logging for Pod Security Admission
    • Analyze logs for policy violations
    • Set up alerts for repeated violations
    • Example audit policy:
      apiVersion: audit.k8s.io/v1
      kind: Policy
      rules:
      - level: RequestResponse
        resources:
        - group: ""
          resources: ["pods"]
      
  2. Compliance dashboards
    • Create dashboards showing PSS compliance
    • Track violations by namespace and profile
    • Monitor trends in security posture
    • Example monitoring tools: Prometheus, Grafana, Falco
  3. Regular security reviews
    • Periodically review PSS implementation
    • Adjust profiles based on new threats
    • Update policies to address emerging vulnerabilities
    • Example review schedule:
      Monthly: Review violation logs and adjust policies
      Quarterly: Comprehensive security posture review
      Annually: Full security policy audit and update
      

Pod Security Standards provide a robust framework for securing Kubernetes workloads according to their specific security requirements. By understanding and properly implementing PSS, organizations can significantly enhance their Kubernetes security posture while maintaining operational flexibility.