Accedi ai secret memorizzati al di fuori dei cluster GKE utilizzando le librerie client

Questo tutorial mostra come archiviare i dati sensibili utilizzati dai cluster Google Kubernetes Engine (GKE) in Secret Manager. Scopri come accedere in modo più sicuro ai dati dai tuoi pod utilizzando Workload Identity Federation for GKE e le librerie clientGoogle Cloud .

L'archiviazione dei dati sensibili al di fuori dello spazio di archiviazione del cluster riduce il rischio di accesso non autorizzato ai dati in caso di attacco. L'utilizzo di Workload Identity Federation for GKE per accedere ai dati consente di evitare i rischi associati alla gestione delle chiavi dei account di servizio di lunga durata e di controllare l'accesso ai tuoi secret utilizzando Identity and Access Management (IAM) anziché le regole RBAC nel cluster. Puoi utilizzare qualsiasi fornitore di secret store esterno, come Secret Manager o HashiCorp Vault.

Questa pagina è rivolta agli esperti di sicurezza che vogliono spostare i dati sensibili al di fuori dello spazio di archiviazione nel cluster. Per scoprire di più sui ruoli comuni e sulle attività di esempio a cui facciamo riferimento nei contenuti di Google Cloud , consulta Ruoli utente e attività comuni di GKE.

Questo tutorial utilizza un cluster GKE Autopilot. Per eseguire i passaggi utilizzando GKE Standard, devi abilitare manualmente Workload Identity Federation for GKE.

Puoi utilizzare Workload Identity Federation for GKE per accedere a qualsiasi API Google Cloud dai carichi di lavoro GKE senza dover utilizzare approcci meno sicuri come i file delle chiavi dell'account di servizio statici. Questo tutorial utilizza Secret Manager come esempio, ma puoi utilizzare gli stessi passaggi per accedere ad altre Google Cloud API. Per saperne di più, consulta la pagina Workload Identity Federation for GKE.

Obiettivi

  • Crea un secret in Google Cloud Secret Manager.
  • Crea un cluster GKE Autopilot, spazi dei nomi Kubernetes e account di servizio Kubernetes.
  • Crea criteri di autorizzazione IAM per concedere l'accesso ai tuoi service account Kubernetes sul secret.
  • Utilizza le applicazioni di test per verificare l'accesso al account di servizio.
  • Esegui un'app di esempio che accede al secret utilizzando l'API Secret Manager.

Costi

In questo documento vengono utilizzati i seguenti componenti fatturabili di Google Cloud:

Per generare una stima dei costi in base all'utilizzo previsto, utilizza il calcolatore prezzi.

I nuovi utenti di Google Cloud potrebbero avere diritto a una prova senza costi.

Al termine delle attività descritte in questo documento, puoi evitare l'addebito di ulteriori costi eliminando le risorse che hai creato. Per saperne di più, consulta Esegui la pulizia.

Prima di iniziare

  1. Accedi al tuo account Google Cloud . Se non conosci Google Cloud, crea un account per valutare le prestazioni dei nostri prodotti in scenari reali. I nuovi clienti ricevono anche 300 $di crediti senza costi per l'esecuzione, il test e il deployment dei workload.
  2. Installa Google Cloud CLI.

  3. Se utilizzi un provider di identità (IdP) esterno, devi prima accedere a gcloud CLI con la tua identità federata.

  4. Per inizializzare gcloud CLI, esegui questo comando:

    gcloud init
  5. Crea o seleziona un Google Cloud progetto.

    Ruoli richiesti per selezionare o creare un progetto

    • Seleziona un progetto: la selezione di un progetto non richiede un ruolo IAM specifico. Puoi selezionare qualsiasi progetto per il quale ti è stato concesso un ruolo.
    • Crea un progetto: per creare un progetto, devi disporre del ruolo Autore progetto (roles/resourcemanager.projectCreator), che contiene l'autorizzazione resourcemanager.projects.create. Scopri come concedere i ruoli.
    • Creare un progetto Google Cloud :

      gcloud projects create PROJECT_ID

      Sostituisci PROJECT_ID con un nome per il progetto Google Cloud che stai creando.

    • Seleziona il progetto Google Cloud che hai creato:

      gcloud config set project PROJECT_ID

      Sostituisci PROJECT_ID con il nome del progetto Google Cloud .

  6. Verifica che la fatturazione sia abilitata per il tuo progetto Google Cloud .

  7. Abilita le API Kubernetes Engine e Secret Manager:

    Ruoli richiesti per abilitare le API

    Per abilitare le API, devi disporre del ruolo IAM Amministratore utilizzo dei servizi (roles/serviceusage.serviceUsageAdmin), che include l'autorizzazione serviceusage.services.enable. Scopri come concedere i ruoli.

    gcloud services enable container.googleapis.com secretmanager.googleapis.com
  8. Installa Google Cloud CLI.

  9. Se utilizzi un provider di identità (IdP) esterno, devi prima accedere a gcloud CLI con la tua identità federata.

  10. Per inizializzare gcloud CLI, esegui questo comando:

    gcloud init
  11. Crea o seleziona un Google Cloud progetto.

    Ruoli richiesti per selezionare o creare un progetto

    • Seleziona un progetto: la selezione di un progetto non richiede un ruolo IAM specifico. Puoi selezionare qualsiasi progetto per il quale ti è stato concesso un ruolo.
    • Crea un progetto: per creare un progetto, devi disporre del ruolo Autore progetto (roles/resourcemanager.projectCreator), che contiene l'autorizzazione resourcemanager.projects.create. Scopri come concedere i ruoli.
    • Creare un progetto Google Cloud :

      gcloud projects create PROJECT_ID

      Sostituisci PROJECT_ID con un nome per il progetto Google Cloud che stai creando.

    • Seleziona il progetto Google Cloud che hai creato:

      gcloud config set project PROJECT_ID

      Sostituisci PROJECT_ID con il nome del progetto Google Cloud .

  12. Verifica che la fatturazione sia abilitata per il tuo progetto Google Cloud .

  13. Abilita le API Kubernetes Engine e Secret Manager:

    Ruoli richiesti per abilitare le API

    Per abilitare le API, devi disporre del ruolo IAM Amministratore utilizzo dei servizi (roles/serviceusage.serviceUsageAdmin), che include l'autorizzazione serviceusage.services.enable. Scopri come concedere i ruoli.

    gcloud services enable container.googleapis.com secretmanager.googleapis.com
  14. Concedi ruoli al tuo account utente. Esegui il seguente comando una volta per ciascuno dei seguenti ruoli IAM: roles/secretmanager.admin, roles/container.clusterAdmin

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE

    Sostituisci quanto segue:

    • PROJECT_ID: il tuo ID progetto.
    • USER_IDENTIFIER: l'identificatore del tuo account utente . Ad esempio: myemail@example.com.
    • ROLE: il ruolo IAM che concedi al tuo account utente.

Prepara l'ambiente

Clona il repository GitHub che contiene i file di esempio per questo tutorial:

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd ~/kubernetes-engine-samples/security/wi-secrets

Crea un secret in Secret Manager

  1. L'esempio seguente mostra i dati che utilizzerai per creare un secret:

    key=my-api-key
  2. Crea un secret per archiviare i dati di esempio:

    gcloud secrets create bq-readonly-key \
        --data-file=manifests/bq-readonly-key \
        --ttl=3600s
    

    Questo comando esegue le seguenti operazioni:

    • Crea un nuovo secret Secret Manager con la chiave di esempio nella regione us-central1 Google Cloud .
    • Imposta la scadenza del secret un'ora dopo l'esecuzione del comando.

Crea il cluster e le risorse Kubernetes

Crea un cluster GKE, spazi dei nomi Kubernetes e service account Kubernetes. Crea due spazi dei nomi, uno per l'accesso di sola lettura e uno per l'accesso in lettura/scrittura al secret. Crea anche un account di servizio Kubernetes in ogni spazio dei nomi da utilizzare con Workload Identity Federation for GKE.

  1. Crea un cluster GKE Autopilot:

    gcloud container clusters create-auto secret-cluster \
        --location=us-central1
    

    Il deployment del cluster potrebbe richiedere circa cinque minuti. I cluster Autopilot hanno sempre abilitata la federazione delle identità per i carichi di lavoro per GKE. Se invece vuoi utilizzare un cluster GKE Standard, devi abilitare manualmente Workload Identity Federation for GKE prima di continuare.

  2. Crea uno spazio dei nomi readonly-ns e uno spazio dei nomi admin-ns:

    kubectl create namespace readonly-ns
    kubectl create namespace admin-ns
    
  3. Crea un account di servizio Kubernetes readonly-sa e un account di servizio Kubernetes admin-sa:

    kubectl create serviceaccount readonly-sa --namespace=readonly-ns
    kubectl create serviceaccount admin-sa --namespace=admin-ns
    

Creazione di criteri di autorizzazione IAM

  1. Concedi al account di servizio readonly-sa l'accesso di sola lettura al secret:

    gcloud secrets add-iam-policy-binding bq-readonly-key \
        --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/readonly-ns/sa/readonly-sa \
        --role='roles/secretmanager.secretAccessor' \
        --condition=None
    

    Sostituisci quanto segue:

    • PROJECT_NUMBER: il numero di progetto Google Cloud numerico.
    • PROJECT_ID: il tuo ID progetto Google Cloud .
  2. Concedi all'account di servizio admin-sa l'accesso in lettura e scrittura al secret:

    gcloud secrets add-iam-policy-binding bq-readonly-key \
        --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/admin-ns/sa/admin-sa \
        --role='roles/secretmanager.secretAccessor' \
        --condition=None
    gcloud secrets add-iam-policy-binding bq-readonly-key \
        --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/admin-ns/sa/admin-sa \
        --role='roles/secretmanager.secretVersionAdder' \
        --condition=None
    

Verifica l'accesso segreto

Esegui il deployment dei pod di test in ogni spazio dei nomi per verificare l'accesso in lettura e scrittura e di sola lettura.

  1. Rivedi il manifest del pod di sola lettura:

    # Copyright 2022 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: readonly-test
      namespace: readonly-ns
    spec:
      containers:
      - image: google/cloud-sdk:slim
        name: workload-identity-test
        command: ["sleep","infinity"]
        resources:
          requests:
            cpu: "150m"
            memory: "150Mi"
      serviceAccountName: readonly-sa

    Questo pod utilizza il account di servizio readonly-sa nello spazio dei nomi readonly-ns.

  2. Esamina il manifest del pod di lettura/scrittura:

    # Copyright 2022 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: admin-test
      namespace: admin-ns
    spec:
      containers:
      - image: google/cloud-sdk:slim
        name: workload-identity-test
        command: ["sleep","infinity"]
        resources:
          requests:
            cpu: "150m"
            memory: "150Mi"
      serviceAccountName: admin-sa

    Questo pod utilizza il account di servizio admin-sa nello spazio dei nomi admin-ns.

  3. Esegui il deployment dei pod di test:

    kubectl apply -f manifests/admin-pod.yaml
    kubectl apply -f manifests/readonly-pod.yaml
    

    L'avvio dei pod potrebbe richiedere alcuni minuti. Per monitorare l'avanzamento, esegui questo comando:

    watch kubectl get pods -n readonly-ns
    

    Quando lo stato del pod cambia in RUNNING, premi Ctrl+C per tornare alla riga di comando.

Testare l'accesso di sola lettura

  1. Apri una shell nel pod readonly-test:

    kubectl exec -it readonly-test --namespace=readonly-ns -- /bin/bash
    
  2. Prova a leggere il secret:

    gcloud secrets versions access 1 --secret=bq-readonly-key
    

    L'output è key=my-api-key.

  3. Prova a scrivere nuovi dati nel secret:

    printf "my-second-api-key" | gcloud secrets versions add bq-readonly-key --data-file=-
    

    L'output è simile al seguente:

    ERROR: (gcloud.secrets.versions.add) PERMISSION_DENIED: Permission 'secretmanager.versions.add' denied for resource 'projects/PROJECT_ID/secrets/bq-readonly-key' (or it may not exist).
    

    Il pod che utilizza il account di servizio di sola lettura può leggere solo il secret e non può scrivere nuovi dati.

  4. Esci dal pod:

    exit
    

Testare l'accesso in lettura/scrittura

  1. Apri una shell nel pod admin-test:

    kubectl exec -it admin-test --namespace=admin-ns -- /bin/bash
    
  2. Prova a leggere il secret:

    gcloud secrets versions access 1 --secret=bq-readonly-key
    

    L'output è key=my-api-key.

  3. Prova a scrivere nuovi dati nel secret:

    printf "my-second-api-key" | gcloud secrets versions add bq-readonly-key --data-file=-
    

    L'output è simile al seguente:

    Created version [2] of the secret [bq-readonly-key].
    
  4. Leggi la nuova versione del secret:

    gcloud secrets versions access 2 --secret=bq-readonly-key
    

    L'output è my-second-api-key.

  5. Esci dal pod:

    exit
    

I pod ottengono solo il livello di accesso che hai concesso al account di servizio Kubernetes utilizzato nel manifest del pod. Tutti i pod che utilizzano l'account Kubernetes admin-sa nello spazio dei nomi admin-ns possono scrivere nuove versioni del secret, ma tutti i pod nello spazio dei nomi readonly-ns che utilizzano il account di servizio Kubernetes readonly-sa possono solo leggere il secret.

Accedere ai secret dal codice

In questa sezione, imparerai a:

  1. Esegui il deployment di un'applicazione di esempio che legge il tuo secret in Secret Manager utilizzando le librerie client.

  2. Verifica che l'applicazione possa accedere al secret.

Ti consigliamo di accedere ai secret di Secret Manager dal codice dell'applicazione ogni volta che è possibile, utilizzando l'API Secret Manager.

  1. Esamina il codice sorgente dell'applicazione di esempio:

    // Copyright 2022 Google LLC
    //
    // Licensed under the Apache License, Version 2.0 (the "License");
    // you may not use this file except in compliance with the License.
    // You may obtain a copy of the License at
    //
    //     http://www.apache.org/licenses/LICENSE-2.0
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.
    
    package main
    
    import (
    	"context"
    	"fmt"
    	"log"
    	"os"
    
    	secretmanager "cloud.google.com/go/secretmanager/apiv1"
    	secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
    )
    
    func main() {
    
            // Get environment variables from Pod spec.
            projectID := os.Getenv("PROJECT_ID")
            secretId := os.Getenv("SECRET_ID")
            secretVersion := os.Getenv("SECRET_VERSION")
    
            // Create the Secret Manager client.
            ctx := context.Background()
            client, err := secretmanager.NewClient(ctx)
            if err != nil {
                    log.Fatalf("failed to setup client: %v", err)
            }
            defer client.Close()
    
            // Create the request to access the secret.
            accessSecretReq := &secretmanagerpb.AccessSecretVersionRequest{
                    Name: fmt.Sprintf("projects/%s/secrets/%s/versions/%s", projectID, secretId, secretVersion),
            }
    
            secret, err := client.AccessSecretVersion(ctx, accessSecretReq)
            if err != nil {
                    log.Fatalf("failed to access secret: %v", err)
            }
    
            // Print the secret payload.
            //
            // WARNING: Do not print the secret in a production environment - this
            // snippet is showing how to access the secret material.
            log.Printf("Welcome to the key store, here's your key:\nKey: %s", secret.Payload.Data)
    }
    

    Questa applicazione chiama l'API Secret Manager per tentare di leggere il segreto.

  2. Esamina il manifest del pod dell'applicazione di esempio:

    # Copyright 2022 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: readonly-secret-test
      namespace: readonly-ns
    spec:
      containers:
      - image: us-docker.pkg.dev/google-samples/containers/gke/wi-secret-store:latest
        name: secret-app
        env:
          - name: PROJECT_ID
            value: "YOUR_PROJECT_ID"
          - name: SECRET_ID
            value: "bq-readonly-key"
          - name: SECRET_VERSION
            value: "latest"
        resources:
          requests:
            cpu: "125m"
            memory: "64Mi"
      serviceAccountName: readonly-sa

    Questo manifest fa quanto segue:

    • Crea un pod nello spazio dei nomi readonly-ns che utilizza il account di servizio readonly-sa.
    • Esegue il pull di un'applicazione di esempio da un registro delle immagini Google. Questa applicazione chiama l'API Secret Manager utilizzando le librerie clientGoogle Cloud . Puoi visualizzare il codice dell'applicazione in /main.go nel repository.
    • Imposta le variabili di ambiente da utilizzare per l'applicazione di esempio.
  3. Sostituisci le variabili di ambiente nell'applicazione di esempio:

    sed -i "s/YOUR_PROJECT_ID/PROJECT_ID/g" "manifests/secret-app.yaml"
    
  4. Distribuisci l'applicazione di esempio:

    kubectl apply -f manifests/secret-app.yaml
    

    L'avvio del pod potrebbe richiedere alcuni minuti. Se il pod ha bisogno di un nuovo nodo nel cluster, potresti notare eventi di tipo CrashLoopBackOff mentre GKE esegue il provisioning del nodo. Gli arresti anomali si interrompono quando il nodo viene eseguito il provisioning correttamente.

  5. Verifica l'accesso segreto:

    kubectl logs readonly-secret-test -n readonly-ns
    

    L'output è my-second-api-key. Se l'output è vuoto, il pod potrebbe non essere ancora in esecuzione. Attendi alcuni minuti e riprova.

Approcci alternativi

Se devi montare i tuoi dati sensibili sui pod, utilizza il componente aggiuntivo Secret Manager per GKE. Questo componente aggiuntivo esegue il deployment e gestisce il provider Google Cloud Secret Manager per il driver CSI Kubernetes Secret Store nei tuoi cluster GKE. Per istruzioni, consulta Utilizzare il componente aggiuntivo Secret Manager con GKE.

Fornire secret come volumi montati comporta i seguenti rischi:

  1. I volumi montati sono vulnerabili agli attacchi di attraversamento delle directory.
  2. Le variabili di ambiente possono essere compromesse a causa di configurazioni errate, ad esempio l'apertura di un endpoint di debug.

Se possibile, ti consigliamo di accedere ai secret a livello di programmazione tramite l'API Secret Manager. Per istruzioni, utilizza l'applicazione di esempio in questo tutorial o consulta le librerie client di Secret Manager.

Esegui la pulizia

Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, elimina il progetto che contiene le risorse oppure mantieni il progetto ed elimina le singole risorse.

Elimina singole risorse

  1. Elimina il cluster:

    gcloud container clusters delete secret-cluster \
        --location=us-central1
    
  2. (Facoltativo) Elimina il secret in Secret Manager:

    gcloud secrets delete bq-readonly-key
    

    Se non esegui questo passaggio, il secret scade automaticamente perché hai impostato il flag --ttl durante la creazione.

Elimina il progetto

    Elimina un progetto Google Cloud :

    gcloud projects delete PROJECT_ID

Passaggi successivi