4NK_vault/docs/environment-variables.md
4NK Dev 0bbd4a1b92 feat: Mise à jour du système de templating avec ordre de chargement des fichiers d'environnement
- Mise à jour de l'API pour charger les fichiers .env dans l'ordre: .env.secrets -> .env -> .env.auto -> .env.post
- Ajout du script generate_variables.sh pour générer automatiquement les variables Docker
- Création des fichiers .env.auto et .env.post pour le templating complet
- Mise à jour de la documentation pour refléter le nouvel ordre de chargement
- Génération automatique du docker-compose.yml avec templates des services
- Support complet des variables emboîtées entre les fichiers d'environnement
2025-10-02 12:08:45 +00:00

9.0 KiB

Traitement des Variables d'Environnement

🔧 Vue d'ensemble

L'API Vault 4NK intègre un système avancé de traitement des variables d'environnement qui résout automatiquement les références de variables dans les fichiers de configuration avant leur chiffrement et transmission.

🚀 Fonctionnalités

Résolution automatique des variables

  • Syntaxes supportées : $VAR et ${VAR}
  • Résolution récursive : Les variables peuvent référencer d'autres variables
  • Protection contre les boucles infinies : Détection automatique des dépendances circulaires
  • Traitement en mémoire : Les fichiers originaux ne sont jamais modifiés

Sources de variables (ordre de chargement)

  1. Fichier .env.secrets : storage/<env>/.env.secrets (secrets de base)
  2. Fichier .env : storage/<env>/.env (variables de configuration, peut utiliser les secrets)
  3. Fichier .env.auto : storage/<env>/.env.auto (variables générées automatiquement, peut utiliser les précédentes)
  4. Fichier .env.post : storage/<env>/.env.post (variables finales, peut utiliser toutes les précédentes)
  • Variables système : Non utilisées (isolation complète)
  • Fichiers de sous-répertoires : Non chargés (configurations spécifiques aux services)

📋 Syntaxes supportées

Syntaxe simple : $VAR

# Variables de base
DOMAIN=4nkweb.com
HOST=dev4.$DOMAIN
ROOT_HOST=$HOST
ROOT_URL=https://$ROOT_HOST

# Résolution automatique
DOMAIN → 4nkweb.com
HOST → dev4.4nkweb.com
ROOT_HOST → dev4.4nkweb.com
ROOT_URL → https://dev4.4nkweb.com

Syntaxe avec accolades : ${VAR}

# Variables complexes
LOG_DIR=/home/debian/4NK_env/logs
BITCOIN_LOG_DIR=${LOG_DIR}/bitcoin
TOR_LOG_DIR=${LOG_DIR}/tor

# Résolution automatique
LOG_DIR → /home/debian/4NK_env/logs
BITCOIN_LOG_DIR → /home/debian/4NK_env/logs/bitcoin
TOR_LOG_DIR → /home/debian/4NK_env/logs/tor

🔄 Processus de résolution

1. Chargement des variables (ordre séquentiel)

# Chargement des fichiers d'environnement dans l'ordre correct
env_files = ['.env.secrets', '.env', '.env.auto', '.env.post']
variables = {}

for env_filename in env_files:
    env_file_path = STORAGE_ROOT / env / env_filename
    if env_file_path.exists():
        variables.update(load_env_file(env_file_path))

2. Résolution récursive

def resolve_variable(var_name, visited=None):
    if var_name in visited:  # Protection contre les boucles
        return f"${var_name}"

    visited.add(var_name)
    value = variables[var_name]

    # Résolution des sous-variables
    for match in find_variables(value):
        resolved = resolve_variable(match, visited.copy())
        value = value.replace(f"${{{match}}}", resolved)
        value = value.replace(f"${match}", resolved)

    return value

3. Traitement du contenu

def process_content(content):
    # Pattern pour ${VARIABLE}
    pattern1 = r'\$\{([^}]+)\}'
    for var_name in re.findall(pattern1, content):
        resolved_value = resolve_variable(var_name)
        content = content.replace(f"${{{var_name}}}", resolved_value)

    # Pattern pour $VARIABLE
    pattern2 = r'\$([A-Za-z_][A-Za-z0-9_]*)'
    for var_name in re.findall(pattern2, content):
        if f"${{{var_name}}}" not in content:  # Éviter les doublons
            resolved_value = resolve_variable(var_name)
            content = content.replace(f"${var_name}", resolved_value)

    return content

🛡️ Sécurité et protection

Protection contre les attaques

  • Dépendances circulaires : Détection et prévention automatiques
  • Variables non définies : Conservation de la syntaxe originale
  • Isolation : Seul le fichier .env principal est utilisé

Exemples de protection

# Dépendance circulaire détectée
HOST=dev4.$DOMAIN
DOMAIN=$HOST

# Résultat : Conservation de la syntaxe
HOST → dev4.$DOMAIN  # Variable non résolue
DOMAIN → $HOST       # Variable non résolue

📁 Structure des fichiers

Fichier .env principal

# storage/dev/.env
DOMAIN=4nkweb.com
HOST=dev4.$DOMAIN
ROOT_HOST=$HOST
ROOT_URL=https://$ROOT_HOST
ROOT_DIR_LOGS=/home/debian/4NK_env/logs
TOR_LOGS_DIR=$ROOT_DIR_LOGS/tor
SDK_TOR_DATA_DIR=$ROOT_DIR_LOGS/sdk_tor

Fichier .env.secrets

# storage/dev/.env.secrets
BDD_USER=bdd_user
BDD_PASSWORD=bdd_password
POSTGRESQL_USER=$BDD_USER
POSTGRESQL_PASSWORD=$BDD_PASSWORD
SIGNER_API_KEY=your-api-key-change-this
VITE_JWT_SECRET_KEY=52b3d77617bb00982dfee15b08effd52cfe5b2e69b2f61cc4848cfe1e98c0bc9
GRAFANA_ADMIN_PASSWORD=admin123
BITCOIN_RPC_AUTH=bitcoin:c8ea921c7357bd6a5a8a7c43a12350a7$955e25b17672987b17c5a12f12cd8b9c1d38f0f86201c8cd47fc431f2e1c7956

⚠️ Important : Le fichier .env.secrets contient des informations sensibles et ne doit jamais être committé dans le contrôle de version.

Fichiers de configuration

# storage/dev/bitcoin/bitcoin.conf
datadir=$ROOT_DIR_LOGS/bitcoin
logdir=$ROOT_DIR_LOGS/bitcoin
rpcbind=$HOST
rpcport=8332

Résolution automatique

# Contenu après résolution (en mémoire)
datadir=/home/debian/4NK_env/logs/bitcoin
logdir=/home/debian/4NK_env/logs/bitcoin
rpcbind=dev4.4nkweb.com
rpcport=8332

🔧 Configuration de l'API

Initialisation

class SecureVaultAPI:
    def __init__(self):
        # Processeurs d'environnement par environnement
        self.env_processors = {}

    def _get_env_processor(self, env: str) -> EnvProcessor:
        if env not in self.env_processors:
            env_file = STORAGE_ROOT / env / '.env'
            self.env_processors[env] = EnvProcessor(env_file)
        return self.env_processors[env]

Utilisation dans les endpoints

@self.app.route('/<env>/<path:file_path>', methods=['GET'])
def serve_file(env: str, file_path: str):
    # Lecture du fichier
    file_content = self._read_file(env, file_path)

    # Traitement des variables d'environnement
    env_processor = self._get_env_processor(env)
    processed_content = env_processor.process_content(file_content)

    # Chiffrement du contenu traité
    encrypted_content, next_key = self._encrypt_with_user_key_and_next(
        processed_content, user_id, env
    )

    return encrypted_content

🧪 Tests et validation

Test de résolution

# Test des variables d'environnement
env_processor = EnvProcessor(Path("storage/dev/.env"))

# Test de résolution simple
result = env_processor.process_content("Host: $HOST")
assert result == "Host: dev4.4nkweb.com"

# Test de résolution complexe
result = env_processor.process_content("URL: $ROOT_URL/api")
assert result == "URL: https://dev4.4nkweb.com/api"

Validation des dépendances

# Test de protection contre les boucles
env_processor.process_content("$CIRCULAR_VAR")
# Résultat : $CIRCULAR_VAR (conservé tel quel)

📊 Exemples concrets

Configuration Bitcoin

# Avant résolution
datadir=$ROOT_DIR_LOGS/bitcoin
logdir=$ROOT_DIR_LOGS/bitcoin
rpcbind=$HOST
rpcport=8332

# Après résolution (automatique)
datadir=/home/debian/4NK_env/logs/bitcoin
logdir=/home/debian/4NK_env/logs/bitcoin
rpcbind=dev4.4nkweb.com
rpcport=8332

Configuration Tor

# Avant résolution
DataDirectory $SDK_TOR_DATA_DIR
Log notice file $TOR_LOGS_DIR/tor.log
SocksPort $HOST:9050

# Après résolution (automatique)
DataDirectory /home/debian/4NK_env/logs/sdk_tor
Log notice file /home/debian/4NK_env/logs/tor/tor.log
SocksPort dev4.4nkweb.com:9050

🔍 Debugging et logs

Activation des logs

import logging
logging.basicConfig(level=logging.INFO)

# Logs automatiques
logger.info(f"Variables chargées depuis {env_file}: {len(variables)} variables")
logger.info(f"Variable résolue: {var_name} = {resolved_value}")
logger.warning(f"Dépendance circulaire détectée pour {var_name}")

Messages de debug

INFO: Variables chargées depuis storage/dev/.env: 15 variables
INFO: Variable résolue: HOST = xxx.com
INFO: Variable résolue: ROOT_URL = https://xxx.com
WARNING: Variable non trouvée: UNDEFINED_VAR

🌐 Intégration SDK

Récupération des fichiers traités

// Le SDK reçoit automatiquement les fichiers avec variables résolues
const file = await client.getFile('dev', 'bitcoin/bitcoin.conf');
console.log(file.content); // Variables déjà résolues

// Vérification des variables résolues
const hasVariables = file.content.includes('$');
console.log(`Variables résolues: ${!hasVariables}`);

Synchronisation locale

// Synchronisation avec variables résolues
const syncResult = await client.syncLocalFiles({
  environment: 'dev',
  localDir: '../confs'
});

// Les fichiers dans confs/ contiennent les variables résolues
console.log(`Fichiers synchronisés: ${syncResult.synced}`);

Note : Le traitement des variables d'environnement est entièrement transparent pour l'utilisateur final. Les fichiers originaux dans storage/ ne sont jamais modifiés, et toutes les résolutions se font en mémoire lors de la récupération des fichiers.