Utiliser Secret Manager avec Python

1. Présentation

Dans cet atelier de programmation, vous allez vous concentrer sur l'utilisation de Secret Manager dans Python.

Secret Manager vous permet de stocker des secrets, de les gérer et d'y accéder sous forme de blobs binaires ou de chaînes de texte. Muni des autorisations appropriées, vous pouvez afficher le contenu du secret.

Secret Manager est parfaitement adapté au stockage des informations de configuration telles que les mots de passe de base de données, les clés API ou les certificats TLS requis par une application lors de son exécution.

Points abordés

  • Utiliser Cloud Shell
  • Installer la bibliothèque cliente Secret Manager pour Python
  • Créer des secrets et y accéder à l'aide de la bibliothèque cliente Python
  • Accéder aux secrets dans Cloud Functions à l'aide de la bibliothèque cliente Python

Prérequis

  • Un projet Google Cloud
  • Un navigateur tel que Chrome ou Firefox
  • Maîtrise de l'utilisation de Python 3

Enquête

Comment allez-vous utiliser ce tutoriel ?

Je vais le lire uniquement Je vais le lire et effectuer les exercices

Quel est votre niveau d'expérience avec Python ?

Débutant Intermédiaire Expert

Quel est votre niveau d'expérience avec les services Google Cloud ?

Débutant Intermédiaire Expert

2. Préparation

Configuration de l'environnement au rythme de chacun

  1. Connectez-vous à la console Google Cloud, puis créez un projet ou réutilisez un projet existant. (Si vous ne possédez pas encore de compte Gmail ou Google Workspace, vous devez en créer un.)

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Le nom du projet est le nom à afficher pour les participants au projet. Il s'agit d'une chaîne de caractères non utilisée par les API Google. Vous pouvez le modifier à tout moment.
  • L'ID du projet doit être unique sur l'ensemble des projets Google Cloud et doit être immuable (vous ne pouvez pas le modifier une fois que vous l'avez défini). La console Cloud génère automatiquement une chaîne unique (en général, vous n'y accordez d'importance particulière). Dans la plupart des ateliers de programmation, vous devrez indiquer l'ID du projet (généralement identifié par PROJECT_ID). Si l'ID généré ne vous convient pas, vous pouvez en générer un autre de manière aléatoire. Vous pouvez également en spécifier un et voir s'il est disponible. Après cette étape, l'ID n'est plus modifiable et restera donc le même pour toute la durée du projet.
  • Pour information, il existe une troisième valeur (le numéro de projet) que certaines API utilisent. Pour en savoir plus sur ces trois valeurs, consultez la documentation.
  1. Vous devez ensuite activer la facturation dans la console Cloud pour utiliser les ressources/API Cloud. L'exécution de cet atelier de programmation est très peu coûteuse, voire sans frais. Pour désactiver les ressources et éviter ainsi que des frais ne vous soient facturés après ce tutoriel, vous pouvez supprimer le projet ou les ressources que vous avez créées. Les nouveaux utilisateurs de Google Cloud peuvent participer au programme d'essai sans frais pour bénéficier d'un crédit de 300$.

Démarrer Cloud Shell

Bien que Google Cloud puisse être utilisé à distance depuis votre ordinateur portable, nous allons nous servir de Google Cloud Shell pour cet atelier de programmation, un environnement de ligne de commande exécuté dans le cloud.

Activer Cloud Shell

  1. Dans Cloud Console, cliquez sur Activer Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Si vous n'avez jamais démarré Cloud Shell auparavant, un écran intermédiaire s'affiche en dessous de la ligne de flottaison, décrivant de quoi il s'agit. Si tel est le cas, cliquez sur Continuer. Cet écran ne s'affiche qu'une seule fois. Voici à quoi il ressemble :

9c92662c6a846a5c.png

Le provisionnement et la connexion à Cloud Shell ne devraient pas prendre plus de quelques minutes.

9f0e51b578fecce5.png

Cette machine virtuelle contient tous les outils de développement dont vous avez besoin. Elle comprend un répertoire d'accueil persistant de 5 Go et s'exécute sur Google Cloud, ce qui améliore nettement les performances du réseau et l'authentification. Vous pouvez réaliser une grande partie, voire la totalité, des activités de cet atelier dans un simple navigateur ou sur votre Chromebook.

Une fois connecté à Cloud Shell, vous êtes en principe authentifié et le projet est défini avec votre ID de projet.

  1. Exécutez la commande suivante dans Cloud Shell pour vérifier que vous êtes authentifié :
gcloud auth list

Résultat de la commande

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Exécutez la commande suivante dans Cloud Shell pour vérifier que la commande gcloud connaît votre projet :
gcloud config list project

Résultat de la commande

[core]
project = <PROJECT_ID>

Si vous obtenez un résultat différent, exécutez cette commande :

gcloud config set project <PROJECT_ID>

Résultat de la commande

Updated property [core/project].

3. Activer l'API Secret Manager

Avant de pouvoir utiliser l'API Secret Manager, vous devez l'activer. Dans Cloud Shell, vous pouvez activer l'API à l'aide de la commande suivante :

gcloud services enable secretmanager.googleapis.com

Le résultat doit ressembler à ce qui suit :

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

4. Installer la bibliothèque cliente Secret Manager pour Python

Installez la bibliothèque cliente Secret Manager :

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

5. Démarrer Python en mode interactif

Pour une partie de ce tutoriel, vous allez utiliser un interpréteur Python interactif, appelé IPython, qui est préinstallé dans Cloud Shell. Démarrez une session en exécutant ipython dans Cloud Shell :

ipython

L'écran qui s'affiche devrait ressembler à ce qui suit :

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. Créer des Secrets

Un secret contient une ou plusieurs versions de secret. Vous pouvez les créer à l'aide de la ligne de commande gcloud ou de Python.

Pour utiliser un secret, vous devez d'abord le créer en lui attribuant un nom, puis ajouter une version du secret, qui correspond à sa valeur.

Définissez l'ID de votre projet dans IPython :

PROJECT_ID = "<PROJECT_ID>"

Créer un secret

Copiez le code suivant dans votre session 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}')   

Appelez la fonction pour créer un secret appelé my_secret_value :

create_secret("my_secret_value")

Vous devriez obtenir le résultat suivant :

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

Ajouter une version de secret

Maintenant que le secret existe, vous pouvez lui attribuer une valeur en créant une version.

Copiez le code suivant dans votre session 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}')   

Appelez la fonction pour créer une version de secret :

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

Vous devriez obtenir le résultat suivant :

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

Les secrets peuvent avoir plusieurs versions. Appelez à nouveau la fonction avec une autre valeur :

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

Vous devriez obtenir le résultat suivant :

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

Notez que la nouvelle version de notre secret est beaucoup plus longue que l'originale. Cet attribut sera référencé ultérieurement.

7. Accéder aux secrets

L'accès à la version d'un secret renvoie le contenu de ce secret, ainsi que des métadonnées supplémentaires sur cette version du secret. Lorsque vous accédez à la version d'un secret, vous pouvez spécifier une version spécifique ou simplement demander la dernière version en spécifiant "latest".

Les secrets doivent rester secrets. Stockez les identifiants de base de données en tant que secrets, puis utilisez-les pour vous authentifier, ou stockez les certifications et utilisez-les. Toutefois, n'imprimez pas directement vos secrets, car cela annulerait leur objectif de confidentialité.

Vous allez effectuer des opérations sur nos secrets, en évaluant leur valeur sans les imprimer directement. Au lieu de cela, vous allez imprimer un hachage de la valeur du secret.

Copiez le code suivant dans votre session 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()

Appelez la fonction pour récupérer le secret sous forme de hachage de sa valeur :

secret_hash(access_secret_version("my_secret_value"))

Un résultat semblable à un hachage doit s'afficher (la valeur exacte peut ne pas correspondre à ce résultat) :

83f8a4edb555cde4271029354395c9f4b7d79706ffa90c746e021d11

Comme vous n'avez pas spécifié de version, la dernière valeur a été récupérée.

Appelez la fonction en ajoutant le numéro de version attendu pour confirmer :

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

Vous devriez obtenir le même résultat que la dernière commande :

83f8a4edb555cde4271029354395c9f4b7d79706ffa90c746e021d11

Appelez de nouveau la fonction, mais cette fois en spécifiant la première version :

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

Cette fois, vous devriez obtenir un hachage différent, ce qui indique une sortie différente :

9a3fc8b809ddc611c82aee950c636c7557e220893560ec2c1eeeb177

8. Utiliser Secret Manager avec Cloud Functions

Vous pouvez utiliser des secrets dans de nombreuses parties de Google Cloud. Dans cette section, vous allez vous concentrer sur Cloud Functions, l'offre de calcul sans serveur basée sur les événements de Google.

Si vous souhaitez utiliser Python dans Cloud Functions, vous pouvez suivre l'atelier de programmation HTTP Google Cloud Functions en Python.

Fermez IPython en appelant la fonction exit :

exit

Vous devriez être redirigé vers Cloud Shell :

yourname@cloudshell:~ (<PROJECT_ID>)$

Avant de pouvoir utiliser l'API Cloud Functions, vous devez l'activer. Dans Cloud Shell, vous pouvez activer l'API à l'aide de la commande suivante :

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

Créez un dossier pour créer notre fonction, en créant des fichiers vides dans lesquels écrire :

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

Ouvrez l'éditeur de code en haut à droite de Cloud Shell :

7651a97c51e11a24.png

Accédez au fichier main.py dans le dossier secret-manager-api-demo. C'est là que vous allez placer tout votre code.

9. Écrire une fonction Cloud pour accéder aux secrets

Bien qu'il soit utile de stocker et de récupérer des valeurs secrètes à partir de la ligne de commande ou du terminal IPython, il est beaucoup plus utile de pouvoir accéder à ces secrets dans une fonction.

Vous pouvez utiliser la fonction access_secret_version que vous avez créée précédemment comme base pour votre fonction Cloud.

Copiez le code suivant dans le fichier 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"

Avant de pouvoir déployer votre fonction, vous devez finaliser la configuration de l'environnement. Pour cela, vous devez configurer la dépendance de votre fonction.

Créez un fichier nommé requirements.txt et ajoutez-y le package google-cloud-secret-manager :

requirements.txt

google-cloud-secret-manager==2.10.0

Vous devriez maintenant avoir un dossier contenant uniquement un fichier main.py et un fichier requirements.txt.

Autoriser l'accès à votre secret

Avant de pouvoir déployer votre fonction, vous devez autoriser Cloud Functions à accéder à votre secret.

Revenez au terminal :

c5b686edf94b5222.png

Accordez l'accès au compte de service Cloud Functions pour accéder à votre 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

Vous devriez obtenir le résultat suivant :

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. Déployer votre fonction Cloud

Compte tenu de la configuration que vous avez effectuée dans les sections précédentes, vous pouvez maintenant déployer et tester votre fonction Cloud.

Dans le dossier contenant uniquement les deux fichiers que vous avez créés, déployez la fonction :

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

Vous devriez obtenir le résultat suivant (tronqué) :

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

Récupérez l'URL des métadonnées httpsTrigger.url de votre fonction à l'aide de la commande suivante :

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

Vous pouvez maintenant accéder à la fonction de test avec la valeur de retour attendue en appelant votre fonction :

curl $FUNCTION_URL

Vous devriez obtenir le résultat suivant :

We meet again!

Cette fonction fait référence à la version la plus récente du secret, qui a été définie pour contenir la chaîne "Again". Elle fonctionne donc comme prévu.

11. Félicitations !

Vous avez appris à utiliser l'API Secret Manager avec Python.

Effectuer un nettoyage

Pour éviter que les ressources utilisées dans ce tutoriel soient facturées sur votre compte Google Cloud, procédez comme suit :

  • Dans la console Cloud, accédez à la page Gérer les ressources.
  • Dans la liste des projets, sélectionnez votre projet, puis cliquez sur Supprimer.
  • Dans la boîte de dialogue, saisissez l'ID du projet, puis cliquez sur Arrêter pour supprimer le projet.

En savoir plus

Licence

Ce document est publié sous une licence Creative Commons Attribution 2.0 Generic.