Utilizzo di Secret Manager con Python

1. Panoramica

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

Secret Manager ti consente di archiviare, gestire e accedere ai secret come blob binari o stringhe di testo. Con le autorizzazioni appropriate, puoi visualizzare i contenuti del secret.

Secret Manager funziona bene per archiviare informazioni relative alla configurazione, come password di database, chiavi API o certificati TLS richiesti da un'applicazione in fase di runtime.

Obiettivi didattici

  • Come utilizzare Cloud Shell
  • Come installare la libreria client di Secret Manager per Python
  • Come creare e accedere ai secret utilizzando la libreria client Python
  • Come 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
  • Familiarità con l'utilizzo di Python 3

Sondaggio

Come utilizzerai questo tutorial?

Leggilo e basta Leggilo e completa gli esercizi

Come valuteresti la tua esperienza con Python?

Principiante Intermedio Avanzato

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

Principiante Intermedio Avanzato

2. Configurazione e requisiti

Configurazione dell'ambiente 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 del progetto è il nome visualizzato per i partecipanti a questo progetto. È una stringa di caratteri non utilizzata dalle API di Google. Puoi aggiornarlo 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 interessa di cosa si tratta. Nella maggior parte dei codelab, devi fare riferimento all'ID progetto (in genere è identificato come PROJECT_ID). Se non ti piace l'ID generato, puoi generarne un altro casuale. In alternativa, puoi provare a crearne uno e vedere se è disponibile. Non può essere modificato dopo questo passaggio e rimarrà per tutta la durata del progetto.
  • Per tua informazione, esiste un terzo valore, un numero di progetto, utilizzato da alcune API. Scopri di più su tutti e tre questi valori nella documentazione.
  1. Successivamente, devi abilitare la fatturazione in Cloud Console per utilizzare le risorse/API Cloud. L'esecuzione di questo codelab non dovrebbe costare molto, se non nulla. Per arrestare le risorse in modo da non incorrere in costi di fatturazione al termine di questo tutorial, puoi eliminare le risorse che hai creato o l'intero progetto. I nuovi utenti di Google Cloud possono beneficiare del programma prova senza costi di 300$.

Avvia Cloud Shell

Sebbene Google Cloud possa essere gestito 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. Nella console Cloud, fai clic su Attiva Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Se non hai mai avviato Cloud Shell, viene visualizzata una schermata intermedia (sotto la piega) che ne descrive le funzionalità. In questo caso, fai clic su Continua e non comparirà più. Ecco come si presenta la schermata intermedia:

9c92662c6a846a5c.png

Bastano pochi istanti per eseguire il provisioning e connettersi a Cloud Shell.

9f0e51b578fecce5.png

Questa macchina virtuale è caricata con tutti gli strumenti per sviluppatori di cui hai bisogno. Offre una home directory permanente da 5 GB e viene eseguita in Google Cloud, migliorando notevolmente le prestazioni e l'autenticazione della rete. Gran parte del lavoro per questo codelab, se non tutto, può essere svolto semplicemente con un browser o con 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 verificare che il comando gcloud conosca il 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 abilitarla. Utilizzando Cloud Shell, puoi abilitare l'API con il seguente comando:

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 una parte di 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 di secret

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

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

Imposta l'ID progetto in IPython:

PROJECT_ID = "<PROJECT_ID>"

Crea un secret

Copia il seguente codice nella 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}')   

Chiama 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

Aggiungere una versione del secret

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

Copia il seguente codice nella 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}')   

Chiama la funzione per creare 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. Chiama di nuovo 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 sia 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, nonché metadati aggiuntivi sulla versione del secret. Quando accedi a una versione del secret, puoi specificare una versione specifica o semplicemente richiedere l'ultima versione specificando "latest".

I secret devono essere mantenuti segreti. Archivia le credenziali del database come secret, quindi utilizzale per l'autenticazione o archivia le certificazioni e utilizzale, ma non stampare direttamente i secret, perché in questo modo non sarebbero più segreti.

Eseguirai operazioni sui nostri secret, valutandone il valore senza stamparlo direttamente. Invece, stamperai un hash del valore del segreto.

Copia il seguente codice nella 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()

Chiama la funzione per recuperare il secret come hash del suo valore:

secret_hash(access_secret_version("my_secret_value"))

Dovresti visualizzare 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.

Chiama 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

Chiama di nuovo 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 computing serverless basata su eventi di Google.

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

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 abilitarla. Utilizzando Cloud Shell, puoi abilitare l'API con il seguente comando:

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

Crea una nuova cartella per creare la nostra 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 dalla parte in alto a destra di Cloud Shell:

7651a97c51e11a24.png

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

9. Scrivere 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 siano utili, è molto più utile poter accedere a questi secret all'interno di una funzione.

Utilizzando la funzione access_secret_version creata in precedenza, puoi utilizzarla come base per la tua 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 completare la configurazione dell'ambiente. Per farlo, devi configurare la dipendenza della funzione.

Crea un nuovo file denominato requirements.txt e aggiungici il pacchetto google-cloud-secret-manager:

requirements.txt

google-cloud-secret-manager==2.10.0

Ora dovresti avere una cartella contenente solo un file main.py e un file requirements.txt.

Consentire l'accesso al secret

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

Torna al terminale:

c5b686edf94b5222.png

Concedi l'accesso al service account Cloud Functions per accedere al tuo 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

Data la configurazione nelle sezioni precedenti, ora puoi eseguire il deployment e testare la tua funzione Cloud.

Nella 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 il seguente output (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 tua funzione (metadati httpsTrigger.url) con questo comando:

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

Ora verifica che sia possibile accedere alla funzione con il valore restituito previsto chiamandola:

curl $FUNCTION_URL

Dovresti vedere l'output seguente:

We meet again!

Questa funzione fa riferimento alla versione più recente del secret, impostata in modo da contenere la stringa "Again", quindi funziona come previsto.

11. Complimenti!

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

Esegui la pulizia

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

  • In Cloud Console, vai alla pagina Gestisci risorse.
  • Nell'elenco dei progetti, seleziona il tuo progetto e poi fai clic su Elimina.
  • Nella finestra di dialogo, digita l'ID progetto, quindi 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.