Control de acceso basado en roles (RBAC) en Kubernetes
El control de acceso basado en roles (RBAC) se utiliza para asignar el acceso a un equipo o a los recursos de la red en el clúster de Kubernetes.
En este artículo, entenderemos los fundamentos del RBAC y crearemos los objetos Role, ClusterRole, RoleBinding y ClusterRoleBinding.
A continuación, crearemos un archivo kubeconfig para dar acceso limitado a un usuario concreto en un espacio de nombres seleccionado.
Pero antes de continuar, entendamos primero lo básico.
- Un Rol o ClusterRole contiene un conjunto de permisos.
- Un Rol establece los permisos dentro de un espacio de nombres concreto y el ClusterRole es un recurso sin espacio de nombres.
- Un RoleBinding concede los permisos definidos en un rol a un usuario o conjunto de usuarios, mientras que el ClusterRoleBinding concede ese acceso a todo el clúster
- Un RoleBinding puede hacer referencia a cualquier rol del mismo espacio de nombres. Alternativamente, un RoleBinding puede hacer referencia a un ClusterRole y vincular ese ClusterRole al espacio de nombres del RoleBindin
- Un archivo kubeconfig es un archivo utilizado para configurar el acceso a Kubernetes desde la herramienta de línea de comandos kubectl.
Para entender el RBAC en detalle, visita la documentación oficial de Kubernetes aquí.
Note: Refer screenshots to avoid any confusion before executing the commands. ( ubuntu@master = master node and ubuntu@ip-172-31-25-70 = user machine)
Requisitos previos
- Cluster de Kubernetes con al menos 1 nodo trabajador.
Si quieres aprender a crear un Cluster de Kubernetes, haz clic aquí. Esta guía te ayudará a crear un clúster Kubernetes con 1 Maestro y 2 Nodos en Instancias EC2 de AWS Ubuntu 18.04.
¿Qué vamos a hacer?
- Crear archivos de objetos Role, Role Binding, Cluster Role, Cluster Role Binding.
- Crear objetos Role, Role Binding, Cluster Role, Cluster Role Binding en el cluster.
- Proporcionar acceso a los usuarios mediante el archivo kubeconfig.
- Resumen de la creación del archivo kubeconfig.
Crear un archivo de objetos Role, Role Binding, Cluster Role Binding.
Crea un archivo para crear un Rol en el espacio de nombres «por defecto» que pueda utilizarse para conceder el acceso get, watch y list a los pods.
vim my-role.yml
kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: namespace: default name: pod-reader rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"]
Crea un nuevo archivo para crear un RoleBinding que permita el Role «pod-reader» al usuario «jane» dentro del espacio de nombres «por defecto».
vim my-role-binding.yml
kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: read-pods namespace: default subjects: - kind: User name: jane apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io
Crea un archivo para crear un ClusterRole que pueda utilizarse para conceder el acceso «get», «watch» y «list» a los secretos en cualquier espacio de nombres concreto, o en todos los espacios de nombres, dependiendo de cómo se vincule.
vim my-cluster-role.yml
kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: secret-reader rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "watch", "list"]
Crea un nuevo archivo para crear un ClusterRoleBinding que permita a cualquier usuario del grupo «manager» leer secretos en cualquier espacio de nombres.
vim my-cluster-role-binding.yml
kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: read-secrets-global subjects: - kind: Group name: manager apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: secret-reader apiGroup: rbac.authorization.k8s.io
Crea un objeto Roles, un objeto vinculado a un rol, un objeto vinculado a un rol de clúster y un objeto vinculado a un rol de clúster.
Obtén una lista de Roles y ClusterRoles existentes en el clúster.
kubectl get roles
kubectl get clusterroles
Obtén una lista de RoleBindings y ClusterRoleBindings existentes en el clúster.
kubectl get rolebinding
kubectl get clusterrolebinding
Ahora crea un Role, RoleBinding y ClusterRole ClusterRoleBinding utilizando los archivos que hemos creado en los pasos anteriores.
kubectl create -f my-role.yml
kubectl create -f my-role-binding.yml
kubectl create -f my-cluster-role.yml
kubectl create -f my-cluster-role-binding.yml
Con los siguientes comandos verifica si los objetos se han creado.
kubectl get roles | grep pod-reader
kubectl get rolebinding | grep read-pods
kubectl get clusterroles | grep secret-reader
kubectl get clusterrolebinding | grep read-secrets-global
En la captura de pantalla anterior, puedes ver que se ha creado el Role, RoleBinding y ClusterRole, ClusterRoleBinding.
Proporciona acceso a los usuarios mediante el archivo kubeconfig(config).
Ahora, en esta sección, crearemos un archivo de configuración que pueda ser compartido con un usuario. Para probar este escenario, crearemos un usuario «bob» en el servidor Linux y compartiremos este archivo de configuración con el usuario «bob». A continuación, intentaremos realizar las operaciones permitidas y no permitidas a ese usuario. Vincularemos un ClusterRole de administrador al usuario «bob» que dará acceso a todos los objetos del espacio de nombres «bob».
En los nodos maestros crea una clave y una solicitud de firma de certificado (CSR) utilizando openssl.
pwd
mkdir user-bob
cd user-bob/
openssl req -new -newkey rsa:4096 -nodes -keyout bob-k8s.key -out bob-k8s.csr -subj "/CN=bob/O=devops"
cat bob-k8s.csr | base64 | tr -d '\n'
Crea un archivo de definición del objeto CertificateSigningRequest que contenga la CSR que hemos generado en el paso anterior. En el archivo de abajo añade la salida del comando «cat bob-k8s.csr | base64 | tr -d ‘\n'» a la propiedad «request».
vim k8s-csr.yaml
apiVersion: certificates.k8s.io/v1beta1 kind: CertificateSigningRequest metadata: name: bob-k8s-access spec: groups: - system:authenticated request: # replace output of: cat bob-k8s.csr | base64 | tr -d '\n' usages: - client auth
cat k8s-csr.yaml
Crea un objeto CertificateSigningRequest en Kubernetes que contenga el CSR que hemos generado en el paso anterior.
kubectl get csr
kubectl create -f k8s-csr.yaml
kubectl get csr
Ahora queremos aprobar el objeto CSR (CertificateSigningRequest) que hemos creado en el paso anterior.
kubectl get csr
kubectl certificate approve bob-k8s-access
kubectl get csr
En la captura de pantalla anterior, puedes ver que el CSR ha sido Aprobado, Emitido.
Recupera el certificado disponible en el campo ‘status.certificate’ del objeto CSR.
ls -lt
kubectl get csr bob-k8s-access -o jsonpath='{.status.certificate}' | base64 --decode > bob-k8s-access.crt
ls -lt
cat bob-k8s-access.crt
Recupera el certificado de la CA del clúster que es el siguiente requisito para el archivo kubeconfig de Bob y guárdalo en el archivo «k8s-ca.crt».
ls -lt
kubectl config view -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' --raw | base64 --decode - > k8s-ca.crt
ls -lt
cat k8s-ca.crt
Establece la configuración del clúster en el archivo kubeconfig de Bob. Todos estos detalles se pondrán a partir de nuestro kubeconfig existente utilizando el siguiente comando.
ls -lt
kubectl config set-cluster $(kubectl config view -o jsonpath='{.clusters[0].name}') --server=$(kubectl config view -o jsonpath='{.clusters[0].cluster.server}') --certificate-authority=k8s-ca.crt --kubeconfig=bob-k8s-config --embed-certs
ls -lt
cat bob-k8s-config
Configura el usuario que importará la clave y el cert de Bob en el archivo de configuración.
ls -lt
kubectl config set-credentials bob --client-certificate=bob-k8s-access.crt --client-key=bob-k8s.key --embed-certs --kubeconfig=bob-k8s-config
ls -lt
cat bob-k8s-config
Crea un contexto para el archivo config de «Bob» utilizando el siguiente comando.
ls -lt
kubectl config set-context bob --cluster=$(kubectl config view -o jsonpath='{.clusters[0].name}') --namespace=bob --user=bob --kubeconfig=bob-k8s-config
ls -lt
cat bob-k8s-config
Crea un espacio de nombres para Bob
kubectl get ns
kubectl create ns bob
kubectl get ns -o wide
kubectl label ns bob user=bob env=sandbox
kubectl get ns -o wide
Especifica el contexto que utilizará Bob para sus comandos kubectl.
cat bob-k8s-config
kubectl config use-context bob --kubeconfig=bob-k8s-config
cat bob-k8s-config
Copia «bob-k8s-config» del nodo maestro al archivo «.kube/config» en el directorio principal de Bob y prueba la kubeconfig de Bob ejecutando la ‘versión kubectl’.
vim .kube/config #All the output of "cat bob-k8s-config" command ran on the master node and save it to /home/bob/.kube/config on the user machine.
kubectl version #Execute this on the user machine
Prueba los permisos ejecutando los siguientes comandos desde la máquina del usuario.
kubectl get nodes
kubectl get pods
kubectl get ns
kubectl get deployments
kubectl get all
En la captura de pantalla anterior puedes ver que el usuario «Bob» no puede realizar ninguna operación, ya que no se le ha dado acceso.
Asigna el rol de clúster «admin» por defecto a Bob para crear la mayoría de los tipos de objetos Kubernetes dentro de su espacio de nombres. Este rol «bob-admin» dará acceso de administrador al usuario «Bob» en el espacio de nombres «bob» utilizando el ClusterRole «admin».
Ejecuta el siguiente comando en el nodo maestro.
kubectl create rolebinding bob-admin --namespace=bob --clusterrole=admin --user=bob
kubectl get rolebinding
kubectl get clusterrole | grep admin
Obtén los espacios de nombre creados para Bob.
Ahora, ejecuta todos los siguientes comandos desde la máquina del usuario.
kubectl get ns
kubectl get ns bob
En la captura de pantalla anterior puedes ver que el usuario «Bob» no puede listar los recursos del «espacio de nombres».
Crea un Pod en el espacio de nombres «bob» establecido como espacio de nombres por defecto en el archivo kubeconfig de Bob.
kubectl run nginx --image=nginx
kubectl get pods
kubectl get pods -o wide
Comprueba el espacio de nombres actual establecido como espacio de nombres por defecto
kubectl config get-contexts
En la captura de pantalla anterior, puedes ver que «Bob» puede crear un Pod en el espacio de nombres «bob», ya que hemos vinculado el rol «admin» al usuario «Bob» para el espacio de nombres «bob».
Intenta crear un pod en un espacio de nombres «predeterminado» en el que Bob no tenga ningún permiso. Como hemos permitido que el usuario «Bob» sólo pueda crear objetos en el espacio de nombres «bob», el usuario Bob no podrá crear ningún recurso en otro espacio de nombres que no sea «bob».
kubectl run nginx-2 --image=nginx --namespace=default
Comprueba el espacio de nombres establecido como espacio de nombres por defecto en el archivo kubeconfig. Esto muestra que el espacio de nombres «bob» está establecido como espacio de nombres por defecto en el archivo de configuración.
kubectl config view --minify | grep namespace:
Resumen de la creación del archivo Kubeconfig
- Crea una clave y una solicitud de firma de certificado (CSR) con openssl.
- Crea un archivo de definición del objeto CertificateSigningRequest.
- Crea un objeto CertificateSigningRequest.
- Aprobar la CSR (CertificateSigningRequest).
- Recuperar el certificado del objeto CSR.
- Recuperar el certificado de la CA del clúster.
- Establecer la configuración del clúster en el archivo kubeconfig.
- Configurar el usuario.
- Crear un contexto.
- Crear un espacio de nombres para el usuario.
- Especifica el contexto en el archivo kubeconfig.
- Pasa la kubeconfig al usuario.
- Prueba los permisos utilizando el archivo de configuración del usuario.
- Asigna el rol al usuario
- Prueba los permisos de nuevo utilizando el archivo de configuración del usuario.
Conclusión
En este artículo hemos visto los fundamentos de Role, RoleBinding y ClusterRole, ClusterRoleBinding, también hemos creado estos objetos en nuestro cluster. A continuación, hemos creado un archivo de configuración que permite a un usuario concreto realizar operaciones en un espacio de nombres determinado. Vimos cómo RBAC puede ayudarnos a restringir el acceso al clúster de Kubernetes.