تأمين نظام رصد السلامة في محل العمل

1- مقدمة

في هذا الدرس التطبيقي حول الترميز، ستنشئ تطبيقًا أساسيًا للعرض التوضيحي يوضّح كيفية دمج خدمات Google Cloud المختلفة لخدمة تقع في مشروع يتضمّن قيودًا على الامتثال. يستخدم هذا المشروع إمكانات الأمان التالية:

هذا الدرس التطبيقي حول الترميز مخصّص للمطوّرين من جميع المستويات، بما في ذلك المبتدئون. ستستخدم واجهة سطر الأوامر في Google Cloud Shell ورمز Python. لست بحاجة إلى أن تكون خبيرًا في Python، ولكن سيساعدك الفهم الأساسي لكيفية قراءة الرمز البرمجي في فهم المفاهيم.

ملاحظة: هذا دليل بسيط لإثبات المفهوم، وليس تطبيقًا للإنتاج. في سيناريو حقيقي، عليك اتّخاذ احتياطات إضافية، مثل الوصول الخارجي المصادَق والآمن إلى هذه الخدمة.

2. قبل البدء

إعداد المشروع

../shared/_project-setup.md

بدء Cloud Shell

Cloud Shell هي بيئة سطر أوامر تعمل في Google Cloud ومحمّلة مسبقًا بالأدوات اللازمة.

  1. انقر على تفعيل Cloud Shell في أعلى "وحدة تحكّم Google Cloud":

404e4cce0f23e5c5.png

  1. بعد الاتصال بـ Cloud Shell، شغِّل هذا الأمر لإثبات هويتك في Cloud Shell:
gcloud auth list
  1. شغِّل الأمر التالي للتأكّد من ضبط مشروعك لاستخدامه مع gcloud:
gcloud config get project
  1. تأكَّد من أنّ المشروع هو المشروع المتوقّع، ثم شغِّل الأمر أدناه لضبط رقم تعريف مشروعك:
export PROJECT_ID=$(gcloud config get project)

أذونات "إدارة الهوية وإمكانية الوصول" المطلوبة

يجب أن يكون للحساب الذي تستخدمه في هذا الدرس التطبيقي حول الترميز أدوار "إدارة الهوية وإمكانية الوصول" التالية. هذه الأذونات ضرورية لإنشاء موارد Google Cloud المطلوبة (المشاريع والمجلدات ومجموعات GKE ومفاتيح Cloud KMS وحسابات الخدمة وما إلى ذلك) وضبط حمل العمل المؤكَّد.

على مستوى المؤسسة:

  • roles/assuredworkloads.admin (مشرف أحمال العمل المؤكّدة): لإنشاء مورد "أحمال العمل المؤكّدة" وإدارته بنفسه، ما يضمن ضبط الامتثال

على مستوى حساب الفوترة (في حساب الفوترة):

  • roles/billing.accountUser (مستخدم حساب الفوترة): لربط حساب الفوترة المحدّد

ضبط متغيرات الدرس التطبيقي حول الترميز

لإنشاء البنية الأساسية المطلوبة، عليك توفير متغيرات البيئة التالية:

# The ID of the Billing Account in the format (XXXXXX-XXXXXX-XXXXXX).
# This value will be used to attach in the projects created using Assured Workloads
export BILLING_ACCOUNT=

# The ID of a Google Cloud Platform organization
# Run `gcloud organizations list` to check all your available organizations
export GCP_ORGANIZATION=

# The numeric ID of a folder where the Assured Workloads will create the resources.
export FOLDER_ID=

# Region where the application will be deployed.
# Since you are using Assured Workloads, you MUST use one of the valid locations as described here: <https://docs.cloud.google.com/assured-workloads/docs/locations>
export REGION="us-central1"

# The ID of an existing Google Cloud project to be used for API quota and billing purposes.
# This project will only be used to enable the Assured Workloads API and create an Assured Workload.
export QUOTA_PROJECT_ID=

# Random suffix used to avoid naming collisions when creating the GCP projects.
export RANDOM_SUFFIX=$(cat /dev/urandom | tr -dc 'a-z0-9' | head -c 5 ; echo)

# The ID of the projects that will be created using Assured Workloads.
# You can modify this value if you want a custom id.
export PROJECT_ID="il5-gemini-vision-aw-${RANDOM_SUFFIX}"
export KMS_PROJECT_ID="il5-gemini-vision-kms-${RANDOM_SUFFIX}"

3. إنشاء أساس "أحمال العمل المؤكّدة"

يمكنك الآن وضع أساس تطبيقك في بيئة منظَّمة. استخدِم أحمال العمل المؤكّدة للمساعدة في فرض متطلبات الامتثال من خلال إنشاء بيئة خاضعة للرقابة لمواردك.

ضبط مشروع الحصة

فعِّل Assured Workloads API في مشروع الحصة. هذه الواجهة ضرورية لإنشاء "أحمال العمل المؤكّدة" وإدارتها.

gcloud services enable assuredworkloads.googleapis.com \
  --project="${QUOTA_PROJECT_ID}"

إنشاء بيئة "أحمال العمل المؤكّدة"

ينشئ الأمر التالي "منطقة وصول" آمنة لعرضك التوضيحي. وينشئ مشروعَين جديدَين على Google Cloud ضمن المجلد وحساب الفوترة اللذين تحدّدهما.

  • يستضيف أحد المشاريع مجموعة GKE وتطبيقك.
  • يدير المشروع الآخر مفاتيح التشفير التي يديرها العميل (CMEK).

يطبّق تلقائيًا عناصر التحكّم في الامتثال المحدّدة على مستوى IL5 على كلا المشروعَين منذ لحظة إنشائهما.

شغِّل الأمر التالي لإنشاء بيئة حمل العمل.

export ASSURED_WORKLOAD_ID=$(gcloud assured workloads create \
    --project="${QUOTA_PROJECT_ID}" \
    --display-name="DoD IL5 Gemini Vision Demo" \
    --compliance-regime="IL5" \
    --billing-account="billingAccounts/${BILLING_ACCOUNT}" \
    --location="${REGION}" \
    --organization="${GCP_ORGANIZATION}" \
    --provisioned-resources-parent="folders/${FOLDER_ID}" \
    --resource-settings="consumer-project-id=${PROJECT_ID},consumer-project-name=DoD IL5 Workloads,encryption-keys-project-id=${KMS_PROJECT_ID},encryption-keys-project-name=DoD IL5 KMS" \
    --labels="codelab=gemini-vision-demo" \
    --format="value(name)")

echo "Assured Workload created: ${ASSURED_WORKLOAD_ID}"

export WORKLOAD_FOLDER_ID=$(gcloud assured workloads describe ${ASSURED_WORKLOAD_ID} \
    --location="${REGION}" \
    --project="${QUOTA_PROJECT_ID}" \
    --format="json" | grep -B 1 "CONSUMER_FOLDER" | grep -oE "[0-9]{10,}")

echo "Assured Workload folder created: ${WORKLOAD_FOLDER_ID}"

gcloud projects create "${PROJECT_ID}" \
    --folder="${WORKLOAD_FOLDER_ID}" \
    --name="DoD IL5 Workloads"

gcloud billing projects link "${PROJECT_ID}" \
    --billing-account="${BILLING_ACCOUNT}"

export PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}" --format="value(projectNumber)")

تفعيل واجهات برمجة تطبيقات Google Cloud المطلوبة

قبل الإنشاء، فعِّل واجهات برمجة التطبيقات المطلوبة للخدمات اللازمة.

يفعِّل الأمر أدناه جميع الخدمات الضرورية لهذا الدرس التطبيقي حول الترميز ضمن مشروع حمل العمل الأساسي.

gcloud services enable \
    aiplatform.googleapis.com \
    artifactregistry.googleapis.com \
    cloudkms.googleapis.com \
    compute.googleapis.com \
    container.googleapis.com \
    iam.googleapis.com \
    logging.googleapis.com \
    monitoring.googleapis.com \
    --project="${PROJECT_ID}"

4. إعداد البنية الأساسية لـ GKE

أنشئ البنية الأساسية الأساسية التي تدعم مجموعة GKE. يتضمّن ذلك إعداد شبكة مخصّصة لمجموعتك وضبط مفاتيح التشفير الخاصة بك لحماية البيانات على عُقدك.

ضبط شبكة VPC

أنشئ سحابة إلكترونية خاصة افتراضية (VPC) وشبكة فرعية مخصّصة. يمنحك هذا النهج تحكّمًا كاملاً في نطاق عناوين IP ويضمن عزل مجموعتك على النحو المطلوب.

شغِّل الأوامر التالية لإنشاء شبكة VPC وشبكة فرعية ضمن منطقتك المحدّدة.

export GKE_NETWORK_NAME="il5-gke-network"
export GKE_SUBNETWORK_NAME="il5-gke-subnet"

gcloud compute networks create "${GKE_NETWORK_NAME}" \
    --description="VPC network for GKE cluster in DoD IL5 Assured Workload" \
    --subnet-mode="custom" \
    --project="${PROJECT_ID}"

gcloud compute networks subnets create "${GKE_SUBNETWORK_NAME}" \
    --network="${GKE_NETWORK_NAME}" \
    --range="10.10.0.0/20" \
    --region="${REGION}" \
    --description="Subnet for GKE cluster nodes in DoD IL5 Assured Workload" \
    --project="${PROJECT_ID}"

ضبط التشفير باستخدام Cloud KMS

للوفاء بمتطلبات الامتثال الصارمة للبيانات الثابتة، استخدِم مفاتيح التشفير التي يديرها العميل (CMEK). يمنحك ذلك تحكّمًا مباشرًا في المفاتيح المستخدَمة لتشفير أقراص الإقلاع لعُقد GKE.

export KMS_KEYRING_NAME="il5_gke_key_ring"
export KMS_KEY_NAME="il5_gke_key"

gcloud kms keyrings create "${KMS_KEYRING_NAME}" \
    --location="$REGION" \
    --project="${KMS_PROJECT_ID}"

gcloud kms keys create "${KMS_KEY_NAME}" \
    --keyring="${KMS_KEYRING_NAME}" \
    --location="${REGION}" \
    --purpose="encryption" \
    --project="${KMS_PROJECT_ID}"

بما أنّ مفتاح التشفير موجود في مشروع Cloud KMS منفصل عن الخدمة التي تحتاج إلى استخدامه، يحتاج وكيل خدمة Google Compute Engine في مشروع حمل العمل إلى الوصول إلى المفتاح.

عليك منح وكيل خدمة GCE من مشروع حمل العمل إذن استخدام هذا المفتاح بشكل صريح. يضيف الأمر أدناه ربط سياسة "إدارة الهوية وإمكانية الوصول" إلى المفتاح، ما يمنح الدور اللازم لوكيل الخدمة.

gcloud kms keys add-iam-policy-binding "${KMS_KEY_NAME}" \
    --location="${REGION}" \
    --keyring="${KMS_KEYRING_NAME}" \
    --member="serviceAccount:service-${PROJECT_NUMBER}@compute-system.iam.gserviceaccount.com" \
    --role="roles/cloudkms.cryptoKeyEncrypterDecrypter" \
    --project="${KMS_PROJECT_ID}"

ضبط حساب خدمة لعُقد GKE

export GKE_NODE_SA=gke-node-sa

gcloud iam service-accounts create "${GKE_NODE_SA}" \
    --display-name="GKE Node Service Account" \
    --project="${PROJECT_ID}"

gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --member="serviceAccount:${GKE_NODE_SA}@${PROJECT_ID}.iam.gserviceaccount.com" \
    --role="roles/logging.logWriter"

gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --member="serviceAccount:${GKE_NODE_SA}@${PROJECT_ID}.iam.gserviceaccount.com" \
    --role="roles/monitoring.metricWriter"

5. إنشاء مجموعة GKE وضبطها

يمكنك الآن إنشاء مجموعة GKE. يوفّر الأمر التالي مجموعة GKE مع تفعيل العديد من ميزات الأمان.

يستغرق إكمال هذه العملية عدة دقائق لأنّ Google Cloud يوفّر العُقد ولوحة التحكّم.

export GKE_CLUSTER=ppe-app

gcloud beta container clusters create "${GKE_CLUSTER}" \
    --project="$PROJECT_ID" \
    --region="$REGION" \
    --service-account="${GKE_NODE_SA}@${PROJECT_ID}.iam.gserviceaccount.com" \
    --release-channel="regular" \
    --machine-type="n2d-standard-4" \
    --image-type="COS_CONTAINERD" \
    --disk-type="pd-ssd" \
    --disk-size="50" \
    --boot-disk-kms-key="projects/${KMS_PROJECT_ID}/locations/${REGION}/keyRings/${KMS_KEYRING_NAME}/cryptoKeys/${KMS_KEY_NAME}" \
    --metadata disable-legacy-endpoints=true \
    --num-nodes="1" \
    --network="projects/${PROJECT_ID}/global/networks/${GKE_NETWORK_NAME}" \
    --subnetwork="projects/${PROJECT_ID}/regions/${REGION}/subnetworks/${GKE_SUBNETWORK_NAME}" \
    --security-posture="standard" \
    --workload-vulnerability-scanning="disabled" \
    --workload-pool="${PROJECT_ID}.svc.id.goog" \
    --workload-metadata=GKE_METADATA \
    --addons="HorizontalPodAutoscaling,HttpLoadBalancing,NodeLocalDNS,GcePersistentDiskCsiDriver" \
    --max-surge-upgrade=1 \
    --max-unavailable-upgrade=0 \
    --binauthz-evaluation-mode="DISABLED" \
    --no-enable-basic-auth \
    --enable-autoupgrade \
    --enable-autorepair \
    --enable-confidential-nodes \
    --confidential-node-type=sev \
    --enable-ip-access \
    --enable-ip-alias \
    --enable-managed-prometheus \
    --enable-dns-access \
    --enable-shielded-nodes \
    --shielded-integrity-monitoring \
    --shielded-secure-boot

الاتصال بالمجموعة الجديدة

للتفاعل مع مجموعتك الجديدة، اضبط أداة سطر الأوامر kubectl المحلية.

يسترد هذا الأمر بيانات اعتماد المجموعة ونقطة النهاية، ويضبط تلقائيًا ملف kubeconfig المحلي. بعد تشغيل هذا الأمر، سيتم توجيه أي أوامر kubectl تشغّلها إلى مجموعة GKE الجديدة.

gcloud container clusters get-credentials "${GKE_CLUSTER}" \
    --region="${REGION}" \
    --project="${PROJECT_ID}" \
    --dns-endpoint

6. ضبط هوية التطبيق

لربط حساب خدمة Kubernetes بحساب خدمة على Google Cloud IAM، اضبط Workload Identity.

إنشاء حسابات الخدمة

أنشئ حساب خدمة مخصّصًا على Kubernetes (KSA) داخل مجموعتك.

export GKE_NAMESPACE=default
export GKE_SA=ppe-sa

kubectl create sa "${GKE_SA}" --namespace="${GKE_NAMESPACE}"

بعد ذلك، يحتاج تطبيقك إلى هوية ضمن Google Cloud. أنشئ حساب خدمة على Google Cloud IAM للتطبيق. بعد إنشاء حساب الخدمة، امنَحه الأدوار اللازمة.

# Create GCP service account
gcloud iam service-accounts create "${GKE_SA}" \
    --project="${PROJECT_ID}"
# Grant necessary roles
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --member="serviceAccount:${GKE_SA}@${PROJECT_ID}.iam.gserviceaccount.com" \
    --role="roles/aiplatform.user"

السماح لحساب خدمة Kubernetes بانتحال هوية حساب خدمة IAM

بعد إنشاء كلا حسابَي الخدمة، تتمثل الخطوة الأخيرة في إنشاء الرابط بينهما. تتكوّن هذه العملية من جزأين. أولاً، أضِف سياسة "إدارة الهوية وإمكانية الوصول" إلى حساب خدمة Google Cloud.

# Allow the Kubernetes service account to act as GCP service account by using Workload Identity
gcloud iam service-accounts add-iam-policy-binding "${GKE_SA}@${PROJECT_ID}.iam.gserviceaccount.com" \
    --project="${PROJECT_ID}" \
    --role="roles/iam.workloadIdentityUser" \
    --member="serviceAccount:${PROJECT_ID}.svc.id.goog[${GKE_NAMESPACE}/${GKE_SA}]"

ثانيًا، أضِف تعليقًا توضيحيًا إلى حساب خدمة Kubernetes.

kubectl annotate --namespace="${GKE_NAMESPACE}" serviceaccount "$GKE_SA" \
    iam.gke.io/gcp-service-account="${GKE_SA}@${PROJECT_ID}.iam.gserviceaccount.com"

بعد إكمال هذه الخطوة، يمكن لأي وحدة pod تعمل في مجموعتك باستخدام حساب خدمة Kubernetes الوصول الآن إلى Vertex API.

ملاحظة: من الممكن إلغاء انتحال هوية حساب الخدمة لتبسيط هذا الإعداد. يمكنك الاطّلاع هنا على التفاصيل والقيود.

7. إنشاء التطبيق ونشره

حان الوقت لتجميع تطبيقك وتخزينه ونشره في مجموعة GKE.

إنشاء مستودع Artifact Registry

قبل أن تتمكّن من تشغيل التطبيق، عليك تجميعه كحاوية Docker وتخزينه داخل مستودع Artifact Registry. استخدِم الأمر أدناه لإنشاء هذا المستودع.

export REPOSITORY_ID=ppe-repo

gcloud artifacts repositories create "${REPOSITORY_ID}" \
  --repository-format=docker \
  --location="${REGION}" \
  --project="${PROJECT_ID}" \
  --description="Regional Docker repo for PPE App"

عليك منح حساب الخدمة الذي تستخدمه عُقد GKE إمكانية القراءة من مستودعك الجديد بشكل صريح.

gcloud artifacts repositories add-iam-policy-binding "${REPOSITORY_ID}" \
    --location="${REGION}" \
    --role="roles/artifactregistry.reader" \
    --project="${PROJECT_ID}" \
    --member="serviceAccount:${GKE_NODE_SA}@${PROJECT_ID}.iam.gserviceaccount.com"

إنشاء صورة Docker ونقلها

أنشئ صورة Docker وانقلها إلى المستودع. أولاً، استنسِخ رمز المصدر وأنشئ صورة الحاوية. بعد ذلك، ضع علامة عليها باستخدام مسار Artifact Registry الكامل، وانقلها إلى المستودع الذي أنشأته سابقًا.

git clone https://github.com/GoogleCloudPlatform/next-26-sessions.git

cd BRK3-034-workplace-safety

cd ppe

export IMAGE_TAG="${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPOSITORY_ID}/ppe-app:v15"
docker build -t "${IMAGE_TAG}" .
docker push "${IMAGE_TAG}"

النشر على GKE

بعد توفّر صورة الحاوية في Artifact Registry، تتمثل الخطوة الأخيرة في توجيه GKE إلى سحبها وتشغيلها. يتم تحقيق ذلك من خلال تحديد موارد تطبيقك في ملف بيان Kubernetes وتطبيقه على المجموعة. ينشئ هذا الأمر كائنَي النشر والخدمة المحدّدَين في الملف.

export GKE_DEPLOY=ppe-detector

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ${GKE_DEPLOY}
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ${GKE_DEPLOY}
  template:
    metadata:
      labels:
        app: ${GKE_DEPLOY}
    spec:
      serviceAccountName: ${GKE_SA}
      containers:
      - name: ${GKE_DEPLOY}
        image: ${IMAGE_TAG}
        env:
        - name: PROJECT_ID
          value: ${PROJECT_ID}
        - name: LOCATION
          value: ${REGION}
        ports:
        - containerPort: 8080
        resources:
          requests:
            cpu: "250m"
            memory: "512Mi"
          limits:
            cpu: "500m"
            memory: "1Gi"
---
apiVersion: v1
kind: Service
metadata:
  name: ${GKE_DEPLOY}
spec:
  type: LoadBalancer
  selector:
    app: ${GKE_DEPLOY}
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
EOF

8. اختبار التطبيق

الخطوة الأخيرة هي الوصول إلى التطبيق التجريبي واختباره. يتضمّن ذلك استرداد عنوان IP الخارجي المخصّص للخدمة والتفاعل معه من خلال واجهة أمامية بسيطة.

استرداد عنوان IP الخارجي للخدمة

احصل على عنوان IP الخارجي للخدمة المعروضة (يستغرق توفيرها 30 ثانية تقريبًا)

export IP_ADDRESS=$(kubectl get service "${GKE_DEPLOY}" -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo $IP_ADDRESS

تشغيل الواجهة الأمامية محليًا

في هذا العرض التوضيحي، تكون الواجهة الأمامية عبارة عن صفحة بسيطة بتنسيق HTML/JavaScript لا تشكّل جزءًا من عملية النشر على GKE. تم تصميمها للتشغيل على جهازك المحلي.

يجب عرض الواجهة الأمامية من Google Cloud في تطبيق إنتاج. على الجهاز المحلي:

# Update the index.html file with the server IP address
cd frontend

# For Linux
sed -i "s#\(const BACKEND_URL = \"http://\)[^/]\+\(\/analyze\";\)#\1${IP_ADDRESS}\2#g" "index.html"

# For MacOS
#sed -i '' "s#\(const BACKEND_URL = #\"http://\)[^/]*\(\/analyze\";\)#\1${IP_ADDRESS}\2#g" "index.html"

python3 -m http.server 8001

افتح http://localhost:8001/index.html في Chrome.

9- تنظيف

لتجنُّب الرسوم المستمرة، احذف الموارد التي تم إنشاؤها في هذا الدرس التطبيقي حول الترميز.

إيقاف مجموعة GKE

لحذف التطبيق بأكمله، ما عليك سوى حذف مجموعة GKE. لإجراء ذلك، شغِّل:

gcloud container clusters delete "${GKE_CLUSTER}" \
    --region="$REGION" \
    --project="${PROJECT_ID}"

حذف "أحمال العمل المؤكّدة"

شغِّل الأوامر التالية لحذف جميع الموارد ذات الصلة بـ "أحمال العمل المؤكّدة".

# Workload project deletion
gcloud billing projects unlink "${PROJECT_ID}"
gcloud projects delete "${PROJECT_ID}"

# KMS project deletion
gcloud billing projects unlink "${KMS_PROJECT_ID}"
gcloud projects delete "${KMS_PROJECT_ID}"

# Assured Workload folder deletion
gcloud resource-manager folders delete ${WORKLOAD_FOLDER_ID} --quiet

# Assured Workload deletion
gcloud assured workloads delete "${ASSURED_WORKLOAD_ID}" \
    --location="${REGION}" \
    --organization="${GCP_ORGANIZATION}" \
    --project="${QUOTA_PROJECT_ID}"

10. تهانينا

اكتملت المهمة! لقد أنشأت بنجاح نظامًا لرصد السلامة في مكان العمل للصناعات المنظَّمة يستخدم Gemini لرصد الخوذات الواقية.

المهام التي أنجزتها:

  • حماية البيانات وخصوصيتها: لقد وفّرت عُقدة سرية على GKE باستخدام مفاتيح التشفير التي يديرها العميل (CMEK)
  • نطاقات البيانات: لقد فعّلت عناصر التحكّم في الامتثال للنظام الأساسي في بيئة منظَّمة

المستندات المرجعية