Skip to main content

Pregunta 43 | CKS Challenge 3 - Hardening Completo de Cluster con Kube-bench

¡Llévame al laboratorio!

Ten en cuenta que el estado de competición para los Desafíos CKS ha terminado. Por favor no envíes una solución. No será puntuada.

Este es un cluster de Kubernetes de dos nodos. Usando la utilidad kube-bench, identifica y corrige todos los problemas que se reportaron como fallidos para los componentes del controlplane y el worker node.

Inspecciona los problemas en detalle haciendo clic en los iconos del diagrama de arquitectura interactivo a la derecha y completa las tareas para asegurar el cluster. Una vez hecho, haz clic en el botón Check para validar tu trabajo.

Haz clic en cada icono (en el laboratorio) para ver más detalles. Una vez hecho, haz clic en el botón Check para probar tu trabajo.

Realiza las tareas en este orden:

  • Descarga kube-bench de AquaSec y extráelo bajo el sistema de archivos /opt. Usa los pasos apropiados de la documentación de kube-bench para completar esta tarea.
  • Ejecuta kube-bench con el directorio de configuración establecido en /opt/cfg y /opt/cfg/config.yaml como el archivo de configuración. Redirige el resultado al archivo /var/www/html/index.html.

Cuando se creó este desafío, la versión v0.6.2 de kube-bench estaba vigente, así que descargaremos esa versión para mejor compatibilidad.

Descargar y colocar bajo opt

curl -L https://github.com/aquasecurity/kube-bench/releases/download/v0.6.2/kube-bench_0.6.2_linux_amd64.tar.gz | tar -xz -C /opt

Crear directorio para el informe

mkdir -p /var/www/html

Ejecutar con las instrucciones de configuración dadas

/opt/kube-bench --config-dir /opt/cfg --config /opt/cfg/config.yaml > /var/www/html/index.html

A pesar del hecho de que redirigimos la salida a index.html, el contenido del archivo es texto y puede ser inspeccionado así

less /var/www/html/index.html

kubelet (node)

  • Asegúrate de que el argumento --protect-kernel-defaults esté configurado como true (node01)

Conecta por ssh a node01

ssh node01

Edita la configuración del kubelet

vi /var/lib/kubelet/config.yaml

Añade la siguiente línea al final del archivo

protectKernelDefaults: true

Guarda y sal de vi, luego reinicia kubelet

systemctl restart kubelet

Vuelve al nodo controlplane

kubelet (controlplane)

  • Asegúrate de que el argumento --protect-kernel-defaults esté configurado como true (node01)

Haz exactamente lo mismo que arriba, pero esta vez no necesitas conectarte por ssh a ningún lugar primero.

kube-controller-mananger

  • Asegúrate de que el argumento --profiling esté configurado como false

Edita el manifiesto

vi /etc/kubernetes/manifests/kube-controller-manager.yaml

Añade lo siguiente a la lista de argumentos en la sección command de la especificación del pod:

    - --profiling=false

Guarda y sal de vi. El pod del controller manager se reiniciará en aproximadamente un minuto

kube-scheduler

Asegúrate de que el argumento --profiling esté configurado como false

Realiza exactamente los mismos pasos que arriba, pero con /etc/kubernetes/manifests/kube-scheduler.yaml

etcd

  • Corrige la propiedad del directorio de datos de etcd
    • Ve el informe como se discutió en la sección kube-bench arriba, y encuentra el FAIL en la sección 1.1.12

    • Verifica el directorio de datos verificando la sección volumes del manifiesto estático del pod etcd para el hostPath.

    • Corrige la propiedad como se indica

      chown -R etcd:etcd /var/lib/etcd

kube-apiserver

  • Asegúrate de que el argumento --profiling esté configurado como false
  • Asegúrate de que el controlador de admisión PodSecurityPolicy esté habilitado
  • Asegúrate de que el argumento --insecure-port esté configurado como 0
  • Asegúrate de que el argumento --audit-log-path esté configurado como /var/log/apiserver/audit.log
  • Asegúrate de que el argumento --audit-log-maxage esté configurado como 30
  • Asegúrate de que el argumento --audit-log-maxbackup esté configurado como 10
  • Asegúrate de que el argumento --audit-log-maxsize esté configurado como 100

Así que esto parece un montón de cambios de argumentos. Bueno, lo es, pero hay un poco más de trabajo que eso. Si le decimos al apiserver que abra un log en un directorio dado, entonces ese directorio se espera que esté en la máquina host, es decir, controlplane mismo. Esto significa que también necesitamos crear un volume y volumeMount para satisfacer este criterio, y también el directorio host debe existir.

El directorio en el que irá el archivo de log necesita existir primero

mkdir -p /var/log/apiserver

Edita el archivo del manifiesto

vi /etc/kubernetes/manifests/kube-apiserver.yaml

Añade todos los nuevos argumentos

    - --profiling=false
- --insecure-port=0
- --audit-log-maxage=30
- --audit-log-maxbackup=10
- --audit-log-path=/var/log/apiserver/audit.log
- --audit-log-maxsize=100

Habilita el controlador de admisión, añadiendo PodSecurityPolicy al argumento --enable-admission-plugins para que se vea así

    - --enable-admission-plugins=NodeRestriction,PodSecurityPolicy

Crea un volume para el archivo de log (añade a los volumes existentes)

    volumes:
- hostPath:
path: /var/log/apiserver/audit.log
type: FileOrCreate
name: audit-log

Crea un volumeMount para este volumen (añade a los volumeMounts existentes)

    volumeMounts:
- mountPath: /var/log/apiserver/audit.log
name: audit-log

Guarda y sal de vi. Espera hasta un minuto para que el servidor api se reinicie. Ten en cuenta cómo depurar un apiserver fallido ¡si lo estropeas!