Capitulo 18: Seguridad

Por: Artiko
k3skubernetesseguridadrbacnetwork-policies

Capitulo 18: Seguridad

< Volver al Indice del Tutorial

Seguridad por Capas

La seguridad en Kubernetes no es un unico mecanismo sino multiples capas que se complementan:

  1. Red: Controlar que pods pueden comunicarse entre si
  2. Pod: Restringir privilegios de los contenedores
  3. Acceso: Limitar que usuarios y ServiceAccounts pueden hacer
  4. Datos: Encriptar secrets en reposo
  5. Infraestructura: Hardening del cluster y sus componentes

Cada capa agrega proteccion independiente. Si una falla, las demas siguen protegiendo el cluster.

Network Policies

Por defecto, todos los pods pueden comunicarse con todos los demas pods del cluster. Las Network Policies restringen este trafico.

Requisito: Network Plugin Compatible

K3s usa Flannel por defecto, que no soporta Network Policies. Para habilitarlas necesitas un plugin compatible:

# Instalar K3s con Canal (Flannel + Calico para policies)
curl -sfL https://get.k3s.io | sh -s - --flannel-backend=none \
  --disable-network-policy

# Luego instalar Calico
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

Default Deny: Bloquear Todo por Defecto

La primera politica en cualquier namespace de produccion debe ser bloquear todo el trafico entrante:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: mi-app
spec:
  podSelector: {}
  policyTypes:
    - Ingress

Con esto, ningun pod en el namespace mi-app recibe trafico a menos que una politica lo permita explicitamente.

Permitir Trafico Especifico

Solo el frontend puede hablar con el backend:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: mi-app
spec:
  podSelector:
    matchLabels:
      app: backend
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - port: 8080

Solo el backend puede hablar con la base de datos:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-backend-to-db
  namespace: mi-app
spec:
  podSelector:
    matchLabels:
      app: database
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: backend
      ports:
        - port: 5432

Pod Security Standards

Kubernetes define tres niveles de seguridad para pods:

NivelDescripcion
PrivilegedSin restricciones. Solo para componentes del sistema
BaselinePreviene escalaciones conocidas. Minimo recomendado
RestrictedHardening completo. Recomendado para produccion

Configurar por Namespace

Se aplican con labels en el namespace:

apiVersion: v1
kind: Namespace
metadata:
  name: produccion
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/audit: restricted

Los modos son:

Una estrategia comun es empezar con warn para detectar problemas y luego activar enforce.

Pod Compatible con Restricted

apiVersion: v1
kind: Pod
metadata:
  name: app-segura
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: mi-app:1.0
      securityContext:
        allowPrivilegeEscalation: false
        capabilities:
          drop: ["ALL"]
        runAsNonRoot: true

RBAC Avanzado

Principio de Menor Privilegio

Cada usuario o servicio debe tener solo los permisos que necesita. Audita los permisos existentes:

# Que puede hacer el ServiceAccount "deploy-sa" en el namespace "staging"
kubectl auth can-i --list --as=system:serviceaccount:staging:deploy-sa -n staging

# Puede este usuario crear deployments
kubectl auth can-i create deployments [email protected] -n produccion

Roles Granulares por Equipo

Role para el equipo de desarrollo (solo lectura + logs):

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: desarrollador
  namespace: staging
rules:
  - apiGroups: [""]
    resources: ["pods", "pods/log", "services", "configmaps"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["apps"]
    resources: ["deployments", "replicasets"]
    verbs: ["get", "list", "watch"]

Role para el equipo de operaciones (gestion completa):

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: operaciones
  namespace: produccion
rules:
  - apiGroups: ["", "apps", "batch"]
    resources: ["*"]
    verbs: ["*"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get", "list"]

Nota que operaciones puede hacer todo excepto ver el contenido de los secrets (solo listarlos).

Vincular Roles

kubectl create rolebinding dev-binding \
  --role=desarrollador \
  [email protected] \
  -n staging

Secrets Encryption at Rest

Por defecto, los secrets se almacenan en texto plano en la base de datos. Para encriptarlos:

# Al instalar K3s
curl -sfL https://get.k3s.io | sh -s - server --secrets-encryption

Para un cluster existente:

# Habilitar encriptacion
k3s secrets-encrypt enable

# Reencriptar secrets existentes
k3s secrets-encrypt reencrypt

# Verificar estado
k3s secrets-encrypt status

Despues de habilitar la encriptacion, los nuevos secrets se almacenan encriptados con AES-CBC. Los existentes necesitan reencriptarse manualmente.

CIS Benchmark para K3s

El CIS Benchmark es un conjunto de recomendaciones de seguridad para Kubernetes. K3s tiene su propio perfil CIS.

Ejecutar kube-bench

# Instalar kube-bench
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml

# Ver resultados
kubectl logs job/kube-bench

kube-bench evalua la configuracion del cluster contra las recomendaciones CIS y reporta que pasa, que falla y que necesita atencion manual.

Iniciar K3s en Modo CIS

curl -sfL https://get.k3s.io | sh -s - server \
  --protect-kernel-defaults \
  --secrets-encryption

El flag --protect-kernel-defaults hace que K3s falle si los parametros del kernel no cumplen con los requisitos de seguridad en lugar de modificarlos silenciosamente.

Hardening Basico

Deshabilitar Acceso Anonimo

K3s deshabilita el acceso anonimo por defecto, pero verifica:

kubectl auth can-i --list --as=system:anonymous

Si ves permisos asignados a anonymous, revisa los ClusterRoleBindings.

Rotar Tokens

Los tokens de los nodos no rotan automaticamente. Para rotar:

# Regenerar token del server
k3s token rotate

# Los agents necesitan reconectarse con el nuevo token

Limitar Acceso al API Server

Usa firewall para que solo IPs autorizadas accedan al puerto 6443:

# Con iptables
iptables -A INPUT -p tcp --dport 6443 -s 10.0.0.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 6443 -j DROP

Checklist de Seguridad


Siguiente: Capitulo 19: GitOps con Flux —>