Sicherheit eines Systems zur Erkennung von Arbeitssicherheitsrisiken

1. Einführung

In diesem Codelab erstellen Sie eine einfache Demoanwendung, die veranschaulicht, wie Sie verschiedene Google Cloud-Dienste für einen Dienst in einem Projekt mit Compliance-Einschränkungen einbinden. In diesem Projekt werden die folgenden Sicherheitsfunktionen verwendet:

Dieses Codelab richtet sich an Entwickler aller Erfahrungsstufen, auch an Anfänger. Sie verwenden die Befehlszeile in Google Cloud Shell und Python-Code. Sie müssen kein Python-Experte sein, aber ein grundlegendes Verständnis dafür, wie man Code liest, hilft Ihnen, die Konzepte zu verstehen.

Hinweis:Dies ist ein vereinfachter Proof-of-Concept und keine Produktionsanwendung. In einem realen Szenario sollten Sie zusätzliche Vorsichtsmaßnahmen wie authentifizierten und gesicherten externen Zugriff auf diesen Dienst anwenden.

2. Hinweis

Projekteinrichtung

../shared/_project-setup.md

Cloud Shell starten

Cloud Shell ist eine Befehlszeilenumgebung, die in Google Cloud ausgeführt wird und mit den erforderlichen Tools vorinstalliert ist.

  1. Klicken Sie oben in der Google Cloud Console auf Cloud Shell aktivieren:

404e4cce0f23e5c5.png

  1. Sobald Sie mit Cloud Shell verbunden sind, führen Sie diesen Befehl aus, um Ihre Authentifizierung in Cloud Shell zu bestätigen:
gcloud auth list
  1. Führen Sie den folgenden Befehl aus, um zu bestätigen, dass Ihr Projekt für die Verwendung mit gcloud konfiguriert ist:
gcloud config get project
  1. Prüfen Sie, ob das Projekt wie erwartet ist, und führen Sie dann den folgenden Befehl aus, um Ihre Projekt-ID festzulegen:
export PROJECT_ID=$(gcloud config get project)

Erforderliche IAM-Berechtigungen

Das Konto, das Sie für dieses Codelab verwenden, muss die folgenden IAM-Rollen haben. Diese Berechtigungen sind erforderlich, um die erforderlichen Google Cloud-Ressourcen (Projekte, Ordner, GKE-Cluster, KMS-Schlüssel, Dienstkonten usw.) zu erstellen und die Assured Workload zu konfigurieren.

Auf Organisationsebene:

  • roles/assuredworkloads.admin (Assured Workloads-Administrator): Zum Erstellen und Verwalten der Assured Workloads-Ressource selbst und zum Sicherstellen der Compliance-Konfiguration.

Auf Rechnungskontoebene (in Ihrem Rechnungskonto):

  • roles/billing.accountUser (Rechnungskontonutzer): Zum Verknüpfen des angegebenen Rechnungskontos.

Codelab-Variablen konfigurieren

Zum Erstellen der erforderlichen Infrastruktur müssen Sie die folgenden Umgebungsvariablen angeben:

# 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-Grundlage erstellen

Sie können jetzt den Grundstein für Ihre Anwendung in einer regulierten Umgebung legen. Mit Assured Workloads können Sie Compliance-Anforderungen durchsetzen, indem Sie eine kontrollierte Umgebung für Ihre Ressourcen erstellen.

Kontingentprojekt konfigurieren

Aktivieren Sie die Assured Workloads API in Ihrem Kontingentprojekt. Diese API ist zum Erstellen und Verwalten von Assured Workloads erforderlich.

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

Assured Workloads-Umgebung erstellen

Mit dem folgenden Befehl wird eine sichere „Landing Zone“ für Ihre Demo erstellt. Dabei werden zwei neue Google Cloud-Projekte unter dem angegebenen Ordner und Rechnungskonto erstellt.

  • Ein Projekt hostet Ihren GKE-Cluster und Ihre Anwendung.
  • Im anderen Projekt werden Ihre kundenverwalteten Verschlüsselungsschlüssel (Customer Managed Encryption Keys, CMEK) verwaltet.

Die angegebenen IL5-Compliance-Kontrollen werden automatisch auf beide Projekte angewendet, sobald sie erstellt werden.

Führen Sie den folgenden Befehl aus, um die Arbeitslastumgebung zu erstellen.

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)")

Erforderliche Google Cloud APIs aktivieren

Aktivieren Sie vor dem Erstellen die erforderlichen APIs für die benötigten Dienste.

Mit dem folgenden Befehl werden alle erforderlichen Dienste für dieses Codelab in Ihrem primären Arbeitslastprojekt aktiviert.

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-Infrastruktur einrichten

Erstellen Sie die Kerninfrastruktur, die Ihren GKE-Cluster unterstützt. Dazu müssen Sie ein dediziertes Netzwerk für Ihren Cluster einrichten und Ihre eigenen Verschlüsselungsschlüssel konfigurieren, um die Daten auf Ihren Knoten zu schützen.

VPC-Netzwerk konfigurieren

Benutzerdefiniertes VPC-Netzwerk (Virtual Private Cloud) und Subnetzwerk erstellen So haben Sie die volle Kontrolle über den IP-Adressbereich und stellen sicher, dass Ihr Cluster wie vorgesehen isoliert ist.

Führen Sie die folgenden Befehle aus, um das VPC-Netzwerk und ein Subnetzwerk in der angegebenen Region zu erstellen.

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}"

Verschlüsselung mit Cloud KMS konfigurieren

Wenn Sie strenge Compliance-Anforderungen für inaktive Daten erfüllen müssen, verwenden Sie kundenverwaltete Verschlüsselungsschlüssel (Customer-Managed Encryption Keys, CMEK). So haben Sie die direkte Kontrolle über die Schlüssel, mit denen die Bootlaufwerke Ihrer GKE-Knoten verschlüsselt werden.

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}"

Da sich der Verschlüsselungsschlüssel in einem separaten KMS-Projekt vom Dienst befindet, der ihn verwenden muss, benötigt der Google Compute Engine-Dienst-Agent im Arbeitslastprojekt Zugriff auf den Schlüssel.

Sie müssen dem GCE-Dienst-Agenten aus dem Arbeitslastprojekt explizit die Berechtigung zur Verwendung dieses Schlüssels erteilen. Mit dem folgenden Befehl wird dem Schlüssel eine IAM-Richtlinienbindung hinzugefügt, die dem Dienst-Agenten die erforderliche Rolle zuweist.

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-Knotendienstkonto konfigurieren

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-Cluster erstellen und konfigurieren

Jetzt können Sie den GKE-Cluster erstellen. Mit dem folgenden Befehl wird ein GKE-Cluster mit mehreren aktivierten Sicherheitsfunktionen bereitgestellt.

Das kann einige Minuten dauern, da Google Cloud die Knoten und die Steuerungsebene bereitstellt.

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

Verbindung zum neuen Cluster herstellen

Konfigurieren Sie Ihr lokales kubectl-Befehlszeilentool, um mit Ihrem neuen Cluster zu interagieren.

Mit diesem Befehl werden die Anmeldedaten und der Endpunkt des Clusters abgerufen und Ihre lokale kubeconfig-Datei wird automatisch konfiguriert. Danach werden alle kubectl-Befehle, die Sie ausführen, an Ihren neuen GKE-Cluster weitergeleitet.

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

6. Konfiguration der Anwendungsidentität

Wenn Sie ein Kubernetes-Dienstkonto mit einem Google Cloud-IAM-Dienstkonto verbinden möchten, konfigurieren Sie Workload Identity.

Dienstkonten erstellen

Erstellen Sie ein dediziertes Kubernetes-Dienstkonto (Kubernetes Service Account, KSA) in Ihrem Cluster.

export GKE_NAMESPACE=default
export GKE_SA=ppe-sa

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

Als Nächstes benötigt Ihre Anwendung eine Identität in Google Cloud. Erstellen Sie ein Google Cloud IAM-Dienstkonto für die Anwendung. Nachdem Sie das Dienstkonto erstellt haben, weisen Sie ihm die erforderlichen Rollen zu.

# 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"

Dem Kubernetes-Dienstkonto erlauben, die Identität des IAM-Dienstkontos zu übernehmen

Nachdem Sie beide Dienstkonten erstellt haben, müssen Sie sie verknüpfen. Der Vorgang besteht aus zwei Teilen. Fügen Sie zuerst Ihrem Google Cloud-Dienstkonto eine IAM-Richtlinie hinzu.

# 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}]"

Zweitens müssen Sie Ihr Kubernetes-Dienstkonto annotieren.

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

Danach kann jeder Pod, der in Ihrem Cluster mit dem Kubernetes-Dienstkonto ausgeführt wird, auf die Vertex API zugreifen.

Hinweis: Sie können die Dienstkonto-Identitätsübernahme vermeiden, um diese Konfiguration zu vereinfachen. Weitere Informationen und Einschränkungen finden Sie hier.

7. Anwendungs-Build und ‑Bereitstellung

Jetzt ist es an der Zeit, Ihre Anwendung zu verpacken, zu speichern und in Ihrem GKE-Cluster bereitzustellen.

Artifact Registry-Repository erstellen

Bevor Sie die App ausführen können, müssen Sie sie als Docker-Container verpacken und in einem Artifact Registry-Repository speichern. Verwenden Sie den folgenden Befehl, um dieses Repository zu erstellen.

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"

Sie müssen dem von den GKE-Knoten verwendeten Dienstkonto explizit die Berechtigung zum Lesen aus Ihrem neuen Repository erteilen.

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-Image erstellen und per Push übertragen

Docker-Image erstellen und per Push in das Repository übertragen Klonen Sie zuerst den Quellcode und erstellen Sie das Container-Image. Taggen Sie es dann mit dem vollständigen Artifact Registry-Pfad und übertragen Sie es per Push in das Repository, das Sie zuvor erstellt haben.

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}"

In GKE bereitstellen

Nachdem das Container-Image in Artifact Registry verfügbar ist, müssen Sie GKE nur noch anweisen, es abzurufen und auszuführen. Dazu definieren Sie die Ressourcen Ihrer Anwendung in einer Kubernetes-Manifestdatei und wenden sie auf den Cluster an. Mit diesem Befehl werden die in der Datei definierten Deployment- und Dienstobjekte erstellt.

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. Anwendung testen

Im letzten Schritt greifen Sie auf die Demo-App zu und testen sie. Dazu muss die dem Dienst zugewiesene externe IP-Adresse abgerufen und über ein einfaches Frontend mit ihr interagiert werden.

Externe IP-Adresse des Diensts abrufen

Rufen Sie die externe IP-Adresse des freigegebenen Dienstes ab (die Bereitstellung dauert etwa 30 Sekunden).

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

Frontend lokal ausführen

Für diese Demonstration ist das Frontend eine einfache HTML-/JavaScript-Seite, die nicht Teil des GKE-Deployments ist. Es ist für die Ausführung auf Ihrem lokalen Computer konzipiert.

Das Frontend sollte in einer Produktionsanwendung über GCP bereitgestellt werden. Auf dem lokalen Computer:

# 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

Öffnen Sie http://localhost:8001/index.html in Chrome.

9. Bereinigen

Löschen Sie die in diesem Codelab erstellten Ressourcen, um laufende Gebühren zu vermeiden.

GKE-Cluster löschen

Wenn Sie die gesamte Anwendung löschen möchten, müssen Sie nur den GKE-Cluster löschen. Führen Sie dazu den folgenden Befehl aus:

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

Assured Workloads löschen

Führen Sie die folgenden Befehle aus, um alle mit Assured Workloads verknüpften Ressourcen zu löschen.

# 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. Glückwunsch

Mission abgeschlossen! Sie haben erfolgreich ein System zur Erkennung von Arbeitsschutzmaßnahmen für regulierte Branchen entwickelt, das Gemini verwendet, um Schutzhelme zu erkennen.

Ihr Lernerfolg:

  • Datenschutz und ‑sicherheit:Sie haben einen Confidential GKE-Knoten mit CMEK bereitgestellt.
  • Datengrenzen:Sie haben Plattform-Compliance-Einstellungen für eine regulierte Umgebung aktiviert.

Referenzdokumente