Protezione di un sistema di rilevamento della sicurezza sul lavoro

1. Introduzione

In questo codelab creerai un'applicazione dimostrativa di base che illustra come integrare vari servizi Google Cloud per un servizio che si trova in un progetto con limitazioni di conformità. Questo progetto utilizza le seguenti funzionalità di sicurezza:

Questo codelab è rivolto a sviluppatori di tutti i livelli, inclusi i principianti. Utilizzerai l'interfaccia a riga di comando in Google Cloud Shell e il codice Python. Non devi essere un esperto di Python, ma una conoscenza di base di come leggere il codice ti aiuterà a comprendere i concetti.

Nota: si tratta di una prova di concetto semplificata, non di un'applicazione di produzione. In uno scenario reale, applica ulteriori precauzioni, come l'accesso esterno autenticato e protetto a questo servizio.

2. Prima di iniziare

Configurazione del progetto

../shared/_project-setup.md

Avvia Cloud Shell

Cloud Shell è un ambiente a riga di comando in esecuzione in Google Cloud che viene fornito con gli strumenti necessari precaricati.

  1. Fai clic su Attiva Cloud Shell nella parte superiore della console Google Cloud:

404e4cce0f23e5c5.png

  1. Una volta connesso a Cloud Shell, esegui questo comando per verificare l'autenticazione in Cloud Shell:
gcloud auth list
  1. Esegui il comando seguente per verificare che il progetto sia configurato per l'utilizzo con gcloud:
gcloud config get project
  1. Verifica che il progetto sia quello previsto, quindi esegui il comando riportato di seguito per impostare l'ID progetto:
export PROJECT_ID=$(gcloud config get project)

Autorizzazioni IAM obbligatorie

L'account che utilizzi per questo codelab deve disporre dei seguenti ruoli IAM. Queste autorizzazioni sono necessarie per creare le risorse Google Cloud richieste (progetti, cartelle, cluster GKE, chiavi KMS, service account e così via) e configurare il carico di lavoro Assured.

A livello di organizzazione:

  • roles/assuredworkloads.admin (Amministratore Assured Workloads): per creare e gestire la risorsa Assured Workloads stessa, garantendo la configurazione di conformità.

A livello di account di fatturazione (nel tuo account di fatturazione):

  • roles/billing.accountUser (Utente account di fatturazione): per collegare l'account di fatturazione specificato.

Configurazione delle variabili del codelab

Per creare l'infrastruttura necessaria, devi fornire le seguenti variabili di ambiente:

# 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. Creazione della base di Assured Workloads

Ora puoi creare la base per la tua applicazione in un ambiente regolamentato. Utilizza Assured Workloads per applicare i requisiti di conformità creando un ambiente controllato per le tue risorse.

Configura il progetto di quota

Abilita l'API Assured Workloads nel progetto di quota. Questa API è necessaria per creare e gestire Assured Workloads.

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

Crea l'ambiente Assured Workloads

Il comando seguente crea una "landing zone" sicura per la tua demo. Crea due nuovi progetti Google Cloud nella cartella e nell'account di fatturazione specificati.

  • Un progetto ospita il cluster GKE e l'applicazione.
  • L'altro progetto gestisce le chiavi di crittografia gestite dal cliente (CMEK).

Applica automaticamente i controlli di conformità IL5 specificati a entrambi i progetti dal momento della creazione.

Esegui il comando seguente per creare l'ambiente del carico di lavoro.

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

Abilitazione delle API Cloud richieste

Prima di creare, abilita le API richieste per i servizi necessari.

Il comando riportato di seguito attiva tutti i servizi necessari per questo codelab all'interno del progetto del carico di lavoro principale.

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. Configurazione dell'infrastruttura GKE

Crea l'infrastruttura di base che supporta il cluster GKE. Ciò comporta la configurazione di una rete dedicata per il cluster e la configurazione delle tue chiavi di crittografia per proteggere i dati sui nodi.

Configurazione della rete VPC

Crea un virtual private cloud (VPC) e una subnet personalizzati. Questo approccio ti offre il controllo completo sull'intervallo di indirizzi IP e garantisce che il cluster sia isolato come previsto.

Esegui i comandi seguenti per creare la rete VPC e una subnet nella regione specificata.

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

Configurazione della crittografia con Cloud KMS

Per soddisfare i rigorosi requisiti di conformità per i dati at-rest, utilizza le chiavi di crittografia gestite dal cliente (CMEK). In questo modo hai il controllo diretto sulle chiavi utilizzate per criptare i dischi di avvio dei nodi 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}"

Poiché la chiave di crittografia esiste in un progetto KMS separato dal servizio che deve utilizzarla, l'agente di servizio Google Compute Engine nel progetto del carico di lavoro deve avere accesso alla chiave.

Devi concedere esplicitamente all'agente di servizio GCE del progetto del carico di lavoro l'autorizzazione a utilizzare questa chiave. Il comando riportato di seguito aggiunge un'associazione di policy IAM alla chiave, assegnando il ruolo necessario all'agente di servizio.

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

Configurazione di un service account del nodo 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. Creazione e configurazione del cluster GKE

Ora puoi creare il cluster GKE. Il comando seguente esegue il provisioning di un cluster GKE con diverse funzionalità di sicurezza abilitate.

Il completamento richiede diversi minuti, poiché Google Cloud esegue il provisioning dei nodi e del piano di controllo.

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

Connessione al nuovo cluster

Per interagire con il nuovo cluster, configura lo strumento a riga di comando kubectl locale.

Questo comando recupera le credenziali e l'endpoint del cluster e configura automaticamente il file kubeconfig locale. Dopo aver eseguito questo comando, tutti i comandi kubectl che esegui verranno indirizzati al nuovo cluster GKE.

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

6. Configurazione dell'identità dell'applicazione

Per collegare un service account Kubernetes a un service account IAM di Google Cloud, configura Workload Identity.

Creazione account di servizio

Crea un service account Kubernetes (KSA) dedicato all'interno del cluster.

export GKE_NAMESPACE=default
export GKE_SA=ppe-sa

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

Successivamente, l'applicazione ha bisogno di un'identità in Google Cloud. Crea un service account IAM di Google Cloud per l'applicazione. Dopo aver creato il service account, concedigli i ruoli necessari.

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

Consentire al service account Kubernetes di impersonare quello IAM

Dopo aver creato entrambi i service account, l'ultimo passaggio consiste nel creare il collegamento tra di essi. Si tratta di una procedura in due parti. Innanzitutto, aggiungi una policy IAM al tuo service account 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}]"

In secondo luogo, annota il service account Kubernetes.

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

Al termine, tutti i pod in esecuzione nel cluster con il service account Kubernetes possono ora accedere all'API Vertex.

Nota: è possibile eliminare la simulazione dell'identità dei service account per semplificare questa configurazione. Per dettagli e limitazioni, consulta questa pagina.

7. Creazione e deployment dell'applicazione

È il momento di pacchettizzare l'applicazione, archiviarla ed eseguirne il deployment nel cluster GKE.

Creazione del repository Artifact Registry

Prima di poter eseguire l'app, pacchettizzala come container Docker e archiviala in un repository Artifact Registry. Utilizza il comando riportato di seguito per creare questo repository.

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"

Devi concedere esplicitamente al service account utilizzato dai nodi GKE la possibilità di leggere dal nuovo repository.

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"

Creazione ed esecuzione del push dell'immagine Docker

Crea ed esegui il push dell'immagine Docker nel repository. Innanzitutto, clona il codice sorgente e crea l'immagine container. Quindi, tagga l'immagine con il percorso completo di Artifact Registry ed eseguine il push nel repository creato in precedenza.

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

Deployment in GKE

Con l'immagine container disponibile in Artifact Registry, l'ultimo passaggio consiste nell'indicare a GKE di eseguirne il pull e l'esecuzione. A questo scopo, definisci le risorse dell'applicazione in un file manifest Kubernetes e applicalo al cluster. Questo comando crea gli oggetti Deployment e Service definiti nel file.

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. Test dell'applicazione

L'ultimo passaggio consiste nell'accedere all'applicazione demo ed eseguirne il test. Ciò comporta il recupero dell'indirizzo IP esterno assegnato al servizio e l'interazione con esso tramite un semplice frontend.

Recupero dell'IP esterno del servizio

Ottieni l'IP esterno del servizio esposto (il provisioning richiede circa 30 secondi)

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

Esecuzione del frontend in locale

Per questa dimostrazione, il frontend è una semplice pagina HTML/JavaScript che non fa parte del deployment GKE. È progettato per essere eseguito sulla macchina locale.

Il frontend deve essere pubblicato da Google Cloud in un'applicazione di produzione. Sulla macchina locale:

# 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

Apri http://localhost:8001/index.html in Chrome.

9. Elimina

Per evitare addebiti continui, elimina le risorse create in questo codelab.

Eliminazione del cluster GKE

Per eliminare l'intera applicazione, devi solo eliminare il cluster GKE. A tal fine, esegui:

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

Eliminazione di Assured Workloads

Esegui i comandi seguenti per eliminare tutte le risorse correlate ad Assured Workloads.

# 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. Complimenti

Missione completata Hai creato correttamente un sistema di rilevamento della sicurezza sul lavoro per i settori regolamentati che utilizza Gemini per rilevare i caschi di sicurezza.

Cosa hai fatto:

  • Protezione e privacy dei dati: hai eseguito il provisioning di un nodo GKE riservato con CMEK
  • Confini dei dati: hai abilitato i controlli di conformità della piattaforma per un ambiente regolamentato

Documenti di riferimento