Comprensión de RBAC en Kubernetes

Nota perev. : Este artículo fue escrito por Javier Salmerón, ingeniero de la conocida comunidad de Kubernetes en Bitnami, y publicado en el blog de CNCF a principios de agosto. El autor habla sobre los conceptos básicos del mecanismo RBAC (control de acceso basado en roles) que apareció en Kubernetes hace un año y medio. El material será especialmente útil para aquellos que estén familiarizados con el dispositivo de componentes clave de K8 (ver enlaces a otros artículos similares al final).


Diapositiva de una presentación realizada por un empleado de Google con motivo del lanzamiento de Kubernetes 1.6

Muchos usuarios experimentados de Kubernetes pueden recordar la versión 1.6 de Kubernetes, cuando la autorización basada en el control de acceso basado en roles (RBAC) se convirtió en beta. Entonces apareció un mecanismo de autenticación alternativo, que complementaba el Control de acceso basado en atributos (ABAC) ya existente, pero difícil de administrar y comprender. Todos acogieron con entusiasmo la nueva función, pero al mismo tiempo innumerables usuarios quedaron decepcionados. StackOverflow y GitHub abundaban en informes de restricciones de RBAC porque la mayoría de la documentación y los ejemplos no tenían en cuenta RBAC (pero ahora todo está bien). El ejemplo de referencia fue Helm: simplemente ejecutar helm init + helm install ya no funcionaba. De repente, necesitábamos agregar elementos "extraños" como ServiceAccounts o RoleBindings incluso antes de implementar el gráfico con WordPress o Redis (consulte las instrucciones para obtener más información al respecto).

Dejando a un lado estos primeros intentos fallidos, no se puede negar la enorme contribución que RBAC hizo para convertir a Kubernetes en una plataforma lista para la producción. Muchos de nosotros logramos jugar con Kubernetes con todos los privilegios de administrador, y entendemos perfectamente que en un entorno real es necesario:

  • Tener muchos usuarios con diferentes propiedades que brinden el mecanismo de autenticación deseado.
  • Tenga control total sobre las operaciones que puede realizar cada usuario o grupo de usuarios.
  • Tenga control total sobre las operaciones que puede realizar cada proceso en el corazón.
  • Limite la visibilidad de ciertos recursos en espacios de nombres.

Y a este respecto, RBAC es un elemento clave que proporciona capacidades muy necesarias. En el artículo, repasaremos rápidamente los conceptos básicos (vea este video para más detalles; siga el enlace del webinar de Bitnami de 1 hora en inglés - aprox. Transl. ) Y profundice un poco en los momentos más confusos.

La clave para entender RBAC en Kubernetes


Para realizar plenamente la idea de RBAC, debe comprender que hay tres elementos involucrados en él:

  • Temas : un conjunto de usuarios y procesos que desean tener acceso a la API de Kubernetes;
  • Recursos : una colección de objetos API de Kubernetes disponibles en un clúster. Sus ejemplos (entre otros) son Pods , implementaciones , servicios , nodos , volúmenes persistentes ;
  • Verbos (verbos): un conjunto de operaciones que se pueden realizar en los recursos. Hay varios verbos (get, watch, create, delete, etc.), pero todos ellos son, en última instancia, operaciones CRUD (Create, Read, Update, Delete).



Con estos tres elementos en mente, la idea clave de RBAC es:

"Queremos conectar los temas, los recursos API y las operaciones". En otras palabras, queremos indicar para un usuario determinado qué operaciones se pueden realizar en una variedad de recursos .

Comprender los objetos RBAC en la API


Al combinar estos tres tipos de entidades, los objetos RBAC disponibles en la API de Kubernetes quedan claros:

  • Roles conectan recursos y verbos. Se pueden reutilizar para diferentes temas. Vinculado a un espacio de nombres (no podemos usar plantillas que representen más de un [espacio de nombres], pero podemos implementar el mismo objeto de rol en diferentes espacios de nombres). Si desea aplicar el rol a todo el clúster, hay un objeto ClusterRoles similar.
  • RoleBindings conecta las entidades restantes de la entidad. Al especificar un rol que ya vincula los objetos API a los verbos, ahora seleccionamos los temas que pueden usarlos. El equivalente para el nivel de clúster (es decir, sin vinculación a espacios de nombres) es ClusterRoleBindings .

En el siguiente ejemplo, le damos al usuario jsalmeron el derecho de leer, obtener una lista y crear hogares en el espacio de nombres de prueba . Esto significa que jsalmeron podrá ejecutar estos comandos:

 kubectl get pods --namespace test kubectl describe pod --namespace test pod-name kubectl create --namespace test -f pod.yaml #      

... pero no así:

 kubectl get pods --namespace kube-system #    kubectl get pods --namespace test -w #    watch 



Ejemplos de archivos YAML:

 kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: pod-read-create namespace: test rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "create"] 

 kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: salme-pods namespace: test subjects: - kind: User name: jsalmeron apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-read-create apiGroup: rbac.authorization.k8s.io 

Otro punto interesante es este: ahora que el usuario puede crear pods, ¿podemos limitar cuánto? Esto requerirá otros objetos que no estén directamente relacionados con la especificación RBAC y le permitirá configurar límites de recursos: ResourceQuota y LimitRanges . Definitivamente vale la pena explorarlos al configurar un componente de clúster tan importante [como crear hogares].

Temas: Usuarios y ... ¿Cuentas de servicio?


Una de las dificultades que enfrentan muchos usuarios de Kubernetes en el contexto de los temas es la distinción entre usuarios regulares y ServiceAccounts . En teoría, todo es simple:

  • Users : usuarios globales, diseñados para personas o procesos que viven fuera del clúster;
  • ServiceAccounts : limitadas por espacio de nombres y destinadas a procesos dentro del clúster que se ejecutan en pods.

La similitud de ambos tipos radica en la necesidad de autenticarse con la API para realizar ciertas operaciones en muchos recursos, y sus áreas temáticas parecen muy específicas. También pueden pertenecer a grupos, por lo que RoleBinding permite vincular más de un tema (aunque solo se permite un grupo para ServiceAccounts - system:serviceaccounts ). Sin embargo, la principal diferencia es la causa del dolor de cabeza: los usuarios no tienen objetos que les correspondan en la API de Kubernetes. Resulta que tal operación existe:

 kubectl create serviceaccount test-service-account # OK 

... pero este se fue:

 kubectl create user jsalmeron # ! 

Esta situación tiene una consecuencia grave: si el clúster no almacena información sobre los usuarios, el administrador tendrá que administrar cuentas fuera del clúster. Hay diferentes formas de resolver el problema: certificados TLS, tokens, OAuth2, etc.

Además, deberá crear contextos kubectl que podamos acceder al clúster a través de estas nuevas cuentas. Para crear archivos con ellos, puede usar los comandos de kubectl config (que no requieren acceso a la API de Kubernetes, para que cualquier usuario pueda ejecutarlos). El video anterior tiene un ejemplo de cómo crear un usuario con certificados TLS.

RBAC en implementaciones: ejemplo


Vimos un ejemplo en el que el usuario especificado tiene derechos para operaciones en el clúster. Pero, ¿qué pasa con las implementaciones que requieren acceso a la API de Kubernetes? Considere un escenario específico para obtener una mejor comprensión.

Tomemos como ejemplo la popular aplicación de infraestructura: RabbitMQ. Utilizaremos el Bitmami Helm Chart para RabbitMQ (del repositorio oficial de helm / charts), que utiliza el contenedor bitnami / rabbitmq . Un complemento para Kubernetes está integrado en el contenedor, que es responsable de detectar otros miembros del clúster RabbitMQ. Debido a esto, el proceso dentro del contenedor requiere acceso a la API de Kubernetes, y debemos configurar ServiceAccount con los privilegios RBAC correctos.

Cuando se trata de ServiceAccounts , siga esta buena práctica:

- Configure cuentas de servicio para cada implementación con un conjunto mínimo de privilegios .

Para las aplicaciones que requieren acceso a la API de Kubernetes, puede tener la tentación de crear algún tipo de " ServiceAccount privilegiada" que puede hacer casi cualquier cosa en el clúster. Aunque esto parece una solución más simple, en última instancia puede conducir a una vulnerabilidad de seguridad que podría permitir operaciones no deseadas. (El video analiza un ejemplo de un Tiller [componente Helm] y las consecuencias de tener ServiceAccounts con grandes privilegios).

Además, diferentes implementaciones tendrán diferentes necesidades en términos de acceso a la API, por lo que es razonable que cada implementación tenga diferentes ServiceAccounts .

Teniendo esto en cuenta, veamos qué configuración de RBAC es correcta para el caso de implementación con RabbitMQ.

En la documentación del complemento y su código fuente, puede ver que está solicitando una lista de puntos finales de la API de Kubernetes. Así es como se detectan los miembros restantes del clúster RabbitMQ. Por lo tanto, el gráfico Bitnami RabbitMQ crea:

  • ServiceAccount para hogares con RabbitMQ:

     {{- if .Values.rbacEnabled }} apiVersion: v1 kind: ServiceAccount metadata: name: {{ template "rabbitmq.fullname" . }} labels: app: {{ template "rabbitmq.name" . }} chart: {{ template "rabbitmq.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" {{- end }} 
  • Rol (suponemos que todo el clúster RabbitMQ se implementa en un solo espacio de nombres), permitiendo que el verbo obtenga el recurso Endpoint :

     {{- if .Values.rbacEnabled }} kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: {{ template "rabbitmq.fullname" . }}-endpoint-reader labels: app: {{ template "rabbitmq.name" . }} chart: {{ template "rabbitmq.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" rules: - apiGroups: [""] resources: ["endpoints"] verbs: ["get"] {{- end }} 
  • RoleBinding conectando una cuenta de servicio a un rol:

     {{- if .Values.rbacEnabled }} kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: {{ template "rabbitmq.fullname" . }}-endpoint-reader labels: app: {{ template "rabbitmq.name" . }} chart: {{ template "rabbitmq.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" subjects: - kind: ServiceAccount name: {{ template "rabbitmq.fullname" . }} roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: {{ template "rabbitmq.fullname" . }}-endpoint-reader {{- end }} 



El diagrama muestra que permitimos que los procesos que se ejecutan en pods RabbitMQ realicen operaciones de obtención en objetos Endpoint . Este es el conjunto mínimo de operaciones que se requieren para que todo funcione. Al mismo tiempo, sabemos que el gráfico desplegado es seguro y no realizará acciones no deseadas dentro del clúster de Kubernetes.

Pensamientos finales


Para trabajar con Kubernetes en producción, las políticas RBAC no son opcionales. No se pueden considerar como un conjunto de objetos API que solo los administradores deben conocer. Los desarrolladores realmente los necesitan para implementar aplicaciones seguras y aprovechar al máximo el potencial que ofrece la API de Kubernetes para aplicaciones nativas de la nube. Se puede encontrar más información sobre RBAC en estos enlaces:


PD del traductor


Lea también en nuestro blog:

Source: https://habr.com/ru/post/es422801/


All Articles