Files
nas-runbooks/common/transfert-secret-inter-machines.md

3.2 KiB

Transferer un secret entre deux machines sans jamais l'exposer

Cas d'usage vecu (18/07/2026) : deplacer HERMES_PERSO_OPENROUTER_KEY du NAS (hermes-platform/.env) vers le VPS Contabo (hermes-nabil/data/.env), alors que aucun canal direct NAS -> VPS n'existe (SSH NAS->VPS non fonctionnel, Tailscale userspace sur Synology) et que le seul lien commun est l'agent (Claude), dont le contexte de conversation ne doit jamais contenir un secret en clair.

Principe : chiffrement asymetrique, la cle privee ne bouge pas

Seuls transitent par l'agent la cle publique (non sensible) et le ciphertext (opaque). Le secret n'apparait en clair a aucun moment dans la conversation, ni dans un log, ni dans un historique shell. La cle privee est detruite immediatement apres usage (secret de transit jetable).

Procedure (RSA-3072 + OAEP-SHA256)

1. Machine destinataire — generer la paire, publier la cle publique

umask 077; mkdir -p ~/.transit && cd ~/.transit
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out priv.pem
openssl rsa -in priv.pem -pubout -out pub.pem
chmod 600 priv.pem
cat pub.pem            # seule sortie affichee : non sensible

2. Machine source — extraire sans afficher, chiffrer

umask 077; mkdir -p /tmp/transit && cd /tmp/transit
cat > pub.pem <<'PEM'
<coller la cle publique>
PEM
grep -m1 "^MA_VARIABLE=" /chemin/.env | cut -d= -f2- | tr -d '"'\''' | tr -d '\r\n' > secret.bin
echo "longueur=$(wc -c < secret.bin)"          # controle SANS afficher la valeur
openssl pkeyutl -encrypt -pubin -inkey pub.pem \
  -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 \
  -in secret.bin -out secret.enc
shred -u secret.bin
base64 -w0 secret.enc                           # ciphertext opaque, transitable

3. Destinataire — dechiffrer, injecter, tout detruire

cd ~/.transit
base64 -d secret.b64 > secret.enc
openssl pkeyutl -decrypt -inkey priv.pem \
  -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 \
  -in secret.enc -out secret.bin
echo "longueur=$(wc -c < secret.bin)"           # doit egaler celle de la source
ENV=~/projet/data/.env
[ -n "$(tail -c1 $ENV)" ] && echo >> $ENV       # garantir un saut de ligne final
grep -v '^MA_VARIABLE=' $ENV > $ENV.tmp && mv $ENV.tmp $ENV   # idempotence
{ printf 'MA_VARIABLE='; cat secret.bin; printf '\n'; } >> $ENV
chmod 600 $ENV
shred -u secret.bin secret.enc secret.b64 priv.pem pub.pem; rmdir ~/.transit

Puis cote source : rm -rf /tmp/transit.

Regles

  • Jamais echo $SECRET, cat .env, ni un grep qui imprime la valeur. Controler par longueur (wc -c) et prefixe booleen (head -c 6 f | grep -q '^sk-or-' && echo oui).
  • Piege : ${#VAR} sur le nom de variable renvoie la longueur du nom. Indirection obligatoire : eval v=\${VAR}; echo ${#v}.
  • RSA-3072 + OAEP-SHA256 : charge utile max ~318 octets — largement suffisant pour une cle API. Au-dela (fichier, keystore) : chiffrer le fichier en AES puis chiffrer la cle AES en RSA.
  • Cle privee jetable et detruite apres l'operation : meme si le ciphertext reste dans un historique, il devient indechiffrable (forward secrecy artisanale).
  • Ne dispense pas de la regle generale : un secret reellement expose en clair = rotation immediate.