Pregunta 3 | Seguridad del Apiserver
Usar contexto: kubectl config use-context workload-prod
Recibiste una lista del equipo DevSecOps que realizó una investigación de seguridad del clúster k8s cluster1 (workload-prod). La lista establece lo siguiente sobre la configuración del apiserver:
Accesible a través de un NodePort Service
Cambia la configuración del apiserver para que:
Solo sea accesible a través de un ClusterIP Service
Respuesta:
Para modificar los parámetros del apiserver, primero hacemos ssh al nodo maestro y verificamos con qué parámetros se está ejecutando el proceso del apiserver:
➜ ssh cluster1-controlplane1
➜ root@cluster1-controlplane1:~# ps aux | grep kube-apiserver
root 27622 7.4 15.3 1105924 311788 ? Ssl 10:31 11:03 kube-apiserver --advertise-address=192.168.100.11 --allow-privileged=true --authorization-mode=Node,RBAC --client-ca-file=/etc/kubernetes/pki/ca.crt --enable-admission-plugins=NodeRestriction --enable-bootstrap-token-auth=true --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key --etcd-servers=https://127.0.0.1:2379 --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --kubernetes-service-node-port=31000 --proxy-client-cert-
...
Podemos notar el siguiente argumento:
--kubernetes-service-node-port=31000
También podemos verificar el Service y ver que es de tipo NodePort:
➜ root@cluster1-controlplane1:~# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes NodePort 10.96.0.1 <none> 443:31000/TCP 5d2h
El apiserver se ejecuta como un Pod estático, por lo que podemos editar el manifiesto. Pero antes de hacer esto también creamos una copia en caso de que estropeemos las cosas:
➜ root@cluster1-controlplane1:~# cp /etc/kubernetes/manifests/kube-apiserver.yaml ~/3_kube-apiserver.yaml
➜ root@cluster1-controlplane1:~# vim /etc/kubernetes/manifests/kube-apiserver.yaml
Deberíamos eliminar las configuraciones inseguras:
# /etc/kubernetes/manifests/kube-apiserver.yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 192.168.100.11:6443
creationTimestamp: null
labels:
component: kube-apiserver
tier: control-plane
name: kube-apiserver
namespace: kube-system
spec:
containers:
- command:
- kube-apiserver
- --advertise-address=192.168.100.11
- --allow-privileged=true
- --authorization-mode=Node,RBAC
- --client-ca-file=/etc/kubernetes/pki/ca.crt
- --enable-admission-plugins=NodeRestriction
- --enable-bootstrap-token-auth=true
- --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
- --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
- --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
- --etcd-servers=https://127.0.0.1:2379
- --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt
- --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
# - --kubernetes-service-node-port=31000 # eliminar o establecer en 0
- --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
- --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
...
Una vez realizados los cambios, dale al apiserver algo de tiempo para que se reinicie. Verifica el estado del Pod del apiserver y los parámetros del proceso:
➜ root@cluster1-controlplane1:~# kubectl -n kube-system get pod | grep apiserver
kube-apiserver-cluster1-controlplane1 1/1 Running 0 38s
➜ root@cluster1-controlplane1:~# ps aux | grep kube-apiserver | grep node-port
El apiserver se reinició sin las configuraciones inseguras. Sin embargo, el Service kubernetes seguirá siendo de tipo NodePort:
➜ root@cluster1-controlplane1:~# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes NodePort 10.96.0.1 <none> 443:31000/TCP 5d3h
Necesitamos eliminar el Service para que los cambios surtan efecto:
➜ root@cluster1-controlplane1:~# kubectl delete svc kubernetes
service "kubernetes" deleted
Después de unos segundos:
➜ root@cluster1-controlplane1:~# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6s
Esto debería satisfacer al equipo DevSecOps.