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.17.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

FeatureKyvernoOPA Gatekeeper
LanguageYAML (native K8s)Rego (learning curve)
MutationBuilt-inSeparate admission
GenerationCreate resourcesNot supported
ComplexityLowerHigher

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

CapabilityFalcoGatekeeperKyverno
Runtime detectionYesNoNo
Admission controlNoYesYes
Policy languageYAML/JSONRegoYAML
Resource mutationNoLimitedYes
Resource generationNoNoYes
System call monitoringYesNoNo

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

Quick check: how does this lesson land for you?

Quiz

Module 5: Container & Kubernetes Security

Take Quiz
FREE WEEKLY NEWSLETTER

Stay on the Nerd Track

One email per week — courses, deep dives, tools, and AI experiments.

No spam. Unsubscribe anytime.