SOPS + age : secrets dans Git sans Vault

À la fin de ce tutoriel, vous saurez installer age et Mozilla SOPS, générer une clé age1…, configurer .sops.yaml, chiffrer des fichiers YAML/JSON/ENV (clés lisibles, valeurs chiffrées), les committer dans Git, déchiffrer/éditer en local, et brancher un déchiffrement contrôlé dans GitHub Actions — sans déployer HashiCorp Vault.

Niveau : Intermédiaire · Temps estimé : 45–60 min · Versions testées : SOPS 3.9+, age (FiloSottile), Git, GitHub Actions · Dernière vérification : 2026-09-11 · Region : ca-central-1

Slug : wow-sops-age-git · Série : WOW (12/50) · Mot-clé SEO : sops age git · Publish : READY (feu vert Maître)

← Précédent : HashiCorp Vault pour secrets DevOps · → Suivant : External Secrets Operator · Aussi : Kubernetes Secrets · Pipeline DevSecOps · GitHub Actions OIDC AWS

Prérequis

  • Bases Git (commit, .gitignore, PR) et notions YAML/JSON
  • Éditeur terminal (vim, nano ou VS Code)
  • Compte GitHub (optionnel) pour la partie CI
  • Notions secrets K8s — Kubernetes Secrets
  • Survol de Vault secrets DevOps (WOW 11) pour le contraste dynamique vs secrets-as-code
  • Aucun cluster Kubernetes ni Vault requis pour ce lab

Coût estimé : 0 € — lab local + runners GitHub Actions. Pas de ressources AWS obligatoires ; ca-central-1 est la convention DEH (tags / exemple d’app).

export AWS_PROFILE=lab
export AWS_DEFAULT_REGION=ca-central-1

Ce que nous allons construire

Lab SOPS + age (WOW 12/50) — ca-central-1
  ├── keys/age/          # clé privée HORS Git (.gitignore)
  ├── .sops.yaml         # path_regex + destinataires age publics
  ├── secrets/
  │   ├── app.yaml       # YAML chiffré (clés lisibles)
  │   ├── config.json
  │   └── demo.env
  ├── .github/workflows/sops-decrypt.yml
  ├── workflow : decrypt → edit → re-encrypt
  └── multi-destinataires + rotation + FAQ + quiz

(Schéma — alt : « Secret clair → SOPS+age → fichier chiffré dans Git → CI déchiffre avec identité age privée en secret runner ».)

Étape 1 — Pourquoi SOPS + age (sans Vault)

Mozilla SOPS chiffre les valeurs d’un fichier structuré tout en laissant les clés lisibles — idéal pour les revues de PR. age (FiloSottile) offre un chiffrement moderne (clés age1…), sans la lourdeur PGP.

Approche Modèle Force Limite
SOPS + age Secrets-as-code dans Git Auditable, PR-friendly, offline Secrets statiques ; rotation manuelle
Vault (WOW 11) Secrets dynamiques / lease TTL, audit central Ops, HA, réseau
External Secrets (WOW 13) Sync → Secret K8s Bridge cloud/Vault → cluster Dépend d’un backend
Sealed Secrets Controller K8s Chiffre pour un cluster Moins portable hors K8s

Chez DevOps Elastic Hayway : SOPS pour configs sensibles versionnées, Vault pour le dynamisme, ESO pour injecter dans Kubernetes. Voir Argo CD GitOps et Sealed Secrets en complément.

Étape 2 — Installer age et SOPS

AGE_VERSION=1.2.1
curl -sL "https://github.com/FiloSottile/age/releases/download/v${AGE_VERSION}/age-v${AGE_VERSION}-linux-amd64.tar.gz" 
  | tar -xz
sudo mv age/age age/age-keygen /usr/local/bin/
age --version && age-keygen --version

SOPS_VERSION=3.9.4
curl -sL "https://github.com/getsops/sops/releases/download/v${SOPS_VERSION}/sops-v${SOPS_VERSION}.linux.amd64" 
  -o sops && chmod +x sops && sudo mv sops /usr/local/bin/
sops --version

macOS : brew install age sops. Lab :

mkdir -p ~/lab-sops-age/{keys/age,secrets,.github/workflows}
cd ~/lab-sops-age
printf 'keys/n*.keynkeys/age/key.txtn' >> .gitignore

Règle d’or : la clé privée age ne quitte jamais le disque local (ou un secret CI). Seule la clé publique (age1…) va dans .sops.yaml.

Étape 3 — Générer une clé age et .sops.yaml

age-keygen -o keys/age/key.txt
# Public key: age1xxxxxxxx...
grep 'public key:' keys/age/key.txt
export SOPS_AGE_KEY_FILE="$HOME/lab-sops-age/keys/age/key.txt"

Remplacez CHANGE_ME_AGE_PUBLIC par votre age1… réel :

# .sops.yaml — destinataires publics uniquement
creation_rules:
  - path_regex: secrets/.*.(yaml|yml|json|env)$
    age: >-
      CHANGE_ME_AGE_PUBLIC
  - path_regex: secrets/prod/.*.(yaml|yml)$
    age: >-
      CHANGE_ME_AGE_PUBLIC,age1OTHER_TEAM_RECIPIENT_DEMO

path_regex cible les fichiers chiffrés automatiquement. Plusieurs destinataires age = chaque détenteur de la clé privée correspondante peut déchiffrer (équipe + CI).

git check-ignore -v keys/age/key.txt
# Ne committez JAMAIS keys/age/key.txt

Étape 4 — Chiffrer un fichier secrets et committer dans Git

cat > secrets/app.yaml <<'EOF'
app:
  name: wow-demo
  region: ca-central-1
  database:
    host: db.lab.example.internal
    username: app_user
    password: CHANGE_ME_super_secret_password
  api:
    token: CHANGE_ME_api_token_demo
  aws:
    default_region: ca-central-1
    bucket: wow-lab-demo-ca-central-1
EOF

sops --encrypt --in-place secrets/app.yaml
head -n 30 secrets/app.yaml

Les clés (password, token, region) restent lisibles ; les valeurs sensibles deviennent ENC[AES256_GCM,data:…]. C’est le point fort SOPS pour les reviews Git.

git add .sops.yaml secrets/app.yaml .gitignore
git commit -m "feat(secrets): SOPS+age demo ca-central-1"

echo '{"db_password":"CHANGE_ME","region":"ca-central-1"}' > secrets/config.json
sops --encrypt --in-place secrets/config.json

printf 'API_TOKEN=CHANGE_MEnAWS_REGION=ca-central-1n' > secrets/demo.env
sops --encrypt --in-place secrets/demo.env

Étape 5 — Déchiffrer, éditer, re-chiffrer (workflow quotidien)

export SOPS_AGE_KEY_FILE="$HOME/lab-sops-age/keys/age/key.txt"

sops --decrypt secrets/app.yaml | head
sops secrets/app.yaml   # éditeur : decrypt → edit → re-encrypt au save

sops --decrypt secrets/app.yaml > /tmp/app.clear.yaml
rm -f /tmp/app.clear.yaml

sops exec-env injecte un ENV chiffré comme variables pour une commande :

sops exec-env secrets/demo.env -- env | grep -E 'API_TOKEN|AWS_REGION'
sops exec-env secrets/demo.env -- ./scripts/migrate-demo.sh

Plugin helm-secrets (mention) : helm secrets upgrade … -f secrets/values.enc.yaml déchiffre à la volée — utile avec Argo CD si vous restez en secrets-as-code.

Checklist DEH : (1) SOPS_AGE_KEY_FILE local, (2) sops fichier.yaml pour éditer, (3) diff Git = blobs ENC[], (4) PR reviewable (structure visible).

Étape 6 — CI (GitHub Actions) : déchiffrement contrôlé

Stockez la clé privée dans le secret Actions SOPS_AGE_KEY (contenu de key.txt). Ne loggez jamais la clé.

# .github/workflows/sops-decrypt.yml
name: sops-decrypt-lab
on:
  pull_request:
  workflow_dispatch:
jobs:
  decrypt-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install SOPS + age
        run: |
          curl -sL "https://github.com/getsops/sops/releases/download/v3.9.4/sops-v3.9.4.linux.amd64" 
            -o /usr/local/bin/sops && chmod +x /usr/local/bin/sops
          curl -sL "https://github.com/FiloSottile/age/releases/download/v1.2.1/age-v1.2.1-linux-amd64.tar.gz" 
            | tar -xz -C /tmp && sudo mv /tmp/age/age /usr/local/bin/
      - name: Decrypt demo (no echo of values)
        env:
          SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}
        run: |
          printf '%sn' "$SOPS_AGE_KEY" > /tmp/age-key.txt
          chmod 600 /tmp/age-key.txt
          export SOPS_AGE_KEY_FILE=/tmp/age-key.txt
          sops --decrypt secrets/app.yaml > /tmp/app.yaml
          grep -q 'ca-central-1' /tmp/app.yaml
          grep -q 'wow-demo' /tmp/app.yaml
          shred -u /tmp/age-key.txt /tmp/app.yaml

Pour AWS en ca-central-1, combinez avec GitHub Actions OIDC AWS : OIDC pour le cloud, SOPS pour Git. Dans un pipeline DevSecOps, le job de decrypt est least-privilege (environnement protégé).

Étape 7 — Multi-destinataires, rotation, bonnes pratiques

Multi-destinataires : plusieurs age1… séparés par des virgules dans .sops.yaml, puis sops updatekeys secrets/app.yaml.

Rotation : (1) age-keygen -o keys/age/key-new.txt, (2) ajoutez la nouvelle publique (gardez l’ancienne temporairement), (3) sops updatekeys -y secrets/*.yaml, (4) distribuez la nouvelle privée (CI + password manager), (5) retirez l’ancienne et updatekeys à nouveau.

Bonnes pratiques DEH : jamais de clé privée dans Git/Slack/README ; préfixe secrets/ + path_regex strict ; placeholders CHANGE_ME en lab ; contraste SOPS=Git / Vault=dynamique / ESO=sync K8s ; tags exemples en ca-central-1.

Troubleshooting

Symptôme Cause / correction
no age identity found SOPS_AGE_KEY_FILE absent ou mauvais chemin
failed to get the data key Mauvaise clé privée / destinataire absent de .sops.yaml
Fichier clair commité Pre-commit + rotation immédiate
Diff Git illisible Normal sur ENC[] ; éditez via sops fichier
CI OK, local KO Clé CI ≠ destinataire ; sops updatekeys
path_regex ignore le fichier Regex trop stricte ; sops -e fichier explicite
Helm ne déchiffre pas Plugin helm-secrets + clé age correcte

FAQ

SOPS remplace-t-il Vault ?
Non. SOPS versionne des secrets statiques dans Git. Vault (WOW 11) gère dynamisme, leases et audit. Ils se complètent.

Pourquoi age plutôt que PGP ?
Plus simple (age1…), moins d’erreurs, moderne (X25519). SOPS supporte aussi AWS KMS / GCP KMS.

Peut-on chiffrer tout le fichier ?
Oui (--input-type binary), mais vous perdez la review des clés. Préférez le mode structuré YAML/JSON.

Où stocker la clé privée en équipe ?
Password manager + secret CI (SOPS_AGE_KEY). Jamais dans le repo. Alternative : KMS comme destinataire SOPS.

Lien avec External Secrets Operator ?
SOPS alimente Git ; ESO (WOW 13) synchronise Vault/ASM vers Secrets K8s — plus idiomatique en prod cluster.

Et Sealed Secrets ?
Chiffre pour un cluster précis. SOPS+age reste multi-env / multi-cloud sans controller obligatoire.

Quiz (5 questions)

1. Avec SOPS sur un YAML, que reste-t-il lisible après chiffrement ?
– A. Rien (fichier binaire opaque)
– B. Les clés (chemins) ; les valeurs sensibles sont ENC[…]
– C. Uniquement le mot de passe en clair

2. Que committez-vous dans Git ?
– A. La clé privée age (key.txt)
– B. La clé publique age1… dans .sops.yaml + fichiers chiffrés
– C. Les secrets en clair « juste pour le lab prod »

3. Par rapport à Vault (WOW 11), SOPS+age est surtout :
– A. Un serveur de secrets dynamiques avec TTL
– B. Des secrets-as-code chiffrés dans Git
– C. Un ingress TLS automatique

4. La région lab DEH utilisée dans les exemples est :
– A. us-east-1 uniquement
– B. ca-central-1
– C. eu-west-3 obligatoire

5. En CI GitHub Actions, la pratique sûre est :
– A. Echo de SOPS_AGE_KEY dans les logs pour debug
– B. Stocker la clé privée en secret Actions, déchiffrer, shred les temporaires
– C. Committer keys/age/key.txt sur la branche ci

Réponses : 1‑B · 2‑B · 3‑B · 4‑B · 5‑B

Pour aller plus loin

Maillage série WOW

← Précédent HashiCorp Vault pour secrets DevOps
→ Suivant External Secrets Operator
Aussi Kubernetes Secrets · DevSecOps · GitHub Actions OIDC AWS · Argo CD · Sealed Secrets

Meta publication (SEO)

  • Title SEO : SOPS + age : secrets dans Git sans Vault (guide FR)
  • Meta description : Mozilla SOPS + FiloSottile age : chiffrez YAML/JSON/ENV dans Git, .sops.yaml, workflow quotidien, CI GitHub Actions, rotation multi-destinataires, FAQ. Région ca-central-1 — DevOps Elastic Hayway WOW 12/50.
  • Focus keyword : sops age git
  • Secondary : sops age, secrets git chiffrement, mozilla sops, age encryption devops
  • Schemas : Article + HowTo + FAQ
  • Image : assets/web/devopelastichayway/cover-wow-sops-age-git-1200x630.webp (à générer)
  • Catégorie : WOW / Secrets · Niveau : Intermédiaire
  • Parent WP : /tutoriels/ (parent 5463)
  • URL cible : https://devopelastichayway.com/tutoriels/wow-sops-age-git/
  • Post live : N/A (nouveau) · slug wow-sops-age-git · Publish : READY (feu vert Maître + auto-push WP-CLI)

← Catalogue Tutoriels

Pour aller plus loin — hubs live

Retour parcours Catalogue Tutoriels — hub de la série et leçons sœurs.