Pod Security Standards adalah kumpulan kebijakan keamanan bawaan yang membatasi isi manifest Pod dengan beberapa tingkat ketegasan, dan penerapannya diatur per namespace melalui label. Standar ini memindahkan kebijakan keamanan dari penulisan security context yang bergantung pada tiap aplikasi menjadi pengaturan kluster yang menutup seluruh namespace sekaligus. Topik ini membahas tiga profil standar, tiga mode penerapan yang masing-masing memiliki reaksi berbeda, serta evaluasi Pod contoh terhadap profil restricted yang dapat dijalankan di sandbox.
Tiga profil standar#
Standar ini mendefinisikan tiga profil dengan tingkat ketegasan yang meningkat. Profil privileged tidak menerapkan batasan apa pun dan hanya tepat untuk komponen sistem yang memang membutuhkan akses host. Profil baseline melarang pengaturan yang paling istimewa, sedangkan profil restricted menuntut kebiasaan pengamanan container modern. Ketiganya dirangkum pada tabel berikut:
| Profil | Batasan inti | Peruntukan |
|---|---|---|
| privileged | tanpa batasan | komponen sistem dengan kebutuhan akses host |
| baseline | melarang privileged, hostNetwork, hostPath, dan kemampuan istimewa | aplikasi umum yang masih membutuhkan sedikit kemudahan istimewa |
| restricted | menuntut non-root, seccomp, dan drop ALL | aplikasi yang mengikuti kebiasaan pengamanan modern |
Profil restricted menuntut runAsNonRoot, seccompProfile bertipe RuntimeDefault atau Localhost, allowPrivilegeEscalation bernilai false, dan capabilities dengan drop ALL, dengan pengecualian penambahan NET_BIND_SERVICE. Definisi profil ditetapkan oleh proyek Kubernetes sehingga identik antara kluster, sedangkan kluster hanya memilih profilnya per namespace. Pemilihan ini menjadikan kebijakan dapat ditinjau dengan membaca label namespace saja, tanpa membuka manifest setiap aplikasi, dan alat pemindai keamanan dapat menilai namespace dengan asumsi yang sama seperti admission controller kluster.
Mode penerapan melalui label namespace#
Penerapan standar dilakukan oleh admission controller bawaan bernama Pod Security Admission, yaitu komponen yang menilai setiap Pod pada saat pembuatan. Pengaturannya berupa label Namespace dengan bentuk pod-security.kubernetes.io/<mode>=<level>, dan terdapat tiga mode dengan reaksi berbeda, yaitu enforce yang menolak Pod yang melanggar, audit yang merekam pelanggaran pada audit log tanpa menolak, dan warn yang menampilkan peringatan pada respons kubectl tanpa menolak. Manifest berikut menerapkan profil restricted pada namespace aplikasi-catatan:
apiVersion: v1
kind: Namespace
metadata:
name: aplikasi-catatan
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: v1.37
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restrictedLabel enforce-version berisi versi yang disematkan, pada contoh ini v1.37, yang mengunci definisi profil terhadap definisi versi tersebut. Penguncian ini menjaga agar kebijakan tidak berubah diam-diam apabila definisi profil diperbarui pada rilis kluster berikutnya. Mode audit dan warn pada manifest memungkinkan pelanggaran terlihat lebih dahulu sebelum menjadi alasan penolakan yang menghentikan pengerjaan.
Evaluasi Pod contoh terhadap profil restricted#
Manifest berikut memuat dua Pod dalam satu berkas, yaitu Pod lama yang ditulis sebelum kebijakan ada dan Pod baru yang mengikuti profil restricted:
apiVersion: v1
kind: Pod
metadata:
name: catatan-lama
namespace: aplikasi-catatan
spec:
hostNetwork: true
containers:
- name: catatan
image: busybox:1.36
command: ["sh", "-c", "sleep 3600"]
securityContext:
privileged: true
capabilities:
add: ["NET_ADMIN"]
---
apiVersion: v1
kind: Pod
metadata:
name: catatan-baru
namespace: aplikasi-catatan
spec:
securityContext:
runAsNonRoot: true
runAsUser: 65532
seccompProfile:
type: RuntimeDefault
containers:
- name: catatan
image: busybox:1.36
command: ["sh", "-c", "sleep 3600"]
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]Skrip berikut membaca label enforce namespace dan kedua Pod tersebut, lalu menilai setiap container terhadap syarat profil restricted:
"""Evaluasi pod contoh terhadap profil Pod Security Standards restricted."""
import yaml
with open("pss-namespace.yaml", encoding="utf-8") as f:
namespace = yaml.safe_load(f)
with open("pod-pss.yaml", encoding="utf-8") as f:
pods = [p for p in yaml.safe_load_all(f) if p]
label = namespace["metadata"]["labels"]
enforce = label["pod-security.kubernetes.io/enforce"]
versi = label["pod-security.kubernetes.io/enforce-version"]
print(f"Namespace {namespace['metadata']['name']} dengan enforce={enforce} (versi {versi})")
print()
# kemampuan yang dianggap terlalu istimewa pada profil restricted
CAPS_PRIVILEGED = {"NET_ADMIN", "SYS_ADMIN", "SYS_PTRACE", "SYS_BOOT", "SYS_TIME"}
def pelanggaran(pod):
hasil = []
spec = pod["spec"]
sc_pod = spec.get("securityContext", {})
if spec.get("hostNetwork") or spec.get("hostPID") or spec.get("hostIPC"):
hasil.append("host namespace tidak diizinkan (hostNetwork/hostPID/hostIPC)")
for c in spec["containers"]:
sc = c.get("securityContext", {})
if sc.get("privileged"):
hasil.append(f"privileged=true pada container {c['name']}")
if sc.get("allowPrivilegeEscalation", True):
hasil.append(f"allowPrivilegeEscalation tidak bernilai false pada container {c['name']}")
if not (sc.get("runAsNonRoot") or sc_pod.get("runAsNonRoot")):
hasil.append(f"runAsNonRoot tidak bernilai true pada container {c['name']}")
seccomp = sc.get("seccompProfile", sc_pod.get("seccompProfile", {})).get("type")
if seccomp not in ("RuntimeDefault", "Localhost"):
hasil.append(f"seccompProfile bukan RuntimeDefault atau Localhost pada container {c['name']}")
tambah = sc.get("capabilities", {}).get("add", [])
kotor = [cap for cap in tambah if cap in CAPS_PRIVILEGED]
if kotor:
hasil.append(f"capabilities add berisi {', '.join(kotor)} pada container {c['name']}")
if "ALL" not in sc.get("capabilities", {}).get("drop", []):
hasil.append(f"capabilities drop ALL tidak diatur pada container {c['name']}")
return hasil
for pod in pods:
nama = pod["metadata"]["name"]
daftar = pelanggaran(pod)
if daftar:
print(f"Pod {nama} : DITOLAK ({len(daftar)} pelanggaran)")
for item in daftar:
print(f" - {item}")
else:
print(f"Pod {nama} : DITERIMA")
print()Namespace aplikasi-catatan dengan enforce=restricted (versi v1.37)
Pod catatan-lama : DITOLAK (7 pelanggaran)
- host namespace tidak diizinkan (hostNetwork/hostPID/hostIPC)
- privileged=true pada container catatan
- allowPrivilegeEscalation tidak bernilai false pada container catatan
- runAsNonRoot tidak bernilai true pada container catatan
- seccompProfile bukan RuntimeDefault atau Localhost pada container catatan
- capabilities add berisi NET_ADMIN pada container catatan
- capabilities drop ALL tidak diatur pada container catatan
Pod catatan-baru : DITERIMAPod catatan-lama ditolak karena tujuh pelanggaran yang disebut satu per satu, mulai dari privileged dan hostNetwork sampai seccompProfile yang tidak diatur. Pod catatan-baru lolos karena memenuhi seluruh syarat, yaitu runAsNonRoot pada level Pod, seccompProfile bertipe RuntimeDefault, allowPrivilegeEscalation bernilai false, dan capabilities yang hanya berisi drop ALL. Daftar pelanggaran pada keluaran meniru isi peringatan Pod Security Admission yang sebenarnya, sehingga skrip ini dapat digunakan sebagai pratinjau cepat sebelum manifest dikirim ke kluster. Kasus Pod lama juga memperlihatkan perilaku kebijakan yang menghasilkan daftar temuan, yaitu admission menampung seluruh pelanggaran dalam satu respons dan tidak berhenti pada pelanggaran pertama, sehingga perbaikan dapat dilakukan sekali jalan. Perintah berikut memperlihatkan reaksi kluster ketika kedua Pod diterapkan:
# tidak-dijalankan
# terapkan namespace dengan label keamanan pod
kubectl apply -f pss-namespace.yaml
# terapkan dua pod contoh, satu melanggar dan satu memenuhi profil
kubectl apply -f pod-pss.yamlnamespace/aplikasi-catatan created
Error from server (Forbidden): error when creating "pod-pss.yaml": pods "catatan-lama" is forbidden: violates PodSecurity "restricted:v1.37": privileged (container "catatan" must not set privileged=true), hostNetwork (pod must not set hostNetwork=true), allowPrivilegeEscalation (container "catatan" must set securityContext.allowPrivilegeEscalation=false), runAsNonRoot (pod or container must set securityContext.runAsNonRoot=true), seccompProfile (pod or container must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost"), capabilities (container "catatan" must not add "NET_ADMIN" in securityContext.capabilities.add)
pod/catatan-baru createdKesalahan umum#
Tiga kesalahan berikut paling sering muncul saat standar ini mulai diterapkan pada namespace yang sudah terisi workload. Ketiganya berpangkal pada perbedaan antara kebijakan yang berlaku untuk Pod baru dan keadaan namespace yang sudah terisi:
- Memasang label enforce restricted pada namespace yang dipenuhi workload lama tanpa evaluasi awal. Pod yang sudah berjalan tidak terganggu, tetapi setiap Pod baru pada namespace tersebut ditolak, termasuk Pod sementara yang dibuat oleh perkakas lain. Perbaikannya adalah memasang mode audit dan warn terlebih dahulu, memperbaiki manifest yang tercatat melanggar, lalu mengaktifkan enforce.
- Menganggap Pod yang lolos di satu namespace berarti lolos di semua namespace. Definisi profil sama di seluruh kluster, tetapi label setiap namespace dapat berbeda. Perbaikannya adalah memeriksa label namespace tujuan dengan
kubectl describe namespace <nama>sebelum manifest dipindahkan. - Menghapus
seccompProfileagar manifest lebih pendek. Profil restricted menuntutnya pada level Pod atau container, sehingga Pod langsung ditolak. Perbaikannya adalah menetapkanseccompProfilebertipe RuntimeDefault pada level Pod.
Ringkasan#
- Pod Security Standards menyediakan tiga profil, yaitu privileged tanpa batasan, baseline yang melarang pengaturan paling istimewa, dan restricted yang menuntut kebiasaan pengamanan modern.
- Penerapan dilakukan Pod Security Admission melalui label namespace dengan mode enforce yang menolak, audit yang merekam, dan warn yang memperingatkan.
- Label hanya dinilai pada saat Pod dibuat, sehingga Pod lama yang sudah berjalan tidak ikut dievaluasi.
- Profil restricted menuntut runAsNonRoot, seccompProfile, allowPrivilegeEscalation false, dan capabilities drop ALL dengan pengecualian penambahan NET_BIND_SERVICE.
Referensi#
- Pod Security Standards — Kubernetes — Definisi tiga profil kebijakan beserta daftar batasan untuk setiap versi profil.
- Pod Security Admission — Kubernetes — Mekanisme penerapan standar melalui label namespace beserta ketiga mode penerapannya.