Turvallisuuden ABC Kubernetesissa: todennus, valtuutus, tarkastus

Turvallisuuden ABC Kubernetesissa: todennus, valtuutus, tarkastus

Ennemmin tai myöhemmin minkä tahansa järjestelmän toiminnassa nousee esiin turvallisuuskysymys: autentikoinnin tarjoaminen, oikeuksien erottaminen, auditointi ja muut tehtävät. Kubernetesille jo rakennettu monia ratkaisuja, joiden avulla voit saavuttaa standardien noudattamisen myös erittäin vaativissa ympäristöissä ... Sama materiaali on omistettu sisäänrakennetuissa K8s-mekanismeissa toteutettaville perusturvallisuusnäkökohdille. Ensinnäkin siitä on hyötyä niille, jotka ovat aloittamassa tutustumista Kubernetesiin - lähtökohtana turvallisuuteen liittyvien asioiden tutkimiseen.

todennus

Kubernetesissa on kahdenlaisia ​​käyttäjiä:

  • Palvelun tilit - Kubernetes API:n hallinnoimat tilit;
  • käyttäjät - "normaalit" käyttäjät, joita hallinnoivat ulkoiset, riippumattomat palvelut.

Suurin ero näiden tyyppien välillä on, että Kubernetes API:ssa on erikoisobjekteja palvelutileille (niitä kutsutaan näin - ServiceAccounts), jotka on sidottu nimiavaruuteen ja valtuutustietojen joukkoon, jotka on tallennettu klusteriin Secrets-tyyppisissä objekteissa. Tällaiset käyttäjät (palvelutilit) on tarkoitettu pääasiassa hallitsemaan Kubernetes-klusterissa käynnissä olevien prosessien Kubernetes API:n käyttöoikeuksia.

Tavallisilla käyttäjillä sitä vastoin ei ole merkintöjä Kubernetes API:ssa: niitä täytyy hallita ulkoisilla mekanismeilla. Ne on tarkoitettu klusterin ulkopuolella asuville ihmisille tai prosesseille.

Jokainen API-pyyntö on sidottu joko palvelutiliin tai käyttäjään tai sitä pidetään nimettömänä.

Käyttäjän todennustiedot sisältävät:

  • Käyttäjätunnus — käyttäjätunnus (kirjainkoolla on merkitystä!);
  • UID - koneellisesti luettava käyttäjätunnusmerkkijono, joka on "yhtenäisempi ja yksilöllisempi kuin käyttäjätunnus";
  • Ryhmät — luettelo ryhmistä, joihin käyttäjä kuuluu;
  • Lisää - lisäkenttiä, joita valtuutusmekanismi voi käyttää.

Kubernetes voi käyttää useita todennusmekanismeja: X509-varmenteita, siirtotokeneja, todennusvälityspalvelinta, HTTP-perustodennusta. Näiden mekanismien avulla voit toteuttaa suuren määrän valtuutusmalleja: staattisesta salasanatiedostosta OpenID OAuth2:een.

Lisäksi useita valtuutusjärjestelmiä voidaan käyttää samanaikaisesti. Oletusarvoisesti klusteri käyttää:

  • palvelutilitunnukset - palvelutilejä varten;
  • X509 - käyttäjille.

Palvelutilien hallinta ei kuulu tämän artikkelin piiriin, ja niille, jotka haluavat lisätietoja tästä ongelmasta, suosittelen aloittamaan viralliset asiakirjasivut. Tarkastellaan lähemmin X509-varmenteiden myöntämistä.

Varmenteet käyttäjille (X.509)

Klassinen tapa työskennellä sertifikaattien kanssa sisältää:

  • avaimen sukupolvi:
    mkdir -p ~/mynewuser/.certs/
    openssl genrsa -out ~/.certs/mynewuser.key 2048
  • varmennepyynnön luominen:
    openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company"
  • varmennepyynnön käsittely Kubernetes-klusterin CA-avaimilla, käyttäjävarmenteen hankkiminen (varmenteen saamiseksi on käytettävä tiliä, jolla on pääsy Kubernetes-klusterin CA-avaimeen, joka oletuksena sijaitsee /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
  • konfigurointitiedoston luominen:
    • klusterin kuvaus (määritä tietyn klusterin asennuksen CA-varmennetiedoston osoite ja sijainti):
      kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443
    • vai miten eisuositeltu vaihtoehto - et voi määrittää juurivarmennetta (kubectl ei tarkista klusterin api-palvelimen oikeellisuutta):
      kubectl config set-cluster kubernetes  --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443
    • käyttäjän lisääminen asetustiedostoon:
      kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt  --client-key=.certs/mynewuser.key
    • kontekstin lisääminen:
      kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser
    • oletuskontekstin määritys:
      kubectl config use-context mynewuser-context

Yllä olevien manipulointien jälkeen tiedostossa .kube/config näkymän konfiguraatio luodaan:

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

Helpottaaksesi asetusten siirtämistä tilien ja palvelimien välillä on hyödyllistä muokata seuraavien avainten arvoja:

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

Voit tehdä tämän koodaamalla niissä määritetyt tiedostot base64:llä ja rekisteröimällä ne asetuksiin lisäämällä pääte avainten nimeen -data, eli otettu vastaan certificate-authority-data jne.

Sertifikaatit kubeadmilla

Vapautuksen kanssa Kubernetes 1.15 varmenteiden käsittelystä on tullut paljon helpompaa sen tuen alfaversion ansiosta kubeadm-apuohjelma. Esimerkiksi tältä käyttäjäavaimia sisältävän asetustiedoston luominen voi näyttää nyt:

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

NB: Edellytetään mainosta osoite voidaan tarkastella api-server-kokoonpanossa, joka sijaitsee oletuksena /etc/kubernetes/manifests/kube-apiserver.yaml.

Tuloksena oleva konfiguraatio tulostetaan stdout-tiedostoon. Se on säilytettävä sisällä ~/.kube/config käyttäjätiliin tai ympäristömuuttujassa määritettyyn tiedostoon KUBECONFIG.

Kaivaa syvemmälle

Niille, jotka haluavat tarkastella kuvattuja asioita tarkemmin:

Lupa

Valtuutetulla tilillä ei ole oletusarvoisesti oikeuksia toimia klusterissa. Lupien myöntämiseksi Kubernetes ottaa käyttöön valtuutusmekanismin.

Ennen versiota 1.6 Kubernetes käytti valtuutustyyppiä nimeltä ABAC (Attribuuttipohjainen pääsynhallinta). Yksityiskohdat siitä löytyy osoitteesta virallinen dokumentaatio. Tätä lähestymistapaa pidetään tällä hetkellä vanhana, mutta voit silti käyttää sitä samanaikaisesti muiden valtuutustyyppien kanssa.

Varsinaista (ja joustavampaa) tapaa erottaa klusterin käyttöoikeudet kutsutaan RBAC (Roolipohjainen kulunvalvonta). Se on julistettu vakaaksi versiosta lähtien Kubernetes 1.8. RBAC toteuttaa oikeusmallin, joka kieltää kaiken, mikä ei ole nimenomaisesti sallittua.
Ota RBAC käyttöön, sinun on käynnistettävä Kubernetes api-server parametrilla --authorization-mode=RBAC. Parametrit asetetaan luettelossa api-palvelinkokoonpanolla, joka oletuksena sijaitsee polun varrella /etc/kubernetes/manifests/kube-apiserver.yaml, osiossa command. Oletusarvon mukaan RBAC on kuitenkin jo käytössä, joten todennäköisesti sinun ei pitäisi huolehtia siitä: voit varmistaa tämän arvolla authorization-mode (jo mainitussa kube-apiserver.yaml). Muuten, sen arvojen joukossa voi olla muun tyyppisiä valtuuksia (node, webhook, always allow), mutta jätämme niiden tarkastelun materiaalin ulkopuolelle.

Olemme muuten jo julkaisseet Artikkeli jossa on melko yksityiskohtainen tarina RBAC:n kanssa työskentelyn periaatteista ja ominaisuuksista, joten rajoitan edelleen lyhyeen luetteloon perusteista ja esimerkeistä.

Seuraavia API-kokonaisuuksia käytetään hallitsemaan pääsyä Kubernetesiin RBAC:n kautta:

  • Role и ClusterRole - käyttöoikeuksia kuvaavat roolit:
  • Role voit kuvata nimiavaruuden oikeuksia;
  • ClusterRole - klusterin sisällä, mukaan lukien klusterikohtaiset objektit, kuten solmut, ei-resurssien URL-osoitteet (eli eivät liity Kubernetes-resursseihin - esim. /version, /logs, /api*);
  • RoleBinding и ClusterRoleBinding - käytetään sitomiseen Role и ClusterRole käyttäjälle, käyttäjäryhmälle tai ServiceAccountille.

Role- ja RoleBinding-oliot ovat nimiavaruuteen sidottuja, ts. on oltava samassa nimiavaruudessa. RoleBinding voi kuitenkin viitata ClusterRoleen, jonka avulla voit luoda joukon yleisiä käyttöoikeuksia ja hallita pääsyä niillä.

Roolit kuvaavat oikeuksia käyttämällä sääntöjoukkoja, jotka sisältävät:

  • API-ryhmät - katso virallinen dokumentaatio apiGroupsin ja lähdön kautta kubectl api-resources;
  • resurssit (resurssit: pod, namespace, deployment ja niin edelleen.);
  • Verbit (verbit: set, update jne.).
  • resurssien nimet (resourceNames) - tapaukseen, jossa sinun on annettava pääsy tiettyyn resurssiin, ei kaikkiin tämäntyyppisiin resursseihin.

Kubernetesin valtuutuksen tarkempi erittely löytyy sivulta virallinen dokumentaatio. Sen sijaan (tai pikemminkin tämän lisäksi) annan esimerkkejä, jotka havainnollistavat sen toimintaa.

Esimerkkejä RBAC-kokonaisuuksista

yksinkertainen Role, jonka avulla voit saada luettelon ja tilan podista ja seurata niitä nimiavaruudessa 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"]

Esimerkki ClusterRole, jonka avulla voit saada luettelon ja tilan podista ja seurata niitä kaikkialla klusterissa:

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

Esimerkki RoleBinding, jonka avulla käyttäjä voi mynewuser "lukea" paloja nimiavaruudessa 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

Tapahtuman auditointi

Kaavamaisesti Kubernetesin arkkitehtuuri voidaan esittää seuraavasti:

Turvallisuuden ABC Kubernetesissa: todennus, valtuutus, tarkastus

Pyyntöjen käsittelystä vastaava Kubernetes-komponentti on − api-palvelin. Kaikki klusterin toiminnot kulkevat sen läpi. Voit lukea lisää näistä sisäisistä mekanismeista artikkelista "Mitä Kubernetesissa tapahtuu, kun suoritat kubectl run -ohjelman?'.

Järjestelmän tarkastus on mielenkiintoinen ominaisuus Kubernetesissa, joka on oletuksena poistettu käytöstä. Sen avulla voit kirjata kaikki puhelut Kubernetes API:lle. Kuten arvata saattaa, kaikki klusterin tilan seurantaan ja muuttamiseen liittyvät toimet suoritetaan tämän API:n kautta. Hyvä kuvaus sen ominaisuuksista löytyy (tavalliseen tapaan). virallinen dokumentaatio K8s. Seuraavassa yritän selittää aiheen yksinkertaisemmin.

Niin, auditoinnin mahdollistamiseksi, meidän on välitettävä kolme vaadittua parametria api-palvelimen säilöön, jotka kuvataan tarkemmin alla:

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

Näiden kolmen pakollisen parametrin lisäksi auditointiin liittyy monia muita asetuksia: lokin kiertämisestä webhook-kuvauksiin. Esimerkki lokin kiertoparametreista:

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

Mutta emme käsittele niitä tarkemmin - löydät kaikki yksityiskohdat täältä kube-apiserver -dokumentaatio.

Kuten jo mainittiin, kaikki parametrit asetetaan luettelossa api-palvelimen kokoonpanolla (oletuksena /etc/kubernetes/manifests/kube-apiserver.yaml), osiossa command. Palataan kolmeen vaadittuun parametriin ja analysoidaan niitä:

  1. audit-policy-file - polku YAML-tiedostoon, jossa on kuvaus tarkastuksen käytännöstä (käytännöstä). Palaamme sen sisältöön, mutta toistaiseksi huomautan, että api-palvelinprosessin on voitava lukea tiedoston. Siksi sinun on asennettava se säiliön sisään, jota varten voit lisätä seuraavan koodin konfiguroinnin asianmukaisiin osiin:
      volumeMounts:
        - mountPath: /etc/kubernetes/policies
          name: policies
          readOnly: true
      volumes:
      - hostPath:
          path: /etc/kubernetes/policies
          type: DirectoryOrCreate
        name: policies
  2. audit-log-path - polku lokitiedostoon. Polun on oltava myös api-palvelinprosessin käytettävissä, joten kuvaamme sen asennuksen samalla tavalla:
      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 — tarkastuslokin muoto. Oletus on json, mutta myös vanha tekstimuoto on saatavilla (legacy).

Tarkastuspolitiikka

Nyt mainitusta tiedostosta, jossa on kuvaus lokikäytännöstä. Ensimmäinen tilintarkastuspolitiikan käsite on level, kirjaustaso. Ne ovat seuraavat:

  • None - älä kirjaudu;
  • Metadata — lokipyynnön metatiedot: käyttäjä, pyynnön aika, kohderesurssi (pod, nimiavaruus jne.), toimintotyyppi (verbi) jne.;
  • Request - lokin metatiedot ja pyynnön runko;
  • RequestResponse - lokin metatiedot, pyynnön runko ja vastauksen runko.

Kaksi viimeistä tasoaRequest и RequestResponse) älä kirjaa pyyntöjä, jotka eivät käyttäneet resursseja (viittaukset niin kutsuttuihin ei-resurssien URL-osoitteisiin).

Lisäksi kaikki pyynnöt menevät läpi useita vaiheita:

  • RequestReceived - vaihe, jolloin käsittelijä vastaanottaa pyynnön, eikä sitä ole vielä siirretty eteenpäin käsittelijöiden ketjussa;
  • ResponseStarted - Vastauksen otsikot lähetetään, mutta ennen vastaustekstin lähettämistä. Luotu pitkiä kyselyitä varten (esim. watch);
  • ResponseComplete - vastauselin on lähetetty, enempää tietoja ei lähetetä;
  • Panic — Tapahtumat luodaan, kun havaitaan epänormaali tilanne.

Voit ohittaa vaiheet käyttämällä omitStages.

Käytäntötiedostossa voimme kuvata useita osioita eri kirjaustasoilla. Käytännön kuvauksesta löydettyä ensimmäistä vastaavaa sääntöä sovelletaan.

Kubelet-daemon kuuntelee muutosta manifestissa api-palvelinkokoonpanon kanssa ja käynnistää api-palvelinsäilön, jos sellainen on, uudelleen. Mutta on tärkeä yksityiskohta: käytäntötiedoston muutokset ohitetaan. Kun olet tehnyt muutoksia käytäntötiedostoon, sinun on käynnistettävä api-palvelin uudelleen manuaalisesti. Koska api-palvelin käynnistetään nimellä staattinen pod, tiimi kubectl delete ei käynnistä sitä uudelleen. Se on tehtävä manuaalisesti docker stop kube-mastereissa, joiden tarkastuskäytäntöä on muutettu:

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

Auditointia sallittaessa on tärkeää muistaa tämä Kube-apiserverin kuormitus kasvaa. Erityisesti muistin kulutus kyselykontekstin tallentamiseen kasvaa. Kirjaaminen alkaa vasta, kun vastausotsikko on lähetetty. Kuorma riippuu myös tarkastuskäytännön konfiguraatiosta.

Esimerkkejä politiikasta

Analysoidaan käytäntötiedostojen rakennetta esimerkkien avulla.

Tässä on yksinkertainen tiedosto policykirjata kaikki tasolle Metadata:

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

Käytännössä voit määrittää luettelon käyttäjistä (Users и ServiceAccounts) ja käyttäjäryhmät. Esimerkiksi tällä tavalla ohitamme järjestelmän käyttäjät, mutta kirjaamme kaiken muun tasolle 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

Voit myös kuvata kohdetta:

  • nimiavaruudet (namespaces);
  • Verbit (verbit: get, update, delete ja muut);
  • resurssit (resurssit, Seuraavasti: pod, configmaps jne.) ja resurssiryhmiä (apiGroups).

Kiinnitä huomiota! Resurssit ja resurssiryhmät (API-ryhmät eli apiGroups) sekä niiden klusteriin asennetut versiot saadaan komennoilla:

kubectl api-resources
kubectl api-versions

Seuraava tarkastuspolitiikka on osoitus parhaista käytännöistä Alibaba Cloud -dokumentaatio:

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

Toinen hyvä esimerkki tilintarkastuspolitiikasta on GCE:ssä käytetty profiili.

Tarkastustapahtumiin reagoimiseksi nopeasti on mahdollista kuvaile webhookia. Tämä kysymys on käsitelty virallinen dokumentaatioJätän sen tämän artikkelin ulkopuolelle.

Tulokset

Tämä artikkeli tarjoaa yleiskatsauksen Kubernetes-klusterien perussuojausmekanismeihin, jotka mahdollistavat henkilökohtaisten käyttäjätilien luomisen, heidän oikeuksiensa erottamisen ja toimintojen kirjaamisen. Toivon, että siitä on hyötyä niille, jotka kohtaavat tällaisia ​​ongelmia teoriassa tai jo käytännössä. Suosittelen myös tutustumaan luetteloon muista Kubernetesin tietoturva-aiheisista materiaaleista, joka on annettu "PS:ssä", ehkä niiden joukosta löydät tarvittavat tiedot sinulle tärkeistä ongelmista.

PS.

Lue myös blogistamme:

Lähde: will.com

Lisää kommentti