Cluster Hardening #

Keamanan aplikasi yang berjalan di Kubernetes bergantung juga pada keamanan cluster itu sendiri. API Server yang tidak terlindungi, etcd yang bisa diakses sembarangan, atau kubelet yang mengizinkan akses anonymous adalah celah yang bisa dieksploitasi untuk mengakses seluruh cluster. Artikel ini membahas langkah-langkah hardening di level cluster — di luar aplikasi dan Pod.

Mengamankan API Server #

API Server adalah komponen yang paling banyak terekspos. Konfigurasi yang salah di sini adalah kegagalan keamanan yang fundamental.

Konfigurasi API Server yang harus diverifikasi:

1. Anonymous auth dinonaktifkan
   --anonymous-auth=false
   → Semua request harus autentikasi; tidak ada akses tanpa identitas

2. RBAC sebagai authorization mode
   --authorization-mode=Node,RBAC
   → Jangan gunakan AlwaysAllow atau ABAC

3. Admission controllers yang diaktifkan
   --enable-admission-plugins=NodeRestriction,PodSecurity,...

4. Audit logging aktif
   --audit-policy-file=/etc/kubernetes/audit-policy.yaml
   --audit-log-path=/var/log/kubernetes/audit.log

5. TLS untuk semua komunikasi
   --tls-cert-file, --tls-private-key-file (sudah default di cluster modern)
   --client-ca-file (untuk client certificate auth)

6. Etcd connection menggunakan TLS
   --etcd-certfile, --etcd-keyfile, --etcd-cafile
# Verifikasi konfigurasi API Server (self-managed cluster)
kubectl get pod kube-apiserver-<node> -n kube-system -o yaml | \
  grep -A 50 "command:"

Mengamankan Etcd #

Etcd menyimpan seluruh state cluster termasuk Secret (meski hanya base64). Akses langsung ke etcd melewati semua RBAC dan audit logging.

Proteksi etcd:

1. Akses hanya dari API Server
   Etcd harus listen hanya di loopback atau interface internal
   Port 2379 (client) dan 2380 (peer) tidak boleh accessible dari luar

2. TLS mutual authentication
   Hanya API Server dengan certificate yang tepat bisa connect ke etcd

3. Enkripsi at-rest
   Aktifkan enkripsi Secret di etcd via EncryptionConfiguration
   (dibahas di artikel Secret Management)

4. Backup terenkripsi
   Backup etcd secara regular dan simpan di tempat yang aman
   Backup mengandung semua Secret cluster — perlakukan seperti data kritikal
# Verifikasi etcd hanya listen di interface yang tepat
# Di node control plane:
ss -tlnp | grep 2379
# Harus: 127.0.0.1:2379 atau IP internal, BUKAN 0.0.0.0:2379

# Cek apakah etcd menggunakan TLS
ETCDCTL_API=3 etcdctl \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  endpoint health

Hardening Kubelet #

Kubelet berjalan di setiap node dan punya akses langsung ke container runtime. Konfigurasi default bisa terlalu permisif.

# /var/lib/kubelet/config.yaml
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authentication:
  anonymous:
    enabled: false          # nonaktifkan anonymous auth
  webhook:
    enabled: true           # autentikasi via API Server
  x509:
    clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
  mode: Webhook             # otorisasi via API Server (bukan AlwaysAllow)
readOnlyPort: 0             # nonaktifkan readonly port (port 10255)
protectKernelDefaults: true # protect kernel defaults dari modifikasi
eventRecordQPS: 5
rotateCertificates: true    # rotasi sertifikat otomatis
# Verifikasi kubelet config
ssh worker-node-1
cat /var/lib/kubelet/config.yaml

# Verifikasi readonly port tidak aktif
curl http://worker-node-1:10255/pods  # harus gagal/tidak accessible

Admission Controllers #

Admission controllers memproses request ke API Server setelah autentikasi dan otorisasi tapi sebelum objek disimpan ke etcd. Mereka bisa memvalidasi atau memodifikasi request.

Admission controllers yang direkomendasikan:

NodeRestriction:
  → Batasi kubelet agar hanya bisa modify node dan Pod yang ada di node-nya
  → Mencegah node yang dikompromis memodifikasi resource node lain

PodSecurity:
  → Enforce Pod Security Standards (Privileged/Baseline/Restricted)
  → Menggantikan PodSecurityPolicy yang sudah deprecated

ResourceQuota:
  → Pastikan Pod memiliki resource requests/limits
  → Cegah denial-of-service dari resource yang tidak terbatas

LimitRanger:
  → Set default resource limits untuk Pod yang tidak mendefinisikannya

MutatingAdmissionWebhook + ValidatingAdmissionWebhook:
  → Untuk custom policy enforcement (Kyverno, OPA/Gatekeeper)
# Cek admission plugins yang aktif
kubectl get pod kube-apiserver-<node> -n kube-system -o yaml | \
  grep "enable-admission-plugins"

Node Security #

# Minimal node hardening:

# 1. OS tetap up-to-date
apt update && apt upgrade -y   # atau yum update -y

# 2. Matikan service yang tidak dibutuhkan
systemctl disable bluetooth cups avahi-daemon

# 3. Konfigurasi firewall (hanya izinkan port Kubernetes yang dibutuhkan)
ufw allow 6443/tcp   # API Server
ufw allow 2379/tcp   # etcd client (hanya dari API Server)
ufw allow 10250/tcp  # kubelet API (hanya dari API Server)
ufw allow 30000:32767/tcp  # NodePort range

# 4. Nonaktifkan SSH password auth, gunakan key-based
# /etc/ssh/sshd_config:
# PasswordAuthentication no
# PermitRootLogin no

# 5. Audit tool untuk cek security posture node
lynis audit system   # atau CIS-CAT

CIS Kubernetes Benchmark #

CIS (Center for Internet Security) menerbitkan benchmark untuk Kubernetes dengan ratusan check. Gunakan kube-bench untuk automated verification:

# Jalankan kube-bench di control plane node
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml
kubectl logs job.batch/kube-bench

# Output:
# [PASS] 1.1.1 Ensure that the API server pod specification file permissions are set to 600 or more restrictive
# [FAIL] 1.1.2 Ensure that the API server pod specification file ownership is set to root:root
# [WARN] 1.2.1 Ensure that the --anonymous-auth argument is set to false
# ...
# == Summary master ==
# 42 checks PASS
# 8 checks FAIL
# 12 checks WARN

Update dan Patch Management #

Kebijakan update yang direkomendasikan:

Kubernetes version:
  → Upgrade setidaknya setiap 3-4 bulan
  → Kubernetes mendukung 3 versi minor terbaru
  → Setelah itu: security fix tidak backport

Node OS:
  → Security patch dalam 48-72 jam setelah release
  → Automated dengan unattended-upgrades atau Ansible

Container images:
  → Rebuild image secara berkala meski tidak ada perubahan kode
  → Base image update otomatis via Dependabot atau Renovate
  → Scan CVE setelah setiap build

etcd:
  → Upgrade bersamaan dengan Kubernetes (kurang lebih)
  → Selalu backup sebelum upgrade

Ringkasan #

  • API Server: nonaktifkan anonymous auth, gunakan RBAC — dua konfigurasi ini menutup celah paling fundamental; --anonymous-auth=false dan --authorization-mode=Node,RBAC.
  • Etcd tidak boleh accessible dari luar cluster — port 2379/2380 hanya untuk loopback atau interface internal; backup etcd harus diperlakukan seperti data Secret.
  • Kubelet: nonaktifkan anonymous auth dan readonly portauthentication.anonymous.enabled: false dan readOnlyPort: 0 di kubelet config.
  • Admission controllers untuk policy enforcement — NodeRestriction, PodSecurity, dan ResourceQuota adalah minimum; tambahkan Kyverno atau OPA untuk custom policy.
  • kube-bench untuk audit CIS compliance — automated check terhadap ratusan benchmark item; jalankan setelah setup dan secara berkala.
  • Update kubernetes dan node OS secara regular — security patch harus diterapkan dalam 48-72 jam; Kubernetes versi lebih dari 3 minor release ke belakang tidak mendapat security fix.

← Sebelumnya: Audit Logging   Berikutnya: Anti-Pattern Security →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact