Retour aux articles
Cas d'usage

Injecter les Secrets dans les Scripts de Déploiement en Toute Sécurité

Arrêtez de coder les identifiants en dur dans les scripts et les variables d'environnement. Utilisez kh kv run pour injecter les secrets directement dans les commandes sans les exposer au shell.

·Par L'équipe KeyHarbour

Le problème avec les variables d’environnement dans les scripts

Les scripts de déploiement ont besoin de configuration. Un script qui déploie sur AWS a besoin d’une clé d’accès et de la région AWS. Un script qui migre une base de données a besoin d’un mot de passe et du nom d’hôte de la base de données. Un script qui déclenche un pipeline CI/CD a besoin d’un jeton d’API et du point de terminaison de l’API.

Certaines de ces valeurs sont des secrets qui doivent être protégés. D’autres sont des valeurs de configuration qui sont différentes pour chaque environnement mais pas sensibles.

Un script qui fonctionne pour la staging devrait fonctionner pour la production en changeant uniquement les variables d’environnement. La base de données de staging est en us-east-1. La base de données de production est en ca-central-1. Le point de terminaison de l’API de staging est https://api-staging.example.com. Le point de terminaison de production est https://api.example.com.

Les équipes gèrent généralement cela de trois façons non sécurisées.

D’abord, coder les variables en dur dans le script. Le script est archivé dans git. Les valeurs sensibles sont visibles à quiconque a accès au dépôt. Quand les valeurs changent, le script est mis à jour et les anciennes valeurs restent dans l’historique de git. Mettre à jour le script pour un nouvel environnement signifie créer une copie du script, qui dérive avec le temps.

Deuxièmement, exporter les variables avant d’exécuter le script. Les valeurs sensibles sont visibles dans l’historique de votre shell. Le script hérite des variables. Si le script plante ou journalise son environnement, les valeurs apparaissent dans la sortie d’erreur. Les variables restent en mémoire jusqu’à ce que vous fermiez le terminal. Gérer différents ensembles de variables pour différents environnements signifie créer des profils shell ou des fichiers d’exportation, que vous devez vous souvenir de sourcer avant d’exécuter le script.

Troisièmement, passer les variables en tant qu’arguments de ligne de commande. Les valeurs sensibles sont visibles dans la liste des processus. Elles apparaissent dans l’historique de votre shell. Elles s’affichent dans les journaux des commandes exécutées. Cette approche ne s’adapte pas quand un script a besoin de dix ou vingt variables.

Les trois approches créent soit des trous de sécurité, soit une complexité opérationnelle.

Un modèle plus sûr

KeyHarbour offre une approche différente. Stockez toutes vos variables d’environnement en tant que paires clé-valeur dans un workspace. Créez des workspaces séparés pour chaque environnement: staging, production, développement. Quand vous avez besoin d’exécuter un script, utilisez la commande kh kv run pour injecter l’environnement entier dans le script sans exposer les variables à votre shell parent.

Le script reçoit toutes les variables dont il a besoin. Votre shell ne les voit pas. L’historique de votre shell ne les voit pas. La liste des processus ne les voit pas. Les variables sont scoped à l’environnement auquel elles appartiennent.

Exemple réel : déploiement multi-environnement

Votre équipe maintient une application qui se déploie sur trois environnements: développement, staging et production. Le même script de déploiement s’exécute sur les trois, mais la configuration change.

Vous créez trois workspaces dans KeyHarbour: un pour le développement, un pour la staging, un pour la production.

Dans le workspace de développement, vous stockez ces variables:

kh kv set APP_ENV "development" --workspace dev
kh kv set AWS_REGION "us-east-1" --workspace dev
kh kv set DATABASE_HOST "db-dev.internal" --workspace dev
kh kv set DATABASE_NAME "app_dev" --workspace dev
kh kv set DATABASE_USER "app_user" --workspace dev
kh kv set DATABASE_PASSWORD "dev-password" --workspace dev --encrypt
kh kv set API_ENDPOINT "https://api-dev.internal" --workspace dev
kh kv set LOG_LEVEL "debug" --workspace dev
kh kv set ENABLE_DEBUG_MODE "true" --workspace dev
kh kv set SLACK_WEBHOOK_URL "https://hooks.slack.com/dev/..." --workspace dev

Dans le workspace de production, les mêmes variables mais avec des valeurs de production:

kh kv set APP_ENV "production" --workspace prod
kh kv set AWS_REGION "ca-central-1" --workspace prod
kh kv set DATABASE_HOST "db-prod.internal" --workspace prod
kh kv set DATABASE_NAME "app_prod" --workspace prod
kh kv set DATABASE_USER "app_prod_user" --workspace prod
kh kv set DATABASE_PASSWORD "prod-password" --workspace prod --encrypt
kh kv set API_ENDPOINT "https://api.example.com" --workspace prod
kh kv set LOG_LEVEL "warning" --workspace prod
kh kv set ENABLE_DEBUG_MODE "false" --workspace prod
kh kv set SLACK_WEBHOOK_URL "https://hooks.slack.com/prod/..." --workspace prod

Le même script de déploiement fonctionne pour les deux environnements. Vous ne changez que le workspace que vous utilisez.

# Déployer sur le développement
kh kv run --workspace dev -- ./deploy.sh

# Déployer sur la production
kh kv run --workspace prod -- ./deploy.sh

À l’intérieur de deploy.sh, toutes les variables sont disponibles. Le script s’adapte à l’environnement automatiquement.

#!/bin/bash

# Toutes les variables sont disponibles ici
echo "Deploying to $APP_ENV in region $AWS_REGION"

# Se connecter à la bonne base de données pour cet environnement
psql -h "$DATABASE_HOST" -d "$DATABASE_NAME" -U "$DATABASE_USER" < schema.sql

# Configurer l'application avec les paramètres spécifiques à l'environnement
aws configure set region "$AWS_REGION"
export API_ENDPOINT
export LOG_LEVEL

# Exécuter l'application
./app/bin/start

# Notifier le bon canal Slack pour cet environnement
curl -X POST "$SLACK_WEBHOOK_URL" \
  -d "{\"text\":\"Deployment complete in $APP_ENV\"}"

Quand le script se termine, aucune variable ne reste dans votre shell. Elles n’apparaissent pas dans votre historique. Chaque environnement est complètement isolé.

Filtrer les secrets par préfixe

Tous les secrets d’un workspace ne s’appliquent pas à chaque script. Votre workspace peut contenir des secrets pour les migrations de base de données, le provisionnement d’infrastructure et le déploiement d’applications. Chaque script a besoin uniquement des secrets pertinents pour lui.

Utilisez le flag --prefix pour injecter uniquement les secrets qui commencent par un préfixe spécifique. Le préfixe est supprimé, donc le script reçoit des noms de variables propres.

kh kv set DEPLOY_AWS_KEY "AKIA..." --workspace prod
kh kv set DEPLOY_DB_URL "postgres://..." --workspace prod
kh kv set APP_API_TOKEN "secret" --workspace prod

# Ce script reçoit uniquement DEPLOY_AWS_KEY et DEPLOY_DB_URL
# Ils sont renommés en AWS_KEY et DB_URL
kh kv run --workspace prod --prefix DEPLOY_ -- ./deploy.sh

À l’intérieur du script, les variables sont AWS_KEY et DB_URL. Le préfixe DEPLOY_ est automatiquement supprimé. Le APP_API_TOKEN n’est pas injecté car il ne correspond pas au préfixe.

Exporter vers .env pour le développement local

En développement, vous pourriez vouloir charger tous les secrets du workspace dans un fichier .env que vos outils locaux lisent.

kh kv env --workspace staging --format dotenv > .env

Cela crée un fichier .env avec tous les secrets du workspace de staging au format standard. Chargez-le en utilisant direnv ou le framework de votre choix.

Pour la production, utilisez kh kv run à la place. Ne jamais écrire les secrets de production sur disque.

Utiliser avec les pipelines CI/CD

Le même modèle fonctionne dans les CI/CD. Votre runner de pipeline a accès à KH_TOKEN et KH_ENDPOINT. Tout le reste provient du workspace.

Un pipeline GitLab CI qui déploie sur plusieurs environnements.

deploy_staging:
  script:
    - kh kv run --workspace staging -- ./scripts/deploy.sh

deploy_production:
  script:
    - kh kv run --workspace prod -- ./scripts/deploy.sh

Chaque environnement a son propre workspace avec ses propres secrets. Le pipeline ne stocke pas les identifiants individuels. Il stocke un jeton qui a la permission de lire dans les deux workspaces.

Pourquoi c’est important

Les secrets fuient quand ils sont visibles. Moins il y a d’endroits où un secret apparaît, moins il y a de chances qu’il s’échappe. En injectant les secrets directement dans l’environnement d’une commande sans les exposer au shell parent, vous réduisez la surface d’attaque.

Le secret vit dans KeyHarbour, chiffré. Il se déplace de KeyHarbour directement dans la mémoire du script. Il ne touche jamais votre shell, votre historique ou la liste des processus. Quand le script se termine, le secret est parti.

C’est le même modèle utilisé par les gestionnaires de mots de passe et les moteurs de secrets dans l’infrastructure de production. Utilisez-le aussi pour vos déploiements locaux.

La référence complète de la CLI est disponible sur docs.keyharbour.ca. Contactez-nous à info@keyharbour.ca pour toute question.

devopssecretsdéploiementsécuritécli