ABC for sikkerhed i Kubernetes: Autentificering, autorisation, revision

ABC for sikkerhed i Kubernetes: Autentificering, autorisation, revision

Før eller siden, i driften af ​​ethvert system, opstår spørgsmålet om sikkerhed: levering af autentificering, adskillelse af rettigheder, revision og andre opgaver. Allerede oprettet til Kubernetes mange løsninger, som giver dig mulighed for at opnå standardoverholdelse selv i meget krævende miljøer ... Det samme materiale er afsat til de grundlæggende sikkerhedsaspekter implementeret i de indbyggede K8s-mekanismer. Først og fremmest vil det være nyttigt for dem, der begynder at stifte bekendtskab med Kubernetes - som udgangspunkt for at studere spørgsmål relateret til sikkerhed.

autentificering

Der er to typer brugere i Kubernetes:

  • Servicekonti - konti administreret af Kubernetes API;
  • Brugere - "normale" brugere administreret af eksterne, uafhængige tjenester.

Den største forskel mellem disse typer er, at der er specielle objekter til servicekonti i Kubernetes API (de kaldes sådan - ServiceAccounts), der er bundet til et navneområde og et sæt autorisationsdata gemt i klyngen i objekter af typen Secrets. Sådanne brugere (servicekonti) er hovedsageligt beregnet til at administrere adgangsrettigheder til Kubernetes API for processer, der kører i en Kubernetes-klynge.

Almindelige brugere har på den anden side ikke indgange i Kubernetes API: de skal administreres af eksterne mekanismer. De er beregnet til mennesker eller processer, der lever uden for klyngen.

Hver API-anmodning er knyttet til enten en tjenestekonto eller en bruger eller betragtes som anonym.

Brugergodkendelsesdata inkluderer:

  • Brugernavn — brugernavn (der skelnes mellem store og små bogstaver!);
  • UID - en maskinlæsbar brugeridentifikationsstreng, der er "mere konsistent og unik end et brugernavn";
  • Grupper — liste over grupper, som brugeren tilhører;
  • Ekstra - yderligere felter, der kan bruges af godkendelsesmekanismen.

Kubernetes kan bruge et stort antal godkendelsesmekanismer: X509-certifikater, bærer-tokens, autentificeringsproxy, HTTP Basic Auth. Ved at bruge disse mekanismer kan du implementere et stort antal autorisationsordninger: fra en statisk adgangskodefil til OpenID OAuth2.

Desuden kan flere autorisationsordninger bruges på samme tid. Som standard bruger klyngen:

  • servicekontotokens - til servicekonti;
  • X509 - til brugere.

Spørgsmålet om at administrere ServiceAccounts ligger uden for rammerne af denne artikel, og for dem, der ønsker at lære mere om dette problem, anbefaler jeg at starte med officielle dokumentationssider. Vi vil se nærmere på spørgsmålet om X509-certifikater.

Certifikater til brugere (X.509)

Den klassiske måde at arbejde med certifikater på involverer:

  • nøglegenerering:
    mkdir -p ~/mynewuser/.certs/
    openssl genrsa -out ~/.certs/mynewuser.key 2048
  • generere en certifikatanmodning:
    openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company"
  • behandle certifikatanmodningen ved hjælp af CA-nøglerne til Kubernetes-klyngen, opnå et brugercertifikat (for at opnå et certifikat skal du bruge en konto, der har adgang til nøglen til Kubernetes-klyngen CA, som som standard er placeret i /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
  • oprettelse af en konfigurationsfil:
    • beskrivelse af klyngen (angiv adressen og placeringen af ​​CA-certifikatfilen for den specifikke klyngeinstallation):
      kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443
    • eller hvordan nejanbefalet mulighed - du kan ikke angive rodcertifikatet (så vil kubectl ikke kontrollere korrektheden af ​​cluster api-serveren):
      kubectl config set-cluster kubernetes  --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443
    • tilføjelse af en bruger til konfigurationsfilen:
      kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt  --client-key=.certs/mynewuser.key
    • tilføje kontekst:
      kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser
    • standard kontekst tildeling:
      kubectl config use-context mynewuser-context

Efter ovenstående manipulationer, i filen .kube/config visningskonfigurationen vil blive oprettet:

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

For at lette overførslen af ​​konfigurationen mellem konti og servere er det nyttigt at redigere værdierne for følgende nøgler:

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

For at gøre dette kan du kode filerne specificeret i dem ved hjælp af base64 og registrere dem i konfigurationen, tilføje suffikset til navnet på nøglerne -data, dvs. modtaget certificate-authority-data etc.

Certifikater med kubeadm

Med frigivelse Kubernetes 1.15 arbejdet med certifikater er blevet meget nemmere takket være alfaversionen af ​​dets support i kubeadm værktøj. For eksempel, her er, hvordan genereringen af ​​en konfigurationsfil med brugernøgler kan se ud nu:

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

NB: Påkrævet annoncere adresse kan ses i api-server-konfigurationen, som er placeret som standard i /etc/kubernetes/manifests/kube-apiserver.yaml.

Den resulterende konfiguration vil blive udskrevet til stdout. Den skal opbevares inde ~/.kube/config brugerkonto eller til en fil angivet i en miljøvariabel KUBECONFIG.

Grave dybere

For dem, der ønsker at se nærmere på de beskrevne problemer:

Tilladelse

En autoriseret konto har som standard ikke rettigheder til at handle på klyngen. For at give tilladelser implementerer Kubernetes en autorisationsmekanisme.

Før version 1.6 brugte Kubernetes en autorisationstype kaldet ABAC (Attribut-baseret adgangskontrol). Detaljer om det kan findes i officiel dokumentation. Denne tilgang betragtes i øjeblikket som legacy, men du kan stadig bruge den på samme tid som andre autorisationstyper.

Den faktiske (og mere fleksible) måde at adskille adgangsrettigheder til en klynge på kaldes RBAC (Rollebaseret adgangskontrol). Det er blevet erklæret stabilt siden version Kubernetes 1.8. RBAC implementerer en rettighedsmodel, der forbyder alt, hvad der ikke udtrykkeligt er tilladt.
For at aktivere RBAC, skal du starte Kubernetes api-server med parameteren --authorization-mode=RBAC. Parametrene indstilles i manifestet med api-server-konfigurationen, som som standard er placeret langs stien /etc/kubernetes/manifests/kube-apiserver.yaml, i afsnittet command. Men som standard er RBAC allerede aktiveret, så højst sandsynligt bør du ikke bekymre dig om det: du kan bekræfte dette ved værdien authorization-mode (i det allerede nævnte kube-apiserver.yaml). Forresten, blandt dens værdier kan der være andre typer autorisation (node, webhook, always allow), men vi vil lade deres overvejelser ligge uden for materialets rammer.

Vi har i øvrigt allerede offentliggjort en artikel med en ret detaljeret historie om principperne og funktionerne ved at arbejde med RBAC, så yderligere vil jeg begrænse mig til en kort liste over det grundlæggende og eksempler.

Følgende API-enheder bruges til at kontrollere adgangen til Kubernetes via RBAC:

  • Role и ClusterRole - roller, der tjener til at beskrive adgangsrettigheder:
  • Role giver dig mulighed for at beskrive rettighederne inden for navneområdet;
  • ClusterRole - inden for klyngen, herunder til klyngespecifikke objekter såsom noder, ikke-ressource-urls (dvs. ikke relateret til Kubernetes-ressourcer - f.eks. /version, /logs, /api*);
  • RoleBinding и ClusterRoleBinding - bruges til indbinding Role и ClusterRole til en bruger, brugergruppe eller servicekonto.

Entiteterne Role og RoleBinding er navneområdebundet, dvs. skal være inden for samme navneområde. En RoleBinding kan dog referere til en ClusterRole, som giver dig mulighed for at oprette et sæt generiske tilladelser og kontrollere adgangen med dem.

Roller beskriver rettigheder ved hjælp af regelsæt, der indeholder:

  • API-grupper - se officiel dokumentation af apiGroups og output kubectl api-resources;
  • ressourcer (ressourcer: pod, namespace, deployment og så videre.);
  • Verber (verber: set, update osv.).
  • ressourcenavne (resourceNames) - for det tilfælde, hvor du skal give adgang til en specifik ressource, og ikke til alle ressourcer af denne type.

En mere detaljeret opdeling af autorisation i Kubernetes kan findes på siden officiel dokumentation. I stedet (eller rettere, udover dette) vil jeg give eksempler, der illustrerer dets arbejde.

Eksempler på RBAC-enheder

simpel Role, som giver dig mulighed for at få en liste og status over pods og holde styr på dem i navnerummet 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"]

Eksempel ClusterRole, som giver dig mulighed for at få en liste og status over pods og overvåge dem i hele klyngen:

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

Eksempel RoleBinding, som tillader brugeren mynewuser "læs" pods i navnerummet 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

Begivenhedsrevision

Skematisk kan arkitekturen af ​​Kubernetes repræsenteres som følger:

ABC for sikkerhed i Kubernetes: Autentificering, autorisation, revision

Den centrale Kubernetes-komponent, der er ansvarlig for behandling af anmodninger, er − api-server. Alle operationer på klyngen går igennem den. Du kan læse mere om disse interne mekanismer i artiklen "Hvad sker der i Kubernetes, når du kører kubectl run?'.

Systemrevision er en interessant funktion i Kubernetes, som er deaktiveret som standard. Det giver dig mulighed for at logge alle opkald til Kubernetes API. Som du måske kan gætte, udføres alle handlinger relateret til kontrol og ændring af klyngens tilstand gennem denne API. En god beskrivelse af dens muligheder kan (som sædvanligt) findes i officiel dokumentation K8s. I det følgende vil jeg forsøge at forklare emnet på en enklere måde.

således for at muliggøre revision, skal vi sende tre nødvendige parametre til containeren i api-serveren, som er beskrevet mere detaljeret nedenfor:

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

Ud over disse tre nødvendige parametre er der mange yderligere indstillinger relateret til revision: fra logrotation til webhook-beskrivelser. Eksempel på logrotationsparametre:

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

Men vi vil ikke dvæle mere ved dem - du kan finde alle detaljerne i kube-apiserver dokumentation.

Som allerede nævnt er alle parametre indstillet i manifestet med api-server-konfigurationen (som standard /etc/kubernetes/manifests/kube-apiserver.yaml), i afsnittet command. Lad os gå tilbage til de 3 nødvendige parametre og analysere dem:

  1. audit-policy-file - stien til YAML-filen med en beskrivelse af revisionens politik (politik). Vi vender tilbage til indholdet, men indtil videre vil jeg bemærke, at filen skal kunne læses af api-server-processen. Derfor skal du montere den inde i beholderen, for hvilken du kan tilføje følgende kode til de relevante sektioner af konfigurationen:
      volumeMounts:
        - mountPath: /etc/kubernetes/policies
          name: policies
          readOnly: true
      volumes:
      - hostPath:
          path: /etc/kubernetes/policies
          type: DirectoryOrCreate
        name: policies
  2. audit-log-path - sti til logfilen. Stien skal også være tilgængelig for api-serverprocessen, så vi beskriver dens montering på samme måde:
      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 — revisionslogformat. Standard er json, men det ældre tekstformat er også tilgængeligt (legacy).

Revisionspolitik

Nu om den nævnte fil med en beskrivelse af logningspolitikken. Det første koncept i en revisionspolitik er level, logningsniveau. De er som følger:

  • None - log ikke;
  • Metadata — loganmodningsmetadata: bruger, anmodningstidspunkt, målressource (pod, navneområde osv.), handlingstype (verbum) osv.;
  • Request - log metadata og anmodningstekst;
  • RequestResponse - log metadata, anmodningstekst og svarlegeme.

De sidste to niveauerRequest и RequestResponse) log ikke anmodninger, der ikke har adgang til ressourcer (referencer til de såkaldte ikke-ressourcer urls).

Også alle anmodninger går igennem flere stadier:

  • RequestReceived - stadiet, hvor anmodningen modtages af handleren og endnu ikke er blevet overført videre langs kæden af ​​behandlere;
  • ResponseStarted - Svarhovederne sendes, men før svarteksten sendes. Genereret til langvarige forespørgsler (f.eks. watch);
  • ResponseComplete - svarinstansen er sendt, der sendes ikke flere oplysninger;
  • Panic — Hændelser genereres, når en unormal situation detekteres.

For at springe alle stadier over, kan du bruge omitStages.

I politikfilen kan vi beskrive flere sektioner med forskellige logningsniveauer. Den første matchningsregel, der findes i politikbeskrivelsen, anvendes.

Kubelet-dæmonen lytter efter en ændring i manifestet med api-server-konfigurationen og, hvis nogen, genstarter api-server-beholderen. Men der er en vigtig detalje: ændringer i politikfilen vil blive ignoreret. Efter at have foretaget ændringer i politikfilen, skal du genstarte api-serveren manuelt. Siden api-server er startet som statisk pod, hold kubectl delete vil ikke genstarte den. Skal gøre det manuelt docker stop på kube-masters, hvor revisionspolitikken er blevet ændret:

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

Når du aktiverer revision, er det vigtigt at huske det belastningen stiger på kube-apiserver. Især øges hukommelsesforbruget til lagring af forespørgselskonteksten. Logning starter først, efter at svarhovedet er sendt. Belastningen afhænger også af konfigurationen af ​​revisionspolitikken.

Politiske eksempler

Lad os analysere strukturen af ​​politikfiler ved hjælp af eksempler.

Her er en simpel fil policyat logge alt på niveauet Metadata:

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

I politik kan du angive en liste over brugere (Users и ServiceAccounts) og brugergrupper. For eksempel er det sådan, vi vil ignorere systembrugere, men logge alt andet på niveauet 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

Det er også muligt at beskrive målet:

  • navnerum (namespaces);
  • Verber (verber: get, update, delete og andre);
  • ressourcer (ressourcer, nemlig: pod, configmaps osv.) og ressourcegrupper (apiGroups).

Vær opmærksom! Ressourcer og ressourcegrupper (API-grupper, dvs. apiGroups), såvel som deres versioner installeret i klyngen, kan fås ved hjælp af kommandoerne:

kubectl api-resources
kubectl api-versions

Følgende revisionspolitik er givet som en demonstration af bedste praksis inden for Alibaba Cloud dokumentation:

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

Et andet godt eksempel på en revisionspolitik er profil brugt i GCE.

For hurtig respons på revisionsbegivenheder er det muligt at beskriv webhook. Dette spørgsmål er dækket ind officiel dokumentationJeg vil lade det ligge uden for rammerne af denne artikel.

Resultaterne af

Denne artikel giver et overblik over de grundlæggende sikkerhedsmekanismer i Kubernetes-klynger, der gør det muligt at oprette personlige brugerkonti, adskille deres rettigheder og logge deres handlinger. Jeg håber, det vil være nyttigt for dem, der står over for sådanne problemer i teorien eller allerede i praksis. Jeg anbefaler også, at du gør dig bekendt med listen over andre materialer om emnet sikkerhed i Kubernetes, som er givet i "PS", måske blandt dem vil du finde de nødvendige detaljer om de problemer, der er relevante for dig.

PS

Læs også på vores blog:

Kilde: www.habr.com

Tilføj en kommentar