Container & Kubernetes Security

Cloud-Native Security Tools

4 min read

Runtime detection, policy enforcement, and admission control are essential layers in Kubernetes security. Tools like Falco, OPA/Gatekeeper, and Kyverno provide defense-in-depth for cloud-native workloads.

Runtime Threat Detection

Falco - Runtime Security

Falco detects anomalous behavior at runtime by monitoring system calls:

# Falco installation via Helm
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm install falco falcosecurity/falco \
  --set falco.grpc.enabled=true \
  --set falco.grpcOutput.enabled=true

Default detection rules:

# Detect shell spawned in container
- rule: Terminal shell in container
  desc: Detect shell execution in a container
  condition: >
    spawned_process and container and
    shell_procs and proc.tty != 0 and
    container_entrypoint
  output: >
    Shell spawned in container (user=%user.name container=%container.name
    shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline)
  priority: NOTICE
  tags: [container, shell, mitre_execution]

# Detect sensitive file access
- rule: Read sensitive file in container
  desc: Attempt to read sensitive files like /etc/shadow
  condition: >
    open_read and container and
    sensitive_files and not proc.name in (allowed_readers)
  output: >
    Sensitive file read in container (user=%user.name
    file=%fd.name container=%container.name)
  priority: WARNING
  tags: [container, filesystem, mitre_credential_access]

Custom Falco Rules

# Detect cryptocurrency mining
- rule: Detect crypto mining process
  desc: Detect processes commonly associated with crypto mining
  condition: >
    spawned_process and container and
    proc.name in (xmrig, minerd, cpuminer, cgminer, bfgminer)
  output: >
    Crypto mining process detected (user=%user.name container=%container.name
    process=%proc.name cmdline=%proc.cmdline)
  priority: CRITICAL
  tags: [container, crypto, mitre_resource_hijacking]

# Detect outbound connection to suspicious ports
- rule: Outbound connection to mining pool
  desc: Detect connections to common mining pool ports
  condition: >
    outbound and container and
    fd.sport in (3333, 4444, 5555, 7777, 8888, 9999)
  output: >
    Suspicious outbound connection (container=%container.name
    connection=%fd.name)
  priority: WARNING

Policy Enforcement with OPA Gatekeeper

Gatekeeper Architecture

┌─────────────────────────────────────────────────────┐
│                  Kubernetes API                      │
└──────────────────────┬──────────────────────────────┘
┌─────────────────────────────────────────────────────┐
│              Admission Webhook                       │
│  ┌─────────────────────────────────────────────┐   │
│  │            OPA Gatekeeper                    │   │
│  │  ┌──────────────┐  ┌──────────────────────┐ │   │
│  │  │ Constraint   │  │ ConstraintTemplate   │ │   │
│  │  │ (Instance)   │  │ (Policy Definition)  │ │   │
│  │  └──────────────┘  └──────────────────────┘ │   │
│  └─────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────┘

Installing Gatekeeper

# Install Gatekeeper
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/v3.14.0/deploy/gatekeeper.yaml

# Verify installation
kubectl get pods -n gatekeeper-system

Constraint Templates and Constraints

Require labels on all resources:

# ConstraintTemplate - defines the policy schema
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8srequiredlabels
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredLabels
      validation:
        openAPIV3Schema:
          type: object
          properties:
            labels:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredlabels

        violation[{"msg": msg}] {
          provided := {label | input.review.object.metadata.labels[label]}
          required := {label | label := input.parameters.labels[_]}
          missing := required - provided
          count(missing) > 0
          msg := sprintf("Missing required labels: %v", [missing])
        }
---
# Constraint - applies the policy
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: require-team-label
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
  parameters:
    labels: ["team", "environment"]

Block privileged containers:

apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8sblockprivileged
spec:
  crd:
    spec:
      names:
        kind: K8sBlockPrivileged
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sblockprivileged

        violation[{"msg": msg}] {
          c := input.review.object.spec.containers[_]
          c.securityContext.privileged == true
          msg := sprintf("Privileged container not allowed: %v", [c.name])
        }
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sBlockPrivileged
metadata:
  name: block-privileged-containers
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]

Kyverno - Kubernetes Native Policy Engine

Kyverno Advantages

Feature Kyverno OPA Gatekeeper
Language YAML (native K8s) Rego (learning curve)
Mutation Built-in Separate admission
Generation Create resources Not supported
Complexity Lower Higher

Kyverno Policy Examples

Require resource limits:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-resource-limits
spec:
  validationFailureAction: Enforce
  rules:
  - name: check-resource-limits
    match:
      any:
      - resources:
          kinds:
          - Pod
    validate:
      message: "CPU and memory limits are required"
      pattern:
        spec:
          containers:
          - resources:
              limits:
                memory: "?*"
                cpu: "?*"

Auto-add labels (mutation):

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-default-labels
spec:
  rules:
  - name: add-team-label
    match:
      any:
      - resources:
          kinds:
          - Pod
    mutate:
      patchStrategicMerge:
        metadata:
          labels:
            managed-by: kyverno
            +(team): platform

Admission Controllers

Built-in Admission Controllers

# Check enabled admission controllers
kubectl api-versions | grep admission

# Key admission controllers
# - PodSecurity (replaces PodSecurityPolicy)
# - ResourceQuota
# - LimitRanger
# - ValidatingAdmissionWebhook
# - MutatingAdmissionWebhook

Validating Webhook Example

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: image-policy-webhook
webhooks:
  - name: validate.images.example.com
    admissionReviewVersions: ["v1"]
    sideEffects: None
    clientConfig:
      service:
        name: image-policy-service
        namespace: security
        path: "/validate"
    rules:
      - operations: ["CREATE", "UPDATE"]
        apiGroups: [""]
        apiVersions: ["v1"]
        resources: ["pods"]
    failurePolicy: Fail
    matchPolicy: Exact

Security Tool Comparison

Capability Falco Gatekeeper Kyverno
Runtime detection Yes No No
Admission control No Yes Yes
Policy language YAML/JSON Rego YAML
Resource mutation No Limited Yes
Resource generation No No Yes
System call monitoring Yes No No

Next, we'll cover supply chain security including image signing, SBOM, and vulnerability management. :::

Quiz

Module 5: Container & Kubernetes Security

Take Quiz