0Pricing
DevOps Bootcamp · Leçon

Gérer les secrets en toute sécurité et assainir l’environnement

Évitez d’exposer les identifiants dans les listes de processus et les journaux en utilisant l’entrée standard, des fichiers et des environnements nettoyés.

Gérer les secrets en toute sécurité et assainir l’environnement est une leçon DevOps Bootcamp gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage DevOps Bootcamp, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours DevOps Bootcamp comprend 4 leçons au total.

Pourquoi l’hygiène des secrets est importante

Les secrets — clés d’API, mots de passe, jetons — sont les données les plus sensibles de tout système. Une mauvaise gestion dans les scripts Bash constitue l’une des erreurs de sécurité les plus fréquentes et les plus dommageables.

  • Listes des processus : les arguments transmis aux commandes apparaissent dans ps aux, /proc/<pid>/cmdline et les journaux d’audit du système ; ils sont visibles par tous les utilisateurs de l’hôte.
  • Historique du shell : les commandes saisies de manière interactive (et parfois les scripts) sont enregistrées dans ~/.bash_history.
  • Fichiers journaux : les traces de set -x, les journaux des applications et les sorties de l’intégration et du déploiement continus peuvent capturer les valeurs des variables.
  • Fuite par l’environnement : les processus enfants héritent de l’environnement complet de leur parent, y compris les secrets exportés.

Un script renforcé traite les secrets comme une matière radioactive : minimiser la durée d’exposition, limiter la surface concernée et tout assainir lors de la sortie.

La surface d’attaque liée à la liste des processus

Lorsque vous transmettez un secret comme argument de ligne de commande, tous les utilisateurs du système peuvent le lire immédiatement via ps. Ce n’est pas théorique : cette méthode est régulièrement exploitée dans les environnements d’hébergement partagé et de conteneurs.

L’extrait ci-dessous présente le problème et sa correction côte à côte.

#!/usr/bin/env bash
# DANGEROUS: password visible in 'ps aux' output
# curl -u "admin:SuperSecret123" https://api.example.com/data

# SAFE: pass credentials via stdin or a flag that reads from a file
# Many tools support reading secrets from stdin with '-' or dedicated flags:

# Option 1 — pipe the secret so it never appears in argv
echo 'SuperSecret123' | curl -u 'admin' --password-stdin \
  https://api.example.com/data 2>/dev/null || true

# Option 2 — write a temporary netrc and point curl at it
# (covered in a later scene)
echo 'Secret never touches the command line this way'

Lire les secrets depuis l’entrée standard

La méthode interactive la plus sûre consiste à lire un secret au moment de l’exécution avec read -rs. L’option -s désactive l’écho afin que les caractères ne soient jamais affichés, tandis que -r empêche l’interprétation des barres obliques inverses.

Points clés :

  • La variable n’est jamais exportée ; les processus enfants ne peuvent donc pas la voir via /proc/<pid>/environ.
  • Après utilisation, supprimez immédiatement la variable avec unset afin de réduire la fenêtre d’exposition.
  • Évitez echo "$SECRET" — utilisez printf '%s' pour empêcher qu’un saut de ligne final ne corrompe la valeur et pour qu’elle reste invisible dans les traces.
#!/usr/bin/env bash
set -euo pipefail

# Prompt on stderr so stdout stays clean for piping
read -rsp 'Enter API token: ' API_TOKEN <&2
printf '\n' >&2

# Use the secret — printf keeps it out of argv
response=$(printf '%s' "$API_TOKEN" | curl -sS -X POST \
  -H 'Content-Type: application/json' \
  --data-binary @- \
  https://httpbin.org/post 2>/dev/null) || true

echo "Request sent."

# Scrub immediately — unset removes it from shell memory
unset API_TOKEN

Secrets dans les fichiers : permissions et propriété

Lorsqu’un secret doit être conservé sur le disque (par exemple, une clé de compte de service), les permissions du fichier constituent votre première ligne de défense.

  • Mode 0600 — lisible et modifiable uniquement par le propriétaire. Aucun accès pour le groupe ni pour les autres utilisateurs.
  • Mode 0400 — accessible en lecture seule par le propriétaire. Privilégiez ce mode pour les clés que vous ne devez jamais écraser accidentellement.
  • Stockez les fichiers de secrets dans un répertoire dédié, tel que ~/.secrets/ ou /run/secrets/ (ce dernier est un tmpfs reposant sur la RAM dans de nombreux systèmes Linux et ne subsiste que jusqu’au redémarrage).
  • Ne placez jamais de fichiers de secrets dans un répertoire suivi par git sans un fichier .gitignore parfaitement fiable.
#!/usr/bin/env bash
set -euo pipefail

SECRETS_DIR="${HOME}/.secrets"
mkdir -p "$SECRETS_DIR"
chmod 700 "$SECRETS_DIR"   # directory: only owner can list contents

KEY_FILE="${SECRETS_DIR}/api_token"

# Write secret — atomically restrict permissions before writing content
install -m 0600 /dev/null "$KEY_FILE"
printf '%s' 'my-super-secret-token' > "$KEY_FILE"

echo "Permissions:"
ls -la "$KEY_FILE"

# Read back safely — no subshell, no echo
API_TOKEN=$(< "$KEY_FILE")
echo "Token length: ${#API_TOKEN} chars (value not printed)"
unset API_TOKEN

Utiliser un fichier .netrc avec curl

curl prend en charge un fichier ~/.netrc (ou un chemin quelconque indiqué via --netrc-file) qui associe des noms d’hôte à des identifiants. Les données d’authentification restent ainsi complètement absentes de la ligne de commande et du corps du script.

Le format du fichier est simple :

machine api.example.com
  login admin
  password s3cr3t

Bonnes pratiques :

  • Définissez toujours chmod 0600 ~/.netrc — curl refuse le fichier s’il est lisible par tous sur certains systèmes.
  • Utilisez --netrc-file /run/secrets/netrc pour désigner un secret reposant sur un tmpfs ou injecté dans un conteneur.
  • Supprimez les fichiers netrc temporaires avec un trap sur EXIT.
#!/usr/bin/env bash
set -euo pipefail

TMP_NETRC=$(mktemp)
chmod 0600 "$TMP_NETRC"

# Trap ensures cleanup even on error or signal
trap 'rm -f "$TMP_NETRC"' EXIT

# Write credentials to the temp netrc
cat > "$TMP_NETRC" <<'EOF'
machine httpbin.org
  login myuser
  password mypassword
EOF

curl -fsS --netrc-file "$TMP_NETRC" \
  https://httpbin.org/basic-auth/myuser/mypassword \
  -o /dev/null -w 'HTTP %{http_code}\n' || true

# trap fires here: $TMP_NETRC is deleted
echo 'Temp netrc cleaned up by trap.'

Hygiène des variables d’environnement

Les variables d’environnement sont un moyen courant d’injecter des secrets dans les scripts (applications 12 facteurs, chaînes CI/CD). Cependant, elles sont transmises à chaque processus fils et apparaissent dans /proc/<pid>/environ pendant toute la durée de vie du processus.

Mesures défensives :

  • Importez immédiatement le secret dans une variable locale et annulez la variable d’environnement afin que les processus fils ne puissent pas en hériter.
  • Transmettez les secrets aux commandes concernées à l’aide de env -i ou d’une affectation en ligne, plutôt qu’au moyen de l’environnement entièrement hérité.
  • N’exportez jamais une variable contenant un secret — utilisez si possible une affectation seule (sans export).
#!/usr/bin/env bash
set -euo pipefail

# Simulate a secret arriving via environment (e.g., from CI system)
export DB_PASSWORD='hunter2'   # set by CI — we did not choose this

# Capture locally, then strip from environment immediately
db_password="$DB_PASSWORD"
unset DB_PASSWORD

# Verify the env var is gone before spawning any child process
if printenv DB_PASSWORD 2>/dev/null; then
  echo 'ERROR: DB_PASSWORD still in environment!' >&2
  exit 1
fi

echo 'Secret captured and env var scrubbed.'
echo "Password length: ${#db_password}"
unset db_password

Empêcher l’apparition des secrets dans les traces de set -x

set -x (xtrace) est extrêmement utile pour le débogage, mais affiche sur stderr la valeur de chaque variable qu’il développe — y compris les secrets. Ces traces finissent souvent dans les journaux CI ou syslog.

Stratégies pour protéger les secrets tout en conservant des traces utiles :

  • Désactivez temporairement les traces autour des opérations sensibles avec { set +x; } 2>/dev/null.
  • Réactivez-les ensuite avec set -x.
  • Redirigez la sortie xtrace vers un descripteur de fichier distinct qui pointe vers un fichier journal protégé, et non vers le flux de journal public.
#!/usr/bin/env bash
set -euo pipefail
set -x   # tracing ON — safe for non-sensitive sections

echo 'Building application...'
SRC_DIR='/tmp/build'
mkdir -p "$SRC_DIR"

# Disable xtrace around secret handling (suppress the set +x line itself)
{ set +x; } 2>/dev/null

read -rsp 'Token (hidden from trace): ' SECRET_TOKEN <&2
printf '\n' >&2
token_len=${#SECRET_TOKEN}
unset SECRET_TOKEN

set -x  # tracing back ON

echo "Token captured (length=$token_len). Continuing build..."
ls "$SRC_DIR"

Nettoyage des secrets dans les fichiers journaux

Même lorsque vous êtes prudent, des secrets se retrouvent parfois dans la sortie des journaux — en particulier dans les scripts verbeux ou anciens. Une fonction d’encapsulation de la journalisation qui masque les motifs connus ajoute un filet de sécurité.

Cette méthode utilise un remplacement fondé sur une expression régulière pour toute la sortie des journaux. Il s’agit d’une couche de dernier recours, et non d’un remplacement des autres pratiques d’hygiène déjà présentées.

#!/usr/bin/env bash
set -euo pipefail

# A logging function that scrubs common secret patterns before writing
log() {
  local line
  # Replace anything that looks like key=VALUE or password=VALUE
  line=$(printf '%s\n' "$*" \
    | sed -E 's/(password|token|secret|key)=[^[:space:]]*/\1=***REDACTED***/gi')
  printf '[%s] %s\n' "$(date -u '+%T')" "$line"
}

# Usage:
log 'Connecting to database with password=hunter2'
log 'Loaded API token=sk-abc123xyz secret'
log 'Build step completed successfully'   # unchanged

Environnements isolés avec env -i

env -i démarre une commande avec un environnement complètement vide, empêchant toute variable héritée — y compris les secrets transmis accidentellement — d’atteindre le processus fils. Vous transmettez ensuite explicitement uniquement ce qui est nécessaire.

C’est particulièrement utile pour exécuter des scripts non fiables, des outils de compilation ou des utilitaires tiers susceptibles d’exfiltrer les données d’environnement.

#!/usr/bin/env bash
set -euo pipefail

# Polluted parent environment (simulating a CI runner)
export AWS_SECRET_ACCESS_KEY='AKIAIOSFODNN7EXAMPLE'
export GITHUB_TOKEN='ghp_faketoken123'
export HOME="$HOME"
export PATH="$PATH"

echo '--- Child sees full environment:'
env | grep -E 'AWS|GITHUB' | head -5

echo '--- Sanitised child (env -i) sees nothing secret:'
env -i HOME="$HOME" PATH="$PATH" TERM="${TERM:-dumb}" \
  bash -c 'env | grep -E "AWS|GITHUB" || echo "No secrets visible"'

unset AWS_SECRET_ACCESS_KEY GITHUB_TOKEN

Fichiers de secrets temporaires sur tmpfs

tmpfs est un système de fichiers reposant sur la RAM. Les fichiers qui y sont écrits ne sont jamais vidés sur le disque, ce qui élimine le risque que des secrets subsistent dans l’espace d’échange, le cache disque ou des instantanés.

  • Sous Linux, /dev/shm et /run/user/<uid> sont généralement des montages tmpfs.
  • Associez toujours l’utilisation de tmpfs à un trap EXIT afin de supprimer les fichiers lorsque le script se termine.
  • Dans les conteneurs (Docker, Kubernetes), les secrets peuvent être montés directement comme volumes tmpfs dans /run/secrets.
#!/usr/bin/env bash
set -euo pipefail

# Prefer /run/user/$UID (user-owned tmpfs) or /dev/shm (world-readable dir!)
if [[ -d "/run/user/$UID" ]]; then
  TMPFS_DIR="/run/user/$UID"
elif [[ -d '/dev/shm' ]]; then
  TMPFS_DIR='/dev/shm'
else
  # Fallback: warn that disk will be used
  echo 'WARNING: No tmpfs available; using /tmp (disk-backed)' >&2
  TMPFS_DIR='/tmp'
fi

SECRET_FILE=$(mktemp "${TMPFS_DIR}/secret.XXXXXX")
chmod 0600 "$SECRET_FILE"
trap 'shred -u "$SECRET_FILE" 2>/dev/null || rm -f "$SECRET_FILE"' EXIT

printf '%s' 'my-runtime-token' > "$SECRET_FILE"
echo "Secret stored in: $SECRET_FILE"
df -T "$SECRET_FILE" | awk 'NR==2 {print "Filesystem type:", $2}'

# Use the secret...
token=$(< "$SECRET_FILE")
echo "Token length: ${#token}"
unset token
# trap fires on exit: file shredded

Tout mettre en pratique : un script de déploiement renforcé

Le script suivant combine toutes les techniques de cette leçon dans un assistant de déploiement réaliste. Observez comment chaque couche de défense renforce les autres :

  • Lecture depuis stdin avec -s — aucun écho dans le terminal
  • Fichier de secrets tmpfs avec nettoyage par trap
  • Nettoyage de l’environnement — le secret est annulé avant tout sous-processus
  • Protection contre xtrace — les traces sont suspendues autour du code sensible
  • Masquage des journaux — expression régulière de sécurité avant l’écriture dans le journal
#!/usr/bin/env bash
set -euo pipefail

### 1. Redacting logger
log() {
  local msg
  msg=$(printf '%s' "$*" \
    | sed -E 's/(password|token|secret|key)=[^[:space:]]*/\1=***/gi')
  printf '[%s] %s\n' "$(date -u +%T)" "$msg"
}

### 2. tmpfs secret store
TMPFS_DIR="${XDG_RUNTIME_DIR:-/tmp}"
SECRET_FILE=$(mktemp "${TMPFS_DIR}/deploy_token.XXXXXX")
chmod 0600 "$SECRET_FILE"
trap 'rm -f "$SECRET_FILE"; log "Secret file cleaned up."' EXIT

### 3. Read secret without trace
{ set +x; } 2>/dev/null
read -rsp 'Deploy token: ' _tok <&2; printf '\n' >&2
printf '%s' "$_tok" > "$SECRET_FILE"
unset _tok
set -x

### 4. Scrub inherited env vars before subprocess
unset DEPLOY_TOKEN 2>/dev/null || true

log 'Starting deployment...'
# Simulate deploy using secret from file (token never in argv)
# curl -H "Authorization: Bearer $(< $SECRET_FILE)" https://api.example.com/deploy
log 'Deployment complete. token=hidden_by_redactor'

echo 'Done.'

Vérification des connaissances : exposition des secrets via la liste des processus

Vérifiez votre compréhension de la manière dont les secrets sont divulgués dans les listes de processus et de la façon de l’empêcher.

Récapitulatif de la leçon : gestion sécurisée des secrets

Vous avez terminé Gestion sécurisée des secrets et hygiène de l’environnement. Voici une référence concise de tout ce qui a été abordé :

  • Listes de processus : ne transmettez jamais de secrets comme arguments de ligne de commande — ils apparaissent dans ps aux et /proc/<pid>/cmdline. Utilisez plutôt un acheminement via stdin ou --netrc-file.
  • Lectures depuis stdin : utilisez read -rs pour recueillir les secrets de manière interactive, sans écho dans le terminal ni exposition dans l’historique du shell.
  • Permissions des fichiers : les fichiers de secrets doivent être en chmod 0600 (ou 0400). Utilisez install -m 0600 pour une création atomique.
  • Fichiers netrc : déléguez les identifiants à un fichier temporaire désigné par --netrc-file ; supprimez-le avec trap EXIT.
  • Hygiène de l’environnement : utilisez immédiatement unset sur les variables d’environnement secrètes après les avoir capturées localement ; ne les exportez jamais sans nécessité ; utilisez env -i pour isoler les processus fils.
  • Protection contre xtrace : entourez le code sensible de { set +x; } 2>/dev/null ... set -x afin d’empêcher les traces de débogage de divulguer les valeurs.
  • Masquage des journaux : utilisez un outil de journalisation fondé sur sed comme filet de sécurité de dernier recours.
  • tmpfs : stockez les secrets d’exécution dans /run/user/$UID ou /dev/shm afin qu’ils ne touchent jamais le disque ; détruisez-les à la sortie.

La défense en profondeur est l’état d’esprit essentiel : aucune mesure unique ne suffit, mais leur association rend la fuite de secrets extrêmement difficile.

Questions Fréquemment Posées

La leçon « Gérer les secrets en toute sécurité et assainir l’environnement » est-elle gratuite ?

Oui — le texte complet de « Gérer les secrets en toute sécurité et assainir l’environnement » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours DevOps Bootcamp, passe à CoddyKit PRO. Le cours DevOps Bootcamp comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Gérer les secrets en toute sécurité et assainir l’environnement » ?

Évitez d’exposer les identifiants dans les listes de processus et les journaux en utilisant l’entrée standard, des fichiers et des environnements nettoyés. Tu pratiques DevOps Bootcamp avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer DevOps Bootcamp ?

Aucune expérience préalable n'est requise. DevOps Bootcamp sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.

Combien de temps prend la leçon « Gérer les secrets en toute sécurité et assainir l’environnement » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon DevOps Bootcamp ?

Oui. Chaque leçon DevOps Bootcamp inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Prévenir l’injection de commandes et d’arguments
  2. Gérer les secrets en toute sécurité et assainir l’environnement
  3. Exécuter avec le principe du moindre privilège et discipliner sudo
  4. Analyse statique et audit avec ShellCheck
← Retour à DevOps Bootcamp