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.