Kubernetes: Cómo gestionar autorización de recursos con RBAC (Parte 2) #docker #kubernetes

Continuamos con nuestro artículo sobre Kubernetes y RBAC justo donde lo dejamos en la primera parte (jugando con los espacios de nombres), así que echa un vistazo al anterior post para repasar y manos a la obra. Ahora vamos a centrarnos en la creación de roles y su asociación a diferentes usuarios y grupos.

Figura 6: Kubernetes: Cómo gestionar autorización de recursos con RBAC (Parte 2)

En este ejemplo, que vamos a usar de base para explicar sus componentes, podemos ver un fichero de creación de un role para tener control total total al espacio de nombres de cybercaronte (luego veremos como se crea):
    kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: cybercaronte-full-control
namespace: cybercaronte
rules:
- apiGroups: [""]
resources: ["*"]
verbs: ["*"]
Como todo objeto en Kubernetes, vemos como en este caso tenemos definidos los atributos kind, apiVersion y metadata. Ojo a este caso, como estamos creando un role, tenemos que especificar el espacio de nombres donde queremos crearlo con el atributo namespace dentro de metadata.

Figura 7: Proceso de arranque de minikube

Lo siguiente es definir las reglas (rules). En este case vemos como tenemos entradas bajo rules:
apiGroups: aquí especificamos la(s) API(s) que queremos autorizar. Si lo dejamos vacío (""), implica que dicha regla (rule), se aplica a las APIs core de Kubernetes. Alguno de los grupos disponibles, además del core, son: extensions, apps, etc. Si quieres ver todas las APIs disponible en tu clúster, puedes ejecutar el siguiente comando:
kubectl api-versions
resources: aquí, si queremos aplicar la regla a todos los dispositivos, podemos poner un asterisco, o bien listar los recursos que deseamos. Por ejempo: pods, secrets, configmaps, deployments, services, etc.
verbs: en Kubernetes el recibe todas las peticiones es el component API Server, que no es ni más ni menos que un servicio Rest. Por lo que toda petición se basa en un recurso y un verbo: GET, POST, PUT, etc. En el caso de Kubernetes, éste define su propia lista de verbos como son: get, list, watch, create, update, patch, delete, bind, etcetera.
Si creamos ese role y se lo asignamos a un usuario, dicho usuario prácticamente tendría control total sobre el espacio de nombres donde dicho role es creado. Un apunte importante es que podemos añadir varias reglas a un role:
    rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: ["batch", "extensions"]
resources: ["jobs"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
En este caso, tenemos dos reglas, la primera indica que podemos leer, listar y observar pods a través del uso de cualquier API de Kubernetes. La segunda indica que podemos obtener, listar, observar, crear, actualizar, parchear y borrar recursos del tipo (Kind) job definidos bajo las APIs batch y extensions.

Ahora sí, vamos a crear los dos roles, uno para el espacio de nombres cybercaronte:
    kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: cybercaronte-full-control
namespace: cybercaronte
rules:
- apiGroups: [""]
resources: ["*"]
verbs: ["*"]
Y otro para el espacio de nombres tuxotron:
    kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: tuxotron-full-control
namespace: tuxotron
rules:
- apiGroups: [""]
resources: ["*"]
verbs: ["*"]
Creamos dos ficheros (cybercaronte-fullcontrol-role.yaml y tuxotron-fullcontrol-role.yaml) con dicho contenido y ejecuta:
  kubectl apply -f cybercaronte-fullcontrol-role.yaml
kubectl apply -f tuxotron-fullcontrol-role.yaml
Para comprobar que los roles se han creado:
  kubectl get role -n cybercaronte
kubectl get role -n tuxotron
Ahora que tenemos los usuarios y los roles creados, tenemos que asignarles los roles a los usuarios. Para ello necesitamos crear los objectos RoleBinding.
Primero vamos a asignar al usuario cybercaronte el role cybercaronte-full-control. Para ello creamos un fichero (cybercaronte-fullcontrol-binding.yaml) con el siguiente contenido
    kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: full-control
namespace: cybercaronte
subjects:
- kind: User
name: cybercaronte
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: cybercaronte-full-control
apiGroup: rbac.authorization.k8s.io
Crea el RoleBinding:
    kubectl apply -f cybercaronte-fullcontrol-binding.yaml
Para probar si funciona, cambiemos de contexto a cybercaronte y a ver si ahora podemos consultar los pods del espacio de nombres cybercaronte:
kubectl config use-context cybercaronte kubectl get pods -n cybercaronte No resources found.
Como podemos ver esta vez no recibimos ningún error. Si intentamos consultar los pods del espacio de nombres tuxotron:
  kubectl get pods -n tuxotron
Error from server (Forbidden): pods is forbidden: User "cybercaronte" cannot list resource "pods" in API group "" in the namespace "tuxotron"
Vemos como recibimos un error porque el usuario cybercaronte no tiene acceso a los pods del espacio de nombres tuxotron.

Figura 8: Rafael Troncoso (tuxotron), Chema Alonso (sujetando el libro Docker:SecDevOps), Elías Grande
y Fran Ramírez (cybercaronte) en la RootedCon 2019. Al fondo, el poster del "Profesor Alonso" de Cels Piñol.
Hagamos lo mismo con el usuario tuxotron. Crea un fichero (tuxotron-fullcontrol-binding.yaml) con el siguiente contenido:
    kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: full-control
namespace: tuxotron
subjects:
- kind: User
name: tuxotron
apiGroup: rbac.authorization.k8s.io
roleRef:
- kind: Role
name: tuxotron-full-control
apiGroup: rbac.authorization.k8s.io
Antes de poder crear este RoleBinding tenemos que cambiar de contexto a minikube primero:
    kubectl config use-context minikube
kubectl apply -f tuxotron-fullcontrol-binding.yaml
Vamos a explicar un poco la estructura de este objeto. Lo primero a recalcar es el nombre (metadata.name), si te fijas bien en los dos RoleBindings que hemos creado usan exactamente el mismo nombre. Esto es posible, porque los RoleBindings pertenecen a un nombre de espacio, y en nuestro ejemplo hemos creado cada RoleBidning en distintos espacios de nombre. Si hubiéramos usado el CLusterRoleBinding, esto no sería posible porque en ese caso habría un conflicto de nombres.

El apartado subjects es donde decimos a quién la vamos a asignar el role. El atributo Kind debe ser User, Group o ServiceAccount. Luego tenemos name, éste corresponde al nombre de usuario, grupo o cuenta de servicio y por último el apiGroup que es rbac.authorization.k8s.io

Luego tenemos el apartado roleRef. Aquí es dónde especificamos el role que queremos asignar. El atributo Kind define el tipo de role: Role o ClusterRole. Name es el nombre del role en sí y finalmente el apiGroup que al igual que el caso anterior es rbac.authorization.k8s.io

Por último, veamos un ejemplo donde daremos acceso al espacio de nombres equipo al grupo developers. Vamos a crear un role a nivel de clúster para dar acceso total sobre pods, deployments, servicios, replicasets y secretos:
    kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: full-control
rules:
- apiGroups: ["extensions", "apps", ""]
resources: ["pods", "deployments", "secrets", "services", "replicasets"]
verbs: ["*"]
Copiamos el contenido a un fichero (developers-role.yaml) y ejecuta el siguiente comando:
    kubectl apply -f developers-role.yaml
Un par de apuntes sobre este fichero. Lo primero es que el tipo (Kind) es ClusterRole y como vemos no tiene especificado el espacio de nombres (namespace). Este es un objeto global del clúster. Ahora creemos otro fichero (developers-binding.yaml) con el siguiente contenido:
    kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: full-control
namespace: equipo
subjects:
- kind: Group
name: developers
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: full-control
apiGroup: rbac.authorization.k8s.io
Como vemos, el contenido de este fichero es similar a los anteriores, con par de diferencias. En el apartado subjects, usamos el tipo Group, porque estamos asignando el role a un grupo y no a un usuario. Y en el apartado roleRef, el tipo es ClusterRole y no Role, ya que el role al que estamos haciendo referencia es del tipo ClusterRole. Para crear dicho RoleBinding:
    kubectl apply -f developers-binding.yaml
Recuerda que cuando creamos los usuarios, ambos los creamos bajo la organización developers `/O=developers`. Por lo tanto, cybercaronte y tuxotron deberían tener acceso a los pods, servicios, secretos, replicasets y deployments del espacio de nombres. Comprobemos que cybercaronte tiene acceso:

kubectl config use-context cybercaronte
Switched to context "cybercaronte".

kubectl get pod -n equipo
No resources found.

kubectl get deployment -n equipo
No resources found.

kubectl get configmap -n equipo
Error from server (Forbidden): configmaps is forbidden: User "cybercaronte" cannot list resource "configmaps" in API group "" in the namespace "equipo"
Como hemos podido comprobar, cuando consultamos los pods y los deployments no recibimos ningún error. “No resources found” es porque no hemos creado nada en el espacio de nombres. Cuando consultamos los configmaps vemos que recibimos un error, ya que ese recurso no tenemos acceso. Si hacemos las mismas pruebas con el usuario tuxotron, los resultados deberían ser el mismo.


Figura 9: Kubernetes: Cómo gestionar autorización de recursos con RBAC [Parte 2]

Kubernetes no sólo permite el control de acceso a un recurso complete, sino que incluso a parte del mismo. Por ejemplo, podrías dar acceso a los logs de los pods, sin dar acceso a los pods en sí. Tienes en el vídeo todo el proceso que hemos realizado en esta parte del artículo.

Esperamos que te hayas animado a llegar al final de este artículo y por lo menos tengas suficiente información para entender como funciona el RBAC en Kubernetes. Os dejamos por aquí también algunas de las referencias que tenemos sobre Docker escritas ya en este blog, para que tengáis toda la información disponible y accesible.

[BlogPost] Docker: SecDevOps: Contenido y descripción del libro
[BlogPost] SecDevOps: Una explicación en 5 minutos (o poco más)
[BlogPost] Cómo montar un entorno de pentesting desde cero en Docker
[BlogPost] SuperLatch Docker: Integrar Latch con Docker y Kubernetes en tus apps
[BlogPost] Docker Distroless Images: Cómo crear imágenes Docker sin SO ni shell
[BlogPost] Dagda Docker Security Suite: Auditoría de seguridad en aplicaciones dockerizadas
[BlogPost] Docker de My WordPress in Paranoid Mode
[BlogPost] Docker de My WordPress in Paranoid Mode (WPM): "The Making of"
[BlogPost] Hacking Kubernetes: Auditoría de seguridad y explotación de vulnerabilidades
[BlogPost] Kubernetes: Cómo gestionar autorización de recursos con RBAC

Fran Ramírez, (@cyberhadesblog) es investigador de seguridad y miembro del equipo de Ideas Locas en CDO en Telefónica, co-autor del libro "Microhistorias: Anécdotas y Curiosidades de la historia de la informática (y los hackers)", del libro "Docker: SecDevOps" y del blog Cyberhades.

Rafael Troncoso (@tuxotron) es Senior Software Engineer en SAP Concur, co-autor del libro "Microhistorias: Anécdotas y Curiosidades de la historia de la informática (y los hackers)", del libro "Docker: SecDevOps" y del blog Cyberhades.

Via: www.elladodelmal.com
Kubernetes: Cómo gestionar autorización de recursos con RBAC (Parte 2) #docker #kubernetes Kubernetes: Cómo gestionar autorización de recursos con RBAC (Parte 2) #docker #kubernetes Reviewed by Anónimo on 2:23 Rating: 5