Czy mój Kubernetes jest bezpieczny? Czyli K8s Security 101.

Warning: DOMDocument::loadHTML(): Tag template invalid in Entity, line: 12 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag svg invalid in Entity, line: 14 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag path invalid in Entity, line: 15 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag template invalid in Entity, line: 27 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag svg invalid in Entity, line: 29 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag path invalid in Entity, line: 30 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag template invalid in Entity, line: 12 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag svg invalid in Entity, line: 14 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag path invalid in Entity, line: 15 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag template invalid in Entity, line: 27 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag svg invalid in Entity, line: 29 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag path invalid in Entity, line: 30 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag template invalid in Entity, line: 12 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag svg invalid in Entity, line: 14 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag path invalid in Entity, line: 15 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag template invalid in Entity, line: 27 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag svg invalid in Entity, line: 29 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag path invalid in Entity, line: 30 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag template invalid in Entity, line: 12 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag svg invalid in Entity, line: 14 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag path invalid in Entity, line: 15 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag template invalid in Entity, line: 27 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag svg invalid in Entity, line: 29 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466 Warning: DOMDocument::loadHTML(): Tag path invalid in Entity, line: 30 in D:\HostingSpaces\tszostak\toszo.com\wwwroot\wp-content\plugins\gistpress-develop\includes\class-gistpress.php on line 466

Instalacja klastra z jednym masterem jest bardzo łatwa i pomimo tego, że dokumentacja Kubernetes dotycząca kubeadm jest napisana w bardzo przystępny sposób to jest dość obszerna. Powodem takiej sytuacji jest oczywiście mnogość wspieranych systemów operacyjnych – RedHat family, Debian family, pluginów sieciowych – Flannel, Calico, Cannal, Cilium, Weave Net czy możliwych ustawień – jak np. proxy.

Instalacja klastra

Zakładając że kubeadm jest już zainstalowany, instalacje klastra można sprowadzić do następujących komend:

# Exec on Master
# Master init
kubeadm init --pod-network-cidr 10.244.0.0/16
# Wynikiem tej komendy będzie token (TWOJ_JOIN_TOKEN) i discovery token (TWOJ_DISCO_TOKEN), który będzie wykorzystany do dołączania worker Node'ów.
# Deployment pluginu sieciowego na Masterze.
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml
# Exec on Node
# kubeadm join <master-ip>:<master-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
kubeadm join 10.4.1.1:6443 --token TWOJ_JOIN_TOKEN --discovery-token-ca-cert-hash sha256:TWOJ_DISCO_TOKEN
view raw gistfile1.txt hosted with ❤ by GitHub

Prosta i szybka instalacja i jak twierdzi twórca dokumentacji:

kubeadm helps you bootstrap a minimum viable Kubernetes cluster that conforms to best practices

Czy dobrze korzystać z takiego klastra na produkcji? Sprawdzam.

Spec od security polecił mi jako pierwszy krok zapoznanie się z CIS – organizacją która ustanawia światowe standardy i dobre praktyki w dziedzinie bezpieczeństwa. Tak się składa, że opracowali również CIS benchmark dla Kubernetes który jest określany jako consensus-driven – czyli jest szansa na to, że zalecenia nie będą powodowały spadku wydajności klastra jak i bólu głowy Opsów którzy będą się nim opiekować.

CIS Benchmark – to dokument liczący ponad 250 stron, wiedziałem, że IT Security to trudna działka i jak widać sprawdza się to od samego początku.

Jestem wielkim zwolennikiem automatyzacji wszelkiego rodzaju i po zapoznaniu się z większością punktów z tego dokumentu stwierdziłem, że taki benchmark można zautomatyzować. Pierwszy krok, sprawdzenie czy ktoś to już zrobił … i voila!

Kube-bench – Kubernetes Security

Natrafiłem na projekt opensource kube-bench od firmy AquaSecurity który chwali się tym, że jest aplikacją sprawdzającą czy Kubernetes jest zainstalowany w bezpieczny sposób. Do dzieła!

Benchmark można uruchamiać na kilka sposobów ja wybieram ten wygodny – czyli przez kontener Docker. Dodaje informacje o lokalizacji mojego kubectl (which kubectl) oraz parametr „master” na końcu, mówiący o tym, że ten test będzie wykonywany w kontekście mastera. Dzięki temu nie muszę nic zmieniać w plikach konfiguracyjnych i polegam na domyślnej konfiguracji.

docker run --pid=host -v /etc:/etc:ro -v /var:/var:ro -t -v $(which kubectl):/usr/bin/kubectl aquasec/kube-bench:latest master

Jeśli jest to pierwsze uruchomienie tego obrazu to na pewno zostanie pobrany automatycznie z repozytorium aquasec i wyswietli długą listę sukcesów i porażek (ostrzeżeń też).

Podsumowanie kube-bench:

26 – PASS
32 – FAIL
9 – WARN

32 FAIL? Jak widać więcej niż połowa polityk tego benchmarku mówi „no go!” jeśli chodzi o bezpieczeństwo. Mam diagnozę, co dalej? Kube-bench, oprócz uruchomienia testu pokazuje co dokładnie poszło nie tak – i co najlepsze, jak to naprawić!

Przykład:

[FAIL] 1.1.1 Ensure that the --allow-privileged argument is set to false (Scored)
[FAIL] 1.1.2 Ensure that the --anonymous-auth argument is set to false (Scored)
...
== Remediations ==
1.1.1 Edit the /etc/kubernetes/apiserver file on the master node and set the KUBE_ALLOW_PRIV parameter to "--allow-privileged=false"
1.1.2 Edit the /etc/kubernetes/apiserver file on the master node and set the KUBE_API_ARGS parameter to "--anonymous-auth=false"
...

Pełny wynik testu kube-bench dla Kubernetes mastera znajdziesz tutaj.

Stosuje na początek dwie zmiany których żąda benchmark i … już tylko „30 FAILED”. 28 to go. Jeżeli się nie zgadzasz ze wszystkimi zastrzeżeniami ze strony kube-bench lub po prostu są one mało zrozumiałe – odsyłam do źródłowego benchmarku CIS na bazie którego powstała ta automatyzacja.

Kube-bench dla Node’a

Przykład powyżej dotyczy Kubernetes Mastera, który jest bardzo ważny z uwagi na funkcję którą pełni, ale warto nie zapominać o pozostałych członkach tego zespołu – Node’ach.

Tak samo jak dla Mastera można skorzystać z benchmarku w formie obrazu Docker.

sudo docker run --pid=host -v /etc:/etc:ro -v /var:/var:ro -t -v $(which kubectl):/usr/bin/kubectl aquasec/kube-bench:latest node

Wynik tutaj wygląda jeszcze ciekawiej:

4 – PASS
15 – FAIL
0 – WARN

Wynik testu kube-bench dla Kubernetes Node znajdziesz tutaj.

Podsumowanie

Wygląda na to, że podstawowa instalacja z wykorzystaniem kubeadm, która co prawda jest „minimum viable Kubernetes” ale jak widać takie minimum nie jest bardzo bezpieczne – przynajmniej nie wg. CIS Benchmark. Dobrą wiadomością jest – że łatwo zintegrować kube-bench z własnym build pipelinem, monitorować i poprawiać problemy wtedy kiedy występują.

Linki:

  1. CIS Benchmark: https://www.cisecurity.org/benchmark/kubernetes/
  2. Instalacja kubeadm: https://kubernetes.io/docs/setup/independent/install-kubeadm/
  3. Instalacja klastra Kubernetes: https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/
  4. Kube-bench: https://github.com/aquasecurity/kube-bench
  5. Wynik testu na masterze:
    https://gist.githubusercontent.com/toszo/15e1e21efc60d3dbbc5b8fe3260268da/raw/7fce77ecd914419b5462cdd33ffa12421fcb9cbd/master-sec-benchmark-result.txt
  6. Wynik testu na nodzie:
    https://gist.githubusercontent.com/toszo/a95b44d7d8843bf56890473a5268b706/raw/89fa0e5ac38638fd16ec15401897bf0df0c3fdfe/kube-bench-node.txt