#!/usr/bin/env python3 """ Test de l'API Vault sécurisée avec authentification par clés utilisateur """ import requests import json import base64 from datetime import datetime # Configuration BASE_URL = 'https://127.0.0.1:6666' USER_ID = 'demo_user_001' # ID utilisateur de test VERIFY_SSL = False # Certificats auto-signés def test_health(): """Test de l'endpoint de santé""" print("🔍 Test de santé de l'API...") try: response = requests.get( f"{BASE_URL}/health", verify=VERIFY_SSL, headers={'X-User-ID': USER_ID} ) if response.status_code == 200: health_data = response.json() print(f"✅ API en bonne santé") print(f" Service: {health_data.get('service')}") print(f" Chiffrement: {health_data.get('encryption')}") print(f" Algorithme: {health_data.get('algorithm')}") print(f" Authentification: {health_data.get('authentication')}") print(f" Rotation des clés: {health_data.get('key_rotation')}") return True else: print(f"❌ Erreur de santé: {response.status_code}") print(f" Réponse: {response.text}") return False except Exception as e: print(f"❌ Erreur de connexion: {e}") return False def test_info(): """Test de l'endpoint d'informations""" print("\n📋 Test des informations API...") try: response = requests.get( f"{BASE_URL}/info", verify=VERIFY_SSL, headers={'X-User-ID': USER_ID} ) if response.status_code == 200: info_data = response.json() print(f"✅ Informations récupérées") print(f" Nom: {info_data.get('name')}") print(f" Version: {info_data.get('version')}") print(f" Domaine: {info_data.get('domain')}") print(f" Protocole: {info_data.get('protocol')}") print(f" Authentification: {info_data.get('authentication')}") return True else: print(f"❌ Erreur d'informations: {response.status_code}") print(f" Réponse: {response.text}") return False except Exception as e: print(f"❌ Erreur de connexion: {e}") return False def test_file_access(): """Test d'accès à un fichier""" print("\n📁 Test d'accès au fichier...") try: # Test avec l'environnement dev qui existe response = requests.get( f"{BASE_URL}/dev/bitcoin/bitcoin.conf", verify=VERIFY_SSL, headers={'X-User-ID': USER_ID} ) if response.status_code == 200: print(f"✅ Fichier récupéré avec succès") print(f" Taille: {len(response.content)} bytes") print(f" Type de contenu: {response.headers.get('Content-Type')}") print(f" Type de chiffrement: {response.headers.get('X-Encryption-Type')}") print(f" Algorithme: {response.headers.get('X-Algorithm')}") print(f" ID utilisateur: {response.headers.get('X-User-ID')}") print(f" Rotation des clés: {response.headers.get('X-Key-Rotation')}") # Tentative de décodage des métadonnées try: decoded = base64.b64decode(response.content) if len(decoded) >= 16: nonce = decoded[:12] metadata_size = int.from_bytes(decoded[12:16], 'big') metadata_json = decoded[16:16+metadata_size] metadata = json.loads(metadata_json.decode('utf-8')) print(f"\n📊 Métadonnées de chiffrement:") print(f" Utilisateur: {metadata.get('user_id')}") print(f" Version de clé: {metadata.get('key_version')}") print(f" Timestamp: {metadata.get('timestamp')}") print(f" Algorithme: {metadata.get('algorithm')}") except Exception as e: print(f"⚠️ Impossible de décoder les métadonnées: {e}") return True else: print(f"❌ Erreur d'accès au fichier: {response.status_code}") print(f" Réponse: {response.text}") return False except Exception as e: print(f"❌ Erreur de connexion: {e}") return False def test_authentication(): """Test d'authentification avec différents ID utilisateur""" print("\n🔐 Test d'authentification...") test_users = [ ('valid_user_001', True), ('invalid@user', False), ('ab', False), # Trop court ('a' * 51, False), # Trop long ('', False), # Vide ] for user_id, should_succeed in test_users: print(f"\n Test utilisateur: '{user_id}' (attendu: {'succès' if should_succeed else 'échec'})") try: response = requests.get( f"{BASE_URL}/health", verify=VERIFY_SSL, headers={'X-User-ID': user_id} if user_id else {} ) success = response.status_code == 200 if success == should_succeed: print(f" ✅ Résultat attendu") else: print(f" ❌ Résultat inattendu: {response.status_code}") except Exception as e: if not should_succeed: print(f" ✅ Erreur attendue: {e}") else: print(f" ❌ Erreur inattendue: {e}") def test_https_requirement(): """Test de l'obligation HTTPS""" print("\n🔒 Test de l'obligation HTTPS...") # Tentative d'accès HTTP (devrait échouer) http_url = BASE_URL.replace('https://', 'http://') try: response = requests.get( f"{http_url}/health", verify=VERIFY_SSL, headers={'X-User-ID': USER_ID}, timeout=5 ) print(f"❌ HTTP autorisé (ne devrait pas l'être): {response.status_code}") except Exception as e: print(f"✅ HTTP refusé comme attendu: {e}") def test_key_rotation(): """Test de la rotation des clés""" print("\n🔄 Test de la rotation des clés...") try: # Premier accès response1 = requests.get( f"{BASE_URL}/dev/bitcoin/bitcoin.conf", verify=VERIFY_SSL, headers={'X-User-ID': USER_ID} ) if response1.status_code == 200: # Attendre un peu et refaire un accès import time time.sleep(2) response2 = requests.get( f"{BASE_URL}/dev/bitcoin/bitcoin.conf", verify=VERIFY_SSL, headers={'X-User-ID': USER_ID} ) if response2.status_code == 200: # Comparer les réponses (les clés peuvent avoir changé) print(f"✅ Accès multiples réussis") print(f" Premier accès: {len(response1.content)} bytes") print(f" Deuxième accès: {len(response2.content)} bytes") # Les réponses peuvent être différentes à cause de la rotation des clés if response1.content != response2.content: print(f" ✅ Contenu différent détecté (rotation des clés possible)") else: print(f" ⚠️ Contenu identique (rotation pas encore déclenchée)") return True else: print(f"❌ Deuxième accès échoué: {response2.status_code}") else: print(f"❌ Premier accès échoué: {response1.status_code}") except Exception as e: print(f"❌ Erreur lors du test de rotation: {e}") return False def main(): """Fonction principale de test""" print("🚀 Test de l'API Vault sécurisée") print("=" * 50) print(f"URL de base: {BASE_URL}") print(f"ID utilisateur: {USER_ID}") print(f"Vérification SSL: {VERIFY_SSL}") print("=" * 50) # Tests tests = [ ("Santé de l'API", test_health), ("Informations API", test_info), ("Accès aux fichiers", test_file_access), ("Authentification", test_authentication), ("Obligation HTTPS", test_https_requirement), ("Rotation des clés", test_key_rotation), ] results = [] for test_name, test_func in tests: try: result = test_func() results.append((test_name, result)) except Exception as e: print(f"❌ Erreur dans le test '{test_name}': {e}") results.append((test_name, False)) # Résumé print("\n" + "=" * 50) print("📊 RÉSUMÉ DES TESTS") print("=" * 50) passed = 0 total = len(results) for test_name, result in results: status = "✅ PASSÉ" if result else "❌ ÉCHOUÉ" print(f"{status} - {test_name}") if result: passed += 1 print(f"\nRésultat global: {passed}/{total} tests passés") if passed == total: print("🎉 Tous les tests sont passés avec succès!") else: print("⚠️ Certains tests ont échoué. Vérifiez la configuration.") if __name__ == '__main__': main()