تقوية أمن السحابة وKubernetes

تصليب Kubernetes: مستوى المجموعة

18 دقيقة الدرس 6 من 28

تصليب Kubernetes: مستوى المجموعة

تمنع ضوابط مستوى الحاوية (Pod) تسرب الأعباء المخترقة من صندوق الرمل الخاص بها. أما تصليب مستوى المجموعة (Cluster) فهو تخصص مختلف: يحمي مستوى التحكم ذاته — خادم API وقاعدة بيانات etcd والجدول الزمني وخط أنابيب القبول (Admission). المهاجم الذي يصل إلى مستوى التحكم لا يحتاج إلى الإفلات من أي حاوية؛ بوسعه إنشاء حاويات جديدة، وقراءة كل Secret، وتعديل كائنات المجموعة كما يشاء. ونطاق الضرر هنا هو المجموعة بأكملها، عبر كل نطاق فرعي (namespace).

يتناول هذا الدرس الركائز الأربع لمستوى التحكم التي تراجعها فرق الأمان في الإنتاج أولاً: تقليص تعرض خادم API، ومراجعة الحد الأدنى من الصلاحيات في RBAC، وسجلات التدقيق (Audit Logs)، وتشفير etcd عند الحفظ. لكل منها ثغرات افتراضية معروفة يرثها الفرق من إعدادات مريحة أو إعدادات مزودي الخدمة السحابية التي أولت سهولة الإعداد على حساب وضع الأمان.

تعرض خادم API: تضييق سطح الهجوم

خادم API هو نقطة الدخول الوحيدة للمجموعة. كل أمر kubectl، وكل حلقة تسوية في المتحكمات (Controllers)، وكل استدعاء Webhook يمر عبره. تركه قابلاً للوصول من الإنترنت يعادل كشف منفذ إدارة قاعدة البيانات للعموم — تكتشفه الماسحات في دقائق، ويصبح هدفاً دائماً للتخمين واستغلال الثغرات.

في الحلول المُدارة (EKS وGKE وAKS) يعمل خادم API داخل الـ VPC الخاص بالمزود، ويكون أمام موازن حمل بعنوان IP عام افتراضياً. الخطوة الأولى في التصليب هي تعطيل الوصول العام وتقييد النقطة النهائية على VPC المجموعة فقط، إلى جانب نطاقات CIDR محددة تستخدمها عمليات CI والمهندسون.

# EKS: تقييد خادم API على الوصول الخاص بـ VPC فقط aws eks update-cluster-config \ --name production-cluster \ --resources-vpc-config \ endpointPrivateAccess=true,endpointPublicAccess=false # إذا كان الوصول العام ضرورياً (مثلاً: لا VPN)، قيّد على CIDRs محددة فقط: aws eks update-cluster-config \ --name production-cluster \ --resources-vpc-config \ endpointPublicAccess=true,\ publicAccessCidrs="10.0.0.0/8,203.0.113.42/32" # التحقق من الإعداد الناتج aws eks describe-cluster --name production-cluster \ --query "cluster.resourcesVpcConfig"

بالإضافة إلى تضييق التعرض الشبكي، يجب تصليب خادم API على مستوى الأعلام (Flags). المجموعات المُدارة ذاتياً (kubeadm وk3s وRancher) ترث الأعلام التي ضبطها المثبّت. أهم الأعلام التي يجب مراجعتها في /etc/kubernetes/manifests/kube-apiserver.yaml:

  • --anonymous-auth=false — تعطيل المستخدم system:anonymous، مما يمنع الطلبات غير الموثقة من الوصول إلى طبقة التفويض.
  • --insecure-port=0 — تعطيل منفذ HTTP القديم (الافتراضي 8080). Kubernetes 1.20 أهمل هذا؛ تأكد من ضبطه صراحةً على 0.
  • --enable-admission-plugins — يجب أن يشمل NodeRestriction (يمنع kubelets من تعديل كائنات العقد الأخرى) وAlwaysPullImages (يفرض التحقق من الاعتمادات عند كل بدء تشغيل للحاوية).
  • --authorization-mode=Node,RBAC — لا تستخدم أبداً AlwaysAllow الذي يمنح كل طلب موثق صلاحيات كاملة.
مخاطر الإنتاج — انجراف معيار CIS: المجموعات المُدارة (EKS وGKE) تدير أعلام خادم API نيابةً عنك وتطبق إعدادات افتراضية معقولة، لكنها لا تمنحك وصولاً مباشراً للأعلام. شغّل ماسح CIS من أداة kube-bench على مجموعتك لاكتشاف الفحوصات الناجحة والتي يديرها المزود. لا تفترض أبداً أن المجموعة المُدارة مُصلَّبة بالكامل جاهزةً — تعرض النقطة النهائية وإعداد RBAC يظلان مسؤوليتك.

مراجعة الحد الأدنى من الصلاحيات في RBAC

التحكم في الوصول القائم على الأدوار (RBAC) في Kubernetes معبّر — وسهل سوء الاستخدام. الأنماط الثلاثة الأكثر خطورة التي تتكرر في مراجعات أمان الإنتاج هي:

  1. الأفعال أو الموارد بالواصفة Wildcard: verbs: ["*"] أو resources: ["*"] في ClusterRole تمنح الموضوع صلاحية فعل أي شيء لأي شيء. يظهر هذا كثيراً في حسابات خدمة CI لأنه "الطريقة الأبسط لتشغيل خط الأنابيب."
  2. الربط على مستوى المجموعة لعمل محدود النطاق: يربط ClusterRoleBinding الدور بالموضوع عبر كل namespace — الحالية والمستقبلية. معظم حسابات خدمة التطبيقات يجب أن تستخدم RoleBindings محددة النطاق بـ namespace واحد.
  3. إساءة استخدام حساب الخدمة الافتراضي: كل Pod يحصل على حساب الخدمة default في namespace الخاص به إذا لم يُحدَّد serviceAccountName. إذا كان أي شيء مرتبطاً بذلك الحساب الافتراضي، فإن كل Pod في الـ namespace يرث تلك الصلاحيات.
# تدقيق: الحصول على كل ClusterRoleBindings والموضوعات المرتبطة بها kubectl get clusterrolebindings -o json \ | jq -r '.items[] | "\(.metadata.name)\t\(.roleRef.name)\t\(.subjects[]?.name)"' # تدقيق: البحث عن أي دور يمنح أفعالاً أو موارد بالواصفة Wildcard kubectl get clusterroles,roles -A -o json \ | jq -r ' .items[] | select(.rules[]? | (.verbs[]? == "*") or (.resources[]? == "*")) | "\(.metadata.namespace // "cluster")\t\(.metadata.name)" ' # فحص ما يمكن لحساب خدمة محدد فعله عبر المجموعة kubectl auth can-i --list \ --as=system:serviceaccount:production:my-app-sa \ --all-namespaces

نمط المعالجة هو بناء الأدوار من الأساس: تعداد مجموعات API والموارد والأفعال التي يحتاجها الحمل الفعلياً. متحكم نشر تطبيق ويب نموذجي يحتاج get وlist وwatch وpatch على Deployments فقط في namespace الخاص به — لا أكثر. استخدم مخرجات kubectl auth can-i --list كخط أساس، ثم اقطع كل ما لم يُستخدم في الإنتاج.

ممارسة متقدمة — تحليل RBAC الآلي: أدوات مثل rbac-tool (kubectl rbac-tool lookup <subject>) وrakkess تنتج مصفوفات وصول تُظهر بالضبط ما يمكن لكل موضوع فعله لكل مورد. شغّلها في خط أنابيب التدقيق وقارن المخرجات عبر الإصدارات لاكتشاف تضخم الصلاحيات قبل وصوله للإنتاج.

سجلات التدقيق في Kubernetes

سجلات التدقيق هي الإجابة على: "من غيّر ذلك ClusterRoleBinding في الساعة الثانية صباحاً، وماذا أيضاً؟" بدون سجلات التدقيق أنت تعمل بشكل أعمى خلال الحوادث — لا تستطيع تحديد الاعتمادات المستخدمة أو الموارد التي تم الوصول إليها أو ما إذا تم تأسيس ثبات للمهاجم. هذه هي أكبر ثغرة جنائية في المجموعات التي تواجهها فرق الأمان بعد الاختراق.

يدعم خادم API أربعة مستويات تدقيق — None وMetadata وRequest وRequestResponse — مطبقة عبر ملف سياسة تدقيق. النمط الإنتاجي هو تسجيل Metadata لمسارات القراءة عالية الحجم (يقلل تكلفة التخزين) وRequestResponse لكل عمليات التعديل (الكتابات وexec وport-forward).

# /etc/kubernetes/audit-policy.yaml — سياسة تدقيق على مستوى الإنتاج apiVersion: audit.k8s.io/v1 kind: Policy omitStages: - RequestReceived # تخطي حدث الاستقبال الأولي؛ تسجيل الاستجابات فقط rules: # لا تسجل بيانات Secrets (يمنع تسرب الأسرار في السجلات) - level: None resources: - group: "" resources: ["secrets"] verbs: ["get", "list", "watch"] # تسجيل كل التعديلات بمستوى RequestResponse - level: RequestResponse verbs: ["create", "update", "patch", "delete", "deletecollection"] # تسجيل exec/attach/port-forward بمستوى RequestResponse — حرج للتحقيق الجنائي - level: RequestResponse resources: - group: "" resources: ["pods/exec", "pods/attach", "pods/portforward"] # تسجيل الأحداث المرتبطة بـ RBAC بمستوى RequestResponse - level: RequestResponse resources: - group: "rbac.authorization.k8s.io" resources: ["clusterroles", "clusterrolebindings", "roles", "rolebindings"] # كل شيء آخر بمستوى Metadata (من وأي مورد ورمز النتيجة — بدون النصوص) - level: Metadata

طبّق السياسة بإضافة أعلام لـ manifest الخاص بخادم API وأرسل السجلات إلى SIEM مركزي (Splunk أو Elastic أو خدمة سحابية أصلية مثل AWS CloudWatch أو GCP Cloud Audit Logs). العلمان هما --audit-log-path=/var/log/kubernetes/audit.log و--audit-policy-file=/etc/kubernetes/audit-policy.yaml. للمجموعات المُدارة، تفعيل سجل التدقيق يختلف حسب المزود: في EKS، فعّل نوع السجل audit في إعدادات تسجيل المجموعة؛ في GKE، سجلات Admin Activity وData Access قابلة للإعداد ضمن Cloud Audit Logs.

Kubernetes Cluster Hardening — Control Plane Security Layers API Server --anonymous-auth=false RBAC Least-privilege roles Audit Logs Policy + SIEM etcd Encryption at rest Network Perimeter Private endpoint · VPC-only · CIDR allowlist · TLS mutual auth
ركائز تصليب المجموعة الأربع — كل حركة مستوى التحكم تمر عبر خادم API المحمي بـ RBAC والمدقَّق، والمدعوم بمخزن etcd مشفر، كل ذلك خلف حدود شبكية خاصة.

تشفير etcd عند الحفظ

etcd هو مخزن بيانات Kubernetes — يحتوي على كل Secret وكل ConfigMap وكل كائن في المجموعة. افتراضياً، تُخزَّن Kubernetes Secrets في etcd كنص عادي مُرمَّز بـ base64. أي شخص يملك وصول قراءة إلى مجلد بيانات etcd (عقدة etcd مخترقة، نسخة احتياطية مُستعادة على جهاز تطوير، أو مجلد نسخ احتياطية مُعرَّض للخطأ) يمكنه فك تشفير كل Secret في المجموعة بأمر base64 -d واحد.

يُعدّ تشفير etcd عند الحفظ عبر ملف EncryptionConfiguration المُشار إليه في خادم API بـ --encryption-provider-config. المزود الموصى به هو aescbc (AES-256 في وضع CBC مع HMAC-SHA1 للسلامة) أو secretbox (XSalsa20-Poly1305، أسرع). للإنتاج على نطاق واسع، استخدم مزود KMS (AWS KMS أو GCP CKMS أو Azure Key Vault) لتشفير مفتاح تشفير البيانات نفسه بمفتاح مُدار عتادياً — المجموعة لا تحتفظ بمفتاح الجذر في الذاكرة.

# /etc/kubernetes/encryption-config.yaml # مزود AES-CBC للـ Secrets والـ ConfigMaps # توليد مفتاح 32 بايت: head -c 32 /dev/urandom | base64 apiVersion: apiserver.config.k8s.io/v1 kind: EncryptionConfiguration resources: - resources: - secrets - configmaps providers: - aescbc: keys: - name: key1 # استبدل بمخرجات: head -c 32 /dev/urandom | base64 secret: <BASE64_ENCODED_32_BYTE_KEY> - identity: {} # احتياطي: يقرأ الكائنات غير المشفرة الموجودة # بعد تطبيق الإعداد وإعادة تشغيل خادم API، # أعد كتابة كل Secrets الموجودة قسراً لتشفيرها: kubectl get secrets --all-namespaces -o json \ | kubectl replace -f - # التحقق: قراءة Secret مباشرةً من etcd للتأكد من عدم وجود نص عادي # (شغّل على عقدة etcd — يتطلب etcdctl وشهادات etcd) 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 \ get /registry/secrets/production/my-secret | hexdump -C | head # يجب أن يبدأ المخرج بـ "k8s:enc:aescbc" — وليس كتلة JSON مقروءة
تدوير المفاتيح مهم: أضف إدخال مفتاح ثانٍ في أعلى قائمة المزودين (المفتاح الجديد أولاً، القديم ثانياً) لتدوير المفاتيح. يشفّر خادم API الكتابات بالمفتاح الأول ويستطيع فك التشفير بأي مفتاح في القائمة. بعد إعادة كتابة كل Secrets قسراً، احذف المفتاح القديم وأعد تشغيل خادم API. نمط التدوير دون توقف هذا هو نفسه المستخدم في تدوير AWS KMS CMK.

الجمع بين الركائز: قائمة تدقيق تصليب المجموعة

كل ضابط من هذه الضوابط يعالج نمط فشل مختلف. هي تتراكم: RBAC بدون سجلات تدقيق يعني عدم قدرتك على اكتشاف استغلال ربط مُعدَّأ للصلاحيات. سجلات التدقيق بدون تشفير etcd تعني أن إدخالات السجل تشير إلى أسرار مخزنة كنص عادي على القرص. شغّل جميعها معاً كوضعية متماسكة، وتحقق منها باستمرار بأدوات مثل kube-bench (ماسح معيار CIS) وTrivy (ماسح إعدادات خاطئة مع دعم Kubernetes) وFalco (محرك قواعد وقت التشغيل الذي يمكنه التنبيه على نشاط خادم API المريب في الوقت الفعلي).

ممارسة متقدمة — أتمتة التدقيق: ادمج kube-bench في خط أنابيب CI/CD كخطوة ما بعد النشر. اضبطه على إفشال خط الأنابيب إذا ظهرت أي فحوصات FAIL من مستوى CIS لملف مجموعتك (EKS أو GKE أو عام). هذا يمنع انحدار التصليب من الشحن بصمت — مكوّن قبول مُعدَّأ أو ClusterRoleBinding جديد بأفعال wildcard يُكتشف قبل وصوله للإنتاج.