
På et tidspunkt i driften af ethvert system opstår spørgsmålet om sikkerhed: sikring af autentificering, opdeling af rettigheder, revision og andre opgaver. For Kubernetes er der allerede udviklet , som gør det muligt at opnå overholdelse af standarder, selv i meget krævende omgivelser… Dette materiale er dedikeret til de grundlæggende aspekter af sikkerhed implementeret i de indbyggede mekanismer i K8s. Først og fremmest vil det være nyttigt for dem, der begynder at lære om Kubernetes, som et udgangspunkt for at studere sikkerhedsrelaterede emner.
Godkendelse
I Kubernetes er der to typer brugere:
- Service Accounts — konti, der administreres af Kubernetes API;
- Users — "normale" brugere, der administreres af eksterne, uafhængige tjenester.
Den primære forskel mellem disse typer er, at der for Service Accounts findes specielle objekter i Kubernetes API (de kaldes netop — ServiceAccounts), som er knyttet til namespaces og en række autorisationsoplysninger, der opbevares i klyngen i objekter af typen Secrets. Disse brugere (Service Accounts) er primært beregnet til at administrere adgangsrettigheder til Kubernetes API for processer, der kører i Kubernetes-klyngen.
Normale Users har ikke poster i Kubernetes API: styring af dem skal udføres af eksterne mekanismer. De er beregnet til mennesker eller processer, der lever uden for klyngen.
Hver anmodning til API'et er knyttet enten til en Service Account, en User, eller betragtes som anonym.
Brugerens autentificeringsoplysninger omfatter:
- Brugernavn — brugernavn (afhængig af store og små bogstaver!);
- UID — en maskinlæsbar identifikationsstreng for brugeren, som "er mere konsistent og unik end brugernavnet";
- Groups — listen over grupper, som brugeren tilhører;
- Ekstra — yderligere felter, der kan bruges af autoriseringsmekanismen.
Kubernetes kan anvende mange autentificeringsmekanismer: X509-certifikater, Bearer tokens, autentificerende proxyer, HTTP Basic Auth. Ved hjælp af disse mekanismer kan der implementeres mange autorisationsordninger: fra en statisk fil med adgangskoder til OpenID OAuth2.
Desuden tillades det at bruge flere autorisationsordninger samtidig. Som standard anvendes der i klyngen:
- service account tokens — til Service Accounts;
- X509 — til Users.
Spørgsmålet om håndtering af ServiceAccounts går ud over denne artikel, og for dem, der ønsker at vide mere om dette emne, anbefaler jeg at starte med . Vi vil derimod se nærmere på spørgsmålet om X509-certifikater.
Certifikater til brugere (X.509)
Den klassiske måde at arbejde med certifikater på indebærer:
- generering af en nøgle:
mkdir -p ~/mynewuser/.certs/ openssl genrsa -out ~/.certs/mynewuser.key 2048 - generering af en anmodning om certifikat:
openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company" - behandling af anmodningen om certifikat ved hjælp af Kubernetes-klusterets CA-nøgler, modtagelse af brugerens certifikat (for at modtage certifikatet skal du bruge en konto, der har adgang til Kubernetes-klusterets certifikatmyndighedsnøgle, som som standard findes 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 klusteret (angiv adresse og placering for CA-certifikatfilen for den specifikke klusterinstallation):
kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443 - eller — som ikkeden anbefalede mulighed — der er ikke nødvendigt at angive rodcertifikatet (så vil kubectl ikke kontrollere gyldigheden af klusterets API-server):
kubectl config set-cluster kubernetes --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443 - tilføjelse af brugeren til konfigurationsfilen:
kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt --client-key=.certs/mynewuser.key - tilføjelse af kontekst:
kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser - angivelse af standardkonteksten:
kubectl config use-context mynewuser-context
- beskrivelse af klusteret (angiv adresse og placering for CA-certifikatfilen for den specifikke klusterinstallation):
Efter de ovennævnte manipulationer vil konfigurationsfilen .kube/config være oprettet i følgende format:
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.keyFor 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 dette kan filerne angivet i dem kodes med base64 og angives i konfigurationen ved at tilføje suffikset -data, dvs. få certificate-authority-data osv.
Certifikater med kubeadm
Med udgivelsen af Arbejdet med certifikater er blevet betydeligt lettere takket være alpha-versionens støtte i . For eksempel, her er hvordan generationen af konfigurationsfilen med brugerens nøgler nu kan se ud:
kubeadm alpha kubeconfig user --client-name=mynewuser --apiserver-advertise-address 192.168.100.200 NB: Det krævede advertise address kan ses i konfigurationen af api-serveren, som som standard ligger i /etc/kubernetes/manifests/kube-apiserver.yaml.
Den resulterende konfiguration vil blive udskrevet til stdout. Den skal gemmes i ~/.kube/config brugerens konto eller i en fil angivet i miljøvariablen KUBECONFIG.
Dykke dybere
For dem, der ønsker at dykke grundigere ned i de beskrevede emner:
- om arbejdet med certifikater i den officielle Kubernetes-dokumentation;
- , hvor emnet certifikater bliver berørt fra en praktisk vinkel.
- om autentificering i Kubernetes.
Godkendelse
Den autoriserede konto har som standard ikke rettigheder til handlinger i klyngen. For at give tilladelser i Kubernetes er der implementeret en autorisationsmekanisme.
Indtil version 1.6 blev der anvendt en autorisationstype i Kubernetes kaldet ABAC (Attributbaseret adgangskontrol). Detaljer om det kan findes i . I øjeblikket betragtes denne tilgang som forældet (legacy), men du kan stadig bruge den samtidig med andre typer autorisation.
Den aktuelle (og mere fleksible) måde at adskille adgangsrettigheder til klyngen kaldes RBAC (). Den blev erklæret stabil med versionen . RBAC implementerer en model for rettigheder, hvor alt, der ikke er eksplicit tilladt, er forbudt.
For at aktivere RBAC, skal du starte Kubernetes api-serveren med parameteren --authorization-mode=RBAC. Parametrene indstilles i manifestet med konfigurationen af api-serveren, som som standard findes på stien /etc/kubernetes/manifests/kube-apiserver.yaml, i sektionen command. Dog er RBAC som standard allerede aktiveret, så det er sandsynligvis ikke nødvendigt at bekymre sig om dette: det kan kontrolleres ved værdien af authorization-mode (i den allerede nævnte kube-apiserver.yaml). For øvrigt kan der blandt dens værdier findes andre typer autorisation (node, webhook, altid tillad), men en gennemgang af dem vil vi lade ligge uden for dette materiale.
For øvrigt har vi allerede publiceret med en temmelig detaljeret beskrivelse af principperne og funktionerne i arbejdet med RBAC, så jeg vil fremover begrænse mig til en kort opregning af grundene og eksempler.
Til at styre adgangen i Kubernetes gennem RBAC bruges følgende API-enheder:
-
RolleogClusterRole— roller, der bruges til at beskrive adgangsrettigheder: -
Rollegiver mulighed for at beskrive rettigheder inden for et navnerum; -
ClusterRole— inden for klyngen, herunder klynge-specifikke objekter som noder, non-resources urls (dvs. ikke relateret til Kubernetes-ressourcer — for eksempel,/version,/logs,/api*); -
RoleBindingogClusterRoleBinding— bruges til at bindesRolleogClusterRoletil en bruger, en gruppen af brugere eller ServiceAccount.
Entiteterne Role og RoleBinding er begrænsede af navnerummet, dvs. de skal være inden for et enkelt navnerum. Dog kan RoleBinding referere til ClusterRole, hvilket muliggør at oprette en standard gruppe af tilladelser og administrere adgang via dem.
Roller beskriver rettigheder ved hjælp af sæt af regler, der indeholder:
- API-grupper — se om apiGroups og output
kubectl api-resources; - ressourcer (resources:
pod,namespace,deploymentog lignende); - verber (verbs:
set,opdateringog lignende). - ressourcenavne (
resourceNames) — i tilfælde hvor der er behov for at give adgang til en bestemt ressource, snarere end til alle ressourcer af denne type.
En mere detaljeret gennemgang af autorisation i Kubernetes kan findes på siden . I stedet (eller rettere sagt — derudover) vil jeg give eksempler, der illustrerer dens funktion.
Eksempler på RBAC-enheder
Simpel Rolle, som giver mulighed for at få en liste og status over pods og overvåge 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, hvilket muliggør at få en liste og status over pods og overvåge dem i hele klyngen:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# der er ingen "namespace" sektion, da ClusterRole involverer hele klyngen
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"] Eksempel RoleBinding, hvilket giver brugeren mynewuser "read" 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 # brugernavnet er case-sensitiv!
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role # her skal det være “Role” eller “ClusterRole”
name: pod-reader # navnet på Role, der findes i samme namespace,
# eller navnet på ClusterRole, hvis brugen deraf
# ønsker vi at tillade for brugeren
apiGroup: rbac.authorization.k8s.ioAudit log events
Kubernetes-arkitekturen kan skitseres således:

Den centrale komponent i Kubernetes, der håndterer forespørgsler, er api-server. Alle operationer på klyngen foregår gennem det. For mere information om disse interne mekanismer kan du læse artiklen “».
System audit er en interessant funktion i Kubernetes, som som standard er deaktiveret. Den gør det muligt at logge alle anmodninger til Kubernetes API. Som man let 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ædvanlig) findes i K8s. Herefter vil jeg forsøge at præsentere emnet på et mere forståeligt sprog.
Så, For at aktivere audits, skal vi overføre tre obligatoriske parametre til containeren i api-serveren, som er beskrevet nærmere 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 findes der mange ekstra indstillinger relateret til audit: fra logrotation til webhook-beskrivelser. Eksempel på logrotationsparametre:
-
--audit-log-maxbackup=10 -
--audit-log-maxsize=100 -
--audit-log-maxage=7
Men vi vil ikke gå nærmere ind på dem — alle detaljer kan findes i .
Som nævnt tidligere, indstilles alle parametre i manifestet med konfigurationen af api-serveren (som standard /etc/kubernetes/manifests/kube-apiserver.yaml), i sektionen command. Lad os vende tilbage til de tre obligatoriske parametre og se nærmere på dem:
-
audit-policy-file— stien til YAML-filen med beskrivelsen af auditpolitikken. Vi vil vende tilbage til indholdet af denne fil, men jeg vil bemærke, at filen skal være læsbar for api-serverprocessen. Derfor skal den monteres i containeren, og man kan tilføje følgende kode i de relevante sektioner af konfigurationen:volumeMounts: - mountPath: /etc/kubernetes/policies name: policies readOnly: true volumes: - hostPath: path: /etc/kubernetes/policies type: DirectoryOrCreate name: policies -
audit-log-path— stien til logfilen. Stien skal også være tilgængelig for api-serverprocessen, så vi beskriver tilsvarende dens montering:volumeMounts: - mountPath: /var/log/kube-audit name: logs readOnly: false volumes: - hostPath: path: /var/log/kube-audit type: DirectoryOrCreate name: logs -
audit-log-format— logformatet for audit. Som standard er dettejson, men en forældet tekstformat er også tilgængeligt (legacy).
Auditpolitikken
Lad os nu tale om den nævnte fil med beskrivelsen af logningspolitikken. Det første begreb audit policy — er niveau, logningsniveau. De kan være følgende:
-
None— ikke logge; -
Metadata— logge metadata for anmodningen: bruger, anmodningens tidsstempel, målressource (pod, namespace osv.), type handling (verb) osv.; -
Request— logge metadata og anmodningsindhold; -
RequestResponse— logge metadata, anmodningsindhold og svarets indhold.
De sidste to niveauer (Request og RequestResponse) logger ikke anmodninger, der ikke henvender sig til ressourcer (henvendelser til såkaldte non-resources URL'er).
Desuden passerer alle anmodninger gennem flere faser:
-
RequestReceived— fasen, hvor anmodningen er modtaget af behandleren og endnu ikke er sendt videre i kæden af behandlere; -
ResponseStarted— svarhovedet er sendt, men før selve svaret sendes. Genereres for langvarige anmodninger (for eksempel,watch); -
ResponseComplete— svaret er sendt, der vil ikke blive sendt mere information; -
Panic— hændelser genereres, når der opdages en unormal situation.
For at springe over nogen faser kan man bruge omitStages.
I politikfilen kan vi beskrive flere sektioner med forskellige loggniveauer. Den første passende regel, der findes i beskrivelsen af politikken, vil blive anvendt.
Dæmonen kubelet overvåger ændringer i manifestet med konfigurationen af api-serveren og genstarter beholdningen med api-serveren ved opdagelse heraf. Men der er en vigtig detalje: ændringer i politikfilen vil blive ignoreret af dem. Efter at der er foretaget ændringer i politikfilen, er det nødvendigt at genstarte api-serveren manuelt. Da api-serveren kører som , holdet kubectl delete vil ikke føre til genstart af den. Det skal gøres manuelt docker stop på kube-mastere, hvor revisionspolitikken er ændret:
docker stop $(docker ps | grep k8s_kube-apiserver | awk '{print $1}')Når revisionen er aktiveret, er det vigtigt at huske, at belastningen på kube-apiserveren stiger. Især øges hukommelsesforbruget til opbevaring af konteksten af anmodninger. Logningen starter først efter, at svarhovedet er sendt. Belastningen afhænger også af konfigurationen af revisionspolitikken.
Eksempler på politikker
Lad os gennemgå strukturen af politikfilerne med eksempler.
Her er en simpel fil policy, for at logge alt på niveau Metadata:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata I politikken kan man angive en liste over brugere (Users og ServiceAccounts) og brugergrupper. For eksempel, på denne måde vil vi ignorere systembrugere men logge alt andet på niveau 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: RequestDer er også mulighed for at beskrive mål:
- navnerum (
namespaces); - verber (verbs:
get,opdatering,sletog andre); - ressourcer (resources, nemlig:
pod,configmapsosv.) og ressourcegrupper (apiGroups).
Vær opmærksom på! Ressourcer og ressourcergrupper (API-grupper, dvs. apiGroups) samt deres versioner, der er installeret i klyngen, kan hentes ved hjælp af kommandoerne:
kubectl api-resources
kubectl api-versionsDen følgende auditpolitisk er givet som et eksempel på bedste praksis i :
apiVersion: audit.k8s.io/v1beta1
kind: Policy
# Undlad at logge fasen RequestReceived
omitStages:
- "RequestReceived"
rules:
# Undlad at logge hændelser, der anses for at være marginale og ikke farlige:
- level: None
users: ["system:kube-proxy"]
verbs: ["watch"]
resources:
- group: "" # dette er api-gruppen med det tomme navn, der omfatter
# de grundlæggende Kubernetes-ressourcer kaldet “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"]
# Undlad at logge adgang til read-only URLs:
- level: None
nonResourceURLs:
- /healthz*
- /version
- /swagger*
# Undlad at logge meddelelser vedrørende ressourcetyper “events”:
- level: None
resources:
- group: "" # core
resources: ["events"]
# Ressourcer som Secret, ConfigMap og TokenReview kan indeholde følsomme oplysninger,
# så log kun metadata relateret til disse anmodninger
- level: Metadata
resources:
- group: "" # core
resources: ["secrets", "configmaps"]
- group: authentication.k8s.io
resources: ["tokenreviews"]
# Handlinger som get, list og watch kan være ressourcekrævende; log ikke dem
- 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"
# Standard logningsniveau for standard API-ressourcer
- 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"
# Standard logningsniveau for alle andre anmodninger
- level: MetadataEt andet godt eksempel på audit-politik — .
For hurtigt at reagere på audit-hændelser er der mulighed for at beskrive en webhook. Dette emne uddybes i , jeg vil efterlade det uden for denne artikel.
Resumé
Artiklen giver en oversigt over mekanismerne til grundlæggende sikkerhedsforanstaltninger i Kubernetes-klynger, der muliggør oprettelse af personificerede brugerkonti, deling af deres rettigheder samt registrering af deres handlinger. Jeg håber, det vil være nyttigt for dem, der har stødt på sådanne spørgsmål i teori eller allerede i praksis. Jeg anbefaler også at kigge på listen over andre materialer om emnet sikkerhed i Kubernetes, som findes i 'P.S.', – måske finder du de nødvendige detaljer til de problemer, der er relevante for dig.
P.S.
Læs også på vores blog:
- «»;
- «»;
- «»;
- «»;
- «».
Kilde: habr.com
