BÖLÜM 2 - KUBERNETES ZAFİYETLERİNİ TESPİT ETMEK VE GÜVENLİĞİ SAĞLAMAK
Bir önceki bölümde, Kubernetes mimarisini inceledik ve yazılım bileşenlerinde ve ayarlarında bulunabilecek bir kaç tür güvenlik zafiyetleri hakkında konuştuk. Şimdi, Kubernetes güvenlik zafiyetlerinin nasıl tespit edileceği ve onlardan nasıl iyi bir şekilde korunabileceğimiz hakkında konuşalım.
K8S ayarlarındaki güvenlik zafiyeti aramak çok mantıklı değildir, çünkü hangi sürümün hangi zafiyeti olduğunu, ayarlarda hangi hataların bulunabileceğini ve çok daha fazlasını bilmeniz gerekir. Güvenlik zafiyeti tarayıcılarını kullanarak otomatik olarak güvenlik zafiyetlerini aramak çok daha uygundur. Örnek olarak bu tür tarayıcılardan birkaç projeden bahsedeceğiz.
kube-bench Scanner
Kube-bench, Kubernetes altyapısının ne kadar güvenli olduğunu kontrol etmek için tasarlanmıştır. Bu kontrol için doğrulama kriterleri olarak CIS Kubernetes Benchmark belgesini referans alır. İlerde “Kubernestes güvenliği nasıl sağlanır” hakkında konuşurken bu belge hakkında daha fazla konuşacağız, ancak şimdilik tarayıcılara bakalım.
Kube-bench'te, kontrol için YAML dosyaları aracılıyla ayarlanan özel testler kullanılır. Kube-Bench varsayılan olarak, Kubernetes'in çalıştırılmış sürümünü otomatik olarak belirlemeye ve CIS Benchmark'ın ilgili sürümüyle karşılaştırmaya çalışıyor. Örneğin, Kubernetes 1.15 sürümü, Kubernetes 1.15 için geçerli olan CIS cis-1.15'in referans sürümü ile karşılaştırılır.
Bu araç ayrıca hangi testlerin başlatılması gerektiğini anlamak için K8S sunucunda başlatılan bileşenleri tanımlamaya çalışıyor (örneğin, ana node testlerini yalnızca API sunucusu başlatılırsa başlatılsın)..
Bu araç, pod'un içinde ayrı bir görev olarak başlatılabilir, ancak çalışan işlemleri kontrol etmek için PID ana bilgisayar isimler alanına erişmenin yanı sıra yapılandırma dosyalarının ve diğer dosyaların saklandığı ana bilgisayardaki bazı kataloglara erişmesi gerekir.
Örnek olarak, kontrolleri görev olarak gerçekleştirmek için kullanılabilecek bir "job.yaml" dosyası hazırlayacağız. Bu dosyadan daha fazla anlayabileceğiniz gibi, çalışmak için birkaç harici katalog monte etmesi gerekecektir.
Kod:
---
apiVersion: batch/v1
kind: Job
metadata:
name: kube-bench
spec:
template:
metadata:
labels:
app: kube-bench
spec:
containers:
- command: ["kube-bench"]
image: docker.io/aquasec/kube-bench:v0.6.17
name: kube-bench
volumeMounts:
- mountPath: /var/lib/etcd
name: var-lib-etcd
readOnly: true
- mountPath: /var/lib/kubelet
name: var-lib-kubelet
readOnly: true
- mountPath: /var/lib/kube-scheduler
name: var-lib-kube-scheduler
readOnly: true
- mountPath: /var/lib/kube-controller-manager
name: var-lib-kube-controller-manager
readOnly: true
- mountPath: /etc/systemd
name: etc-systemd
readOnly: true
- mountPath: /lib/systemd/
name: lib-systemd
readOnly: true
- mountPath: /srv/kubernetes/
name: srv-kubernetes
readOnly: true
- mountPath: /etc/kubernetes
name: etc-kubernetes
readOnly: true
- mountPath: /usr/local/mount-from-host/bin
name: usr-bin
readOnly: true
- mountPath: /etc/cni/net.d/
name: etc-cni-netd
readOnly: true
- mountPath: /opt/cni/bin/
name: opt-cni-bin
readOnly: true
hostPID: true
restartPolicy: Never
volumes:
- hostPath:
path: /var/lib/etcd
name: var-lib-etcd
- hostPath:
path: /var/lib/kubelet
name: var-lib-kubelet
- hostPath:
path: /var/lib/kube-scheduler
name: var-lib-kube-scheduler
- hostPath:
path: /var/lib/kube-controller-manager
name: var-lib-kube-controller-manager
- hostPath:
path: /etc/systemd
name: etc-systemd
- hostPath:
path: /lib/systemd
name: lib-systemd
- hostPath:
path: /srv/kubernetes
name: srv-kubernetes
- hostPath:
path: /etc/kubernetes
name: etc-kubernetes
- hostPath:
path: /usr/bin
name: usr-bin
- hostPath:
path: /etc/cni/net.d/
name: etc-cni-netd
- hostPath:
path: /opt/cni/bin/
name: opt-cni-bin
Bu görevi aşağıdaki gibi çalıştırmak mümkündür:
Kod:
$ kubectl apply -f job.yaml
job.batch/kube-bench created
Ardından, pod'un başlama durumunu kontrol edelim:
Kod:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kube-bench-j76s9 0/1 ContainerCreating 0 3s
Birkaç saniye sonra, pod'un çalışıp çalışmadığını kontrol ediyoruz:
Kod:
# Wait for a few seconds for the job to complete
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kube-bench-j76s9 0/1 Completed 0 11s
Ve pod'un loglarında tarama sonuçlarına bakıyoruz:
Kod:
# The results are held in the pod's logs
kubectl logs kube-bench-j76s9
[INFO] 1 Master Node Security Configuration
[INFO] 1.1 API Server
...
Aşağıdaki görsel, kube-bench kullanarak K8s'in gerçek bir taramasının sonuçlarını göstermektedir.
Checkov Scanner
Kube-bench, doğrudan Kubernetes görevi olarak çalışan küçük bir araçtı, Checkov Scanner ise çok daha güçlü bir araçtır.
Checkov sadece Kubernetes Manifesto'yu kontrol etmekle kalmaz, aynı zamanda public kaynakları gibi yanlış altyapı ayarlarını tanımlamanıza da izin verir ve ayrıca cloud altyapısının en iyi güvenlik süreçlerini gerçekleştirmenize de yardımcı olur.
Örneğin, Kubernetes manifest kontrolleri kullanarak, Kubernetes kaynaklarının güvenliğini sağlamak ve fazla izinleri olan konteynerler, imajların yaşam döngüsünün yanlış metodları, yanlış QoS kurulumu, performans testi vb. gibi problemleri tanımlayabilirsiniz.
Checkov, 50 node'a kadar küçük kuruluşlar için tasarlanmış ücretsiz bir editleme aracına sahiptir. Daha fazla sayıda node için, tarayıcının Bridgecrew'un bulut hizmeti ile etkileşime girdiği ücretli editleme araçlarının kullanılması önerilir. Ücretli editleme araçları sadece güvenlik açıklarını otomatik olarak tanımlamanıza değil, aynı zamanda ortadan kaldırmanıza da yardımcı olacaktır. Boylece tam zafiyet kontrol döngüsünü sağlayabilirsiniz.
Hadi kurup kullanmaya başlayalım.
Checkov Scanner Kurulumu:
Kod:
pip install checkov
Ardından, taramayı çalıştıracağız:
Kod:
checkov -l --framework kubernetes
Birkaç örnek kullanarak tarayıcının nasıl çalıştığını görelim.
Kod:
git clone https://github.com/kubernetes/examples
checkov -d examples/
Kontrollerin sonucu, CIS Kubernetes Benchmark'tan bir test listesi ve bu testlerin kontrol sonuçlarıdır. Aşağıdaki parçada, kontrolün başarılı geçtiğini ve iki güvenlik açığını görüyoruz. Her biri için JSON dosyasının sorunu olan bir parçası verilmiştir:
Kod:
…
kubernetes scan results:
Passed checks: 1650, Failed checks: 2502, Skipped checks: 0
Check: CKV_K8S_27: "Do not expose the docker daemon socket to containers"
PASSED for resource: Deployment.selenium-hub.default
File: /staging/selenium/selenium-hub-deployment.yaml:1-37
Check: CKV_K8S_8: "Liveness Probe Should be Configured"
FAILED for resource: Pod.mongo.default (container 0)
File: /staging/meteor/mongo-pod.json:22-36
22 | {
23 | "name": "mongo",
24 | "image": "mongo:latest",
25 | "ports": [
26 | {
27 | "name": "mongo",
28 | "containerPort": 27017
29 | }
30 | ],
31 | "volumeMounts": [
32 | {
33 | "name": "mongo-disk",
34 | "mountPath": "/data/db"
35 | }
36 | ]
Check: CKV_K8S_12: "Memory requests should be set"
FAILED for resource: Pod.mongo.default (container 0)
File: /staging/meteor/mongo-pod.json:22-36
22 | {
23 | "name": "mongo",
24 | "image": "mongo:latest",
25 | "ports": [
26 | {
27 | "name": "mongo",
28 | "containerPort": 27017
29 | }
30 | ],
31 | "volumeMounts": [
32 | {
33 | "name": "mongo-disk",
34 | "mountPath": "/data/db"
35 | }
36 | ]
Örneğin, Kubernetes çalışma ortamında belirli bir servis kullanılmadığı durumlarda gereksiz kontroller devre dışı bırakılabilir.
Kod:
checkov -d . --skip-check CKV_AWS_20
KUBERNETES GÜVENLİĞİ
Yukarıda açıklanan iki araca ek olarak, internette birçok benzer yardımcı araçlar bulabilirsiniz. Ama şimdi K8s güvenliği nasıl sağlanacağına geçelim.
CIS Kubernetes Benchmark belgesinden başlayalım. Bu belgedeki Kubernetes ile ilgili ana maddeler aşağıdaki gibidir:
- Enable Kubernetes Role-Based Access Control (RBAC)
- Use Third-Party Authentication for API Server.
- Protect etcd with TLS, Firewall and Encryption.
- Isolate Kubernetes Nodes.
- Monitor Network Traffic to Limit Communications.
- Use Process Whitelisting.
- Turn on Audit Logging.
- Keep Kubernetes Version Up to Date.
- Lock Down Kubelet
Role-Based Access Control (RBAC)
Role-Based Access Control (RBAC), Kubernetes API'ına kimin erişimi olduğunu ve hangi izinlerinin olduğunu belirlemenize yardımcı olmaktadır. Kubernetes 1.6 ve üst versiyonlarda RBAC genellikle varsayılan olarak çalışır. Kubernetes, yetkilendirme denetleyicilerini birleştirdiğinden dolayı, RBAC'yi açarken, attribute'lara göre olan eski erişim kontrolünü (ABAC) kapatmak gerekir.
RBAC kullanırken, ad alanına özgü izinleri tercih edin, tüm cluster için olan izinler değil. Hata ayıklama yaparken bile, cluster yöneticisinin haklarını vermeyin. Sadece özel ve gerektiren durumunda erişime izin vermek daha güvenlidir.
RBAC'ı çalıştırmak için, aşağıdaki örnekte gibi Flag-Enthorization modu bayrağıyla API sunucusunu başlatmanız gerekir:
Kod:
kube-apiserver --authorization-mode=Example,RBAC --other-options --more-options
İşte bir pod'un varsayılan ad alanı için okuma hakları sağlamak adına kullanılabilecek bir rol belirleme örneği:
Kod:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
Buradaki bağlantıdan rol ayarları hakkında daha fazla bilgi edinebilirsiniz.
Third-Party Authentication for API Server
Kubernetes'i üçüncü taraf kimlik doğrulama tedarikçisiyle entegre etmeniz önerilir. Bu, çok faktörlü kimlik doğrulama gibi ek güvenlik işlevleri sağlar ve Kube-Appiserver'ın kullanıcı eklerken veya kaldırırken değişmediğini garanti eder. Mümkünse, kullanıcı yönetiminin API düzeyinde gerçekleştirilmediğinden emin olun. OAuth 2.0 protokolünü ve DEX sağlayıcısını da kullanabilirsiniz.
ETCD Güvenliği
ETCD, cluster'ın durumunu kaydetmek için kullanılan anahtarların değerlerini tutan dağıtılmış bir deposudur. ETC, kümenin durumunu ve gizli verilerini depoladığından, saldırganlar için hassas bir kaynak ve çekici bir hedeftir. Yetkisiz kullanıcılar ETCD'ye erişirse, tüm kümeyi ele geçirebilirler. Okuma yetkisi de bir tehlikedir, çünkü saldırganlar bunu yetkilerini yükseltmek için kullanabilirler.
ETCD için TLS'deki Client-Server etkileşimini yapılandırmak için aşağıdaki yapılandırma parametrelerini kullanın:
- "cert-file=" : TLS için kullanılan sertifika
- "--key-file=" : şifrelenmemiş bir sertifika anahtarı
- "--client-cert-auth" : ETCD'nin güvenilir CA'in varlığını kontrol etmek için HTTPS uygulamalarını kontrol etmesi gerektiğini belirtir
- "--trusted-ca-file=<path>" : Güvenilen Sertifikasyon Merkezi
- "--auto-tls" : Client bağlantıları için özel imzalanmış bir sertifika kullanın
ETCD Server-Server bağlantılarında TLS'yi yapılandırmak için aşağıdaki ayarları kullanın:
- "--peer-cert-file=<path>" : Sunucular arasındaki SSL/TLS bağlantıları için kullanılan sertifika
- "--peer-key-file=<path>" : Şifrelenmemiş bir sertifika anahtarı
- "--peer-client-cert-auth" : Bu seçenek işaretlendiğinde, ETCD, gelen tüm istekler için istemci sertifikalarının imzalarının geçerliliğini kontrol eder
- "--peer-trusted-ca-file=<path>" : Güvenilen Sertifikasyon Merkezi
- "--peer-abo-tls" : Point to Point bağlantı tipi için otomatik olarak oluşturulan özel imzalanmış sertifika kullanın
Kubernetes Node İzolasyonu
K8S ağ mimarisini oluştururken, Kubernetes node'larının ayrı bir ağda bulunması ve doğrudan genel ağlara bağlanmaması gerektiği unutulmamalıdır. Daha da iyisi, ortak bir kurumsal ağa doğrudan bağlantılardan kaçının. Ancak bunun için, Kubernetes trafiğini ayrı alt ağları ve bunları birbirinden izole eden veri trafiğini tamamen parçalamak gerekir. Bu, trafiğin ayrı alt ağlara bölünmesi ile aralıklar arası katmanda ACL oluşturulması kullanılarak yapılabilir. Ağ politikalarının kurulmasına ilişkin daha fazla ayrıntı aşağıdaki belgede okunabilir.
https://kubernetes.io/docs/concepts/services-networking/network-policies/
Ağ Trafiğini İzlemek
Konteyner uygulamaları genellikle cluster ağları kullanır. Aktif ağ trafiğini gözlemleyin ve uygulamanızın nasıl etkileşime girdiğini ve anormal iletişimleri tanımlamak için Kubernetes ağ politikasının izin verdiği trafikle karşılaştırın.
Aynı zamanda, aktif trafiği izin verilen trafikle karşılaştırırsanız, cluster'ın aktif olarak iş yükleri kullanılmayan ağ politikalarını belirleyebilirsiniz. Bu bilgiler, izin verilen ağ politikasını daha da güçlendirmek, saldırının yüzeyini azaltıp gereksiz bağlantıları kaldırmak için kullanılabilir.
Process Whitelisting
İşlemler için beyaz liste, beklenmedik işlemleri tanımlamanın etkili bir yoludur. İlk olarak, uygulamanın normal davranışı sırasında başlatılan tüm işlemleri belirlemek için uygulamayı belirli bir süre gözlemlemeniz gerekir. Ardından, uygulama davranışının doğruluğunun gelecekteki analizi için bu listeyi beyaz listeniz olarak kullanabilirsiniz. Uygulamanın işlevinde bariz değişiklikler yapılmadan üçüncü taraf işlemlerin beklenmedik şekilde ortaya çıkması, uygulamada bir sorun olduğuna dair açık bir işarettir.
Denetim Günlüğünü Açma
Olağandışı veya istenmeyen API çağrılarını, özellikle başarısız kimlik doğrulama girişimlerini izlemek için denetim günlüğünün (Audit Logging) tutulması dahil edilmelidir. Yetkilendirmenin reddedilmesi, saldırganın çalınan muhasebe verilerini kullanmaya veya doğru şifreyi seçmeye çalıştığı anlamına gelebilir.
Dosyaları kube-apiserver'a aktarırken, denetim günlüğünü etkinleştirmek için -ududit-policy-file flag'ikullanabilir ve ayrıca hangi olayların kaydedilmesi gerektiğini belirleyebilirsiniz. Günlük (loglama) için aşağıdaki tutma seviyelerinden birini ayarlayabilirsiniz:
- No - sadece meta veriler
- Request - Meta verileri ve istekleri kaydeden, ancak cevapları olmayan
- Üçünü de kaydeden RequestResponse
Bileşenlerin Düzenli Olarak Güncellenmesi
Kubernetes altyapı bileşenlerini düzenli olarak güncelleyin. Bu tavsiyenin klişe olmasına rağmen, birçoğu hala onları ihmal ediyor...
Üst düzeyde, güncelleme işlemi aşağıdaki adımlardan oluşur:
- Ana kontrol node'unu günceller
- Ek kontrol node'ların güncellemeleri
- Çalışma node'larının güncellemeleri
Kubelet Agent'ını Güvenli Bir Şekilde Yapılandırın
Kubelet, modülün başlatılması için konteynerin çalışma ortamıyla etkileşime giren her node'da çalışan bir araçtır. Cluster'daki her Kubelet, modülleri başlatmak, durdurmak ve diğer işlemleri gerçekleştirmek için kullanabileceğiniz bir API ara yüzü sağlar. Yetkisiz bir kullanıcı bu API'ya (herhangi bir node'da) erişim kazanırsa ve kodu cluster'da çalıştırabilirse, tüm kümeyi tehlikeye atabilir.
İşte Kubelet'i korumak için gerçekleştirilebilecek ana eylemler:
- "--anonymous-auth=false" kullanarak anonim erişimin bağlantısını kesin, böylece güvenlik kontrolünü geçmeyen isteklere hata döner. Bunu yapmak için API sunucusu kendini Kubelet ile özdeşleştirmelidir. Bu, "-kubelet-clientcertificate" ve "--kubelet-client-key" flag'leri eklenerek yapılabilir.
- "--authorization mode" parametresine, gelen tüm isteklerin yetkilendirilmesini sağlamak için AlwaysAllow'dan, farklı bir değer ayarlamalıdır.
- Kubelet yetkilerini sınırlandırmak için API "server -admission-control" parametresine NodeRestriction ekleyin. Bu, yalnızca Kubelet'in kendi node nesnesine bağlı modülleri değiştirmesini sağlar.
- Yalnızca okuma için mevcut olan portlarını kapatmak için "--read-only-port=0" ekleyin. Bu, anonim kullanıcıların gerçekleştirilen iş yükü hakkında bilgisine erişimini önler. Bu port, saldırganların cluster'da değişiklik yapmasına izin vermez, ancak saldırının keşif aşamasında kullanılabilir.
- Kubernetes'in eski sürümlerinde ölçüm sağlamak için kullanılan ve yerini Kubernetes API istatistiklerine bırakan cAdvisor seçeneğini devre dışı bırakın. Çalışan iş yükleriyle ilgili bilgilerin ifşa edilmesini önlemek için "-cadvisor-port=0" değerini ayarlayın. Bu, Kubernetes v1.11 için varsayılandır.
Kubernetes Güvenliği serisi 2 bölümden oluşmakta olup burada sonlanmıştır, umarız faydalı olmuştur.