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:
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):
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:
separat artikel om at arbejde med certifikater i den officielle Kubernetes-dokumentation;
god artikel fra Bitnami, hvor udstedelse af certifikater er berørt ud fra en praktisk synsvinkel.
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:
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:
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:
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:
Ud over disse tre nødvendige parametre er der mange yderligere indstillinger relateret til revision: fra logrotation til webhook-beskrivelser. Eksempel på logrotationsparametre:
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:
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:
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:
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:
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:
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
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.