SĂ€kerhetsalfabetet i Kubernetes: autentisering, auktorisering, granskning

SĂ€kerhetsalfabetet i Kubernetes: autentisering, auktorisering, granskning

SÄ smÄningom uppstÄr sÀkerhetsfrÄgor i drift av alla system: att sÀkerstÀlla autentisering, rÀttighetsdelning, granskning och andra uppgifter. För Kubernetes har det redan skapats mÄnga lösningar, som gör det möjligt att uppnÄ compliance med standarderna Àven i mycket krÀvande miljöer... Detta material Àr Àgnat Ät grundlÀggande aspekter av sÀkerhet som realiserats inom ramen för de inbyggda mekanismerna i K8s. FrÀmst kommer det vara anvÀndbart för dem som börjar bekanta sig med Kubernetes, - som en utgÄngspunkt för att studera frÄgor relaterade till sÀkerhet.

Autentisering

I Kubernetes finns det tvÄ typer av anvÀndare:

  • Servicekonton – konton som hanteras av Kubernetes API;
  • AnvĂ€ndare – "normala" anvĂ€ndare, som hanteras av externa, oberoende tjĂ€nster.

Den viktigaste skillnaden mellan dessa typer Àr att det finns speciella objekt i Kubernetes API för Servicekonton (de kallas just ServiceAccounts), som Àr kopplade till ett namnrymd och en uppsÀttning autentiseringsdata som lagras i klustret i objekt av typen Secrets. SÄdana anvÀndare (Service Accounts) Àr huvudsakligen avsedda för att hantera ÄtkomstrÀttigheter till Kubernetes API för processer som körs i Kubernetes-klustret.

Vanliga AnvÀndare har dÀremot inga poster i Kubernetes API: hantering av dem mÄste göras av externa mekanismer. De Àr avsedda för mÀnniskor eller processer som lever utanför klustret.

Varje begÀran till API:t Àr kopplad antingen till ett Service Account, eller till en AnvÀndare, eller betraktas som anonym.

AnvÀndarens autentiseringsuppgifter inkluderar:

  • AnvĂ€ndarnamn – anvĂ€ndarnamn (beroende av versaler!);
  • UID – en maskinlĂ€sbar identitetsstrĂ€ng som "Ă€r mer konsekvent och unik Ă€n anvĂ€ndarnamnet";
  • Grupper – lista över grupper som anvĂ€ndaren tillhör;
  • Extra – ytterligare fĂ€lt som kan anvĂ€ndas av auktoriseringmekanismen.

Kubernetes kan anvÀnda mÄnga olika autentiseringsmekanismer: X509-certifikat, Bearer-token, autentiserande proxy, HTTP Basic Auth. Genom dessa mekanismer kan mÄnga auktoriseringsscheman implementeras: frÄn en statisk fil med lösenord till OpenID OAuth2.

Dessutom tillÄts anvÀndning av flera auktoriseringsscheman samtidigt. Som standard anvÀnds följande i klustret:

  • servicekontots token – för Service Accounts;
  • X509 — för anvĂ€ndare.

FrÄgan om hantering av ServiceAccounts faller utanför denna artikel, och för dem som vill lÀra sig mer rekommenderar jag att börja med sidan med den officiella dokumentationen. Vi ska istÀllet titta nÀrmare pÄ frÄgan om X509-certifikat.

Certifikat för anvÀndare (X.509)

Det klassiska sÀttet att hantera certifikat innebÀr:

  • generering av en nyckel:
    mkdir -p ~/mynewuser/.certs/
    openssl genrsa -out ~/.certs/mynewuser.key 2048
  • generering av en certifikatförfrĂ„gan:
    openssl req -new -key ~/mynewuser/.certs/mynewuser.key -out ~/mynewuser/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company"
  • behandling av certifikatförfrĂ„gan med hjĂ€lp av CA-nycklarna i Kubernetes-klustret, erhĂ„llande av anvĂ€ndarcertifikatet (för att fĂ„ certifikatet mĂ„ste ett konto med tillgĂ„ng till nyckeln för certifikatmyndigheten i Kubernetes-klustret anvĂ€ndas, som som standard ligger i /etc/kubernetes/pki/ca.key):
    openssl x509 -req -in ~/mynewuser/.certs/mynewuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out ~/mynewuser/.certs/mynewuser.crt -days 500
  • skapa en konfigurationsfil:
    • beskrivning av klustret (ange adress och plats för CA-certifikatfilen för den specifika installationen av klustret):
      kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443
    • eller — som inteett rekommenderat alternativ — det gĂ„r att hoppa över rötternas certifikat (dĂ„ kommer kubectl inte att kontrollera api-serverns giltighet i klustret):
      kubectl config set-cluster kubernetes --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443
    • lĂ€gga till anvĂ€ndaren i konfigurationsfilen:
      kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt --client-key=.certs/mynewuser.key
    • lĂ€gga till kontext:
      kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser
    • ange standardkontext:
      kubectl config use-context mynewuser-context

Efter de ovan nÀmnda ÄtgÀrderna kommer filen .kube/config att skapa en konfiguration av följande typ:

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

För att underlÀtta överföringen av konfigurationen mellan konton och servrar Àr det anvÀndbart att redigera vÀrdena för följande nycklar:

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

För detta kan man koda de angivna filerna med hjÀlp av base64 och skriva in dem i konfigurationen, genom att lÀgga till suffixet -data, dvs. fÄ certificate-authority-data och sÄ vidare.

Certifikat med kubeadm

Med releasen Kubernetes 1.15 att arbete med certifikat har blivit mycket enklare tack vare alpha-versionen av dess stöd i verktyget kubeadm. HÀr Àr ett exempel pÄ hur konfigurationen för anvÀndarens nycklar kan se ut:

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

NB: Den nödvÀndiga advertise address kan ses i konfigurationen av api-servern, som som standard ligger i /etc/kubernetes/manifests/kube-apiserver.yaml.

Den resulterande konfigurationen kommer att skrivas ut i stdout. Den mÄste sparas i ~/.kube/config anvÀndarkontot eller i en fil som anges i miljövariabeln KUBECONFIG.

GrÀva djupare

För den som vill gÄ djupare in i de beskrivna frÄgorna:

Behörighet

Det autentiserade kontot har som standard inga rÀttigheter att agera i klustret. För att ge behörigheter i Kubernetes finns en behörighetsmekanism.

Före version 1.6 anvÀndes en behörighetstyp som kallas ABAC (Attributbaserad Ätkomstkontroll). Mer information om detta finns i den officiella dokumentationen. Denna metod anses idag vara förÄldrad (legacy), men du kan fortfarande anvÀnda den samtidigt med andra behörighetstyper.

Det aktuella (och mer flexibla) sÀttet att dela upp ÄtkomstrÀttigheter till klustret kallas RBAC (Rollbaserad Ätkomstkontroll). Den introducerades som stabil i version Kubernetes 1.8. RBAC implementerar en rÀttighetsmodell dÀr allt som inte Àr uttryckligen tillÄtet Àr förbjudet.
För att aktivera RBAC, mÄste du köra Kubernetes api-server med parametern --authorization-mode=RBAC. Parametrarna stÀlls in i manifestet för konfigureringen av api-servern, som som standard ligger pÄ vÀgen /etc/kubernetes/manifests/kube-apiserver.yaml, i avsnittet command. Men i alla fall Àr RBAC som standard redan aktiverat, sÄ det Àr förmodligen inget att oroa sig för: detta kan bekrÀftas av vÀrdet authorization-mode (i den redan nÀmnda kube-apiserver.yaml). För övrigt kan det finnas andra typer av behörighet bland dess vÀrden (node, webhook, always allow), men vi lÀmnar deras behandling utanför detta material.

För övrigt har vi redan publicerat artikeln en tillrÀckligt detaljerad beskrivning av principerna och sÀrskiljningarna av arbetet med RBAC, sÄ jag begrÀnsar mig hÀr till en kort upprÀkning av grunderna och exempel.

För hantering av Ätkomst i Kubernetes via RBAC anvÀnds följande API-entiteter:

  • Roll och ClusterRole — roller som anvĂ€nds för att beskriva Ă„tkomstrĂ€ttigheter:
  • Roll möjliggör att beskriva rĂ€ttigheter inom ett namnrymde;
  • ClusterRole — inom klustret, inklusive kluster-specifika objekt som noder, non-resources urls (dvs. inte relaterade till Kubernetes-resurser — till exempel, /version, /logs, /api*);
  • RoleBinding och ClusterRoleBinding — anvĂ€nds för att binda Roll och ClusterRole till en anvĂ€ndare, anvĂ€ndargrupp eller ServiceAccount.

Entiteterna Role och RoleBinding Àr begrÀnsade till namnrymden, dvs. de mÄste vara inom samma namnrymd. Men RoleBinding kan referera till ClusterRole, vilket möjliggör skapandet av en uppsÀttning typiska behörigheter och hantering av Ätkomst med hjÀlp av dessa.

Roller beskriver behörigheter med hjÀlp av uppsÀttningar regler som innehÄller:

  • API-grupper — se den officiella dokumentationen om apiGroups och kommandot kubectl api-resources;
  • resurser (resources: pod, namnrymd, deployment och liknande);
  • verb (verbs: set, update och liknande).
  • resursnamn (resourceNames) — för fall nĂ€r det Ă€r nödvĂ€ndigt att ge Ă„tkomst till en specifik resurs, inte alla resurser av den typen.

En mer detaljerad genomgĂ„ng av autentisering i Kubernetes kan hittas pĂ„ sidan den officiella dokumentationen. IstĂ€llet för detta (eller snarare — som tillĂ€gg till detta) fĂ„r ni exempel som illustrerar dess funktion.

Exempel pÄ RBAC-enheter

En enkel Roll, som tillÄter att fÄ lista och status pÄ poddar och övervaka dem i namnrymden 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"]

Exempel ClusterRole, vilket möjliggör att fÄ lista och status pÄ poddar och övervaka dem i hela klustret:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # avsnittet "namespace" finns inte, eftersom ClusterRole anvÀnds för hela klustret
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

Exempel RoleBinding, vilket ger anvÀndaren mynewuser "lÀsa" poddar i namnrymden my-namespace:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: target-namespace
subjects:
- kind: User
  name: mynewuser # anvÀndarnamn Àr skiftlÀgeskÀnsligt!
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role # hĂ€r bör vara “Role” eller “ClusterRole”
  name: pod-reader # namnet pÄ Role som finns i samma namnrymd,
                   # eller namnet pÄ ClusterRole vars anvÀndning
                   # vi vill tillÄta för anvÀndaren
  apiGroup: rbac.authorization.k8s.io

HĂ€ndelsegranskning

Schematisk kan Kubernetes-arkitekturen representeras som följande:

SĂ€kerhetsalfabetet i Kubernetes: autentisering, auktorisering, granskning

Den centrala komponenten i Kubernetes som Àr ansvarig för att bearbeta förfrÄgningar Àr api-server. Alla operationer med klustret gÄr genom det. Mer om dessa interna mekanismer kan lÀsas i artikeln "Vad hÀnder i Kubernetes nÀr man kör kubectl run?».

Systemaudit Àr en intressant funktion i Kubernetes som som standard Àr avstÀngd. Den gör det möjligt att logga alla anrop till Kubernetes API. Som man lÀtt kan förstÄ, görs alla ÄtgÀrder relaterade till kontroll och förÀndring av klustrets tillstÄnd via detta API. En bra beskrivning av dess möjligheter kan (som vanligt) hittas i den officiella dokumentationen K8s. Nedan kommer jag att försöka förklara Àmnet pÄ ett enklare sÀtt.

SÄ, För att aktivera audit, mÄste vi överföra tre obligatoriska parametrar till containern i api-servern, mer om dem finns nedan:

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

Förutom dessa tre nödvÀndiga parametrar finns det mÄnga ytterligare instÀllningar relaterade till audit: frÄn loggrotation till beskrivningar av webhook. HÀr Àr ett exempel pÄ loggrotationsparametrar:

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

Men vi kommer inte att gĂ„ djupare in pĂ„ dem — alla detaljer kan hittas i dokumentationen för kube-apiserver.

Som redan nÀmnts stÀlls alla parametrar in i manifestet med konfigurationen av api-servern (som standard /etc/kubernetes/manifests/kube-apiserver.yaml), i sektionen command. LÄt oss ÄtervÀnda till de tre obligatoriska parametrarna och gÄ igenom dem:

  1. audit-policy-file — sökvĂ€g till YAML-filen med beskrivningen av audit policyn. Vi kommer tillbaka till dess innehĂ„ll, men lĂ„t mig pĂ„peka att filen mĂ„ste vara lĂ€sbar för processen api-server. DĂ€rför mĂ„ste den monteras inuti containern, vilket kan göras genom att lĂ€gga till följande kod i de relevanta sektionerna av konfigurationsfilen:
      volumeMounts:
        - mountPath: /etc/kubernetes/policies
          name: policies
          readOnly: true
      volumes:
      - hostPath:
          path: /etc/kubernetes/policies
          type: DirectoryOrCreate
        name: policies
  2. audit-log-path — sökvĂ€g till loggfilen. SökvĂ€gen mĂ„ste ocksĂ„ vara tillgĂ€nglig för processen api-server, sĂ„ vi beskriver ocksĂ„ dess montering:
      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 — formatet för auditloggen. Som standard Ă€r detta json, men det finns ocksĂ„ ett förĂ„ldrat textformat (legacy).

Auditpolicy

Nu om den nĂ€mnda filen med beskrivningen av loggningspolicyn. Det första begreppet audit policy — Ă€r detta nivĂ„, loggningsnivĂ„. Dessa kan vara följande:

  • None — ingen loggning;
  • Metadata — logga metadata om begĂ€ran: anvĂ€ndare, tid för begĂ€ran, mĂ„linnehĂ„llet (pod, namespace osv.), typ av Ă„tgĂ€rd (verb) osv.;
  • BegĂ€ran — logga metadata och kropp av begĂ€ran;
  • BegĂ€ranSvar — logga metadata, kropp av begĂ€ran och kropp av svar.

De senaste tvÄ nivÄerna (BegÀran och BegÀranSvar) loggar inte begÀrningar som inte har riktat sig mot resurser (begÀrningar till sÄ kallade non-resources urls).

Dessutom passerar alla begÀrningar genom flera stadier:

  • BegĂ€ranMottagen — steg dĂ€r begĂ€ran har mottagits av hanteraren och inte har vidarebefordrats i kedjan av hanterare;
  • SvarStartad — svaret har skickats, men före kroppens svar. Genereras för lĂ„nga begĂ€rningar (till exempel, övervaka);
  • SvarFullstĂ€ndig — svarskroppen har skickats, mer information kommer inte att skickas;
  • Panik — hĂ€ndelser genereras nĂ€r ett avvikande tillstĂ„nd upptĂ€ckts.

För att hoppa över vissa stadier kan man anvĂ€nda hoppaÖverStadier.

I policydokumentet kan vi beskriva flera sektioner med olika loggnivÄer. Den första lÀmpliga regeln som hittas i beskrivningen av policyn kommer att tillÀmpas.

Demon kubelet övervakar Àndringar i manifestet med konfigurationen för api-servern och nÀr sÄdana upptÀckts, startar den om containern med api-servern. Men det finns en viktig detalj: Àndringar i policyn kommer att ignoreras av dem.Efter att ha gjort Àndringar i policydokumentet krÀvs det att man startar om api-servern manuellt. Eftersom api-servern har startats som statisk pod, kommandot kubectl ta bort kommer inte att leda till att den startas om. Man mÄste manuellt göra docker stop pÄ kube-master dÀr revisionspolicyn har Àndrats:

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

Vid aktivering av revisionen Àr det viktigt att komma ihÄg att belastningen pÄ kube-apiservern ökar.. FöretrÀdesvis ökar minnesanvÀndningen för att lagra begÀrningskontext. Loggningen börjar först efter att svaret har skickats. Belastningen beror ocksÄ pÄ konfigurationen av revisionspolicyn.

Exempel pÄ policyer

LÄt oss gÄ igenom strukturen av policydokumenten med exempel.

HÀr Àr en enkel fil policy, för att logga allt pÄ nivÄ Metadata:

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

I policyn kan man ange en lista med anvÀndare (AnvÀndare och ServiceAccounts) och anvÀndargrupper. Till exempel, sÄ hÀr kommer vi att ignorera systemanvÀndare, men logga allt annat pÄ nivÄ BegÀran:

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 finns ocksÄ möjlighet att beskriva mÄl:

  • namnrymder (namnrymder);
  • verb (verbs: hĂ€mta, update, ta bort och andra);
  • resurser (resources, nĂ€mligen: pod, configmaps och sĂ„ vidare) och resursgrupper (apiGroups).

Observera! Resurser och resursgrupper (API-grupper, dvs. apiGroups), samt deras versioner som Àr installerade i klustret, kan hÀmtas med kommandona:

kubectl api-resources
kubectl api-versions

Följande audit policy ges som en demonstration av bÀsta praxis i dokumentationen frÄn Alibaba Cloud:

apiVersion: audit.k8s.io/v1beta1
kind: Policy
# Utesluta loggning av steget RequestReceived
omitStages:
  - "RequestReceived"
rules:
  # Utesluta loggning av hÀndelser som bedöms som obetydliga och ofarliga:
  - level: None
    users: ["system:kube-proxy"]
    verbs: ["watch"]
    resources:
      - group: "" # detta Àr api-gruppen med ett tomt namn, som hör till
                  # de grundlĂ€ggande resurserna i Kubernetes, kallade “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"]
  # Utesluta loggning av anrop till read-only URLs:
  - level: None
    nonResourceURLs:
      - /healthz*
      - /version
      - /swagger*
  # Utesluta loggning av meddelanden som rör resurstypen “events”:
  - level: None
    resources:
      - group: "" # core
        resources: ["events"]
  # Resurser av typ Secret, ConfigMap och TokenReview kan innehÄlla hemliga data,
  # sÄ vi loggar endast metadata relaterade till dessa begÀrningar
  - level: Metadata
    resources:
      - group: "" # core
        resources: ["secrets", "configmaps"]
      - group: authentication.k8s.io
        resources: ["tokenreviews"]
  # ÅtgĂ€rder av typen get, list och watch kan vara resurskrĂ€vande; vi loggar inte 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 loggnivÄ för standard API-resurser
  - 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 loggnivÄ för alla andra förfrÄgningar
  - level: Metadata

Ett annat bra exempel pĂ„ audit policy — profilen som anvĂ€nds i GCE.

För att snabbt kunna reagera pÄ audit-hÀndelser finns möjligheten att beskriva en webhook. Denna frÄga beskrivs i den officiella dokumentationen, jag kommer att lÀmna det utanför denna artikel.

Sammanfattning

Artikeln ger en översikt över sĂ€kerhetsmekanismerna i Kubernetes-kluster som möjliggör skapandet av personliga anvĂ€ndarkonton, separation av deras rĂ€ttigheter och registrering av deras aktiviteter. Jag hoppas att det kommer att vara till hjĂ€lp för dem som har stött pĂ„ sĂ„dana frĂ„gor i teorin eller redan i praktiken. Jag rekommenderar ocksĂ„ att lĂ€sa igenom listan över andra resurser om sĂ€kerhet i Kubernetes som anges i "P.S.", — kanske finner du i dem de nödvĂ€ndiga detaljerna om aktuella problem.

P.S.

LÀs Àven i vÄr blogg:

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster