L'ABC de la seguretat a Kubernetes: autenticació, autorització, auditoria

L'ABC de la seguretat a Kubernetes: autenticació, autorització, auditoria

Tard o d'hora, en el funcionament de qualsevol sistema, sorgeix el tema de la seguretat: garantir l'autenticació, la separació de drets, l'auditoria i altres tasques. Ja està creat per a Kubernetes moltes solucions, que permeten aconseguir el compliment dels estàndards fins i tot en entorns molt exigents... El mateix material està dedicat als aspectes bàsics de seguretat implementats dins dels mecanismes integrats dels K8s. En primer lloc, serà útil per a aquells que comencen a familiaritzar-se amb Kubernetes, com a punt de partida per estudiar qüestions relacionades amb la seguretat.

Autenticació

Hi ha dos tipus d'usuaris a Kubernetes:

  • Comptes de servei — comptes gestionats per l'API de Kubernetes;
  • Usuaris — usuaris “normals” gestionats per serveis externs i independents.

La diferència principal entre aquests tipus és que per als comptes de servei hi ha objectes especials a l'API de Kubernetes (s'anomenen així: ServiceAccounts), que estan lligats a un espai de noms i un conjunt de dades d'autorització emmagatzemats al clúster en objectes del tipus Secrets. Aquests usuaris (comptes de servei) estan destinats principalment a gestionar els drets d'accés a l'API de Kubernetes dels processos que s'executen al clúster de Kubernetes.

Els usuaris corrents no tenen entrades a l'API de Kubernetes: s'han de gestionar mitjançant mecanismes externs. Estan destinats a persones o processos que viuen fora del clúster.

Cada sol·licitud d'API s'associa amb un compte de servei, un usuari o es considera anònima.

Les dades d'autenticació de l'usuari inclouen:

  • Nom d'usuari — nom d'usuari (distingeix entre majúscules i minúscules!);
  • UID - una cadena d'identificació d'usuari llegible per màquina que és "més coherent i única que el nom d'usuari";
  • grups — llista de grups als quals pertany l'usuari;
  • Extra — camps addicionals que poden ser utilitzats pel mecanisme d'autorització.

Kubernetes pot utilitzar un gran nombre de mecanismes d'autenticació: certificats X509, testimonis de portador, servidor intermediari d'autenticació, autenticació bàsica HTTP. Amb aquests mecanismes, podeu implementar un gran nombre d'esquemes d'autorització: des d'un fitxer estàtic amb contrasenyes fins a OpenID OAuth2.

A més, és possible utilitzar diversos esquemes d'autorització simultàniament. De manera predeterminada, el clúster utilitza:

  • fitxes de compte de servei: per a comptes de servei;
  • X509 - per a usuaris.

La pregunta sobre la gestió de comptes de servei està fora de l'abast d'aquest article, però per a aquells que vulguin familiaritzar-se amb aquest problema amb més detall, recomano començar amb pàgines de documentació oficial. Veurem més de prop el problema de com funcionen els certificats X509.

Certificats per a usuaris (X.509)

La forma clàssica de treballar amb certificats implica:

  • generació de claus:
    mkdir -p ~/mynewuser/.certs/
    openssl genrsa -out ~/.certs/mynewuser.key 2048
  • generació d'una sol·licitud de certificat:
    openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company"
  • processar una sol·licitud de certificat mitjançant les claus CA del clúster de Kubernetes, obtenir un certificat d'usuari (per obtenir un certificat, heu d'utilitzar un compte que tingui accés a la clau CA del clúster de Kubernetes, que per defecte es troba a /etc/kubernetes/pki/ca.key):
    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
  • creant un fitxer de configuració:
    • descripció del clúster (especifiqueu l'adreça i la ubicació del fitxer de certificat CA per a una instal·lació de clúster específica):
      kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443
    • o com noopció recomanada: no cal que especifiqueu el certificat arrel (aleshores kubectl no comprovarà la correcció del servidor API del clúster):
      kubectl config set-cluster kubernetes  --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443
    • afegint un usuari al fitxer de configuració:
      kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt  --client-key=.certs/mynewuser.key
    • afegint context:
      kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser
    • assignació de context per defecte:
      kubectl config use-context mynewuser-context

Després de les manipulacions anteriors, a l'arxiu .kube/config es crearà una configuració com aquesta:

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

Per facilitar la transferència de la configuració entre comptes i servidors, és útil editar els valors de les claus següents:

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

Per fer-ho, podeu codificar els fitxers especificats en ells mitjançant base64 i registrar-los a la configuració, afegint el sufix al nom de les claus. -data, és a dir havent rebut certificate-authority-data etcètera

Certificats amb kubeadm

Amb el llançament Kubernetes 1.15 treballar amb certificats s'ha tornat molt més fàcil gràcies a la versió alfa del seu suport a utilitat kubeadm. Per exemple, aquest és el que sembla ara generar un fitxer de configuració amb claus d'usuari:

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

NB: Obligatori adreça de publicitat es pot trobar a la configuració del servidor api, que per defecte es troba a /etc/kubernetes/manifests/kube-apiserver.yaml.

La configuració resultant s'enviarà a stdout. Cal desar-lo ~/.kube/config compte d'usuari o a un fitxer especificat en una variable d'entorn KUBECONFIG.

Cavar més profund

Per a aquells que vulguin entendre els problemes descrits més a fons:

Autorització

El compte autoritzat predeterminat no té drets per operar al clúster. Per atorgar permisos, Kubernetes implementa un mecanisme d'autorització.

Abans de la versió 1.6, Kubernetes utilitzava un tipus d'autorització anomenat ABAC (Control d'accés basat en atributs). Els detalls al respecte es poden trobar a documentació oficial. Actualment, aquest enfocament es considera heretat, però encara podeu utilitzar-lo juntament amb altres tipus d'autenticació.

S'anomena la forma actual (i més flexible) de dividir els drets d'accés a un clúster RBAC (Control d'accés basat en rols). S'ha declarat estable des de la versió Kubernetes 1.8. RBAC implementa un model de drets en el qual està prohibit tot allò que no està explícitament permès.
Per habilitar RBAC, heu d'iniciar el servidor API de Kubernetes amb el paràmetre --authorization-mode=RBAC. Els paràmetres s'estableixen al manifest amb la configuració del servidor api, que per defecte es troba al llarg del camí /etc/kubernetes/manifests/kube-apiserver.yaml, a l'apartat command. Tanmateix, RBAC ja està habilitat per defecte, així que probablement no us hauríeu de preocupar: podeu verificar-ho amb el valor authorization-mode (en el ja esmentat kube-apiserver.yaml). Per cert, entre els seus significats hi pot haver altres tipus d'autorització (node, webhook, always allow), però deixarem la seva consideració fora de l'àmbit del material.

Per cert, ja ho hem publicat un article amb una descripció bastant detallada dels principis i característiques de treballar amb RBAC, així que més endavant em limitaré a una breu llista dels fonaments i exemples.

Les entitats de l'API següents s'utilitzen per controlar l'accés a Kubernetes mitjançant RBAC:

  • Role и ClusterRole — rols que serveixen per descriure els drets d'accés:
  • Role us permet descriure drets dins d'un espai de noms;
  • ClusterRole - dins del clúster, inclosos els objectes específics del clúster, com ara nodes, URL que no són recursos (és a dir, no relacionats amb recursos de Kubernetes, per exemple, /version, /logs, /api*);
  • RoleBinding и ClusterRoleBinding - S'utilitza per enquadernar Role и ClusterRole a un usuari, grup d'usuaris o compte de servei.

Les entitats Role i RoleBinding estan limitades per l'espai de noms, és a dir. ha d'estar dins del mateix espai de noms. Tanmateix, un RoleBinding pot fer referència a un ClusterRole, la qual cosa us permet crear un conjunt de permisos genèrics i controlar l'accés utilitzant-los.

Els rols descriuen els drets utilitzant conjunts de regles que contenen:

  • Grups d'API - vegeu documentació oficial per apiGroups i sortida kubectl api-resources;
  • recursos (recursos: pod, namespace, deployment etcètera.);
  • verbs (verbs: set, update etc.).
  • noms de recursos (resourceNames) - per al cas en què necessiteu proporcionar accés a un recurs específic, i no a tots els recursos d'aquest tipus.

Es pot trobar una anàlisi més detallada de l'autorització a Kubernetes a la pàgina documentació oficial. En canvi (o millor dit, a més d'això), posaré exemples que il·lustren la seva obra.

Exemples d'entitats RBAC

Simple Role, que us permet obtenir una llista i l'estat dels pods i supervisar-los a l'espai de noms 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"]

Exemple ClusterRole, que us permet obtenir una llista i l'estat dels pods i supervisar-los a tot el clúster:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # секции "namespace" нет, так как ClusterRole задействует весь кластер
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

Exemple RoleBinding, que permet a l'usuari mynewuser "llegir" pods a l'espai de noms 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 d'esdeveniments

Esquemàticament, l'arquitectura de Kubernetes es pot representar de la següent manera:

L'ABC de la seguretat a Kubernetes: autenticació, autorització, auditoria

El component clau de Kubernetes responsable de processar les sol·licituds és servidor api. Totes les operacions del clúster hi passen. Podeu llegir més sobre aquests mecanismes interns a l'article "Què passa a Kubernetes quan executeu kubectl run?».

L'auditoria del sistema és una característica interessant de Kubernetes, que està desactivada per defecte. Us permet registrar totes les trucades a l'API de Kubernetes. Com podeu endevinar, totes les accions relacionades amb la supervisió i el canvi de l'estat del clúster es realitzen mitjançant aquesta API. Una bona descripció de les seves capacitats es pot trobar (com és habitual) a documentació oficial K8s. A continuació, intentaré presentar el tema amb un llenguatge més senzill.

Per tant, per habilitar l'auditoria, hem de passar tres paràmetres necessaris al contenidor del servidor api, que es descriuen amb més detall a continuació:

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

A més d'aquests tres paràmetres necessaris, hi ha molts paràmetres addicionals relacionats amb l'auditoria: des de la rotació de registres fins a descripcions de webhook. Exemple de paràmetres de rotació del registre:

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

Però no ens atendrem amb més detall: podeu trobar tots els detalls a documentació de kube-apserver.

Com ja s'ha esmentat, tots els paràmetres s'estableixen al manifest amb la configuració del servidor api (per defecte /etc/kubernetes/manifests/kube-apiserver.yaml), a l'apartat command. Tornem als 3 paràmetres necessaris i analitzem-los:

  1. audit-policy-file — camí al fitxer YAML que descriu la política d'auditoria. Tornarem al seu contingut més endavant, però de moment notaré que el fitxer ha de ser llegible pel procés del servidor api. Per tant, és necessari muntar-lo dins del contenidor, per a això podeu afegir el següent codi a les seccions corresponents de la configuració:
      volumeMounts:
        - mountPath: /etc/kubernetes/policies
          name: policies
          readOnly: true
      volumes:
      - hostPath:
          path: /etc/kubernetes/policies
          type: DirectoryOrCreate
        name: policies
  2. audit-log-path — camí al fitxer de registre. El camí també ha de ser accessible per al procés del servidor api, de manera que descriurem el seu muntatge de la mateixa manera:
      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 - format de registre d'auditoria. El valor predeterminat és json, però el format de text heretat també està disponible (legacy).

Política d'auditoria

Ara sobre el fitxer esmentat que descriu la política de registre. El primer concepte de política d'auditoria és level, nivell de registre. Són els següents:

  • None - no registreu;
  • Metadata — metadades de sol·licitud de registre: usuari, temps de sol·licitud, recurs objectiu (pod, espai de noms, etc.), tipus d'acció (verb), etc.;
  • Request — metadades de registre i cos de la sol·licitud;
  • RequestResponse — metadades de registre, cos de la sol·licitud i cos de la resposta.

Els dos últims nivells (Request и RequestResponse) no registre les sol·licituds que no hagin accedit als recursos (accessos als anomenats URL que no són recursos).

També passen totes les peticions diverses etapes:

  • RequestReceived — l'etapa en què el processador rep la sol·licitud i encara no s'ha transmès més al llarg de la cadena de processadors;
  • ResponseStarted — s'envien les capçaleres de resposta, però abans que s'enviï el cos de la resposta. Es genera per a consultes de llarga durada (per exemple, watch);
  • ResponseComplete — s'ha enviat el cos de resposta, no s'enviarà més informació;
  • Panic — es generen esdeveniments quan es detecta una situació anormal.

Per ometre qualsevol pas que pugueu utilitzar omitStages.

En un fitxer de polítiques, podem descriure diverses seccions amb diferents nivells de registre. S'aplicarà la primera regla de concordança que es troba a la descripció de la política.

El dimoni kubelet supervisa els canvis al manifest amb la configuració del servidor api i, si se'n detecta, reinicia el contenidor amb el servidor api. Però hi ha un detall important: els canvis al fitxer de polítiques seran ignorats. Després de fer canvis al fitxer de polítiques, haureu de reiniciar el servidor API manualment. Com que el servidor api s'inicia com beina estàtica, equip kubectl delete no farà que es reiniciï. Haureu de fer-ho manualment docker stop a kube-masters, on s'ha canviat la política d'auditoria:

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

Quan habiliteu l'auditoria, és important recordar-ho la càrrega del kube-apiserver augmenta. En particular, augmenta el consum de memòria per emmagatzemar el context de la sol·licitud. El registre només comença després d'enviar la capçalera de resposta. La càrrega també depèn de la configuració de la política d'auditoria.

Exemples de polítiques

Vegem l'estructura dels fitxers de polítiques utilitzant exemples.

Aquí teniu un fitxer senzill policyper registrar-ho tot al nivell Metadata:

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

A la política podeu especificar una llista d'usuaris (Users и ServiceAccounts) i grups d'usuaris. Per exemple, així és com ignorarem els usuaris del sistema, però registrarem tota la resta al nivell 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

També és possible descriure els objectius:

  • espais de noms (namespaces);
  • verbs (verbs: get, update, delete i altres);
  • recursos (recursos, a saber: pod, configmaps etc.) i grups de recursos (apiGroups).

Preste atenció! Els recursos i els grups de recursos (grups API, és a dir, apiGroups), així com les seves versions instal·lades al clúster, es poden obtenir mitjançant les ordres:

kubectl api-resources
kubectl api-versions

La següent política d'auditoria es proporciona com a demostració de les millors pràctiques a Documentació d'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

Un altre bon exemple de política d'auditoria és perfil utilitzat a GCE.

Per respondre ràpidament als esdeveniments d'auditoria, és possible descriure el webhook. Aquest tema està cobert a documentació oficial, ho deixaré fora de l'àmbit d'aquest article.

Resultats de

L'article ofereix una visió general dels mecanismes de seguretat bàsics als clústers de Kubernetes, que us permeten crear comptes d'usuari personalitzats, separar els seus drets i registrar les seves accions. Espero que sigui útil per a aquells que s'enfronten a aquests problemes en teoria o en la pràctica. També us recomano que llegiu la llista d'altres materials sobre el tema de la seguretat a Kubernetes, que es dóna a "PS"; potser entre ells trobareu els detalls necessaris sobre els problemes que us són rellevants.

PS

Llegeix també al nostre blog:

Font: www.habr.com

Afegeix comentari