ProHoster > blog > administratie > Het ABC van beveiliging in Kubernetes: authenticatie, autorisatie, auditing
Het ABC van beveiliging in Kubernetes: authenticatie, autorisatie, auditing
Vroeg of laat komt bij de werking van elk systeem de kwestie van veiligheid aan de orde: het waarborgen van authenticatie, scheiding van rechten, auditing en andere taken. Al gemaakt voor Kubernetes veel oplossingen, waarmee u zelfs in zeer veeleisende omgevingen aan de normen kunt voldoen... Hetzelfde materiaal is gewijd aan de basisaspecten van beveiliging die zijn geïmplementeerd in de ingebouwde mechanismen van de K8s. Allereerst zal het nuttig zijn voor degenen die kennis maken met Kubernetes - als startpunt voor het bestuderen van beveiligingsgerelateerde kwesties.
authenticatie
Er zijn twee soorten gebruikers in Kubernetes:
Serviceaccounts — accounts beheerd door de Kubernetes API;
Gebruikers — “normale” gebruikers beheerd door externe, onafhankelijke diensten.
Het belangrijkste verschil tussen deze typen is dat er voor serviceaccounts speciale objecten zijn in de Kubernetes API (ze worden zo genoemd: ServiceAccounts), die zijn gekoppeld aan een naamruimte en een set autorisatiegegevens die in het cluster zijn opgeslagen in objecten van het type Geheimen. Dergelijke gebruikers (Service Accounts) zijn primair bedoeld voor het beheren van toegangsrechten tot de Kubernetes API van processen die in het Kubernetes cluster draaien.
Gewone gebruikers hebben geen vermeldingen in de Kubernetes API: ze moeten worden beheerd door externe mechanismen. Ze zijn bedoeld voor mensen of processen die buiten het cluster wonen.
Elk API-verzoek is gekoppeld aan een serviceaccount of een gebruiker of wordt als anoniem beschouwd.
UID - een machinaal leesbare gebruikersidentificatiereeks die “consistentiever en unieker is dan de gebruikersnaam”;
Groepen — lijst met groepen waartoe de gebruiker behoort;
Extra — aanvullende velden die door het autorisatiemechanisme kunnen worden gebruikt.
Kubernetes kan een groot aantal authenticatiemechanismen gebruiken: X509-certificaten, Bearer-tokens, authenticatieproxy, HTTP Basic Auth. Met deze mechanismen kunt u een groot aantal autorisatieschema’s implementeren: van een statisch bestand met wachtwoorden tot OpenID OAuth2.
Bovendien is het mogelijk om meerdere autorisatieschema's tegelijkertijd te gebruiken. Standaard gebruikt het cluster:
serviceaccounttokens - voor serviceaccounts;
X509 - voor gebruikers.
De vraag over het beheren van ServiceAccounts valt buiten het bestek van dit artikel, maar voor degenen die zich meer in detail met dit probleem willen verdiepen, raad ik aan te beginnen met officiële documentatiepagina's. We zullen de kwestie van hoe X509-certificaten werken nader bekijken.
Certificaten voor gebruikers (X.509)
De klassieke manier van werken met certificaten omvat:
het verwerken van een certificaataanvraag met behulp van de Kubernetes cluster CA-sleutels, het verkrijgen van een gebruikerscertificaat (om een certificaat te verkrijgen moet u een account gebruiken dat toegang heeft tot de Kubernetes cluster CA-sleutel, die zich standaard bevindt in /etc/kubernetes/pki/ca.key):
of hoe geenaanbevolen optie - u hoeft het rootcertificaat niet op te geven (dan zal kubectl de juistheid van de api-server van het cluster niet controleren):
Om het gemakkelijker te maken om de configuratie tussen accounts en servers over te dragen, is het handig om de waarden van de volgende sleutels te bewerken:
certificate-authority
client-certificate
client-key
Om dit te doen, kunt u de daarin gespecificeerde bestanden coderen met base64 en ze in de configuratie registreren, waarbij u het achtervoegsel aan de naam van de sleutels toevoegt -data, d.w.z. te hebben ontvangen certificate-authority-data etc.
Certificaten met kubeadm
Met de uitgave Kubernetes 1.15 het werken met certificaten is veel eenvoudiger geworden dankzij de alfaversie van de ondersteuning in kubeadm-hulpprogramma. Dit is bijvoorbeeld hoe het genereren van een configuratiebestand met gebruikerssleutels er nu uit zou kunnen zien:
kubeadm alpha kubeconfig user --client-name=mynewuser --apiserver-advertise-address 192.168.100.200
NB: Vereist adres adverteren is te vinden in de api-serverconfiguratie, die zich standaard bevindt in /etc/kubernetes/manifests/kube-apiserver.yaml.
De resulterende configuratie wordt uitgevoerd naar stdout. Er moet in worden opgeslagen ~/.kube/config gebruikersaccount of naar een bestand dat is opgegeven in een omgevingsvariabele KUBECONFIG.
Graaf dieper
Voor degenen die de beschreven problemen grondiger willen begrijpen:
Een apart artikel over het werken met certificaten in de officiële Kubernetes-documentatie;
goed artikel van Bitnami, waarin de uitgifte van certificaten vanuit een praktisch perspectief wordt belicht.
Het standaard geautoriseerde account heeft geen rechten om op het cluster te werken. Om machtigingen te verlenen implementeert Kubernetes een autorisatiemechanisme.
Vóór versie 1.6 gebruikte Kubernetes een autorisatietype genaamd ABAC (Attribuutgebaseerde toegangscontrole). Details hierover zijn te vinden in officiële documentatie. Deze aanpak wordt momenteel als verouderd beschouwd, maar u kunt deze nog steeds naast andere authenticatietypen gebruiken.
De huidige (en flexibelere) manier om toegangsrechten tot een cluster te verdelen heet RBAC (Op rollen gebaseerde toegangscontrole). Het is sinds de versie stabiel verklaard Kubernetes 1.8. RBAC implementeert een rechtenmodel waarin alles wat niet expliciet is toegestaan, verboden is. Om RBAC in te schakelen, moet u Kubernetes api-server starten met de parameter --authorization-mode=RBAC. De parameters worden in het manifest ingesteld met de api-serverconfiguratie, die zich standaard langs het pad bevindt /etc/kubernetes/manifests/kube-apiserver.yaml, in sectie command. RBAC is echter standaard al ingeschakeld, dus u hoeft zich daar waarschijnlijk geen zorgen over te maken: u kunt dit verifiëren aan de hand van de waarde authorization-mode (in het reeds genoemde kube-apiserver.yaml). Tussen haakjes, onder de betekenissen kunnen er andere soorten autorisatie zijn (node, webhook, always allow), maar we laten hun beschouwing buiten de reikwijdte van het materiaal.
We hebben het trouwens al gepubliceerd статью met een vrij gedetailleerde beschrijving van de principes en kenmerken van het werken met RBAC, dus verder zal ik mezelf beperken tot een korte opsomming van de basisprincipes en voorbeelden.
De volgende API-entiteiten worden gebruikt om de toegang in Kubernetes via RBAC te beheren:
Role и ClusterRole — rollen die dienen om toegangsrechten te beschrijven:
Role stelt u in staat rechten binnen een naamruimte te beschrijven;
ClusterRole - binnen het cluster, inclusief clusterspecifieke objecten zoals knooppunten, niet-resources-URL's (d.w.z. niet gerelateerd aan Kubernetes-resources - bijvoorbeeld /version, /logs, /api*);
RoleBinding и ClusterRoleBinding - gebruikt voor binding Role и ClusterRole aan een gebruiker, gebruikersgroep of ServiceAccount.
De Role- en RoleBinding-entiteiten worden beperkt door de naamruimte, d.w.z. moet zich binnen dezelfde naamruimte bevinden. Een RoleBinding kan echter verwijzen naar een ClusterRole, waarmee u een set algemene machtigingen kunt maken en de toegang hiermee kunt beheren.
Rollen beschrijven rechten met behulp van sets regels die het volgende bevatten:
API-groepen - zie officiële documentatie door apiGroups en uitvoer kubectl api-resources;
resourcenamen (resourceNames) - voor het geval dat u toegang moet verlenen tot een specifieke bron, en niet tot alle bronnen van dit type.
Een meer gedetailleerde analyse van autorisatie in Kubernetes vindt u op de pagina officiële documentatie. In plaats daarvan (of beter gezegd, in aanvulling hierop) zal ik voorbeelden geven die haar werk illustreren.
Voorbeelden van RBAC-entiteiten
eenvoudig Role, waarmee u een lijst en status van pods kunt krijgen en deze in de naamruimte kunt controleren target-namespace:
Voorbeeld ClusterRole, waarmee u een lijst en status van pods kunt krijgen en deze in het hele cluster kunt controleren:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# секции "namespace" нет, так как ClusterRole задействует весь кластер
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
Voorbeeld RoleBinding, waarmee de gebruiker kan mynewuser "lees"-pods in de naamruimte 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
Evenementaudit
Schematisch kan de Kubernetes-architectuur als volgt worden weergegeven:
De belangrijkste Kubernetes-component die verantwoordelijk is voor het verwerken van verzoeken is api-server. Alle bewerkingen op het cluster gaan er doorheen. Meer over deze interne mechanismen kun je lezen in het artikel “Wat gebeurt er in Kubernetes wanneer u kubectl run uitvoert?.
Systeemauditing is een interessante functie in Kubernetes, die standaard is uitgeschakeld. Hiermee kunt u alle oproepen naar de Kubernetes API loggen. Zoals u wellicht kunt raden, worden alle acties met betrekking tot het monitoren en wijzigen van de status van het cluster via deze API uitgevoerd. Een goede beschrijving van de mogelijkheden is (zoals gebruikelijk) te vinden in officiële documentatie K8's. Vervolgens zal ik proberen het onderwerp in eenvoudiger taal te presenteren.
aldus om auditing mogelijk te maken, moeten we drie vereiste parameters doorgeven aan de container in api-server, die hieronder in meer detail worden beschreven:
Naast deze drie noodzakelijke parameters zijn er veel aanvullende instellingen met betrekking tot auditing: van logrotatie tot webhookbeschrijvingen. Voorbeeld van logrotatieparameters:
Zoals reeds vermeld, worden alle parameters in het manifest ingesteld met de api-serverconfiguratie (standaard /etc/kubernetes/manifests/kube-apiserver.yaml), in sectie command. Laten we terugkeren naar de 3 vereiste parameters en deze analyseren:
audit-policy-file — pad naar het YAML-bestand dat het auditbeleid beschrijft. We komen later op de inhoud terug, maar voor nu merk ik op dat het bestand leesbaar moet zijn door het api-serverproces. Daarom is het noodzakelijk om het in de container te monteren, waarvoor u de volgende code aan de juiste secties van de configuratie kunt toevoegen:
audit-log-path — pad naar het logbestand. Het pad moet ook toegankelijk zijn voor het api-serverproces, dus beschrijven we de montage ervan op dezelfde manier:
RequestResponse — log-metagegevens, verzoektekst en antwoordtekst.
De laatste twee niveaus (Request и RequestResponse) log geen verzoeken in die geen toegang hebben tot bronnen (toegang tot zogenaamde niet-resources-URL's).
Ook alle aanvragen komen door verschillende stages:
RequestReceived — het stadium waarin het verzoek door de verwerker wordt ontvangen en nog niet verder in de keten van verwerkers is verzonden;
ResponseStarted — antwoordheaders worden verzonden, maar voordat de antwoordtekst wordt verzonden. Gegenereerd voor langlopende zoekopdrachten (bijvoorbeeld watch);
ResponseComplete — de antwoordtekst is verzonden; er wordt geen informatie meer verzonden;
Panic — gebeurtenissen worden gegenereerd wanneer een abnormale situatie wordt gedetecteerd.
Om stappen over te slaan die u kunt gebruiken omitStages.
In een beleidsbestand kunnen we verschillende secties beschrijven met verschillende logniveaus. De eerste matchingregel die in de polisbeschrijving wordt gevonden, wordt toegepast.
De kubelet-daemon bewaakt wijzigingen in het manifest met de api-server-configuratie en start, als deze worden gedetecteerd, de container opnieuw op met api-server. Maar er is een belangrijk detail: wijzigingen in het beleidsbestand worden erdoor genegeerd. Nadat u wijzigingen in het beleidsbestand hebt aangebracht, moet u de api-server handmatig opnieuw opstarten. Omdat api-server is gestart als statische pod, team kubectl delete zal er niet voor zorgen dat het opnieuw opstart. Je zult het handmatig moeten doen docker stop op kube-masters, waar het auditbeleid is gewijzigd:
Wanneer u auditing inschakelt, is het belangrijk om dat te onthouden de belasting op kube-apiserver neemt toe. In het bijzonder neemt het geheugengebruik voor het opslaan van verzoekcontext toe. Het loggen begint pas nadat de antwoordheader is verzonden. De belasting is ook afhankelijk van de configuratie van het auditbeleid.
Voorbeelden van beleid
Laten we de structuur van beleidsbestanden bekijken aan de hand van voorbeelden.
Hier is een eenvoudig bestand policyom alles op niveau te loggen Metadata:
In beleid kunt u een lijst met gebruikers opgeven (Users и ServiceAccounts) en gebruikersgroepen. Zo negeren we bijvoorbeeld systeemgebruikers, maar loggen we al het andere op niveau Request:
Het is ook mogelijk om de doelstellingen te beschrijven:
naamruimten (namespaces);
Werkwoorden (werkwoorden: get, update, delete en anderen);
bronnen (resources, namelijk: pod, configmaps enz.) en resourcegroepen (apiGroups).
Let op! Resources en resourcegroepen (API-groepen, d.w.z. apiGroups), evenals hun versies die in het cluster zijn geïnstalleerd, kunnen worden verkregen met behulp van de opdrachten:
kubectl api-resources
kubectl api-versions
Het volgende auditbeleid wordt gegeven als demonstratie van best practices op het gebied van: Alibaba Cloud-documentatie:
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
Snel reageren op auditgebeurtenissen is mogelijk webhook beschrijven. Deze kwestie wordt behandeld in officiële documentatie, ik laat het buiten het bestek van dit artikel.
Resultaten van
Het artikel geeft een overzicht van basisbeveiligingsmechanismen in Kubernetes-clusters, waarmee u gepersonaliseerde gebruikersaccounts kunt maken, hun rechten kunt scheiden en hun acties kunt vastleggen. Ik hoop dat het nuttig zal zijn voor degenen die in theorie of in de praktijk met dergelijke kwesties worden geconfronteerd. Ik raad u ook aan om de lijst met ander materiaal over het onderwerp beveiliging in Kubernetes te lezen, die wordt gegeven in "PS" - misschien vindt u daaronder de nodige details over de problemen die voor u relevant zijn.