Compartir a través de


Acceso de contenedor de seguridad a los recursos mediante características de seguridad integradas de Linux

En este artículo, aprenderá a proteger el acceso de contenedores a los recursos de las cargas de trabajo de Azure Kubernetes Service (AKS).

Información general

Por el mismo motivo que debería conceder a los usuarios o a los grupos el menor número de privilegios necesarios, también debería limitar los contenedores a solo las acciones y procesos necesarios. Para minimizar el riesgo de ataques, evite configurar las aplicaciones y los contenedores que requieren elevación de privilegios o acceso a raíz.

Puede usar contextos de seguridad de pod de Kubernetes integrados para definir más permisos, como el usuario o grupo para ejecutarse como, las funcionalidades de Linux que se van a exponer o establecer allowPrivilegeEscalation: false en el manifiesto de pod. Para más recomendaciones, consulte Protección del acceso del pod a los recursos.

Para un control aún más detallado de las acciones de los contenedores, puede usar las características de seguridad incorporadas de Linux como AppArmor y seccomp.

  1. Defina las características de seguridad de Linux en el nivel de nodo.
  2. Implemente las características mediante un manifiesto de pod.

Las características de seguridad integradas de Linux solo están disponibles en los pods y los nodos de Linux.

Nota:

Actualmente, los entornos de Kubernetes no están completamente seguros ante el uso de varios inquilinos hostiles. Otras características de seguridad, como Microsoft Defender para contenedores, AppArmor, seccomp, Pod Security Admission o RBAC para Kubernetes para nodos, bloquean eficazmente las vulnerabilidades de seguridad.

Para una verdadera seguridad al ejecutar cargas de trabajo multiinquilino hostiles, solo debe confiar en un hipervisor. El dominio de seguridad de Kubernetes se convierte en todo el clúster, no en un nodo específico.

En el caso de estos tipos de cargas de trabajo multiinquilino hostiles, debe usar clústeres que estén físicamente aislados.

AppArmor

Para limitar las acciones de los contenedores, puede usar el módulo de seguridad del kernel de Linux denominado AppArmor. AppArmor está disponible como parte del SO del nodo de AKS subyacente del sistema operativo y está habilitado de forma predeterminada. Puede crear perfiles de AppArmor para restringir acciones como leer, escribir o ejecutar, o funciones del sistema como montar sistemas de archivos. Los perfiles de AppArmor predeterminados restringen el acceso a diferentes ubicaciones de /proc y /sys, y proporcionan un medio para aislar lógicamente los contenedores desde el nodo subyacente. AppArmor funciona para cualquier aplicación que se ejecuta en Linux, no solo para los pods de Kubernetes.

Perfiles de AppArmor en uso en un clúster AKS para limitar las acciones del contenedor

Para ver AppArmor en acción, en el ejemplo siguiente se crea un perfil que impide la escritura en archivos.

  1. Acceda mediante SSH a un nodo de AKS.

  2. Cree un archivo denominado deny-write.profile.

  3. Copie y pegue el siguiente contenido:

    #include <tunables/global>
    profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
      #include <abstractions/base>
    
      file,
      # Deny all file writes.
      deny /** w,
    }
    

Los perfiles de AppArmor se agregan con el comando apparmor_parser.

  1. Agregue el perfil a AppArmor.

  2. Especifique el nombre del perfil creado en el paso anterior:

    sudo apparmor_parser deny-write.profile
    

    Si el perfil se analiza y se aplica correctamente a AppArmor, no verá ninguna salida y volverá al símbolo del sistema.

  3. Desde la máquina local, cree un manifiesto de pod denominado aks-apparmor.yaml. Este manifiesto:

    • Define una anotación para container.apparmor.security.beta.kubernetes.
    • Hace referencia al perfil deny-write creado en los pasos anteriores.
    apiVersion: v1
    kind: Pod
    metadata:
      name: hello-apparmor
      annotations:
        container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-deny-write
    spec:
      containers:
      - name: hello
        image: mcr.microsoft.com/dotnet/runtime-deps:6.0
        command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
    
  4. Con el pod implementado, ejecute el comando siguiente y compruebe que el pod hello-apparmor muestra un estado En ejecución:

    kubectl get pods
    
    NAME             READY   STATUS    RESTARTS   AGE
    aks-ssh          1/1     Running   0          4m2s
    hello-apparmor   0/1     Running   0          50s
    

Para más información sobre AppArmor, consulte los perfiles de AppArmor en Kubernetes.

Informática segura (seccomp)

Si bien AppArmor funciona con cualquier aplicación de Linux, seccomp (secure computing) funciona en el nivel de proceso. Seccomp también es un módulo de seguridad del kernel de Linux, y es compatible de forma nativa con el tiempo de ejecución de containerd que utilizan los nodos de AKS. Con seccomp, puede limitar las llamadas del sistema de un contenedor. Seccomp establece una capa adicional de protección contra vulnerabilidades comunes de llamadas del sistema explotadas por actores malintencionados y permite especificar un perfil predeterminado para todas las cargas de trabajo del nodo.

Configuración de un perfil de seccomp predeterminado (versión preliminar)

Puede aplicar perfiles de seccomp predeterminados mediante configuraciones de nodo personalizadas al crear un nuevo grupo de nodos de Linux. Hay dos valores admitidos en AKS: RuntimeDefault y Unconfined. Algunas cargas de trabajo pueden requerir un número menor de restricciones de syscall que otras. Esto significa que pueden producir errores durante el tiempo de ejecución con el perfil 'RuntimeDefault'. Para mitigar este error, puede especificar el perfil Unconfined. Si la carga de trabajo requiere un perfil personalizado, consulte Configuración de un perfil de seccomp personalizado.

Limitaciones

  • SeccompDefault no es un parámetro compatible para los grupos de nodos de Windows.
  • SeccompDefault está disponible a partir de la API 2024-09-02-preview.

Importante

Las características en versión preliminar de AKS están disponibles como opción de participación y autoservicio. Las versiones preliminares se proporcionan "tal cual" y "como están disponibles", y están excluidas de los Acuerdos de nivel de servicio y garantía limitada. Las versiones preliminares de AKS reciben cobertura parcial del soporte al cliente en la medida de lo posible. Por lo tanto, estas características no están diseñadas para su uso en producción. Para más información, consulte los siguientes artículos de soporte:

Registro de la marca de característica KubeletDefaultSeccompProfilePreview

  1. Registre la marca de características de KubeletDefaultSeccompProfilePreview mediante el comando az feature register.

    az feature register --namespace "Microsoft.ContainerService" --name "KubeletDefaultSeccompProfilePreview"
    

    Tarda unos minutos en que el estado muestre Registrado.

  2. Comprobar el estado del registro mediante el comando az feature show.

    az feature show --namespace "Microsoft.ContainerService" --name "KubeletDefaultSeccompProfilePreview"
    
  3. Cuando aparezca el estado Registrado, actualice el registro del proveedor de recursos Microsoft.ContainerService mediante el comando az provider register.

    az provider register --namespace Microsoft.ContainerService
    

Restricción de las llamadas del sistema del contenedor con seccomp

1. Siga los pasos para aplicar un perfil de seccomp en la configuración de kubelet especificando "seccompDefault": "RuntimeDefault".

RuntimeDefault usa el perfil de seccomp predeterminado del contenedor, lo que restringe determinadas llamadas del sistema para mejorar la seguridad. Se producirá un error en las llamadas del sistema restringidas. Para más información, consulte el perfil seccomp predeterminado de containerD.

2. Compruebe que se aplicó la configuración .

Puede confirmar que la configuración se ha aplicado a los nodos mediante la conexión al host y la comprobación de que los cambios de configuración se han realizado en el sistema de archivos.

3. Solución de errores de carga de trabajo.

Cuando SeccompDefault está habilitado, el perfil de seccomp predeterminado del entorno de ejecución del contenedor se usa de forma predeterminada para todas las cargas de trabajo programadas en el nodo. Esto puede provocar un error en las cargas de trabajo debido a llamadas de syscall bloqueadas. Si se ha producido un error de carga de trabajo, es posible que vea errores como:

  • La carga de trabajo existe inesperadamente después de habilitar la característica, con el error "permiso denegado".
  • Los mensajes de error de Seccomp también se pueden ver en auditado o syslog reemplazando SCMP_ACT_ERRNO por SCMP_ACT_LOG en el perfil predeterminado.

Si experimenta los errores anteriores, se recomienda cambiar el perfil de seccomp a Unconfined. Unconfined no aplica restricciones a las llamadas sys, lo que permite todas las llamadas del sistema, lo que reduce la seguridad.

Configuración de un perfil de seccomp personalizado

Con un perfil de seccomp personalizado, puede tener un control más granular sobre las llamadas de sys restringidas. Adopte el procedimiento recomendado de conceder al contenedor el permiso mínimo solo para ejecutarlo mediante:

  • La definición que filtra qué acciones se permiten o deniegan.
  • La anotación dentro de un manifiesto YAML de pod para asociarlo al filtro de seccomp.

Para ver seccomp en acción, cree un filtro que evite el cambio de permisos en un archivo.

  1. Acceda mediante SSH a un nodo de AKS.

  2. Cree un filtro de seccomp denominado /var/lib/kubelet/seccomp/prevent-chmod.

  3. Copie y pegue el siguiente contenido:

    {
      "defaultAction": "SCMP_ACT_ALLOW",
      "syscalls": [
        {
          "name": "chmod",
          "action": "SCMP_ACT_ERRNO"
        },
        {
          "name": "fchmodat",
          "action": "SCMP_ACT_ERRNO"
        },
        {
          "name": "chmodat",
          "action": "SCMP_ACT_ERRNO"
        }
      ]
    }
    

    En la versión 1.19 y versiones posteriores, debe configurar:

    {
      "defaultAction": "SCMP_ACT_ALLOW",
      "syscalls": [
        {
          "names": ["chmod","fchmodat","chmodat"],
          "action": "SCMP_ACT_ERRNO"
        }
      ]
    }
    
  4. En la máquina local, cree un manifiesto de pod denominado aks-seccomp.yaml y pegue el contenido siguiente. Este manifiesto:

    • Define una anotación para seccomp.security.alpha.kubernetes.io.
    • Hace referencia al filtro prevent-chmod que se creó en el paso anterior.
    apiVersion: v1
    kind: Pod
    metadata:
      name: chmod-prevented
      annotations:
        seccomp.security.alpha.kubernetes.io/pod: localhost/prevent-chmod
    spec:
      containers:
      - name: chmod
        image: mcr.microsoft.com/dotnet/runtime-deps:6.0
        command:
          - "chmod"
        args:
         - "777"
         - /etc/hostname
      restartPolicy: Never
    

    En la versión 1.19 y versiones posteriores, debe configurar:

    apiVersion: v1
    kind: Pod
    metadata:
      name: chmod-prevented
    spec:
      securityContext:
        seccompProfile:
          type: Localhost
          localhostProfile: prevent-chmod
      containers:
      - name: chmod
        image: mcr.microsoft.com/dotnet/runtime-deps:6.0
        command:
          - "chmod"
        args:
         - "777"
         - /etc/hostname
      restartPolicy: Never
    
  5. Implemente el pod de ejemplo con el comando kubectl apply:

    kubectl apply -f ./aks-seccomp.yaml
    
  6. Consulte el estado de los pod mediante el comando kubectl get pods.

    • El pod indica un error.
    • El filtro seccomp impide que se ejecute el comando chmod, tal como se muestra en la salida del ejemplo:
    kubectl get pods
    
    NAME                      READY     STATUS    RESTARTS   AGE
    chmod-prevented           0/1       Error     0          7s
    

Opciones de perfil de seguridad de Seccomp

Los perfiles de seguridad de Seccomp son un conjunto de llamadas syscall definidas permitidas o restringidas. La mayoría de los entornos de ejecución de contenedor tienen un perfil de seccomp predeterminado similar si no es el mismo que el que usa Docker. Para obtener más información sobre los perfiles disponibles, consulte Perfiles de seccomp predeterminados de Docker o containerD.

AKS usa el perfil de seccomp predeterminado containerD para RuntimeDefault al configurar seccomp mediante la configuración de nodo personalizada.

Llamadas de syscall significativas bloqueadas por perfil predeterminado

Tanto Docker como containerD mantienen listas de permitidos de llamadas seguras de syscalls. En esta tabla se enumeran las llamadas de sistema significativas (pero no todas) que están bloqueadas de forma eficaz porque no están en la lista de permitidos. Si la carga de trabajo requiere alguna de las llamadas de syscall bloqueadas, no use el perfil de seccomp RuntimeDefault.

Cuando se realizan cambios en Docker y containerD, AKS actualiza su configuración predeterminada para que coincida. Las actualizaciones de esta lista pueden provocar un error en la carga de trabajo. Para obtener actualizaciones de versión, consulte las notas de la versión de AKS.

Llamada syscall bloqueada Descripción
acct Syscall de contabilidad que podría permitir que los contenedores deshabiliten sus propios límites de recursos o contabilidad de procesos. También está cerrado por CAP_SYS_PACCT.
add_key Impedir que los contenedores usen el keyring de kernel, que no tiene espacio de nombres.
bpf Deniegue la carga de programas bpf potencialmente persistentes en kernel, que ya está controlada por CAP_SYS_ADMIN.
clock_adjtime La hora y la fecha no tienen espacio de nombres. También está cerrado por CAP_SYS_TIME.
clock_settime La hora y la fecha no tienen espacio de nombres. También está cerrado por CAP_SYS_TIME.
clone Denegar la clonación de nuevos espacios de nombres. También se ha cerrado por marcas CAP_SYS_ADMIN for CLONE_*, excepto CLONE_NEWUSER.
create_module Denegar la manipulación y las funciones en los módulos de kernel. Obsoleto. También está cerrado por CAP_SYS_MODULE.
delete_module Denegar la manipulación y las funciones en los módulos de kernel. También está cerrado por CAP_SYS_MODULE.
finit_module Denegar la manipulación y las funciones en los módulos de kernel. También está cerrado por CAP_SYS_MODULE.
get_kernel_syms Denegar la recuperación de símbolos de módulo y kernel exportados. Obsoleto.
get_mempolicy Syscall que modifica la memoria del kernel y la configuración de NUMA. Ya está cerrado por CAP_SYS_NICE.
init_module Denegar la manipulación y las funciones en los módulos de kernel. También está cerrado por CAP_SYS_MODULE.
ioperm Impedir que los contenedores modifiquen los niveles de privilegios de E/S del kernel. Ya está cerrado por CAP_SYS_RAWIO.
iopl Impedir que los contenedores modifiquen los niveles de privilegios de E/S del kernel. Ya está cerrado por CAP_SYS_RAWIO.
kcmp Restrinja las funcionalidades de inspección de procesos, ya bloqueadas quitando CAP_SYS_PTRACE.
kexec_file_load Syscall hermana de kexec_load que hace lo mismo, argumentos ligeramente diferentes. También está cerrado por CAP_SYS_BOOT.
kexec_load Denegar la carga de un nuevo kernel para su ejecución posterior. También está cerrado por CAP_SYS_BOOT.
keyctl Impedir que los contenedores usen el keyring de kernel, que no tiene espacio de nombres.
lookup_dcookie Seguimiento o generación de perfiles de syscall, que podría filtrar información sobre el host. También está cerrado por CAP_SYS_ADMIN.
mbind Syscall que modifica la memoria del kernel y la configuración de NUMA. Ya está cerrado por CAP_SYS_NICE.
mount Deniegue el montaje, ya cerrado por CAP_SYS_ADMIN.
move_pages Syscall que modifica la memoria del kernel y la configuración de NUMA.
nfsservctl Denegar la interacción con el demonio nfs del kernel. Obsoleto desde Linux 3.1.
open_by_handle_at Causa de un error de contenedor antiguo. También está cerrado por CAP_DAC_READ_SEARCH.
perf_event_open Seguimiento o generación de perfiles de syscall, que podría filtrar información sobre el host.
personality Impedir que el contenedor habilite la emulación de BSD. No es intrínsecamente peligroso, pero poco probado, potencial para las vulnerabilidades de kernel.
pivot_root Denegar pivot_root, debe ser una operación con privilegios.
process_vm_readv Restrinja las funcionalidades de inspección de procesos, ya bloqueadas quitando CAP_SYS_PTRACE.
process_vm_writev Restrinja las funcionalidades de inspección de procesos, ya bloqueadas quitando CAP_SYS_PTRACE.
ptrace Llamada syscall de seguimiento y generación de perfiles. Bloqueado en las versiones del kernel de Linux anteriores a la versión 4.8 para evitar la omisión de seccomp. Los procesos arbitrarios de seguimiento o generación de perfiles ya están bloqueados quitando CAP_SYS_PTRACE, ya que podría perder información en el host.
query_module Denegar la manipulación y las funciones en los módulos de kernel. Obsoleto.
quotactl Syscall de cuota que podría permitir que los contenedores deshabiliten sus propios límites de recursos o la contabilidad de procesos. También está cerrado por CAP_SYS_ADMIN.
reboot No permita que los contenedores reinicien el host. También está cerrado por CAP_SYS_BOOT.
request_key Impedir que los contenedores usen el keyring de kernel, que no tiene espacio de nombres.
set_mempolicy Syscall que modifica la memoria del kernel y la configuración de NUMA. Ya está cerrado por CAP_SYS_NICE.
setns Denegar la asociación de un subproceso con un espacio de nombres. También está cerrado por CAP_SYS_ADMIN.
settimeofday La hora y la fecha no tienen espacio de nombres. También está cerrado por CAP_SYS_TIME.
stime La hora y la fecha no tienen espacio de nombres. También está cerrado por CAP_SYS_TIME.
swapon Denegar el inicio o detención del intercambio a archivo o dispositivo. También está cerrado por CAP_SYS_ADMIN.
swapoff Denegar el inicio o detención del intercambio a archivo o dispositivo. También está cerrado por CAP_SYS_ADMIN.
sysfs Syscall obsoleta.
_sysctl Obsoleto, reemplazado por /proc/sys.
umount Debe ser una operación con privilegios. También está cerrado por CAP_SYS_ADMIN.
umount2 Debe ser una operación con privilegios. También está cerrado por CAP_SYS_ADMIN.
unshare Denegar la clonación de nuevos espacios de nombres para procesos. También se ha cerrado por CAP_SYS_ADMIN, con la excepción de unshare --user.
uselib La llamada de syscall anterior relacionada con las bibliotecas compartidas, sin usar durante mucho tiempo.
userfaultfd Control de errores de página de espacio de usuarios, en gran medida necesario para la migración de procesos.
ustat Syscall obsoleta.
vm86 En la máquina virtual en modo real de kernel x86. También está cerrado por CAP_SYS_ADMIN.
vm86old En la máquina virtual en modo real de kernel x86. También está cerrado por CAP_SYS_ADMIN.

Pasos siguientes

Para los procedimientos recomendados asociados, consulte Procedimientos recomendados para la seguridad de clústeres y las actualizaciones en AKS y Procedimientos recomendados para la seguridad de pod en AKS.