Files
pmomusic/pmoconfig
Eric Coissac 5b8642a70b Migrate pmoutils to registry and refactor dependencies
Migrate pmoutils crate to registry version 0.1.2 and update all dependencies to use the registry version instead of local path references. Remove pmoutils from Cargo.lock and Cargo.toml files where it was previously used as a local path dependency. Move ToXmlElement trait to pmodidl crate and update all usages to import from pmodidl instead of pmoutils. Fix parameter order in find_process_using_port function call.
2026-03-01 21:43:15 +01:00
..
2025-12-11 21:35:17 +00:00

pmoconfig - PMOMusic Configuration Module

Module de gestion de configuration pour PMOMusic avec support du chiffrement des mots de passe.

Fonctionnalités

  • Configuration YAML avec valeurs par défaut intégrées
  • Fusion automatique entre config par défaut et config utilisateur
  • Overrides via variables d'environnement (PMOMUSIC_CONFIG__)
  • Getters/setters type-safe pour les valeurs de configuration
  • Pattern singleton thread-safe pour l'accès global
  • 🔒 Chiffrement des mots de passe basé sur l'UUID de la machine
  • API REST optionnelle (feature api)

Utilisation de base

use pmoconfig::get_config;

// Obtenir la configuration globale
let config = get_config();

// Lire des valeurs
let port = config.get_http_port();
let cache_dir = config.get_cover_cache_dir()?;

// Modifier des valeurs
config.set_http_port(9000)?;

Chiffrement des mots de passe

PMOConfig intègre un système de chiffrement transparent des mots de passe basé sur l'UUID matériel de la machine.

Chiffrer un mot de passe

cargo run --example encrypt_password -- encrypt "MonMotDePasse"

Sortie :

Original:  MonMotDePasse
Encrypted: encrypted:yRyu/jNlJRSdVz0eE+JX56UC2Tk016TmESDoLT6npLBJB3ZuhJ0XTqNOQjiXkkcB

Add this to your config.yaml:
password: "encrypted:yRyu/jNlJRSdVz0eE+JX56UC2Tk016TmESDoLT6npLBJB3ZuhJ0XTqNOQjiXkkcB"

Configuration

config.yaml avec mot de passe chiffré :

accounts:
  qobuz:
    username: user@example.com
    password: encrypted:yRyu/jNlJRSdVz0eE+JX56UC2Tk016TmESDoLT6npLBJB3ZuhJ0XTqNOQjiXkkcB

Utilisation dans le code

use pmoconfig::encryption;

// Déchiffrement automatique (gère plaintext et encrypted)
let password = encryption::get_password(&value)?;

// Chiffrer
let encrypted = encryption::encrypt_password("secret")?;

// Déchiffrer
let decrypted = encryption::decrypt_password(&encrypted)?;

// Tester si chiffré
if encryption::is_encrypted(&value) {
    // ...
}

Caractéristiques du chiffrement

  • Algorithme : AES-256-GCM
  • Clé : Dérivée de l'UUID matériel (SHA-256)
  • Format : encrypted:BASE64(nonce + ciphertext)
  • Déterministe : Même password = même ciphertext

Avantages

Pas de keyring/keychain requis Pas de clé maître à gérer Transparent pour l'utilisateur Migration progressive (supporte plaintext et encrypted) Déchiffrement automatique

Limitations

⚠️ Non portable entre machines ⚠️ Sécurité limitée contre accès physique ⚠️ Pas de protection contre root/admin

📖 Documentation complète : PASSWORD_ENCRYPTION.md

Structure de la configuration

host:
  http_port: 8080
  base_url: "http://192.168.1.10:8080"
  cover_cache:
    directory: cache_covers
    size: 2000
  audio_cache:
    directory: cache_audio
    size: 500
  logger:
    buffer_capacity: 200
    enable_console: true
    min_level: INFO

playlists:
  directory: playlists

devices:
  mediarenderer:
    pmo_mediarenderer:
      udn: e4b68fbc-2bd5-4cea-98d8-be843fec0bd4
  mediaserver:
    pmo_mediaserver:
      udn: 17fe2ea6-8908-4e30-bc52-b28ea4cab3e4

accounts:
  qobuz:
    username: user@example.com
    password: encrypted:ABC123...  # ← Mot de passe chiffré
    appid: '798273057'
    secret: 806331c3b0b641da923b890aed01d04a

Répertoires de configuration

La configuration est recherchée dans cet ordre :

  1. Répertoire fourni en paramètre
  2. Variable d'environnement PMOMUSIC_CONFIG
  3. .pmomusic dans le répertoire courant
  4. .pmomusic dans le répertoire home (~/.pmomusic)

Overrides via variables d'environnement

# Format: PMOMUSIC_CONFIG__section__key
export PMOMUSIC_CONFIG__host__http_port=9000
export PMOMUSIC_CONFIG__host__logger__min_level=DEBUG

# Lancer l'application
./pmomusic

API REST (feature api)

[dependencies]
pmoconfig = { path = "../pmoconfig", features = ["api"] }
use pmoconfig::api::create_config_router;
use axum::Router;

let config_router = create_config_router();
let app = Router::new().nest("/api/config", config_router);

Endpoints disponibles :

  • GET /api/config - Récupère toute la configuration
  • GET /api/config/{path} - Récupère une valeur spécifique
  • PUT /api/config/{path} - Modifie une valeur
  • GET /api/config/docs - Documentation OpenAPI/Swagger

Exemples

Exemple complet

Voir examples/encrypt_password.rs pour un exemple complet de chiffrement/déchiffrement.

Utilisation dans un projet

use pmoconfig::{get_config, encryption};
use anyhow::Result;

fn main() -> Result<()> {
    let config = get_config();

    // Lire la configuration
    let port = config.get_http_port();
    println!("HTTP port: {}", port);

    // Lire un mot de passe (automatiquement déchiffré)
    let password_value = config.get_value(&["accounts", "service", "password"])?;
    if let serde_yaml::Value::String(s) = password_value {
        let password = encryption::get_password(&s)?;
        println!("Password loaded successfully");
    }

    Ok(())
}

Tests

# Tests unitaires
cargo test

# Tests du module encryption
cargo test encryption

# Tester l'outil de chiffrement
cargo run --example encrypt_password -- test

Dépendances

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9"
anyhow = "1.0"
dirs = "6.0"
uuid = { version = "1.18", features = ["v4"] }
tracing = "0.1"

# Chiffrement
aes-gcm = "0.10"
sha2 = "0.10"
base64 = "0.22"

# Feature API (optionnel)
axum = { version = "0.8", optional = true }
utoipa = { version = "5.3", optional = true }

Licence

Voir LICENSE dans la racine du projet.