Volver

En camino hacia la certificación CKS (Certified Kubernetes Security Specialist)

Imagen del slider

5 de julio de 2021

Por Mickaël D., experto en DevOps

En lugar de un único artículo general sobre cómo prepararse para una certificación, como os he propuesto en otras ocasiones, voy a iniciar una serie de artículos que os ayudarán a comprender mejor los distintos temas sobre los que se os examinará (si decidís presentarla). 

En este dossier, trataremos los siguientes temas:

  1. La configuración del clúster, 
  2. El Cluster Hardening, 
  3. El endurecimiento de sistemas, 
  4. Las vulnerabilidades de los microservicios, 
  5. La seguridad de la cadena de suministro, 
  6. Supervisión, registro y seguridad en tiempo de ejecución. 

Políticas de seguridad de red

Este primer artículo se centrará en el primer aspecto, es decir, la configuración del clúster, y abordará varios puntos, tales como: 

  • Las políticas de seguridad de red
  • CIS Benchmark para comprobar el nivel de seguridad de la configuración de cada componente de Kubernetes, 
  • La seguridad de los controladores de acceso
  • La protección de los metadatos de los nodos
  • El uso de la interfaz de usuario de Kubernetes y su seguridad, 
  • La verificación de los binarios antes de la implementación.

¿Qué son las políticas de seguridad de red? 

Se trata de instrucciones destinadas a especificar cómo un Pod puede comunicarse con entidades de la red mediante una combinación de identificadores: 

  • Los demás pods (excepto él mismo), 
  • Los espacios de nombres con los que puede comunicarse, 
  • Los bloques de IP. Atención: en este caso, un Pod puede acceder a cualquier otro Pod ubicado en el mismo nodo.

Cuando se define una política de seguridad para un pod o un espacio de nombres, se utiliza un selector para especificar qué tráfico se permite desde o hacia el pod o el espacio de nombres asociado a dicho selector

A TENER EN CUENTA: 

  • Por defecto, los Pods aceptan tráfico procedente de cualquier fuente. 
  • Las NetworkPolicies se suman y no entran en conflicto entre sí.
  • Solo hay un requisito: ¡un plugin de red o CNI que admita políticas de red!

Algunos ejemplos:

1. Limitar el tráfico hacia una aplicación

yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: api-allow
spec:
  podSelector:
    matchLabels:
      app: bookstore
      role: api
  ingress:
  - from:
      - podSelector:
          matchLabels:
            app: bookstore

2. Bloquear el tráfico hacia el exterior del clúster de Kubernetes

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: foo-deny-external-egress
spec:
  podSelector:
    matchLabels:
      app: foo
  policyTypes:
  - Egress
  egress:
  - ports:
    - port: 53
      protocol: UDP
    - port: 53
      protocol: TCP
  - to:
    - namespaceSelector: {}

3. Rechazar todo el tráfico no incluido en la lista blanca dirigido a un espacio de nombres

yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: default-deny-all
  namespace: default
spec:
  podSelector: {}
  ingress: []

Puntos de referencia de CIS

El CIS (Center for Internet Security) es un consorcio sin ánimo de lucro que ofrece guías y herramientas para proteger los entornos informáticos. Es algo parecido ala ANSSI en Francia.

Por defecto, un sistema puede ser vulnerable a muchos tipos de ataques, por lo que es importante protegerlo al máximo. Se hablade «hardening»cuando se refuerza la seguridad de la configuración y el funcionamiento de un sistema.

Dos ejemplos:

  1. En el caso de un servidor que disponga de puertos USB y cuyo uso no se haya previsto, estos deben desactivarse para prevenir cualquier tipo de ataque a través de este vector. 
  2. ¿Qué usuarios tienen acceso al sistema y pueden iniciar sesión como root? Si estos realizan cambios que afecten al funcionamiento de los servicios, podría resultar imposible identificar al autor de las modificaciones. 

Por eso, las mejores prácticas recomiendan desactivar la cuenta de root e iniciar sesión con la propia cuenta para, a continuación, elevar los privilegios de esta (mediante sudo). 

Otros ejemplos: solo deben activarse los servicios y/o sistemas de archivos que sean necesarios para el funcionamiento del servidor... Del mismo modo, solo deben abrirse los puertos que sean realmente necesarios y, por lo tanto, hay que configurar el cortafuegos de la forma más precisa posible. 

El sitio web CIS ofrece numerosas pruebas de rendimiento y marcos detrabajo de refuerzo de seguridad para

  • Los sistemas operativos Linux, Windows y OS X, así como los sistemas móviles iOS y Android, 
  • Las plataformas en la nube AWS, Azure, Google
  • Los equipos de red de CheckPoint,Cisco, Juniper y Palo Alto
  • Así como middleware como Tomcat, Docker o Kubernetes.

CIS Benchmark aplicado a Kubernetes: kube-bench

Kube-bench es una aplicación desarrollada en Go, que se basa en gran medida en las recomendaciones de seguridad de CIS con una configuración muy flexible gracias al uso de archivos en yamly que se puede utilizar de varias maneras diferentes: 

  • Al instalarlo desde un contenedor
  • Instalación mediante el archivo binario descargado
  • Al compilar las fuentes
  • Al ejecutarlo desde un contenedor, ya sea un contenedor aislado o dentro de un clúster de Kubernetes u Openshift.

Kube-bench ejecuta las comprobaciones definidas en un archivo yamlnombrado control.yaml y se puede aplicar a cualquier tipo de nodos de tipo maestro o esclavo (independientemente de la versión).

id: 1.2
  text: Programador
  checks:
    - id: 1.2.1
      text: «Asegúrate de que el argumento --profiling esté establecido en false (Puntuado)»
      audit: "ps -ef | grep kube-scheduler | grep -v grep"
      tests:
        bin_op: or
        test_items:
          - flag: "--profiling"
            set: true
          - flag: "--some-other-flag"
            set: false
      corrección: "Edita el archivo /etc/kubernetes/config en el nodo maestro y
        establece el parámetro KUBE_ALLOW_PRIV en '--allow-privileged=false'"
      puntuado: true

Una vez que kube-bench ha realizado las pruebas, los resultados se guardan en un archivo y cada prueba indica un estado según una de las cuatro opciones siguientes: 

  • PASS, La comprobación se ha realizado correctamente. 
  • FAIL: la comprobación ha fallado, pero la solución describe cómo corregir la configuración para que, en la próxima comprobación, el resultado sea correcto. 
  • ADVERTENCIA: la prueba requiere especial atención; consulta la solución para obtener más información. No se trata necesariamente de un informe de error. 
  • INFORMACIÓN

El uso de la interfaz de usuario de Kubernetes y su seguridad

En este caso, se trata de saber cómo instalar el Dashboard de Kubernetes y cómo protegerlo lo mejor posible.  

El Dashboard de Kubernetes se implementa mediante el siguiente comando:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.2.0/aio/deploy/recommended.yaml` y para acceder a él: `kubectl proxy --address 0.0.0.0.   

Hay que tener en cuenta que: 

  • Kubernetes admite cuatro modos de autenticación
  • Estos son gestionados por la API de Kubernetes
  • El Dashboard solo actúa como proxy y sirve de pasarela hacia Kubernetes para toda la información relacionada con la autenticación. 

Los ataques a través del front-end de Kubernetes son numerosos y, durante mucho tiempo, han sido el principal vector de ataque.

La autenticación

Como se ha mencionado anteriormente, Kubernetes admite cuatro modos de autenticación, a saber: 

  • Token al portador, 
  • Nombre de usuario/Contraseña, 
  • Kubeconfig,
  • Encabezado de autorización (compatible desde la versión 1.6 y con la prioridad más alta).

Los tokens al portador

Para configurarlos de la forma más eficaz posible, es necesario estar muy familiarizado con los conceptos de «cuenta de servicio», «rol», «rol de clúster» y los permisos que se les pueden asignar.

Servicio de cuentas 

yaml
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard
EOF

ClusterRoleBinding

yaml
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard

Una vez creados los dos objetos anteriores, se puede obtener el Token al portador mediante el siguiente comando:
kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{{.data.token | base64decode}}"

Nombre de usuario/Contraseña

Desactivado por defecto, ya que la API de Kubernetes requiere una configuración a nivel de atributos y no a nivel de roles.

Kubeconfig

Con este modo de autenticación, solo se tienen en cuenta las opciones especificadas por el indicador modo de autenticación se incluyen en el archivo el mencionado. De lo contrario, aparecerá un error en el panel de control.

Encabezado de autorización

Para este tipo de método de autenticación, necesitarás el token Bearer, ya que lo requerirás en cada solicitud que realices al panel de control.

La verificación de los archivos binarios antes de la instalación

Se trata, ni más ni menos, de comprobar el valor del hash de los archivos binarios relacionados con Kubernetes y compararlos con los que descargas en tu servidor... por si acaso un hacker interceptara tu acción. 

Aunque el llamado «hacker» modifique un archivo del archivo comprimido, hay que tener en cuenta que cualquier modificación de un archivo comprimido también modifica el valor de su hash

Para ello, una vez finalizada la descarga, puedes ejecutar el siguiente comando: shasum -a 512 kubernetes.tar.gz y comparar el valor obtenido con el que aparece en la página de descarga.

Por ejemplo, al descargar:

kubeadm, versión 1.21.0, cuyo valor hash es 7bdaf0d58f0d286538376bc40b50d7e3ab60a3fe7a0709194f53f1605129550f

Obtendré el mismo valor de hash, una vez descargado el archivo (esta vez con el comando shasum -a 256 kubeadm

La seguridad de los controladores de acceso

En primer lugar: ¿qué es un controlador de Ingress? 

Se trata de unobjeto de Kubernetes que gestiona el acceso externo a los servicios de un clúster, normalmente el tráfico HTTP, y que también puede ofrecer funciones como el equilibrio de carga. 

Los temas que se tratarán en esta sección serán: 

  • La creación de certificados TLS
  • La creación de secretos (que incluyen certificados TLS) en Kubernetes,
  • Configuración de los controladores de Ingress que incorporan los secretos.

Creación de un certificado TLS

Partiendo de la base de que ya has creado tu Ingress Controller y que es accesible a través de HTTP, el siguiente paso es proteger su contenido mediante HTTPS... y, por lo tanto, crear un certificado TLS autofirmado:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes

El origen del secreto

Una vez creado el par clave/certificado, y a menos que ya se haya implementado gestor de certificados en Kubernetes, hay que crear un secreto para poder integrar, posteriormente, el certificado TLS en el controlador de Ingress :

kubectl create secret tls-secure-ingress --cert=cert.pem --key=key.pem

Configuración del Ingress Controller

Una vez creados el certificado TLS y la clave secreta, el último paso consiste en integrar la clave secreta en el Ingress Controller.

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  tls:
  - hosts:
      - test-secure-ingress.com
    secretName: tls-secure-ingress
  rules:
  - host: test-secure-ingress.com
    http:
      paths:
      - ruta: /service1
        tipo de ruta: Prefijo
        backend:
          servicio:
            nombre: service1
            puerto:
              número: 80
      - ruta: /service2
        tipo de ruta: Prefijo
        backend:
          servicio:
            nombre: service2
            puerto:
              número: 80

La protección de los metadatos de los nodos

Los nodos de metadatos... ¿En qué consisten?

Todas las máquinas virtuales (nodos) alojadas en la nube deberían tener acceso a los puntos finales de los metadatos de los nodos por diversas razones.Sin embargo, no se recomienda permitir el acceso a todos los recursos.

Para mejorar la seguridad en este ámbito, es necesario aplicar políticas de red, de modo que solo los recursos designados dentro de los clústeres de Kubernetes puedan comunicarse con los puntos finales de los nodos de metadatos

Aquí encontrarás toda la información que puedas necesitar sobre el tema: 

Políticas de red

El principio de las políticas de red consiste en gestionar la comunicación entre pods, entre pods y servicios, y entre entornos externos y servicios, del mismo modo que lo haría un cortafuegos. La identificación de los recursos afectados sigue siendo responsabilidad de los administradores, mediante etiquetas, espacios de nombres o direcciones IP

La documentación oficial indica, por ejemplo, lo siguiente: 

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    puertos:
    - protocolo: TCP
      puerto: 5978

En este caso, lo que nos interesa principalmente es la posibilidad de bloquear el acceso al Metadata Endpoint mediante políticas de red en uno o varios pods (véase más abajo): 

Denegar el tráfico de metadatos

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: cloud-metadata-deny
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
          - <POD_IP_ADDRESS>

Permitir el tráfico hacia los metadatos

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: cloud-metadata-allow
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: metadata-accessor
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
          - <POD_IP_ADDRESS>

El próximo artículo tratará todas las cuestiones relacionadas con el refuerzo de clústeres, a saber:

  • Las restricciones de acceso a la API de Kubernetes, 
  • El uso del control de acceso basado en roles con el fin de minimizar la exposición, 
  • El ajuste fino de las cuentas de servicio, 
  • La frecuencia de las actualizaciones de Kubernetes.