Utilizzo di Secret Manager con Python

1. Panoramica

In questo codelab, ti concentrerai sull'utilizzo di Secret Manager in Python.

Secret Manager consente di archiviare, gestire e accedere ai secret come BLOB binari o stringhe di testo. Se disponi delle autorizzazioni appropriate, puoi visualizzare i contenuti del secret.

Secret Manager funziona bene per archiviare informazioni di configurazione quali password dei database, chiavi API o certificati TLS necessari per un'applicazione in fase di runtime.

Obiettivi didattici

  • Come utilizzare Cloud Shell
  • Come installare la libreria client di Secret Manager per Python
  • Creare e accedere ai secret utilizzando la libreria client Python
  • Accedere ai secret in Cloud Functions utilizzando la libreria client Python

Che cosa ti serve

  • Un progetto Google Cloud
  • Un browser, ad esempio Chrome o Firefox
  • Dimestichezza con Python 3

Sondaggio

Come utilizzerai questo tutorial?

Solo lettura Leggilo e completa gli esercizi

Come valuteresti la tua esperienza con Python?

Principiante Livello intermedio Eccellente

Come giudichi la tua esperienza di utilizzo dei servizi Google Cloud?

Principiante Livello intermedio Eccellente

2. Configurazione e requisiti

Configurazione dell'ambiente da seguire in modo autonomo

  1. Accedi alla console Google Cloud e crea un nuovo progetto o riutilizzane uno esistente. Se non hai ancora un account Gmail o Google Workspace, devi crearne uno.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Il Nome progetto è il nome visualizzato dei partecipanti del progetto. Si tratta di una stringa di caratteri non utilizzata dalle API di Google. Puoi aggiornarla in qualsiasi momento.
  • L'ID progetto deve essere univoco in tutti i progetti Google Cloud ed è immutabile (non può essere modificato dopo essere stato impostato). La console Cloud genera automaticamente una stringa univoca. di solito non ti importa cosa sia. Nella maggior parte dei codelab, dovrai fare riferimento all'ID progetto (in genere è identificato come PROJECT_ID). Se l'ID generato non ti soddisfa, puoi generarne un altro casuale. In alternativa, puoi provarne una personalizzata per verificare se è disponibile. Non può essere modificato dopo questo passaggio e rimarrà per tutta la durata del progetto.
  • Per informazione, c'è un terzo valore, un numero di progetto, utilizzato da alcune API. Scopri di più su tutti e tre questi valori nella documentazione.
  1. Successivamente, dovrai abilitare la fatturazione nella console Cloud per utilizzare risorse/API Cloud. Eseguire questo codelab non dovrebbe costare molto. Per arrestare le risorse in modo da non incorrere in fatturazione oltre questo tutorial, puoi eliminare le risorse che hai creato o eliminare l'intero progetto. I nuovi utenti di Google Cloud sono idonei al programma prova senza costi di 300$.

Avvia Cloud Shell

Anche se Google Cloud può essere utilizzato da remoto dal tuo laptop, in questo codelab utilizzerai Google Cloud Shell, un ambiente a riga di comando in esecuzione nel cloud.

Attiva Cloud Shell

  1. Dalla console Cloud, fai clic su Attiva Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Se non hai mai avviato Cloud Shell, ti viene mostrata una schermata intermedia (below the fold) che descrive di cosa si tratta. In tal caso, fai clic su Continua (e non la vedrai più). Ecco come appare quella singola schermata:

9c92662c6a846a5c.png

Il provisioning e la connessione a Cloud Shell dovrebbero richiedere solo qualche istante.

9f0e51b578fecce5.png

Questa macchina virtuale viene caricata con tutti gli strumenti di sviluppo di cui hai bisogno. Offre una home directory permanente da 5 GB e viene eseguita in Google Cloud, migliorando notevolmente le prestazioni di rete e l'autenticazione. Gran parte, se non tutto, del lavoro in questo codelab può essere svolto semplicemente con un browser o Chromebook.

Una volta eseguita la connessione a Cloud Shell, dovresti vedere che il tuo account è già autenticato e il progetto è già impostato sul tuo ID progetto.

  1. Esegui questo comando in Cloud Shell per verificare che l'account sia autenticato:
gcloud auth list

Output comando

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Esegui questo comando in Cloud Shell per confermare che il comando gcloud è a conoscenza del tuo progetto:
gcloud config list project

Output comando

[core]
project = <PROJECT_ID>

In caso contrario, puoi impostarlo con questo comando:

gcloud config set project <PROJECT_ID>

Output comando

Updated property [core/project].

3. Abilita l'API Secret Manager

Prima di poter iniziare a utilizzare l'API Secret Manager, devi abilitare l'API. Tramite Cloud Shell, puoi abilitare l'API con il comando seguente:

gcloud services enable secretmanager.googleapis.com

Dovresti vedere un output simile al seguente:

Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.

4. Installazione della libreria client di Secret Manager per Python

Installa la libreria client di Secret Manager:

pip3 install --user google-cloud-secret-manager==2.10.0

5. Avvia Python interattivo

Per questo tutorial, utilizzerai un interprete Python interattivo chiamato IPython, preinstallato in Cloud Shell. Avvia una sessione eseguendo ipython in Cloud Shell:

ipython

Il risultato dovrebbe essere simile a questo:

Python 3.9.2 (default, Feb 28 2021, 17:03:44)
Type 'copyright', 'credits' or 'license' for more information
IPython 8.3.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]:

6. Creazione dei secret

Un secret contiene una o più versioni del secret. Possono essere creati utilizzando la riga di comando gcloud, ma anche Python.

Per utilizzare un secret, devi prima creare il secret con il nome del secret, quindi devi aggiungere una versione del secret, ovvero il valore del secret.

Imposta il tuo ID progetto all'interno di IPython:

PROJECT_ID = "<PROJECT_ID>"

Crea un secret

Copia il seguente codice nella tua sessione IPython:

from google.cloud import secretmanager

def create_secret(secret_id):
    # Create the Secret Manager client.
    client = secretmanager.SecretManagerServiceClient()

    # Build the resource name of the parent project.
    parent = f"projects/{PROJECT_ID}"

    # Build a dict of settings for the secret
    secret = {'replication': {'automatic': {}}}

    # Create the secret
    response = client.create_secret(secret_id=secret_id, parent=parent, secret=secret)

    # Print the new secret name.
    print(f'Created secret: {response.name}')   

Richiama la funzione per creare un nuovo secret denominato my_secret_value:

create_secret("my_secret_value")

Dovresti vedere l'output seguente:

Created secret: projects/<PROJECT_NUM>/secrets/my_secret_value

Aggiungi una versione del secret

Ora che il secret esiste, puoi assegnargli un valore creando una versione.

Copia il seguente codice nella tua sessione IPython:

def add_secret_version(secret_id, payload):
    # Create the Secret Manager client.
    client = secretmanager.SecretManagerServiceClient()

    # Build the resource name of the parent secret.
    parent = f"projects/{PROJECT_ID}/secrets/{secret_id}"

    # Convert the string payload into a bytes. This step can be omitted if you
    # pass in bytes instead of a str for the payload argument.
    payload = payload.encode('UTF-8')

    # Add the secret version.
    response = client.add_secret_version(parent=parent, payload={'data': payload})

    # Print the new secret version name.
    print(f'Added secret version: {response.name}')   

Richiama la funzione per creare un'aggiunta di una nuova versione del secret:

add_secret_version("my_secret_value", "Hello Secret Manager")

Dovresti vedere l'output seguente:

Added secret version: projects/<PROJECT_NUM>/secrets/my_secret_value/versions/1

I secret possono avere più versioni. Richiama la funzione con un valore diverso:

add_secret_version("my_secret_value", "Hello Again, Secret Manager")

Dovresti vedere l'output seguente:

Added secret version: projects/<PROJECT_NUM>/secrets/my_secret_value/versions/2

Nota come la nuova versione del nostro secret è molto più lunga dell'originale. A questo attributo verrà fatto riferimento in un secondo momento.

7. Accesso ai secret

L'accesso a una versione del secret restituisce i contenuti del secret, oltre a metadati aggiuntivi sulla versione del secret. Quando accedi a una versione del secret, puoi specificare una versione specifica o richiedere semplicemente la versione più recente specificando "il più recente".

I secret devono essere mantenuti segreti. Archiviare le credenziali dei database come secret e utilizzarle per autenticarle o archiviare le certificazioni e utilizzarle. ma non stampare direttamente i tuoi segreti, poiché questa operazione va contro lo scopo di tenerli segreti.

Eseguirai operazioni sui nostri segreti, valutandone il valore senza stamparlo direttamente. Dovrai invece stampare un hash del valore del secret.

Copia il seguente codice nella tua sessione IPython:

def access_secret_version(secret_id, version_id="latest"):
    # Create the Secret Manager client.
    client = secretmanager.SecretManagerServiceClient()

    # Build the resource name of the secret version.
    name = f"projects/{PROJECT_ID}/secrets/{secret_id}/versions/{version_id}"

    # Access the secret version.
    response = client.access_secret_version(name=name)

    # Return the decoded payload.
    return response.payload.data.decode('UTF-8')
    
import hashlib

def secret_hash(secret_value): 
  # return the sha224 hash of the secret value
  return hashlib.sha224(bytes(secret_value, "utf-8")).hexdigest()

Richiama la funzione per recuperare il secret come hash del relativo valore:

secret_hash(access_secret_version("my_secret_value"))

Dovresti vedere un output simile a un hash (il valore esatto potrebbe non corrispondere a questo output):

83f8a4edb555cde4271029354395c9f4b7d79706ffa90c746e021d11

Poiché non hai specificato una versione, è stato recuperato l'ultimo valore.

Richiama la funzione aggiungendo il numero di versione previsto per confermare:

secret_hash(access_secret_version("my_secret_value", version_id=2))

Dovresti vedere lo stesso output dell'ultimo comando:

83f8a4edb555cde4271029354395c9f4b7d79706ffa90c746e021d11

Richiama la funzione, specificando questa volta la prima versione:

secret_hash(access_secret_version("my_secret_value", version_id=1))

Questa volta dovresti vedere un hash diverso, che indica un output diverso:

9a3fc8b809ddc611c82aee950c636c7557e220893560ec2c1eeeb177

8. Utilizzo di Secret Manager con Cloud Functions

Puoi utilizzare i secret in molte parti di Google Cloud. In questa sezione ti concentrerai su Cloud Functions, l'offerta di serverless computing basata su eventi di Google.

Se ti interessa utilizzare Python in Cloud Functions, puoi seguire il documento HTTP Google Cloud Functions in Python Codelab.

Chiudi IPython chiamando la funzione exit:

exit

Dovresti tornare a Cloud Shell:

yourname@cloudshell:~ (<PROJECT_ID>)$

Prima di poter iniziare a utilizzare l'API Cloud Functions, devi abilitare l'API. Tramite Cloud Shell, puoi abilitare l'API con il comando seguente:

gcloud services enable cloudfunctions.googleapis.com cloudbuild.googleapis.com

Crea una nuova cartella per definire la funzione, creando file vuoti in cui scrivere:

mkdir secret-manager-api-demo
cd secret-manager-api-demo
touch main.py
touch requirements.txt

Apri l'editor di codice dall'angolo in alto a destra di Cloud Shell:

7651a97c51e11a24.png

Vai al file main.py all'interno della cartella secret-manager-api-demo. È qui che inserirai tutto il codice.

9. Scrittura di una funzione Cloud Functions per accedere ai secret

Sebbene l'archiviazione e il recupero dei valori dei secret dalla riga di comando o dal terminale IPython sia utile, è molto più utile essere in grado di accedere a questi secret all'interno di una funzione.

La funzione access_secret_version creata in precedenza può essere utilizzata come base per la funzione Cloud Functions.

Copia il seguente codice nel file main.py:

main.py

import os

from google.cloud import secretmanager

project_id = os.environ["PROJECT_ID"]

client = secretmanager.SecretManagerServiceClient()
name = f"projects/{project_id}/secrets/my_secret_value/versions/latest"
response = client.access_secret_version(name=name)
my_secret_value = response.payload.data.decode("UTF-8")


def secret_hello(request):
    if "Again" in my_secret_value:
        return "We meet again!\n"

    return "Hello there.\n"

Prima di poter eseguire il deployment della funzione, devi finalizzare la configurazione dell'ambiente. Ciò richiede la configurazione della dipendenza della funzione.

Crea un nuovo file denominato requirements.txt e aggiungi al suo interno il pacchetto google-cloud-secret-manager:

requirements.txt

google-cloud-secret-manager==2.10.0

A questo punto dovresti avere una cartella contenente solo un main.py e un requirements.txt.

Consentire l'accesso al secret

Prima di poter eseguire il deployment della funzione, devi consentire a Cloud Functions di accedere al tuo secret.

Torna al terminale:

c5b686edf94b5222.png

Concedi l'accesso all'account di servizio Cloud Functions per accedere al secret:

export PROJECT_ID=$(gcloud config get-value core/project)

gcloud secrets add-iam-policy-binding my_secret_value \
    --role roles/secretmanager.secretAccessor \
    --member serviceAccount:${PROJECT_ID}@appspot.gserviceaccount.com

Dovresti vedere l'output seguente:

Updated IAM policy for secret [my_secret_value].
bindings:
- members:
  - serviceAccount:<PROJECT_ID>@appspot.gserviceaccount.com
  role: roles/secretmanager.secretAccessor
etag: BwWiRUt2oB4=
version: 1

10. Deployment della funzione Cloud Functions

Data la configurazione indicata nelle sezioni precedenti, ora puoi eseguire il deployment della funzione Cloud Functions e testarla.

All'interno della cartella contenente solo i due file che hai creato, esegui il deployment della funzione:

gcloud functions deploy secret_hello \
    --runtime python39 \
    --set-env-vars PROJECT_ID=${PROJECT_ID} \
    --trigger-http \
    --allow-unauthenticated

Dovresti vedere l'output seguente (troncato):

Deploying function (may take a while - up to 2 minutes)...done.

...

entryPoint: secret_hello
httpsTrigger:
  url: https://<REGION>-<PROJECT_ID>.cloudfunctions.net/secret_hello
...
status: ACTIVE
...

Recupera l'URL della funzione (metadati httpsTrigger.url) con il seguente comando:

FUNCTION_URL=$(gcloud functions describe secret_hello --format 'value(httpsTrigger.url)')

Ora, verifica che la funzione sia accessibile con il valore restituito previsto, chiamando la funzione:

curl $FUNCTION_URL

Dovresti vedere l'output seguente:

We meet again!

Questa funzione fa riferimento alla versione più recente del secret, che è stata impostata per contenere la stringa "Again", quindi la funzione funziona come previsto.

11. Complimenti!

Hai imparato a utilizzare l'API Secret Manager con Python.

Esegui la pulizia

Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial:

  • Nella console Cloud, vai alla pagina Gestisci risorse.
  • Nell'elenco dei progetti, seleziona il progetto e fai clic su Elimina.
  • Nella finestra di dialogo, digita l'ID progetto e fai clic su Chiudi per eliminare il progetto.

Scopri di più

Licenza

Questo lavoro è concesso in licenza ai sensi di una licenza Creative Commons Attribution 2.0 Generic.