La ABC de Sekureco en Kubernetes: Aŭtentikigo, Rajtigo, Revizio

La ABC de Sekureco en Kubernetes: Aŭtentikigo, Rajtigo, Revizio

Pli aŭ malpli frue, en la funkciado de iu sistemo, aperas la problemo de sekureco: certigi aŭtentikigon, disigon de rajtoj, revizion kaj aliajn taskojn. Jam kreita por Kubernetes multaj solvoj, kiuj ebligas al vi atingi konformecon al normoj eĉ en tre postulemaj medioj... La sama materialo estas dediĉita al la bazaj aspektoj de sekureco efektivigita ene de la enkonstruitaj mekanismoj de la K8s. Antaŭ ĉio, ĝi estos utila al tiuj, kiuj komencas konatiĝi kun Kubernetes - kiel deirpunkto por studi problemojn pri sekureco.

Aŭtentigo

Estas du specoj de uzantoj en Kubernetes:

  • Servaj Kontoj — kontoj administritaj de la Kubernetes API;
  • uzantoj — "normalaj" uzantoj administritaj de eksteraj, sendependaj servoj.

La ĉefa diferenco inter ĉi tiuj tipoj estas, ke por Servaj Kontoj estas specialaj objektoj en la Kubernetes API (ili nomiĝas tiel - ServiceAccounts), kiuj estas ligitaj al nomspaco kaj aro de rajtigaj datumoj stokitaj en la areto en objektoj de la tipo Secrets. Tiaj uzantoj (Servaj Kontoj) celas ĉefe administri alirrajtojn al la Kubernetes API de procezoj kurantaj en la Kubernetes-areo.

Ordinaraj Uzantoj ne havas enirojn en la Kubernetes API: ili devas esti administritaj per eksteraj mekanismoj. Ili estas destinitaj por homoj aŭ procezoj vivantaj ekster la areto.

Ĉiu API-peto estas asociita aŭ kun Serva Konto, Uzanto aŭ estas konsiderata anonima.

Uzantaj aŭtentikigdatenoj inkluzivas:

  • uzantonomo — uzantnomo (majusklesendebla!);
  • UID - maŝinlegebla uzant-identigĉeno kiu estas "pli konsekvenca kaj unika ol la uzantnomo";
  • Grupoj — listo de grupoj al kiuj la uzanto apartenas;
  • ekstra — pliaj kampoj uzeblaj de la rajtiga mekanismo.

Kubernetes povas uzi grandan nombron da aŭtentikigmekanismoj: X509-atestiloj, Bearer-tokens, aŭtentikiganta prokurilo, HTTP Basic Auth. Uzante ĉi tiujn mekanismojn, vi povas efektivigi grandan nombron da rajtigaj skemoj: de statika dosiero kun pasvortoj ĝis OpenID OAuth2.

Krome, eblas uzi plurajn rajtigajn skemojn samtempe. Defaŭlte, la areto uzas:

  • service account tokens - por Servaj Kontoj;
  • X509 - por Uzantoj.

La demando pri administrado de ServiceAccounts estas ekster la amplekso de ĉi tiu artikolo, sed por tiuj, kiuj volas pli detale konatiĝi kun ĉi tiu afero, mi rekomendas komenci per oficialaj dokumentaj paĝoj. Ni rigardos pli detale la aferon pri kiel funkcias X509-atestiloj.

Atestiloj por uzantoj (X.509)

La klasika maniero labori kun atestiloj implikas:

  • ŝlosila generacio:
    mkdir -p ~/mynewuser/.certs/
    openssl genrsa -out ~/.certs/mynewuser.key 2048
  • kreante atestilpeton:
    openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company"
  • prilabori atestilpeton per la Kubernetes-grupo CA-ŝlosiloj, akiri uzantan atestilon (por akiri atestilon, vi devas uzi konton, kiu havas aliron al la Kubernetes-grupo CA-ŝlosilo, kiu defaŭlte troviĝas en /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
  • kreante agordan dosieron:
    • clusterpriskribo (specifu la adreson kaj lokon de la CA-atestilo por specifa clusterinstalado):
      kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443
    • aŭ kiel nerekomendita opcio - vi ne devas specifi la radikan atestilon (tiam kubectl ne kontrolos la ĝustecon de la api-servilo de la grapolo):
      kubectl config set-cluster kubernetes  --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443
    • aldonante uzanton al la agorda dosiero:
      kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt  --client-key=.certs/mynewuser.key
    • aldonante kuntekston:
      kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser
    • defaŭlta kunteksto-tasko:
      kubectl config use-context mynewuser-context

Post la supraj manipuladoj, en la dosiero .kube/config agordo tia estos kreita:

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

Por faciligi translokigi la agordon inter kontoj kaj serviloj, estas utile redakti la valorojn de la sekvaj ŝlosiloj:

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

Por fari tion, vi povas kodi la dosierojn specifitajn en ili uzante base64 kaj registri ilin en la agordo, aldonante la sufikson al la nomo de la ŝlosiloj. -data, t.e. ricevinte certificate-authority-data ktp

Atestiloj kun kubeadm

Kun la liberigo Kubernetes 1.15 labori kun atestiloj fariĝis multe pli facila danke al la alfa versio de ĝia subteno en kubeadm ilo. Ekzemple, jen kiel generado de agorda dosiero kun uzantŝlosiloj nun povus aspekti:

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

NB: Bezonata reklami adreson troveblas en la api-servila agordo, kiu defaŭlte troviĝas en /etc/kubernetes/manifests/kube-apiserver.yaml.

La rezulta agordo estos eligita al stdout. Ĝi devas esti konservita en ~/.kube/config uzantkonto aŭ al dosiero specifita en mediovariablo KUBECONFIG.

Fosu Pli Profunde

Por tiuj, kiuj volas kompreni la aferojn priskribitajn pli detale:

Rajtigo

La defaŭlta rajtigita konto ne havas rajtojn funkcii sur la areto. Por doni permesojn, Kubernetes efektivigas rajtigan mekanismon.

Antaŭ versio 1.6, Kubernetes uzis rajtigan tipon nomitan ABAC (Atribut-bazita alirkontrolo). Detaloj pri ĝi troveblas en oficiala dokumentaro. Ĉi tiu aliro estas nuntempe konsiderata heredaĵo, sed vi ankoraŭ povas uzi ĝin kune kun aliaj aŭtentikigaj tipoj.

La nuna (kaj pli fleksebla) maniero dividi alirrajtojn al areto nomiĝas RBAC (Rol-bazita alirkontrolo). Ĝi estis deklarita stabila ekde versio Kubernetes 1.8. RBAC efektivigas rajtomodelon en kiu ĉio, kio ne estas eksplicite permesita, estas malpermesita.
Por ebligi RBAC, vi devas komenci Kubernetes api-servilon kun la parametro --authorization-mode=RBAC. La parametroj estas fiksitaj en la manifesto kun la api-servila agordo, kiu defaŭlte situas laŭ la vojo /etc/kubernetes/manifests/kube-apiserver.yaml, en sekcio command. Tamen, RBAC jam estas ebligita defaŭlte, do plej verŝajne vi ne zorgu pri ĝi: vi povas kontroli tion laŭ la valoro authorization-mode (en la jam menciita kube-apiserver.yaml). Cetere, inter ĝiaj signifoj povas esti aliaj specoj de rajtigo (node, webhook, always allow), sed ni lasos ilian konsideron ekster la amplekso de la materialo.

Cetere, ni jam publikigis artikolo kun sufiĉe detala priskribo de la principoj kaj trajtoj de laboro kun RBAC, do plu mi limigos min al mallonga listo de la bazaĵoj kaj ekzemploj.

La sekvaj API-unuoj estas uzataj por kontroli aliron en Kubernetes per RBAC:

  • Role и ClusterRole — roloj kiuj servas por priskribi alirrajtojn:
  • Role permesas vin priskribi rajtojn ene de nomspaco;
  • ClusterRole - ene de la areto, inkluzive de cluster-specifaj objektoj kiel ekzemple nodoj, ne-resursaj urloj (t.e. ne rilataj al Kubernetes-resursoj - ekzemple, /version, /logs, /api*);
  • RoleBinding и ClusterRoleBinding - uzata por ligado Role и ClusterRole al uzanto, uzantgrupo aŭ ServiceAccount.

La entoj Role kaj RoleBinding estas limigitaj de nomspaco, t.e. devas esti ene de la sama nomspaco. Tamen, RoleBinding povas referenci ClusterRole, kiu ebligas al vi krei aron de ĝeneralaj permesoj kaj kontroli aliron uzante ilin.

Roloj priskribas rajtojn uzante arojn de reguloj enhavantaj:

  • API-grupoj - vidu oficiala dokumentaro de apiGroups kaj eligo kubectl api-resources;
  • rimedoj (Rimedoj: pod, namespace, deployment kaj tiel plu.);
  • Verboj (verboj: set, update kaj tiel plu.).
  • nomoj de rimedoj (resourceNames) - por la kazo, kiam vi bezonas doni aliron al specifa rimedo, kaj ne al ĉiuj ĉi-tipaj rimedoj.

Pli detala analizo de rajtigo en Kubernetes troveblas sur la paĝo oficiala dokumentaro. Anstataŭe (aŭ pli ĝuste, krom tio ĉi), mi donos ekzemplojn, kiuj ilustras ŝian laboron.

Ekzemploj de RBAC-unuoj

Simpla Role, kiu ebligas al vi ricevi liston kaj staton de balgoj kaj kontroli ilin en la nomspaco 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"]

Ekzemplo: ClusterRole, kiu ebligas al vi akiri liston kaj statuson de balgoj kaj kontroli ilin tra la areto:

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

Ekzemplo: RoleBinding, kiu permesas al la uzanto mynewuser "legi" podojn en nomspaco 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

Eventa revizio

Skeme, la Kubernetes-arkitekturo povas esti reprezentita jene:

La ABC de Sekureco en Kubernetes: Aŭtentikigo, Rajtigo, Revizio

La ŝlosila komponanto de Kubernetes respondeca pri prilaborado de petoj estas api-servilo. Ĉiuj operacioj sur la areto trairas ĝin. Vi povas legi pli pri ĉi tiuj internaj mekanismoj en la artikolo "Kio okazas en Kubernetes kiam vi kuras kubectl run?".

Sistemreviziado estas interesa trajto en Kubernetes, kiu estas malebligita defaŭlte. Ĝi permesas vin ensaluti ĉiujn vokojn al la Kubernetes API. Kiel vi eble konjektas, ĉiuj agoj rilataj al monitorado kaj ŝanĝo de la stato de la areto estas faritaj per ĉi tiu API. Bona priskribo de ĝiaj kapabloj troveblas (kiel kutime) en oficiala dokumentaro K8s. Poste, mi provos prezenti la temon en pli simpla lingvo.

Kaj tiel, por ebligi revizion, ni devas pasi tri bezonatajn parametrojn al la ujo en api-servilo, kiuj estas priskribitaj pli detale sube:

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

Krom ĉi tiuj tri necesaj parametroj, ekzistas multaj pliaj agordoj rilataj al revizio: de protokolo-rotacio ĝis rethok-priskriboj. Ekzemplo de parametroj de tagalo-rotacio:

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

Sed ni ne pritraktos ilin pli detale - vi povas trovi ĉiujn detalojn en kube-apiserver dokumentado.

Kiel jam menciite, ĉiuj parametroj estas fiksitaj en la manifesto kun la api-servila agordo (defaŭlte /etc/kubernetes/manifests/kube-apiserver.yaml), en sekcio command. Ni revenu al la 3 bezonataj parametroj kaj analizu ilin:

  1. audit-policy-file — vojo al la YAML-dosiero priskribanta la revizian politikon. Ni revenos al ĝia enhavo poste, sed nuntempe mi rimarkos, ke la dosiero devas esti legebla per la api-servila procezo. Tial, estas necese munti ĝin ene de la ujo, por kiu vi povas aldoni la sekvan kodon al la taŭgaj sekcioj de la agordo:
      volumeMounts:
        - mountPath: /etc/kubernetes/policies
          name: policies
          readOnly: true
      volumes:
      - hostPath:
          path: /etc/kubernetes/policies
          type: DirectoryOrCreate
        name: policies
  2. audit-log-path — vojo al la protokoldosiero. La vojo ankaŭ devas esti alirebla por la api-servila procezo, do ni priskribas ĝian muntadon en la sama maniero:
      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 — formato de auditoría protokolo. La defaŭlta estas json, sed la hereda tekstformato ankaŭ haveblas (legacy).

Kontrola Politiko

Nun pri la menciita dosiero priskribanta la ensaluta politiko. La unua koncepto de reviziopolitiko estas level, registra nivelo. Ili estas kiel sekvas:

  • None - ne ensalutu;
  • Metadata — protokolo-peto-metadatumoj: uzanto, petotempo, cela rimedo (pod, nomspaco, ktp.), agotipo (verbo), ktp.;
  • Request — registri metadatumojn kaj petokorpon;
  • RequestResponse — registri metadatenojn, petokorpon kaj respondkorpon.

La lastaj du niveloj (Request и RequestResponse) ne ensalutu petojn, kiuj ne aliris rimedojn (aliroj al tiel nomataj ne-rimedaj urloj).

Ankaŭ ĉiuj petoj trairas pluraj etapoj:

  • RequestReceived — la stadio kiam la peto estas ricevita de la procesoro kaj ankoraŭ ne estis transdonita plu laŭ la ĉeno de procesoroj;
  • ResponseStarted — respondkapoj estas senditaj, sed antaŭ ol la respondkorpo estas sendita. Generita por longdaŭraj demandoj (ekzemple, watch);
  • ResponseComplete — la respondkorpo estas sendita, neniuj pliaj informoj estos senditaj;
  • Panic — okazaĵoj estas generitaj kiam nenormala situacio estas detektita.

Por salti iujn ajn paŝojn, kiujn vi povas uzi omitStages.

En politika dosiero, ni povas priskribi plurajn sekciojn kun malsamaj registradaj niveloj. La unua kongrua regulo trovita en la politika priskribo estos aplikata.

La kubelet-demono monitoras ŝanĝojn en la manifesto kun la api-servilo agordo kaj, se iuj estas detektitaj, rekomencas la ujon per api-servilo. Sed estas grava detalo: ŝanĝoj en la politika dosiero estos ignoritaj de ĝi. Post fari ŝanĝojn al la politika dosiero, vi devos rekomenci la api-servilon permane. Ĉar api-servilo estas komencita kiel statika pod, teamo kubectl delete ne kaŭzos ĝin rekomenci. Vi devos fari ĝin permane docker stop ĉe kube-masters, kie la revizia politiko estis ŝanĝita:

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

Kiam vi ebligas revizion, gravas memori tion la ŝarĝo sur kube-apiserver pliiĝas. Aparte, memorkonsumo por stokado de petokunteksto pliiĝas. Registrado komenciĝas nur post kiam la respondkapo estas sendita. La ŝarĝo ankaŭ dependas de la kontrola agordo.

Ekzemploj de politikoj

Ni rigardu la strukturon de politikaj dosieroj uzante ekzemplojn.

Jen simpla dosiero policyensaluti ĉion je la nivelo Metadata:

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

En politiko vi povas specifi liston de uzantoj (Users и ServiceAccounts) kaj uzantgrupoj. Ekzemple, jen kiel ni ignoros sistemajn uzantojn, sed ensalutu ĉion alian je la nivelo 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

Eblas ankaŭ priskribi la celojn:

  • nomspacoj (namespaces);
  • Verboj (verboj: get, update, delete kaj aliaj);
  • rimedoj (Rimedojnome: pod, configmaps ktp.) kaj rimedgrupoj (apiGroups).

Atentu! Rimedoj kaj rimedgrupoj (API-grupoj, t.e. apiGroups), same kiel iliaj versioj instalitaj en la areto, povas esti akiritaj per la komandoj:

kubectl api-resources
kubectl api-versions

La sekva revizia politiko estas provizita kiel pruvo de plej bonaj praktikoj en Alibaba Cloud-dokumentado:

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

Alia bona ekzemplo de revizia politiko estas profilo uzata en GCE.

Por rapide respondi al reviziaj eventoj, eblas priskribi rethokon. Ĉi tiu afero estas kovrita en oficiala dokumentaro, mi lasos ĝin ekster la amplekso de ĉi tiu artikolo.

Rezultoj

La artikolo provizas superrigardon pri bazaj sekurecaj mekanismoj en Kubernetes-aretoj, kiuj ebligas al vi krei personigitajn uzantkontojn, apartigi iliajn rajtojn kaj registri iliajn agojn. Mi esperas, ke ĝi estos utila al tiuj, kiuj alfrontas tiajn aferojn teorie aŭ praktike. Mi ankaŭ rekomendas, ke vi legu la liston de aliaj materialoj pri la temo de sekureco en Kubernetes, kiu estas donita en "PS" - eble inter ili vi trovos la necesajn detalojn pri la problemoj, kiuj rilatas al vi.

PS

Legu ankaŭ en nia blogo:

fonto: www.habr.com

Aldoni komenton