El ABC de la seguridad en Kubernetes: autenticación, autorización, auditoría



Tarde o temprano, el funcionamiento de cualquier sistema plantea la cuestión de la seguridad: garantizar la autenticación, la separación de derechos, la auditoría y otras tareas. Ya se han creado muchas soluciones para Kubernetes que pueden lograr el cumplimiento de las normas incluso en entornos muy exigentes ... El mismo material está dedicado a los aspectos básicos de seguridad implementados en el marco de los mecanismos integrados de K8. En primer lugar, será útil para aquellos que comienzan a familiarizarse con Kubernetes, como punto de partida para estudiar problemas de seguridad.

Autenticación


Kubernetes tiene dos tipos de usuarios:

  • Cuentas de servicio : cuentas administradas por la API de Kubernetes;
  • Usuarios : usuarios "normales" controlados por servicios externos e independientes.

La principal diferencia entre estos tipos es que para las Cuentas de servicio hay objetos especiales en la API de Kubernetes (se llaman Cuentas de servicio) que están vinculados a un espacio de nombres y a un conjunto de datos de autorización almacenados en un clúster en objetos de tipo Secretos. Dichos usuarios (Cuentas de servicio) están destinados principalmente a administrar los derechos de acceso a los procesos API de Kubernetes que se ejecutan en un clúster de Kubernetes.

Los usuarios ordinarios no tienen entradas en la API de Kubernetes: deben ser administrados por mecanismos externos. Están destinados a personas o procesos que viven fuera del clúster.

Cada solicitud a la API está vinculada a la cuenta de servicio o al usuario, o se considera anónima.

Los datos de autenticación del usuario incluyen:

  • Nombre de usuario - nombre de usuario (mayúsculas y minúsculas);
  • UID es una cadena de identificación de usuario legible por máquina que es "más coherente y única que el nombre de usuario";
  • Grupos : una lista de grupos a los que pertenece el usuario;
  • Extra : campos adicionales que puede utilizar el mecanismo de autorización.

Kubernetes puede utilizar una gran cantidad de mecanismos de autenticación: certificados X509, tokens de portador, proxies de autenticación, autenticación básica HTTP. Con estos mecanismos, se puede implementar una gran cantidad de esquemas de autorización: desde un archivo estático con contraseñas hasta OpenID OAuth2.

Además, se permiten múltiples esquemas de autorización al mismo tiempo. Por defecto, el clúster usa:

  • tokens de cuenta de servicio - para Cuentas de servicio;
  • X509 - para usuarios.

La pregunta sobre la administración de ServiceAccounts está más allá del alcance de este artículo, pero recomiendo comenzar a aprender más sobre este tema en la página de documentación oficial . Consideraremos con más detalle el tema del trabajo de los certificados X509.

Certificados para usuarios (X.509)


La forma clásica de trabajar con certificados implica:

  • generación clave:

     mkdir -p ~/mynewuser/.certs/ openssl genrsa -out ~/.certs/mynewuser.key 2048 
  • generación de solicitud de certificado:

     openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company" 
  • procesando la solicitud de certificado utilizando las claves de CA del clúster de Kubernetes, obteniendo un certificado de usuario (para obtener un certificado, debe usar una cuenta que tenga acceso a la clave de autoridad de certificado del clúster de Kubernetes, que se encuentra en /etc/kubernetes/pki/ca.key de forma predeterminada):

     openssl x509 -req -in ~/.certs/mynewuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out ~/.certs/mynewuser.crt -days 500 
  • creando un archivo de configuración:
    • Descripción del clúster (especifique la dirección y ubicación del archivo de certificado de CA de la instalación particular del clúster):

       kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443 
    • o, si no es la opción recomendada, puede omitir el certificado raíz (entonces kubectl no verificará la corrección del clúster del servidor api):

       kubectl config set-cluster kubernetes --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443 
    • Agregar un usuario al archivo de configuración:

       kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt --client-key=.certs/mynewuser.key 
    • agregando contexto:

       kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser 
    • asignación de contexto predeterminada:

       kubectl config use-context mynewuser-context 

Después de las manipulaciones anteriores, se creará una configuración del formulario en el archivo .kube/config :

 apiVersion: v1 clusters: - cluster: certificate-authority: /etc/kubernetes/pki/ca.crt server: https://192.168.100.200:6443 name: kubernetes contexts: - context: cluster: kubernetes namespace: target-namespace user: mynewuser name: mynewuser-context current-context: mynewuser-context kind: Config preferences: {} users: - name: mynewuser user: client-certificate: /home/mynewuser/.certs/mynewuser.crt client-key: /home/mynewuser/.certs/mynewuser.key 

Para facilitar la transferencia de la configuración entre cuentas y servidores, es útil editar los valores de las siguientes claves:

  • certificate-authority
  • client-certificate
  • client-key

Para hacer esto, puede codificar los archivos indicados en ellos usando base64 y registrarlos en la configuración agregando el sufijo -data al nombre de las claves, es decir. obtener certificate-authority-data , etc.

Certificados con kubeadm


Con el lanzamiento de Kubernetes 1.15, trabajar con certificados se ha vuelto mucho más fácil gracias a la versión alfa de su soporte en la utilidad kubeadm . Por ejemplo, así es como puede verse ahora la generación de un archivo de configuración con claves de usuario:

 kubeadm alpha kubeconfig user --client-name=mynewuser --apiserver-advertise-address 192.168.100.200 

NB : la dirección de publicidad requerida se puede ver en la configuración del servidor api, que se encuentra en /etc/kubernetes/manifests/kube-apiserver.yaml de forma predeterminada.

La configuración resultante se enviará a stdout. Debe guardarse en ~/.kube/config cuenta de usuario o en el archivo especificado en la KUBECONFIG entorno KUBECONFIG .

Cavar más profundo


Para aquellos que desean comprender a fondo los problemas descritos:


Iniciar sesión


Una cuenta autenticada no tiene permiso para actuar en un clúster de forma predeterminada. Kubernetes tiene un mecanismo de autorización para otorgar permisos.

Antes de la versión 1.6, Kubernetes usaba un tipo de autenticación llamado ABAC (control de acceso basado en atributos). Los detalles al respecto se pueden encontrar en la documentación oficial . Actualmente, este enfoque se considera heredado, pero aún puede usarlo al mismo tiempo que otros tipos de autorización.

La forma real (y más flexible) de dividir los derechos de acceso al clúster se denomina RBAC ( control de acceso basado en roles ). Se ha declarado estable desde Kubernetes 1.8 . RBAC implementa un modelo de derechos que prohíbe todo lo que no esté explícitamente permitido.
Para habilitar RBAC , debe ejecutar el servidor de API Kubernetes con la --authorization-mode=RBAC . Los parámetros se establecen en el manifiesto con la configuración del servidor api, que por defecto se encuentra en la ruta /etc/kubernetes/manifests/kube-apiserver.yaml , en la sección de command . Sin embargo, RBAC ya está habilitado de forma predeterminada, por lo que probablemente no debería preocuparse por esto: puede verificar esto mediante el valor del authorization-mode de authorization-mode (en el ya mencionado kube-apiserver.yaml ). Por cierto, entre sus valores puede haber otros tipos de autorización ( node , webhook , always allow ), pero los dejaremos fuera del alcance del material.

Por cierto, ya hemos publicado un artículo con una historia bastante detallada sobre los principios y características de trabajar con RBAC, por lo que me limitaré a una breve lista de los conceptos básicos y ejemplos.

Las siguientes entidades API se utilizan para controlar el acceso a Kubernetes a través de RBAC:

  • Role y ClusterRole son roles que describen privilegios:
  • Role permite describir los derechos dentro de un espacio de nombres;
  • ClusterRole : dentro del clúster, incluidos los objetos específicos del clúster, como nodos, URL que no son recursos (es decir, no están relacionados con los recursos de Kubernetes, por ejemplo, /version , /logs , /api* );
  • RoleBinding y ClusterRoleBinding : sirve para vincular Role y ClusterRole a un usuario, grupo de usuarios o ServiceAccount.

Las entidades Role y RoleBinding están limitadas por el espacio de nombres, es decir debe estar dentro del mismo espacio de nombres. Sin embargo, RoleBinding puede referirse a ClusterRole, que le permite crear un conjunto de permisos estándar y controlar el acceso con ellos.

Los roles describen derechos utilizando conjuntos de reglas que contienen:

  • Grupos de API: consulte la documentación oficial de apiGroups y la salida de kubectl api-resources ;
  • recursos ( recursos : pod , namespace , deployment , etc.);
  • verbos ( verbos : set , update , etc.).
  • nombres de recursos ( resourceNames ): para el caso en que necesita proporcionar acceso a un recurso específico y no a todos los recursos de este tipo.

Puede encontrar una discusión más detallada sobre la autorización en Kubernetes en la página de documentación oficial . En cambio (o más bien, además de esto) daré ejemplos que ilustran su trabajo.

Ejemplos de entidades RBAC


Un Role simple que le permite obtener la lista y el estado de los pods y monitorearlos en el target-namespace :

 apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: target-namespace name: pod-reader rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"] 

Un ejemplo de ClusterRole , que le permite obtener una lista y el estado de los pods y monitorearlos en todo el clúster:

 apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: #  "namespace" ,   ClusterRole    name: pod-reader rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"] 

Ejemplo RoleBinding , que permite al usuario mynewuser "leer" pods en el my-namespace :

 apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: read-pods namespace: target-namespace subjects: - kind: User name: mynewuser #     ! apiGroup: rbac.authorization.k8s.io roleRef: kind: Role #    “Role”  “ClusterRole” name: pod-reader #  Role,      namespace, #   ClusterRole,   #    apiGroup: rbac.authorization.k8s.io 

Auditoria de eventos


Esquemáticamente, la arquitectura de Kubernetes se puede representar de la siguiente manera:

imagen

El componente clave de Kubernetes, que se encarga de procesar las solicitudes, es api-server . Todas las operaciones en el clúster pasan a través de él. Lea más sobre estos mecanismos internos en el artículo " ¿Qué sucede en Kubernetes cuando comienza la ejecución de kubectl? ".

La auditoría del sistema es una característica interesante en Kubernetes, que está desactivada de forma predeterminada. Le permite registrar todas las llamadas a la API de Kubernetes. Como puede adivinar fácilmente, a través de esta API se realizan todas las acciones relacionadas con la supervisión y el cambio del estado del clúster. Una buena descripción de sus características se puede encontrar (como de costumbre) en la documentación oficial de K8. A continuación, intentaré presentar el tema en un lenguaje más simple.

Entonces, para habilitar la auditoría , necesitamos pasar tres parámetros requeridos al contenedor en el servidor api, más sobre el cual se describe a continuación:

  • --audit-policy-file=/etc/kubernetes/policies/audit-policy.yaml
  • --audit-log-path=/var/log/kube-audit/audit.log
  • --audit-log-format=json

Además de estos tres parámetros necesarios, hay muchas configuraciones adicionales relacionadas con la auditoría: desde la rotación de registros hasta las descripciones de webhook. Parámetros de rotación de registro de ejemplo:

  • --audit-log-maxbackup=10
  • --audit-log-maxsize=100
  • --audit-log-maxage=7

Pero no nos detendremos en ellos con más detalle: puede encontrar todos los detalles en la documentación de kube-apiserver .

Como ya se mencionó, todos los parámetros se establecen en el manifiesto con la configuración del servidor api (por defecto /etc/kubernetes/manifests/kube-apiserver.yaml ), en la sección de command . Volvamos a los 3 parámetros requeridos y analícelos:

  1. audit-policy-file : ruta al archivo YAML con la descripción de la política de auditoría. Volveremos a su contenido, pero por ahora noto que el archivo debe ser accesible para que el proceso api-server pueda leerlo. Por lo tanto, es necesario montarlo dentro del contenedor, para lo cual puede agregar el siguiente código a las secciones apropiadas de la configuración:

      volumeMounts: - mountPath: /etc/kubernetes/policies name: policies readOnly: true volumes: - hostPath: path: /etc/kubernetes/policies type: DirectoryOrCreate name: policies 
  2. audit-log-path : ruta al archivo de registro. La ruta también debe ser accesible para el proceso del servidor api, por lo tanto, describimos de manera similar su montaje:

      volumeMounts: - mountPath: /var/log/kube-audit name: logs readOnly: false volumes: - hostPath: path: /var/log/kube-audit type: DirectoryOrCreate name: logs 
  3. audit-log-format : formato del registro de auditoría. Por defecto, esto es json , pero el formato de texto heredado también está disponible.

Política de auditoría


Ahora sobre el archivo mencionado con la descripción de la política de registro. El primer concepto de política de auditoría es el level , el nivel de registro . Son los siguientes:

  • None : no inicie sesión;
  • Metadata : metadatos de solicitud de registro: usuario, tiempo de solicitud, recurso de destino (pod, espacio de nombres, etc.), tipo de acción (verbo), etc.
  • Request : registrar metadatos y cuerpo de solicitud;
  • RequestResponse : RequestResponse metadatos, cuerpo de solicitud y cuerpo de respuesta.

Los dos últimos niveles ( Request y RequestResponse ) no registran las solicitudes que no tuvieron acceso a los recursos (llamadas a las llamadas URL sin recursos).

Además, todas las solicitudes pasan por varias etapas :

  • RequestReceived : la etapa en la que el controlador recibe la solicitud y aún no se ha transferido a lo largo de la cadena de controladores;
  • ResponseStarted : encabezados de respuesta enviados, pero antes de enviar el cuerpo de respuesta. Generado para consultas largas (por ejemplo, watch );
  • ResponseComplete - cuerpo de respuesta enviado, no se enviará más información;
  • Panic : los eventos se generan cuando se detecta una emergencia.

Puede usar omitStages para omitir cualquier etapa.

En el archivo de políticas, podemos describir varias secciones con diferentes niveles de registro. Se aplicará la primera regla coincidente encontrada en la descripción de la política.

El demonio kubelet monitorea el cambio de manifiesto con la configuración del servidor api y, si se detecta alguno, reinicia el contenedor con el servidor api. Pero hay un detalle importante: ignorarán los cambios en el archivo de políticas . Después de realizar cambios en el archivo de políticas, deberá reiniciar api-server manualmente. Dado que api-server se ejecuta como un pod estático , el kubectl delete no lo reiniciará. Tendrá que hacer que docker stop manualmente en kube-masters donde se ha cambiado la política de auditoría:

 docker stop $(docker ps | grep k8s_kube-apiserver | awk '{print $1}') 

Cuando habilita la auditoría, es importante recordar que kube-apiserver tiene una carga más alta . En particular, el consumo de memoria para almacenar el contexto de las solicitudes está aumentando. El registro comienza solo después de enviar el encabezado de respuesta. Además, la carga depende de la configuración de la política de auditoría.

Ejemplos de políticas


Analicemos la estructura de los archivos de políticas utilizando ejemplos.

Aquí hay un archivo de policy simple para registrar todo en el nivel de Metadata :

 apiVersion: audit.k8s.io/v1 kind: Policy rules: - level: Metadata 

Puede especificar una lista de usuarios ( Users y ServiceAccounts ) y grupos de usuarios en la política. Por ejemplo, así es como ignoraremos a los usuarios del sistema, pero registraremos todo lo demás en el nivel de Request :

 apiVersion: audit.k8s.io/v1 kind: Policy rules: - level: None userGroups: - "system:serviceaccounts" - "system:nodes" users: - "system:anonymous" - "system:apiserver" - "system:kube-controller-manager" - "system:kube-scheduler" - level: Request 

También es posible describir el objetivo:

  • namespaces
  • verbos ( verbos : get , update , delete y otros);
  • recursos ( recursos , a saber: pod , configmaps , etc.) y grupos de recursos ( apiGroups ).

¡Presta atención! Los recursos y grupos de recursos (grupos API, es decir, apiGroups), así como sus versiones instaladas en el clúster, se pueden obtener mediante los comandos:

 kubectl api-resources kubectl api-versions 

La siguiente política de auditoría se proporciona como una demostración de las mejores prácticas en la documentación de Alibaba Cloud :

 apiVersion: audit.k8s.io/v1beta1 kind: Policy #    RequestReceived omitStages: - "RequestReceived" rules: #   ,     : - level: None users: ["system:kube-proxy"] verbs: ["watch"] resources: - group: "" #  api group   ,    #   Kubernetes,  “core” resources: ["endpoints", "services"] - level: None users: ["system:unsecured"] namespaces: ["kube-system"] verbs: ["get"] resources: - group: "" # core resources: ["configmaps"] - level: None users: ["kubelet"] verbs: ["get"] resources: - group: "" # core resources: ["nodes"] - level: None userGroups: ["system:nodes"] verbs: ["get"] resources: - group: "" # core resources: ["nodes"] - level: None users: - system:kube-controller-manager - system:kube-scheduler - system:serviceaccount:kube-system:endpoint-controller verbs: ["get", "update"] namespaces: ["kube-system"] resources: - group: "" # core resources: ["endpoints"] - level: None users: ["system:apiserver"] verbs: ["get"] resources: - group: "" # core resources: ["namespaces"] #     read-only URLs: - level: None nonResourceURLs: - /healthz* - /version - /swagger* #   ,     “”: - level: None resources: - group: "" # core resources: ["events"] #   Secret, ConfigMap  TokenReview    , #         - level: Metadata resources: - group: "" # core resources: ["secrets", "configmaps"] - group: authentication.k8s.io resources: ["tokenreviews"] #   get, list  watch   ;    - level: Request verbs: ["get", "list", "watch"] resources: - group: "" # core - group: "admissionregistration.k8s.io" - group: "apps" - group: "authentication.k8s.io" - group: "authorization.k8s.io" - group: "autoscaling" - group: "batch" - group: "certificates.k8s.io" - group: "extensions" - group: "networking.k8s.io" - group: "policy" - group: "rbac.authorization.k8s.io" - group: "settings.k8s.io" - group: "storage.k8s.io" #        API - level: RequestResponse resources: - group: "" # core - group: "admissionregistration.k8s.io" - group: "apps" - group: "authentication.k8s.io" - group: "authorization.k8s.io" - group: "autoscaling" - group: "batch" - group: "certificates.k8s.io" - group: "extensions" - group: "networking.k8s.io" - group: "policy" - group: "rbac.authorization.k8s.io" - group: "settings.k8s.io" - group: "storage.k8s.io" #         - level: Metadata 


Otro buen ejemplo de política de auditoría es el perfil utilizado en GCE .

Para una respuesta rápida a los eventos de auditoría, es posible describir un webhook . Este problema se revela en la documentación oficial , lo dejaré fuera del alcance de este artículo.

Resumen


El artículo proporciona una descripción general de los mecanismos básicos de seguridad en los grupos de Kubernetes que le permiten crear cuentas de usuario personalizadas, compartir sus derechos y registrar sus acciones. Espero que sea útil para aquellos que enfrentan tales preguntas en teoría o ya en la práctica. También le recomiendo que consulte la lista de otros materiales sobre el tema de la seguridad en Kubernetes, que se encuentra en el "PS", tal vez entre ellos encontrará los detalles necesarios sobre temas que son relevantes para usted.

PS


Lea también en nuestro blog:

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


All Articles