الأمن السيبراني

Pod Security Standards وOPA Gatekeeper — قبول صارم CKS 2026

7 دقائق للقراءة

السلسلة: هذا الدرس جزء من سلسلة شهادة CKS. للحصول على نظرة شاملة، اقرأ المقال الرئيسي أولاً.

مقدمة

المجال 4 «Minimize Microservice Vulnerabilities» يزن 20% من امتحان CKS. يختبر قدرتك على تطبيق سياسات قبول صارمة تحجب عند الإنشاء أي Pod لا تحترم معايير الأمان — capabilities مفرطة، runAsRoot، hostNetwork، mounts حساسة. أداتان لا غنى عنهما: Pod Security Standards (مدمَجة أصلياً في Kubernetes منذ 1.25) وOPA Gatekeeper (policies إعلانية بـ Rego، أكثر مرونة). هذا الدرس يطبّق الاثنتين على عنقود kind 1.34، يبيّن الفروق، ويضبط استراتيجية دفاع متعدّد الطبقات.

المتطلبات

  • عنقود kind 1.34 شغّال
  • 40 دقيقة

الخطوة 1 — تفعيل Pod Security Standards Restricted على namespace

Pod Security Standards (PSS) خليفة PodSecurityPolicy. يُفعَّل عبر labels على مستوى namespace، بلا تثبيت إضافي. ثلاث مستويات: Privileged (بلا قيود)، Baseline (مضاد للتصعيد)، Restricted (تحصين أقصى).

kubectl create namespace secure-zone
kubectl label namespace secure-zone \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/warn=restricted

# اختبار بـ Pod غير مطابق
kubectl run nginx --image=nginx:1.27 -n secure-zone
# يجب أن يفشل: Restricted يطلب runAsNonRoot، capabilities drop، إلخ.

Pod nginx الكلاسيكية مرفوضة لأن الصورة تشتغل root افتراضياً. هذا السلوك المنتظر — يجب توفير manifest يلبّي قيود Restricted ليُقبَل.

الخطوة 2 — إنشاء Pod مطابقة Restricted

Pod مطابقة Restricted تتطلب: runAsNonRoot، runAsUser غير صفر، allowPrivilegeEscalation false، capabilities drop ALL، seccompProfile RuntimeDefault.

cat > /tmp/pod-restricted.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: secure-app
  namespace: secure-zone
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: nginxinc/nginx-unprivileged:1.27
      ports:
        - containerPort: 8080
      securityContext:
        allowPrivilegeEscalation: false
        capabilities:
          drop:
            - ALL
        runAsNonRoot: true
EOF

kubectl apply -f /tmp/pod-restricted.yaml
kubectl get pod secure-app -n secure-zone

لاحظ استخدام nginxinc/nginx-unprivileged — صورة nginx الرسمية تشتغل root على المنفذ 80، بينما نسخة unprivileged تشتغل uid 101 على المنفذ 8080. لأحمال CKS، فضّل الصور المصمَّمة للتشغيل بلا امتيازات.

الخطوة 3 — تثبيت OPA Gatekeeper

OPA (Open Policy Agent) Gatekeeper يُوسّع Kubernetes بـ admission webhook يقيّم كل إنشاء/تعديل لمورد ضدّ policies Rego. أكثر مرونة من PSS المحدود بقيود معرَّفة سلفاً.

kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/v3.22.0/deploy/gatekeeper.yaml
sleep 30
kubectl get pods -n gatekeeper-system
kubectl wait --for=condition=ready pod -l control-plane=controller-manager -n gatekeeper-system --timeout=120s

بمجرد تشغيل Gatekeeper، webhook يعترض كل طلبات API. بلا ConstraintTemplate ولا Constraint، يدع كل شيء يمرّ. الخطوة التالية تضيف القواعد.

الخطوة 4 — سياسة أولى — حظر الصور من Docker Hub

حالة استخدام كلاسيكية: فرض كل الصور لتأتي من registry داخلي (Harbor، ECR، GCR). نبدأ بـ ConstraintTemplate يعرّف المنطق بـ Rego، ثم نُجسّده عبر Constraint.

cat > /tmp/template-allowed-repos.yaml <<'EOF'
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8sallowedrepos
spec:
  crd:
    spec:
      names:
        kind: K8sAllowedRepos
      validation:
        openAPIV3Schema:
          type: object
          properties:
            repos:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sallowedrepos
        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          satisfied := [good | repo = input.parameters.repos[_]; good = startswith(container.image, repo)]
          not any(satisfied)
          msg := sprintf("container image %v not allowed from repos %v", [container.image, input.parameters.repos])
        }
EOF

kubectl apply -f /tmp/template-allowed-repos.yaml

cat > /tmp/constraint-allowed-repos.yaml <<'EOF'
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedRepos
metadata:
  name: only-corporate-registry
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    excludedNamespaces: ["kube-system","gatekeeper-system"]
  parameters:
    repos:
      - "registry.example.com/"
      - "ghcr.io/myorg/"
EOF

kubectl apply -f /tmp/constraint-allowed-repos.yaml
sleep 5

# اختبار: Pod nginx عامة يجب أن تُرفض
kubectl run test-block --image=nginx:1.27 -n default
# يجب أن يفشل مع انتهاك Gatekeeper

Pod مرفوضة برسالة صريحة «container image nginx:1.27 not allowed from repos». هذا تماماً السلوك المنتظر في الإنتاج: لا صورة غير مُتحقَّق منها يمكن أن تبلغ العنقود.

الخطوة 5 — سياسة حظر hostPath

volumes hostPath باب مفتوح: Pod مخترَقة تستطيع قراءة/كتابة على نظام ملفات العقدة. سياسة CKS جيدة تحجب hostPath إلا في حالات استثنائية موثَّقة.

cat > /tmp/template-no-hostpath.yaml <<'EOF'
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8snohostpath
spec:
  crd:
    spec:
      names:
        kind: K8sNoHostPath
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8snohostpath
        violation[{"msg": msg}] {
          volume := input.review.object.spec.volumes[_]
          volume.hostPath
          msg := sprintf("hostPath volumes are forbidden, found %v", [volume.name])
        }
EOF

kubectl apply -f /tmp/template-no-hostpath.yaml

cat > /tmp/constraint-no-hostpath.yaml <<'EOF'
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sNoHostPath
metadata:
  name: forbid-hostpath
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    excludedNamespaces: ["kube-system","gatekeeper-system"]
EOF

kubectl apply -f /tmp/constraint-no-hostpath.yaml

اختبار: حاول تطبيق Pod مع hostPath volume — تُرفض فوراً من Gatekeeper. هذه السياسة وحدها تحجب نحو 30% من escapes container الموثَّقة.

الخطوة 6 — وضع Audit للاكتشاف قبل التطبيق

قبل التحوّل إلى enforce، تبدأ كثير من الفرق في audit: Gatekeeper يُسجّل الانتهاكات دون حجبها، ما يسمح بقياس أثر سياسة جديدة.

# رؤية الانتهاكات المكتشفة (audit mode)
kubectl get k8snohostpath forbid-hostpath -o yaml | grep -A 20 status

كتلة status.violations تسرد كل الموارد المنتهكة. في وضع enforcement، تحجب هذه الانتهاكات الإنشاءات الجديدة لكنها لا تحذف Pods الموجودة — يجب تصحيحها واحدة واحدة.

الخطوة 7 — الجمع بين PSS وOPA Gatekeeper

PSS وGatekeeper متكاملان. PSS يدير القيود المعيارية لـ Kubernetes (security context، capabilities، host namespaces). Gatekeeper يدير قيود الأعمال (whitelist registry، labels إلزامية، ResourceQuotas مخصّصة). اجمع الاثنين: PSS على مستوى namespace، Gatekeeper للقواعد العالمية.

# تحقق من توافق النظامين على Pod اختباري
cat > /tmp/test-combined.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: combined-test
  namespace: secure-zone
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: registry.example.com/nginx:1.27
      securityContext:
        allowPrivilegeEscalation: false
        capabilities:
          drop: ["ALL"]
EOF

kubectl apply -f /tmp/test-combined.yaml
# مرفوض من Gatekeeper (registry ليست في القائمة)

إن حاولنا بصورة registry معتمَدة (ghcr.io/myorg/nginx) ومع security context مطابق PSS، Pod تمرّ. هذا وضع الدفاع متعدّد الطبقات المطلوب.

الخطوة 8 — Sandbox runtime gVisor (تقديم)

gVisor هو runtime حاوية user-space يعزل أكثر من runc باعتراض syscalls. موصى به للأحمال غير الموثوقة. الإعداد الكامل يتطلب تعديل containerd config وإنشاء RuntimeClass.

cat > /tmp/runtimeclass-gvisor.yaml <<'EOF'
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: gvisor
handler: runsc
EOF

# Pod تستخدم gVisor:
cat > /tmp/pod-gvisor.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: untrusted-workload
spec:
  runtimeClassName: gvisor
  containers:
    - name: app
      image: nginx:1.27
EOF

لـ kind، gVisor ليس مُثبَّتاً مسبقاً. في الإنتاج، إنه خيار لاستضافة كود مستخدم أو أحمال غير مُتحقَّقة. يقع في المجال 4 كـ «sandbox runtime».

فهم الفرق Validating مقابل Mutating Admission Webhook

Kubernetes لها نوعان من webhooks القبول. Validating يقول نعم أو لا لإنشاء/تعديل — ما يستخدمه Gatekeeper. Mutating يستطيع تعديل المورد قبل تخزينه — ما تفعله Istio لحقن sidecars Envoy. الاثنان قد يتعايشان: Mutating يُنفَّذ أولاً (يحوّل المورد)، ثم Validating (يتحقق من النسخة النهائية).

OPA Gatekeeper يدعم الوضعين منذ v3.10. لـ CKS v1.34، توقّع أسئلة عن Validating أساساً، أحياناً عن Mutating لتحويل manifests.

أخطاء شائعة

الخطأ السبب الحل
PSS Restricted يرفض Pods الموجودة صور تشتغل root هاجر إلى nginx-unprivileged، bitnami/postgresql إلخ
Gatekeeper يدع Pods تمرّ ConstraintTemplate طُبِّق دون Constraint كلاهما ضروري: Template ثم Constraint الذي يجسّده
سياسة Rego لا تتطابق أبداً مسار خاطئ في input.review.object اختبر عبر gator test محلياً قبل النشر
PSS وGatekeeper في تعارض قواعد متكرّرة لكن غير متزامنة وثّق مشاركة المسؤولية: PSS للمعايير K8s، Gatekeeper للأعمال
RuntimeClass gvisor غير موجودة gVisor غير مُثبَّت على العقد اتبع doc gvisor.dev/docs/user_guide/install لـ containerd

دروس مرافقة

أسئلة شائعة

هل OPA Gatekeeper أم Kyverno؟
الاثنان صالحان. Gatekeeper يستخدم Rego (قوي لكن منحنى تعلّم)، Kyverno يستخدم YAML إعلانياً (أبسط). لـ CKS، Gatekeeper في المنهج الرسمي.

هل يمكن فعل كل شيء بـ PSS بلا Gatekeeper؟
لا. PSS يدير فقط قيود Kubernetes المعرَّفة سلفاً. للقواعد البيزنس (registry، labels، quotas مخصّصة)، admission webhook مطلوب.

مقالات ذات صلة

Sponsoriser ce contenu

Cet emplacement est à vous

Position premium en fin d'article — c'est l'instant où les lecteurs sont le plus engagés. Réservez cet espace pour votre marque, votre formation ou votre offre.

Recevoir nos tarifs
Publicité