Lección 3 — Secrets et conteneur

Les secrets : .env, Secret Manager, et l'option sans clé

6 min de lectura

Este contenido aún no está traducido. Se muestra la versión original.

Les secrets : .env, Secret Manager, et l'option sans clé

Un secret, c'est quoi ?

Un secret est une valeur qui donne un pouvoir à qui la possède : une clé d'API Gemini permet de consommer votre quota et de vous faire payer. Une clé qui fuit (dans un dépôt Git, une image Docker, une capture d'écran) doit être considérée comme compromise et révoquée.

flowchart TB
  subgraph L["Poste de développement"]
    E[".env (ignoré par Git)"] --> D["python-dotenv : load_dotenv()"]
  end
  subgraph P["Production sur Cloud Run"]
    SM["Secret Manager"] -->|"--set-secrets"| V["Variable d'environnement du conteneur"]
    SA["Compte de service"] -->|"aucune clé : jeton automatique"| VX["Gemini sur Vertex AI"]
  end
  D --> C["genai.Client() lit l'environnement"]
  V --> C
  SA --> C

En local : .env et python-dotenv

files/main.py
from dotenv import load_dotenv
load_dotenv()   # copie les lignes de .env dans os.environ, sans écraser ce qui existe déjà

genai.Client() sans argument lit lui-même l'environnement : GOOGLE_API_KEY pour l'API Gemini, ou GOOGLE_GENAI_USE_VERTEXAI=TRUE + GOOGLE_CLOUD_PROJECT + GOOGLE_CLOUD_LOCATION pour Vertex AI. Le code ne contient aucune clé et ne change pas d'un environnement à l'autre.

Trois réflexes :

  1. .env dans .gitignore et dans .dockerignore (voir .dockerignore) ;
  2. un .env.example versionné, avec des valeurs factices, pour documenter les variables ;
  3. ne jamais afficher une clé dans un journal ou un message d'erreur.

Vous avez committé une clé d'API, puis l'avez supprimée dans le commit suivant. Est-ce suffisant ?

En production avec une clé : Secret Manager

Si vous devez garder une clé (un fournisseur sans identité Google, un webhook signé), rangez-la dans Secret Manager, le coffre-fort de Google Cloud : chaque secret a des versions, des droits d'accès IAM et un historique d'accès.

terminal
# Créer le secret (la valeur est lue sur l'entrée standard, jamais dans l'historique du shell)
printf '%s' "$MA_CLE" | gcloud secrets create lab-api-ia-cle --data-file=- \
  --replication-policy=user-managed --locations=europe-west1 --project "$PROJECT_ID"

# Autoriser UNIQUEMENT le compte de service de l'API à le lire
gcloud secrets add-iam-policy-binding lab-api-ia-cle --project "$PROJECT_ID" \
  --member "serviceAccount:lab-api-ia@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role roles/secretmanager.secretAccessor

# Le monter en variable d'environnement du service
gcloud run deploy lab-api-ia ... --set-secrets "GOOGLE_API_KEY=lab-api-ia-cle:latest"
Façon de passer la cléVisible parVerdict
en dur dans le codetout lecteur du dépôtjamais
ENV dans le Dockerfilequiconque récupère l'imagejamais
--set-env-varsquiconque peut lire la configuration du serviceà éviter
--set-secrets (Secret Manager)le compte de service autoriséoui, si une clé est indispensable
pas de clé (Vertex AI + compte de service)personne : il n'y a rien à volerle mieux

Sur Google Cloud : pas de clé du tout

Cloud Run donne à chaque service une identité : un compte de service (un compte Google pour une application, pas pour une personne). Le SDK obtient automatiquement des jetons de courte durée pour cette identité. Si ce compte a le rôle Vertex AI User (roles/aiplatform.user), le service appelle Gemini sur Vertex AI sans aucune clé :

files/deploy.sh (extrait)
--set-env-vars "GOOGLE_GENAI_USE_VERTEXAI=TRUE,GOOGLE_CLOUD_PROJECT=${PROJECT_ID},GOOGLE_CLOUD_LOCATION=${REGION},MODEL=gemini-2.5-flash"

Ces variables ne sont pas des secrets : les connaître ne donne aucun droit.

Quelles affirmations sont vraies pour l'API déployée avec Vertex AI et un compte de service ? (plusieurs réponses)

Exercice : faire tourner une clé sans coupure

Votre API utilise (exceptionnellement) une clé montée depuis Secret Manager avec :latest. Décrivez les étapes pour la remplacer par une nouvelle clé sans interrompre le service.

Voir la solution
  1. Créer la nouvelle clé chez le fournisseur, sans révoquer l'ancienne.
  2. Ajouter une version au secret : printf '%s' "$NOUVELLE" | gcloud secrets versions add lab-api-ia-cle --data-file=-.
  3. Redéployer (ou créer une nouvelle révision) pour que les instances relisent :latest au démarrage : gcloud run services update lab-api-ia --region europe-west1 --update-labels rotation=2.
  4. Vérifier dans les journaux que les appels réussissent sur la nouvelle révision.
  5. Révoquer l'ancienne clé chez le fournisseur, puis désactiver l'ancienne version : gcloud secrets versions disable 1 --secret lab-api-ia-cle.

L'ordre compte : on ne révoque qu'une fois que plus rien n'utilise l'ancienne clé.

Résultat obtenu

Vérification réelle du 2026-10-15 avec un secret factice (créé, lu, puis supprimé) :

$ printf 'valeur-factice-pour-le-lab' | gcloud secrets create lab-api-ia-demo --data-file=- \
    --replication-policy=user-managed --locations=europe-west1 --labels=formation-lab=api-ia
Created version [1] of the secret [lab-api-ia-demo].
$ gcloud secrets versions access latest --secret lab-api-ia-demo
valeur-factice-pour-le-lab
$ gcloud secrets delete lab-api-ia-demo --quiet
Deleted secret [lab-api-ia-demo].

Le service déployé du projet final, lui, n'a utilisé aucun secret : Vertex AI et le compte de service suffisent.

Je sais faire

  • Charger la configuration locale avec .env et python-dotenv, sans jamais versionner .env
  • Créer un secret, le restreindre à un compte de service et le monter avec --set-secrets
  • Expliquer pourquoi Vertex AI + compte de service supprime le besoin de clé
  • Faire tourner une clé sans coupure
Siguiente