Skip to main content

Pregunta 5 | CIS Benchmark

Usar contexto: kubectl config use-context infra-prod

Se te pide evaluar configuraciones específicas del cluster2 contra las recomendaciones del CIS Benchmark. Usa la herramienta kube-bench que ya está instalada en los nodos.

Conéctate usando ssh cluster2-controlplane1 y ssh cluster2-node1.

En el nodo maestro asegúrate (corrige si es necesario) que las recomendaciones CIS estén configuradas para:

El argumento --profiling del kube-controller-manager

La propiedad del directorio /var/lib/etcd

En el nodo trabajador asegúrate (corrige si es necesario) que las recomendaciones CIS estén configuradas para:

Los permisos de la configuración kubelet /var/lib/kubelet/config.yaml

El argumento --client-ca-file del kubelet


Respuesta:

Número 1

Primero hacemos ssh al nodo maestro y ejecutamos kube-bench contra los componentes maestros:

ssh cluster2-controlplane1

➜ root@cluster2-controlplane1:~# kube-bench run --targets=master
...
== Summary ==
41 checks PASS
13 checks FAIL
11 checks WARN
0 checks INFO
Vemos algunos aprobados, fallos y advertencias. Verifiquemos la tarea requerida (1) del controller manager:

➜ root@cluster2-controlplane1:~# kube-bench run --targets=master | grep kube-controller -A 3
1.3.1 Edit the Controller Manager pod specification file /etc/kubernetes/manifests/kube-controller-manager.yaml
on the master node and set the --terminated-pod-gc-threshold to an appropriate threshold,
for example:
--terminated-pod-gc-threshold=10
--
1.3.2 Edit the Controller Manager pod specification file /etc/kubernetes/manifests/kube-controller-manager.yaml
on the master node and set the below parameter.
--profiling=false

1.3.6 Edit the Controller Manager pod specification file /etc/kubernetes/manifests/kube-controller-manager.yaml
on the master node and set the --feature-gates parameter to include RotateKubeletServerCertificate=true.
--feature-gates=RotateKubeletServerCertificate=true

Allí vemos 1.3.2 que sugiere establecer --profiling=false, así que obedecemos:

➜ root@cluster2-controlplane1:~# vim /etc/kubernetes/manifests/kube-controller-manager.yaml

# Edita la línea correspondiente:

# /etc/kubernetes/manifests/kube-controller-manager.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
component: kube-controller-manager
tier: control-plane
name: kube-controller-manager
namespace: kube-system
spec:
containers:
- command:
- kube-controller-manager
- --allocate-node-cidrs=true
- --authentication-kubeconfig=/etc/kubernetes/controller-manager.conf
- --authorization-kubeconfig=/etc/kubernetes/controller-manager.conf
- --bind-address=127.0.0.1
- --client-ca-file=/etc/kubernetes/pki/ca.crt
- --cluster-cidr=10.244.0.0/16
- --cluster-name=kubernetes
- --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt
- --cluster-signing-key-file=/etc/kubernetes/pki/ca.key
- --controllers=*,bootstrapsigner,tokencleaner
- --kubeconfig=/etc/kubernetes/controller-manager.conf
- --leader-elect=true
- --node-cidr-mask-size=24
- --port=0
- --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
- --root-ca-file=/etc/kubernetes/pki/ca.crt
- --service-account-private-key-file=/etc/kubernetes/pki/sa.key
- --service-cluster-ip-range=10.96.0.0/12
- --use-service-account-credentials=true
- --profiling=false # agregar
...

Esperamos a que se reinicie el Pod, luego ejecutamos kube-bench nuevamente para verificar si el problema se resolvió:

➜ root@cluster2-controlplane1:~# kube-bench run --targets=master | grep kube-controller -A 3
1.3.1 Edit the Controller Manager pod specification file /etc/kubernetes/manifests/kube-controller-manager.yaml
on the master node and set the --terminated-pod-gc-threshold to an appropriate threshold,
for example:
--terminated-pod-gc-threshold=10
--
1.3.6 Edit the Controller Manager pod specification file /etc/kubernetes/manifests/kube-controller-manager.yaml
on the master node and set the --feature-gates parameter to include RotateKubeletServerCertificate=true.
--feature-gates=RotateKubeletServerCertificate=true

# Problema resuelto y 1.3.2 está aprobado:

root@cluster2-controlplane1:~# kube-bench run --targets=master | grep 1.3.2
[PASS] 1.3.2 Ensure that the --profiling argument is set to false (Scored)

Número 2

La siguiente tarea (2) es verificar la propiedad del directorio /var/lib/etcd, así que primero echamos un vistazo:

➜ root@cluster2-controlplane1:~# ls -lh /var/lib | grep etcd
drwx------ 3 root root 4.0K Sep 11 20:08 etcd
Parece usuario root y grupo root. También es posible verificar usando:

➜ root@cluster2-controlplane1:~# stat -c %U:%G /var/lib/etcd
root:root

¿Pero qué tiene que decir kube-bench sobre esto?

➜ root@cluster2-controlplane1:~# kube-bench run --targets=master | grep "/var/lib/etcd" -B5

1.1.12 On the etcd server node, get the etcd data directory, passed as an argument --data-dir,
from the below command:
ps -ef | grep etcd
Run the below command (based on the etcd data directory found above).
For example, chown etcd:etcd /var/lib/etcd
Para cumplir ejecutamos lo siguiente:

➜ root@cluster2-controlplane1:~# chown etcd:etcd /var/lib/etcd

➜ root@cluster2-controlplane1:~# ls -lh /var/lib | grep etcd
drwx------ 3 etcd etcd 4.0K Sep 11 20:08 etcd

# Esto se ve mejor. Ejecutamos kube-bench nuevamente, y nos aseguramos de que la prueba 1.1.12. esté aprobada.

➜ root@cluster2-controlplane1:~# kube-bench run --targets=master | grep 1.1.12
[PASS] 1.1.12 Ensure that the etcd data directory ownership is set to etcd:etcd (Scored)
Hecho.

Número 3

Para continuar con el número (3), nos dirigiremos al nodo trabajador y nos aseguraremos de que el archivo de configuración kubelet tenga los permisos mínimos necesarios según lo recomendado:

ssh cluster2-node1

➜ root@cluster2-node1:~# kube-bench run --targets=node
...
== Summary ==
13 checks PASS
10 checks FAIL
2 checks WARN
0 checks INFO

También aquí algunos aprobados, fallos y advertencias. Verificamos el nivel de permisos del archivo de configuración kubelet:

➜ root@cluster2-node1:~# stat -c %a /var/lib/kubelet/config.yaml
777
# 777 es un nivel de acceso altamente permisivo y no recomendado por las directrices de kube-bench:

➜ root@cluster2-node1:~# kube-bench run --targets=node | grep /var/lib/kubelet/config.yaml -B2

4.1.9 Run the following command (using the config file location identified in the Audit step)
chmod 644 /var/lib/kubelet/config.yaml

# Obedecemos y establecemos los permisos recomendados:

➜ root@cluster2-node1:~# chmod 644 /var/lib/kubelet/config.yaml

➜ root@cluster2-node1:~# stat -c %a /var/lib/kubelet/config.yaml
644

# Y verificamos si la prueba 2.2.10 está aprobada:

➜ root@cluster2-node1:~# kube-bench run --targets=node | grep 4.1.9
[PASS] 2.2.10 Ensure that the kubelet configuration file has permissions set to 644 or more restrictive (Scored)

Número 4

Finalmente para el número (4), verifiquemos si el argumento --client-ca-file para el kubelet está configurado correctamente según las recomendaciones de kube-bench:

➜ root@cluster2-node1:~# kube-bench run --targets=node | grep client-ca-file
[PASS] 4.2.3 Ensure that the --client-ca-file argument is set as appropriate (Automated)

# Esto se ve aprobado con 4.2.3. Los otros son sobre el archivo al que apunta el parámetro y pueden ignorarse aquí.

# Para investigar más ejecutamos el siguiente comando para localizar el archivo de configuración kubelet, y lo abrimos:

➜ root@cluster2-node1:~# ps -ef | grep kubelet
root 5157 1 2 20:28 ? 00:03:22 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.2
root 19940 11901 0 22:38 pts/0 00:00:00 grep --color=auto kubelet

➜ root@croot@cluster2-node1:~# vim /var/lib/kubelet/config.yaml
# /var/lib/kubelet/config.yaml
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
anonymous:
enabled: false
webhook:
cacheTTL: 0s
enabled: true
x509:
clientCAFile: /etc/kubernetes/pki/ca.crt
...
El clientCAFile apunta a la ubicación del certificado, lo cual es correcto.