
- Modifier examples/usage.ts pour utiliser VAULT_CONFS_DIR depuis .env au lieu de '../confs' hardcodé - Ajouter test-usage.js comme script de test fonctionnel - Nettoyer les anciens fichiers de debug et test - Ajouter **/confs*/ au .gitignore pour éviter de committer les dossiers de test Le SDK respecte maintenant correctement le paramètre VAULT_CONFS_DIR du fichier .env.
437 lines
15 KiB
TypeScript
437 lines
15 KiB
TypeScript
/**
|
||
* Exemple d'utilisation du client Vault
|
||
* Scénario complet : Initialisation → Routes → Parcours → Déchiffrement
|
||
*/
|
||
|
||
import { SecureVaultClient, VaultApiError, VaultAuthenticationError, VaultDecryptionError } from '../src/index';
|
||
|
||
/**
|
||
* ÉTAPE 1: Initialisation + Gestion des erreurs
|
||
*/
|
||
async function step1_Initialization() {
|
||
console.log('🚀 ÉTAPE 1: Initialisation du client + Gestion des erreurs');
|
||
console.log('='.repeat(70));
|
||
|
||
try {
|
||
// Test avec différents IDs utilisateur
|
||
const testUserIds = [
|
||
'demo_user_001', // ID existant
|
||
'invalid@user', // ID invalide (caractères interdits)
|
||
'ab', // ID trop court
|
||
'a'.repeat(129), // ID trop long
|
||
'3506ea43d9207038eea58caca84d51e4ccc01c496b6572bbf4dfda7fa03085b8' // Votre clé
|
||
];
|
||
|
||
let validClient: SecureVaultClient | null = null;
|
||
|
||
for (const userId of testUserIds) {
|
||
try {
|
||
console.log(`\n🔍 Test avec l'ID: ${userId.substring(0, 20)}${userId.length > 20 ? '...' : ''}`);
|
||
|
||
// Utiliser le constructeur avec chargement automatique des clés .env
|
||
// Pour le test avec les vraies clés, utiliser le constructeur sans paramètres
|
||
const client = userId === 'demo_user_001' ? new SecureVaultClient() : new SecureVaultClient({
|
||
baseUrl: 'https://vault.4nkweb.com:6666',
|
||
userId: userId,
|
||
timeout: 30000,
|
||
verifySsl: false
|
||
});
|
||
|
||
// Test de connectivité
|
||
const isConnected = await client.ping();
|
||
|
||
if (isConnected) {
|
||
console.log(` ✅ ID valide et connecté: ${userId}`);
|
||
if (!validClient) {
|
||
validClient = client;
|
||
}
|
||
} else {
|
||
console.log(` ❌ ID valide mais non connecté: ${userId}`);
|
||
}
|
||
|
||
} catch (error: any) {
|
||
if (error instanceof VaultAuthenticationError) {
|
||
console.log(` 🔑 Erreur d'authentification: ${error.message}`);
|
||
} else if (error.message.includes('ID utilisateur requis') || error.message.includes('invalide')) {
|
||
console.log(` ⚠️ ID invalide: ${error.message}`);
|
||
} else {
|
||
console.log(` ❌ Erreur inattendue: ${error.message}`);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!validClient) {
|
||
throw new Error('Aucun client valide trouvé - impossible de continuer');
|
||
}
|
||
|
||
console.log('\n✅ ÉTAPE 1 TERMINÉE: Client initialisé avec succès');
|
||
return validClient;
|
||
|
||
} catch (error) {
|
||
console.error('\n❌ ÉTAPE 1 ÉCHOUÉE:', error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* ÉTAPE 2: Récupération de toutes les routes + Gestion des erreurs
|
||
*/
|
||
async function step2_GetRoutes(client: SecureVaultClient) {
|
||
console.log('\n🛣️ ÉTAPE 2: Récupération de toutes les routes + Gestion des erreurs');
|
||
console.log('='.repeat(70));
|
||
|
||
try {
|
||
// Test de récupération des routes
|
||
console.log('\n📋 Récupération des routes disponibles...');
|
||
const routes = await client.getRoutes();
|
||
|
||
console.log(` ✅ Total des routes: ${routes.total_routes}`);
|
||
console.log(` ✅ Utilisateur: ${routes.user_id}`);
|
||
console.log(` ✅ Type d'authentification: ${routes.authentication.type}`);
|
||
|
||
console.log('\n📝 Routes disponibles:');
|
||
routes.routes.forEach((route, index) => {
|
||
console.log(` ${index + 1}. ${route.method} ${route.path}`);
|
||
console.log(` → ${route.description}`);
|
||
console.log(` → Authentification: ${route.authentication}`);
|
||
console.log(` → Type de réponse: ${route.response_type}`);
|
||
|
||
if (route.parameters) {
|
||
console.log(` → Paramètres:`);
|
||
Object.entries(route.parameters).forEach(([key, value]) => {
|
||
console.log(` • ${key}: ${value}`);
|
||
});
|
||
}
|
||
|
||
if (route.examples && route.examples.length > 0) {
|
||
console.log(` → Exemples:`);
|
||
route.examples.forEach(example => {
|
||
console.log(` • ${example}`);
|
||
});
|
||
}
|
||
console.log('');
|
||
});
|
||
|
||
console.log('✅ ÉTAPE 2 TERMINÉE: Routes récupérées avec succès');
|
||
return routes;
|
||
|
||
} catch (error: any) {
|
||
console.error('\n❌ ÉTAPE 2 ÉCHOUÉE:');
|
||
|
||
if (error instanceof VaultApiError) {
|
||
console.error(` Erreur API: ${error.message}`);
|
||
console.error(` Code HTTP: ${error.statusCode}`);
|
||
console.error(` Code d'erreur: ${error.code}`);
|
||
} else if (error instanceof VaultAuthenticationError) {
|
||
console.error(` Erreur d'authentification: ${error.message}`);
|
||
console.error(` Code HTTP: ${error.statusCode}`);
|
||
} else {
|
||
console.error(` Erreur inattendue: ${error.message}`);
|
||
}
|
||
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* ÉTAPE 3: Parcours de toutes les routes pour récupération du contenu + Gestion des erreurs
|
||
*/
|
||
async function step3_ParseRoutes(routes: any, client: SecureVaultClient) {
|
||
console.log('\n📁 ÉTAPE 3: Parcours des routes pour récupération du contenu + Gestion des erreurs');
|
||
console.log('='.repeat(70));
|
||
|
||
const results: any[] = [];
|
||
|
||
try {
|
||
for (const route of routes.routes) {
|
||
console.log(`\n🔍 Test de la route: ${route.method} ${route.path}`);
|
||
|
||
try {
|
||
let result: any = null;
|
||
|
||
switch (route.path) {
|
||
case '/health':
|
||
result = await client.health();
|
||
console.log(` ✅ Health: ${result.status} - ${result.service}`);
|
||
break;
|
||
|
||
case '/info':
|
||
result = await client.info();
|
||
console.log(` ✅ Info: ${result.name} v${result.version}`);
|
||
break;
|
||
|
||
case '/routes':
|
||
result = await client.getRoutes();
|
||
console.log(` ✅ Routes: ${result.total_routes} routes disponibles`);
|
||
break;
|
||
|
||
default:
|
||
// Route dynamique /<env>/<file_path>
|
||
if (route.path.includes('<env>') && route.path.includes('<file_path>')) {
|
||
console.log(` 📂 Test des fichiers de configuration...`);
|
||
|
||
// Tester quelques fichiers de configuration connus
|
||
const testFiles = [
|
||
'bitcoin/bitcoin.conf',
|
||
'nginx/nginx.conf',
|
||
'grafana/grafana.ini'
|
||
];
|
||
|
||
for (const filePath of testFiles) {
|
||
try {
|
||
const fileResult = await client.getFile('dev', filePath);
|
||
console.log(` ✅ ${filePath}: ${fileResult.size} caractères`);
|
||
results.push({
|
||
route: `${route.method} /dev/${filePath}`,
|
||
success: true,
|
||
data: fileResult
|
||
});
|
||
} catch (fileError: any) {
|
||
console.log(` ❌ ${filePath}: ${fileError.message}`);
|
||
results.push({
|
||
route: `${route.method} /dev/${filePath}`,
|
||
success: false,
|
||
error: fileError.message
|
||
});
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
if (result) {
|
||
results.push({
|
||
route: `${route.method} ${route.path}`,
|
||
success: true,
|
||
data: result
|
||
});
|
||
}
|
||
|
||
} catch (error: any) {
|
||
console.log(` ❌ Erreur: ${error.message}`);
|
||
|
||
if (error instanceof VaultApiError) {
|
||
console.log(` → Code HTTP: ${error.statusCode}`);
|
||
console.log(` → Code d'erreur: ${error.code}`);
|
||
} else if (error instanceof VaultAuthenticationError) {
|
||
console.log(` → Erreur d'authentification`);
|
||
} else if (error instanceof VaultDecryptionError) {
|
||
console.log(` → Erreur de déchiffrement`);
|
||
}
|
||
|
||
results.push({
|
||
route: `${route.method} ${route.path}`,
|
||
success: false,
|
||
error: error.message,
|
||
errorType: error.name
|
||
});
|
||
}
|
||
}
|
||
|
||
console.log(`\n📊 Résumé des tests:`);
|
||
const successCount = results.filter(r => r.success).length;
|
||
const errorCount = results.filter(r => !r.success).length;
|
||
|
||
console.log(` ✅ Succès: ${successCount}/${results.length}`);
|
||
console.log(` ❌ Erreurs: ${errorCount}/${results.length}`);
|
||
|
||
console.log('\n✅ ÉTAPE 3 TERMINÉE: Parcours des routes terminé');
|
||
return results;
|
||
|
||
} catch (error: any) {
|
||
console.error('\n❌ ÉTAPE 3 ÉCHOUÉE:', error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* ÉTAPE 4: Synchronisation locale des fichiers déchiffrés + Gestion des erreurs
|
||
*/
|
||
async function step4_SyncLocalFiles(client: SecureVaultClient) {
|
||
console.log('\n💾 ÉTAPE 4: Synchronisation locale des fichiers déchiffrés + Gestion des erreurs');
|
||
console.log('='.repeat(70));
|
||
|
||
try {
|
||
console.log('\n🔄 Synchronisation des fichiers vers le dossier local...');
|
||
console.log(' Utilise VAULT_CONFS_DIR depuis le fichier .env');
|
||
|
||
// Synchronisation avec options détaillées
|
||
// Ne pas spécifier localDir pour utiliser VAULT_CONFS_DIR du .env
|
||
const syncResult = await client.syncLocalFiles({
|
||
environment: 'dev',
|
||
verbose: true
|
||
});
|
||
|
||
console.log(`\n📊 Résultats de synchronisation:`);
|
||
console.log(` ✅ Fichiers synchronisés: ${syncResult.synced}`);
|
||
console.log(` ⏭️ Fichiers ignorés: ${syncResult.skipped}`);
|
||
console.log(` ❌ Erreurs: ${syncResult.errors}`);
|
||
|
||
// Affichage détaillé des résultats
|
||
if (syncResult.details.length > 0) {
|
||
console.log('\n📋 Détails par fichier:');
|
||
syncResult.details.forEach(detail => {
|
||
const icon = detail.status === 'synced' ? '✅' :
|
||
detail.status === 'skipped' ? '⏭️' : '❌';
|
||
console.log(` ${icon} ${detail.file}: ${detail.status}`);
|
||
if (detail.message) {
|
||
console.log(` → ${detail.message}`);
|
||
}
|
||
});
|
||
}
|
||
|
||
console.log('\n✅ ÉTAPE 4 TERMINÉE: Synchronisation locale terminée');
|
||
|
||
} catch (error: any) {
|
||
console.error('\n❌ ÉTAPE 4 ÉCHOUÉE:');
|
||
|
||
if (error instanceof VaultApiError) {
|
||
console.error(` Erreur API: ${error.message}`);
|
||
console.error(` Code HTTP: ${error.statusCode}`);
|
||
} else if (error.message.includes('synchronisation')) {
|
||
console.error(` Erreur de synchronisation: ${error.message}`);
|
||
} else {
|
||
console.error(` Erreur inattendue: ${error.message}`);
|
||
}
|
||
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* ÉTAPE 5: Déchiffrement des contenus récupérés (non stocké) + Gestion des erreurs
|
||
*/
|
||
async function step5_DecryptContents(results: any[]) {
|
||
console.log('\n🔓 ÉTAPE 5: Déchiffrement des contenus récupérés + Gestion des erreurs');
|
||
console.log('='.repeat(70));
|
||
|
||
try {
|
||
const fileResults = results.filter(r => r.success && r.data && r.data.content);
|
||
|
||
if (fileResults.length === 0) {
|
||
console.log(' ⚠️ Aucun fichier récupéré pour déchiffrement');
|
||
return;
|
||
}
|
||
|
||
console.log(`\n🔍 Déchiffrement de ${fileResults.length} fichier(s)...`);
|
||
|
||
for (const fileResult of fileResults) {
|
||
console.log(`\n📄 Fichier: ${fileResult.route}`);
|
||
|
||
try {
|
||
const content = fileResult.data.content;
|
||
|
||
// Vérifier si le contenu est chiffré (format de démonstration)
|
||
if (content.includes('[CONTENU CHIFFRÉ - DÉCHIFFREMENT NÉCESSAIRE]')) {
|
||
console.log(' 🔐 Contenu chiffré détecté (format de démonstration)');
|
||
|
||
// Extraire les métadonnées du format de démonstration
|
||
const lines = content.split('\n');
|
||
const metadata: any = {};
|
||
|
||
lines.forEach((line: string) => {
|
||
if (line.includes('Utilisateur:')) {
|
||
metadata.user = line.split('Utilisateur:')[1]?.trim() || '';
|
||
} else if (line.includes('Version de clé:')) {
|
||
metadata.keyVersion = line.split('Version de clé:')[1]?.trim() || '';
|
||
} else if (line.includes('Algorithme:')) {
|
||
metadata.algorithm = line.split('Algorithme:')[1]?.trim() || '';
|
||
} else if (line.includes('Rotation:')) {
|
||
metadata.rotation = line.split('Rotation:')[1]?.trim() || '';
|
||
} else if (line.includes('Taille chiffrée:')) {
|
||
metadata.encryptedSize = line.split('Taille chiffrée:')[1]?.trim() || '';
|
||
}
|
||
});
|
||
|
||
console.log(` 📋 Métadonnées extraites:`);
|
||
console.log(` → Utilisateur: ${metadata.user}`);
|
||
console.log(` → Version de clé: ${metadata.keyVersion}`);
|
||
console.log(` → Algorithme: ${metadata.algorithm}`);
|
||
console.log(` → Rotation: ${metadata.rotation}`);
|
||
console.log(` → Taille chiffrée: ${metadata.encryptedSize}`);
|
||
|
||
// Dans un vrai déchiffrement, on utiliserait la clé utilisateur
|
||
console.log(` 🔑 Déchiffrement simulé: Contenu accessible avec la clé utilisateur`);
|
||
|
||
} else {
|
||
console.log(' 📝 Contenu non chiffré détecté');
|
||
console.log(` 📄 Aperçu: ${content.substring(0, 100)}${content.length > 100 ? '...' : ''}`);
|
||
}
|
||
|
||
console.log(` ✅ Déchiffrement traité avec succès`);
|
||
|
||
} catch (error: any) {
|
||
console.log(` ❌ Erreur de déchiffrement: ${error.message}`);
|
||
|
||
if (error instanceof VaultDecryptionError) {
|
||
console.log(` → Erreur de déchiffrement spécifique`);
|
||
console.log(` → Code: ${error.code}`);
|
||
} else if (error.message.includes('déchiffrement')) {
|
||
console.log(` → Erreur de traitement du contenu`);
|
||
} else {
|
||
console.log(` → Erreur inattendue lors du déchiffrement`);
|
||
}
|
||
}
|
||
}
|
||
|
||
console.log('\n✅ ÉTAPE 5 TERMINÉE: Déchiffrement des contenus terminé');
|
||
|
||
} catch (error: any) {
|
||
console.error('\n❌ ÉTAPE 5 ÉCHOUÉE:', error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Fonction principale - Exécute le scénario complet
|
||
*/
|
||
async function main() {
|
||
console.log('🚀 DÉMONSTRATION COMPLÈTE DU CLIENT VAULT');
|
||
console.log('Scénario: Initialisation → Routes → Parcours → Synchronisation → Déchiffrement');
|
||
console.log('='.repeat(80));
|
||
|
||
try {
|
||
// ÉTAPE 1: Initialisation
|
||
const client = await step1_Initialization();
|
||
|
||
// ÉTAPE 2: Récupération des routes
|
||
const routes = await step2_GetRoutes(client);
|
||
|
||
// ÉTAPE 3: Parcours des routes
|
||
const results = await step3_ParseRoutes(routes, client);
|
||
|
||
// ÉTAPE 4: Synchronisation locale
|
||
await step4_SyncLocalFiles(client);
|
||
|
||
// ÉTAPE 5: Déchiffrement
|
||
await step5_DecryptContents(results);
|
||
|
||
console.log('\n🎉 SCÉNARIO COMPLET TERMINÉ AVEC SUCCÈS!');
|
||
console.log('\n📝 Résumé du système sécurisé:');
|
||
console.log(' • ✅ Authentification par ID utilisateur validée');
|
||
console.log(' • ✅ Récupération des routes API fonctionnelle');
|
||
console.log(' • ✅ Parcours de toutes les routes testé');
|
||
console.log(' • ✅ Synchronisation locale des fichiers déchiffrés');
|
||
console.log(' • ✅ Déchiffrement des contenus géré');
|
||
console.log(' • ✅ Gestion d\'erreurs complète à chaque étape');
|
||
console.log(' • ✅ Rotation automatique des clés active');
|
||
console.log(' • ✅ Chiffrement quantum-résistant (ChaCha20-Poly1305)');
|
||
|
||
} catch (error) {
|
||
console.error('\n💥 ÉCHEC DU SCÉNARIO:', error);
|
||
process.exit(1);
|
||
}
|
||
}
|
||
|
||
// Exécution si appelé directement
|
||
if (require.main === module) {
|
||
main().catch(console.error);
|
||
}
|
||
|
||
export {
|
||
step1_Initialization,
|
||
step2_GetRoutes,
|
||
step3_ParseRoutes,
|
||
step4_SyncLocalFiles,
|
||
step5_DecryptContents
|
||
}; |