Die ABC van sekuriteit in Kubernetes: verifikasie, magtiging, ouditering

Die ABC van sekuriteit in Kubernetes: verifikasie, magtiging, ouditering

Vroeër of later, in die werking van enige stelsel, ontstaan ​​die kwessie van sekuriteit: verskaffing van verifikasie, skeiding van regte, ouditering en ander take. Reeds geskep vir Kubernetes baie oplossings, wat jou toelaat om voldoening aan standaarde te bereik, selfs in baie veeleisende omgewings ... Dieselfde materiaal word gewy aan die basiese aspekte van sekuriteit wat binne die ingeboude meganismes van K8's geïmplementeer word. Eerstens sal dit nuttig wees vir diegene wat met Kubernetes begin kennis maak - as 'n beginpunt om kwessies wat verband hou met sekuriteit te bestudeer.

verifikasie

Daar is twee tipes gebruikers in Kubernetes:

  • Diensrekeninge - rekeninge wat deur die Kubernetes API bestuur word;
  • gebruikers - "normale" gebruikers wat deur eksterne, onafhanklike dienste bestuur word.

Die belangrikste verskil tussen hierdie tipes is dat daar spesiale voorwerpe vir diensrekeninge in die Kubernetes API is (hulle word so genoem - ServiceAccounts) wat gebind is aan 'n naamruimte en 'n stel magtigingsdata wat in die groep gestoor is in voorwerpe van die tipe Secrets. Sulke gebruikers (Diensrekeninge) is hoofsaaklik bedoel om toegangsregte tot die Kubernetes API van prosesse wat in 'n Kubernetes-kluster loop, te bestuur.

Gewone Gebruikers, aan die ander kant, het nie inskrywings in die Kubernetes API nie: hulle moet deur eksterne meganismes bestuur word. Hulle is bedoel vir mense of prosesse wat buite die groepering woon.

Elke API-versoek is gekoppel aan óf 'n diensrekening óf 'n gebruiker, of word as anoniem beskou.

Gebruikerstawingdata sluit in:

  • Gebruikersnaam - gebruikersnaam (hooflettergevoelig!);
  • UID - 'n masjienleesbare gebruiker-identifikasiestring wat "meer konsekwent en uniek is as 'n gebruikernaam";
  • groepe — lys van groepe waaraan die gebruiker behoort;
  • ekstra - bykomende velde wat deur die magtigingsmeganisme gebruik kan word.

Kubernetes kan 'n groot aantal verifikasiemeganismes gebruik: X509-sertifikate, Draer-tokens, verifikasie-instaanbediener, HTTP Basiese Auth. Deur hierdie meganismes te gebruik, kan u 'n groot aantal magtigingskemas implementeer: van 'n statiese wagwoordlêer tot OpenID OAuth2.

Boonop kan verskeie magtigingskemas op dieselfde tyd gebruik word. By verstek gebruik die groep:

  • diensrekeningtokens - vir diensrekeninge;
  • X509 - vir gebruikers.

Die kwessie van die bestuur van diensrekeninge val buite die bestek van hierdie artikel, en vir diegene wat meer oor hierdie kwessie wil leer, beveel ek aan om te begin met amptelike dokumentasie bladsye. Ons sal die uitreiking van X509-sertifikate van nader bekyk.

Sertifikate vir gebruikers (X.509)

Die klassieke manier om met sertifikate te werk, behels:

  • sleutel generasie:
    mkdir -p ~/mynewuser/.certs/
    openssl genrsa -out ~/.certs/mynewuser.key 2048
  • genereer 'n sertifikaatversoek:
    openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company"
  • verwerking van die sertifikaatversoek deur die CA-sleutels van die Kubernetes-groepering te gebruik, die verkryging van 'n gebruikersertifikaat (om 'n sertifikaat te verkry, moet jy 'n rekening gebruik wat toegang het tot die sleutel van die Kubernetes-kluster-CA, wat by verstek geleë is in /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
  • skep 'n konfigurasielêer:
    • beskrywing van die groepering (spesifiseer die adres en ligging van die CA-sertifikaatlêer van die spesifieke trosinstallasie):
      kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443
    • of hoe geenaanbevole opsie - jy kan nie die wortelsertifikaat spesifiseer nie (dan sal kubectl nie die korrektheid van die cluster api-bediener nagaan nie):
      kubectl config set-cluster kubernetes  --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443
    • voeg 'n gebruiker by die konfigurasielêer:
      kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt  --client-key=.certs/mynewuser.key
    • konteks byvoeg:
      kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser
    • verstek konteks opdrag:
      kubectl config use-context mynewuser-context

Na die bogenoemde manipulasies, in die lêer .kube/config die aansig konfigurasie sal geskep word:

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

Om die oordrag van die konfigurasie tussen rekeninge en bedieners te vergemaklik, is dit nuttig om die waardes van die volgende sleutels te wysig:

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

Om dit te doen, kan jy die lêers wat daarin gespesifiseer is, enkodeer deur gebruik te maak van base64 en dit in die konfigurasie registreer, en die agtervoegsel by die naam van die sleutels voeg -data, d.w.s. ontvang certificate-authority-data ens.

Sertifikate met kubeadm

Met vrylating Kubernetes 1.15 werk met sertifikate het baie makliker geword danksy die alfa-weergawe van sy ondersteuning in kubeadm nut. Byvoorbeeld, hier is hoe die generering van 'n konfigurasielêer met gebruikerssleutels nou kan lyk:

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

NB: Vereis adres adverteer kan bekyk word in die api-bediener-konfigurasie, wat by verstek geleë is in /etc/kubernetes/manifests/kube-apiserver.yaml.

Die gevolglike konfigurasie sal na stdout gedruk word. Dit moet ingehou word ~/.kube/config gebruikersrekening of na 'n lêer gespesifiseer in 'n omgewingsveranderlike KUBECONFIG.

Grou dieper

Vir diegene wat die kwessies wat beskryf word van nader wil bekyk:

magtiging

'n Gemagtigde rekening het by verstek nie regte om op die groep op te tree nie. Om toestemmings te verleen, implementeer Kubernetes 'n magtigingsmeganisme.

Voor weergawe 1.6 het Kubernetes 'n magtigingstipe genaamd gebruik transaksie basis (Eienskap-gebaseerde toegangsbeheer). Besonderhede daaroor kan gevind word in amptelike dokumentasie. Hierdie benadering word tans as nalatenskap beskou, maar jy kan dit steeds op dieselfde tyd as ander magtigingstipes gebruik.

Die werklike (en meer buigsame) manier om toegangsregte tot 'n groepering te skei word genoem RBAC (Rolgebaseerde toegangsbeheer). Dit is sedert weergawe stabiel verklaar Kubernetes 1.8. RBAC implementeer 'n regte-model wat alles verbied wat nie uitdruklik toegelaat word nie.
Om RBAC te aktiveer, moet jy Kubernetes api-bediener met die parameter begin --authorization-mode=RBAC. Die parameters word in die manifes gestel met die api-bediener-konfigurasie, wat by verstek langs die pad geleë is /etc/kubernetes/manifests/kube-apiserver.yaml, in afdeling command. By verstek is RBAC egter reeds geaktiveer, so waarskynlik moet jy nie daaroor bekommerd wees nie: jy kan dit verifieer deur die waarde authorization-mode (in die reeds genoemde kube-apiserver.yaml). Terloops, onder die waardes daarvan kan daar ander soorte magtiging wees (node, webhook, always allow), maar ons sal hul oorweging buite die bestek van die materiaal laat.

Terloops, ons het reeds gepubliseer 'n artikel met 'n redelik gedetailleerde storie oor die beginsels en kenmerke van die werk met RBAC, so verder sal ek myself beperk tot 'n kort lys van die basiese beginsels en voorbeelde.

Die volgende API-entiteite word gebruik om toegang tot Kubernetes via RBAC te beheer:

  • Role и ClusterRole - rolle wat dien om toegangsregte te beskryf:
  • Role laat jou toe om die regte binne die naamruimte te beskryf;
  • ClusterRole - binne die groepering, insluitend vir groepspesifieke voorwerpe soos nodusse, nie-hulpbron-URL's (dit wil sê, nie verwant aan Kubernetes-hulpbronne nie - byvoorbeeld, /version, /logs, /api*);
  • RoleBinding и ClusterRoleBinding - gebruik vir binding Role и ClusterRole na 'n gebruiker, gebruikersgroep of diensrekening.

Die Rol- en Rolbindende entiteite is naamruimtegebonde, d.w.s. moet binne dieselfde naamruimte wees. 'n Rolbinding kan egter na 'n ClusterRole verwys, wat jou toelaat om 'n stel generiese toestemmings te skep en toegang daarmee te beheer.

Rolle beskryf regte deur stelle reëls te gebruik wat bevat:

  • API-groepe - sien amptelike dokumentasie deur apiGroups en uitvoer kubectl api-resources;
  • hulpbronne (hulpbronne: pod, namespace, deployment en so aan.);
  • Werkwoorde (werkwoorde: set, update en so aan.).
  • hulpbron name (resourceNames) - vir die geval wanneer jy toegang tot 'n spesifieke hulpbron moet verskaf, en nie tot alle hulpbronne van hierdie tipe nie.

'n Meer gedetailleerde uiteensetting van magtiging in Kubernetes kan op die bladsy gevind word amptelike dokumentasie. In plaas daarvan (of eerder, bykomend tot hierdie), sal ek voorbeelde gee wat sy werk illustreer.

RBAC Entiteit Voorbeelde

eenvoudige Role, wat jou toelaat om 'n lys en status van peule te kry en tred te hou met hulle in die naamruimte 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"]

Voorbeeld ClusterRole, wat jou toelaat om 'n lys en status van peule te kry en hulle regdeur die groep te monitor:

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

Voorbeeld RoleBinding, wat die gebruiker toelaat mynewuser "lees" peule in 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

Gebeurtenisoudit

Skematies kan die argitektuur van Kubernetes soos volg voorgestel word:

Die ABC van sekuriteit in Kubernetes: verifikasie, magtiging, ouditering

Die sleutel Kubernetes-komponent wat verantwoordelik is vir die verwerking van versoeke is − api-bediener. Alle bewerkings op die groep gaan daardeur. Jy kan meer lees oor hierdie interne meganismes in die artikel "Wat gebeur in Kubernetes wanneer jy kubectl run hardloop?".

Stelseloudit is 'n interessante kenmerk in Kubernetes wat by verstek gedeaktiveer is. Dit laat jou toe om alle oproepe na die Kubernetes API aan te teken. Soos u kan raai, word alle aksies wat verband hou met die beheer en verandering van die toestand van die groepering deur hierdie API uitgevoer. 'n Goeie beskrywing van sy vermoëns kan (soos gewoonlik) gevind word in amptelike dokumentasie K8s. In wat volg sal ek probeer om die onderwerp op 'n eenvoudiger manier te verduidelik.

So, ouditering moontlik te maak, moet ons drie vereiste parameters aan die houer in api-bediener deurgee, wat hieronder in meer besonderhede beskryf word:

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

Benewens hierdie drie vereiste parameters, is daar baie bykomende instellings wat met ouditering verband hou: van logrotasie tot webhookbeskrywings. Voorbeeld van log rotasie parameters:

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

Maar ons sal nie in meer besonderhede daaroor uitwei nie - jy kan al die besonderhede in vind kube-apiserver dokumentasie.

Soos reeds genoem, word alle parameters in die manifes gestel met die api-bediener-konfigurasie (by verstek /etc/kubernetes/manifests/kube-apiserver.yaml), in die afdeling command. Kom ons gaan terug na die 3 vereiste parameters en ontleed dit:

  1. audit-policy-file - die pad na die YAML-lêer met 'n beskrywing van die beleid (beleid) van die oudit. Ons sal terugkeer na die inhoud daarvan, maar vir eers sal ek daarop let dat die lêer leesbaar moet wees deur die api-bediener proses. Daarom moet u dit binne die houer monteer, waarvoor u die volgende kode by die toepaslike afdelings van die konfigurasie kan voeg:
      volumeMounts:
        - mountPath: /etc/kubernetes/policies
          name: policies
          readOnly: true
      volumes:
      - hostPath:
          path: /etc/kubernetes/policies
          type: DirectoryOrCreate
        name: policies
  2. audit-log-path - pad na die loglêer. Die pad moet ook beskikbaar wees vir die api-bediener proses, so ons beskryf die montering daarvan op dieselfde manier:
      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 - oudit log formaat. Die verstek is json, maar die ou teksformaat is ook beskikbaar (legacy).

Ouditbeleid

Nou oor die genoemde lêer met 'n beskrywing van die aantekenbeleid. Die eerste konsep van 'n ouditbeleid is level, logvlak. Hulle is soos volg:

  • None - moenie aanteken nie;
  • Metadata - log versoek metadata: gebruiker, versoek tyd, teiken hulpbron (peul, naamruimte, ens.), aksie tipe (werkwoord), ens.;
  • Request - log metadata en versoek liggaam;
  • RequestResponse - log metadata, versoek liggaam en reaksie liggaam.

Die laaste twee vlakkeRequest и RequestResponse) moenie versoeke aanteken wat nie toegang tot hulpbronne verkry het nie (verwysings na die sogenaamde nie-hulpbronne-url's).

Ook, alle versoeke gaan deur verskeie stadiums:

  • RequestReceived - die stadium wanneer die versoek deur die hanteerder ontvang word en nog nie verder langs die ketting van hanteerders oorgedra is nie;
  • ResponseStarted - Die antwoordopskrifte word gestuur, maar voordat die antwoordliggaam gestuur word. Gegenereer vir langlopende navrae (byvoorbeeld, watch);
  • ResponseComplete - die reaksieliggaam is gestuur, geen verdere inligting sal gestuur word nie;
  • Panic — Gebeurtenisse word gegenereer wanneer 'n abnormale situasie opgespoor word.

Om enige stadiums oor te slaan, kan jy gebruik omitStages.

In die beleidlêer kan ons verskeie afdelings met verskillende aantekenvlakke beskryf. Die eerste pasreël wat in die polisbeskrywing gevind word, sal toegepas word.

Die kubelet-demoon luister vir 'n verandering in die manifes met die api-bediener-konfigurasie en, indien enige, herbegin die api-bedienerhouer. Maar daar is 'n belangrike detail: veranderinge in die beleidlêer sal geïgnoreer word. Nadat u veranderinge aan die beleidlêer gemaak het, sal u die api-bediener handmatig moet herbegin. Aangesien api-bediener begin is as statiese peul, span kubectl delete sal dit nie herbegin nie. Sal dit handmatig moet doen docker stop op kube-masters waar die ouditbeleid verander is:

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

Wanneer ouditering geaktiveer word, is dit belangrik om dit te onthou las verhoog op kube-apiserver. Veral die geheueverbruik vir die stoor van die navraagkonteks neem toe. Tekening begin eers nadat die antwoordopskrif gestuur is. Die las hang ook af van die opstelling van die ouditbeleid.

Beleidsvoorbeelde

Kom ons ontleed die struktuur van beleidlêers deur voorbeelde te gebruik.

Hier is 'n eenvoudige lêer policyom alles op die vlak aan te teken Metadata:

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

In beleid kan jy 'n lys gebruikers spesifiseer (Users и ServiceAccounts) en gebruikersgroepe. Byvoorbeeld, dit is hoe ons stelselgebruikers sal ignoreer, maar alles anders op die vlak sal aanteken 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

Dit is ook moontlik om die teiken te beskryf:

  • naamruimtes (namespaces);
  • Werkwoorde (werkwoorde: get, update, delete en ander);
  • hulpbronne (hulpbronnenaamlik: pod, configmaps ens.) en hulpbrongroepe (apiGroups).

Gee aandag! Hulpbronne en hulpbrongroepe (API-groepe, d.w.s. apiGroups), sowel as hul weergawes wat in die groep geïnstalleer is, kan verkry word deur die opdragte te gebruik:

kubectl api-resources
kubectl api-versions

Die volgende ouditbeleid word verskaf as 'n demonstrasie van die beste praktyke in Alibaba Wolk-dokumentasie:

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

Nog 'n goeie voorbeeld van 'n ouditbeleid is profiel wat in GCE gebruik word.

Vir vinnige reaksie op ouditgebeure, is dit moontlik om beskryf webhook. Hierdie vraag word gedek in amptelike dokumentasieEk sal dit buite die bestek van hierdie artikel laat.

Resultate van

Die artikel verskaf 'n oorsig van die basiese sekuriteitsmeganismes in Kubernetes-klusters wat dit moontlik maak om gepersonaliseerde gebruikersrekeninge te skep, hul regte te skei en hul handelinge aan te teken. Ek hoop dit sal nuttig wees vir diegene wat in teorie of reeds in die praktyk met sulke kwessies gekonfronteer word. Ek beveel ook aan dat u uself vertroud maak met die lys van ander materiaal oor die onderwerp van sekuriteit in Kubernetes, wat in "PS" gegee word, miskien sal u onder hulle die nodige besonderhede vind oor die probleme wat vir u relevant is.

PS

Lees ook op ons blog:

Bron: will.com

Voeg 'n opmerking