
- ✅ API sécurisée avec authentification par ID utilisateur - ✅ HTTPS obligatoire avec rejet des connexions HTTP - ✅ Clés individuelles par utilisateur ET par environnement - ✅ Rotation automatique des clés avec sauvegarde de l'ancienne - ✅ Stockage sécurisé dans storage/<env>/_keys/ - ✅ Client SDK mis à jour sans stockage de clés côté client - ✅ Documentation complète avec avertissements de sécurité - ✅ Tests complets du système sécurisé - 🔒 Protection des fichiers sensibles dans .gitignore
14 KiB
SDK Client TypeScript - Documentation complète
Vue d'ensemble
Le SDK Client TypeScript pour l'API Vault 4NK fournit une interface type-safe et moderne pour interagir avec l'API de stockage sécurisé. Il inclut le déchiffrement côté client, la gestion d'erreurs avancée, et des utilitaires cryptographiques.
Installation
NPM
npm install @4nk/vault-sdk
Depuis les sources
git clone https://git.4nkweb.com/4nk/vault-sdk.git
cd vault-sdk
npm install
npm run build
Configuration
Importation de base
import { VaultClient, createVaultClient, VaultCrypto } from '@4nk/vault-sdk';
Création d'un client
Méthode simple (recommandée)
const client = createVaultClient(
'https://vault.4nkweb.com:6666'
// Plus de clé de déchiffrement nécessaire - clés dynamiques utilisées
);
Méthode avancée (recommandée)
const client = new VaultClient(
{
baseUrl: 'https://vault.4nkweb.com:6666',
verifySsl: false, // Pour les certificats auto-signés
timeout: 15000, // 15 secondes
}
// Plus de clé de déchiffrement nécessaire - clés dynamiques utilisées
);
Méthode compatible (dépréciée)
const client = new VaultClient(
{
baseUrl: 'https://vault.4nkweb.com:6666',
verifySsl: false,
timeout: 15000,
},
'old_demo_key' // Ignorée mais acceptée pour compatibilité
);
API Reference
Classe VaultClient
Constructeur
constructor(config: VaultConfig, decryptionKey?: string)
Paramètres :
config
: Configuration du clientdecryptionKey
: Clé de déchiffrement optionnelle (32 bytes exactement) - Dépréciée, clés dynamiques utilisées
Configuration :
interface VaultConfig {
baseUrl: string; // URL de base de l'API
verifySsl?: boolean; // Validation SSL (défaut: true)
timeout?: number; // Timeout en ms (défaut: 30000)
}
Méthodes
getFile(env: string, filePath: string): Promise<VaultFile>
Récupère et déchiffre un fichier depuis l'API.
Paramètres :
env
: Environnement (ex: "dev", "prod")filePath
: Chemin du fichier relatif
Retour :
interface VaultFile {
content: string; // Contenu déchiffré
filename: string; // Nom du fichier
size: number; // Taille en caractères
encrypted: boolean; // Était chiffré
algorithm?: string; // Algorithme utilisé
}
Exemple :
try {
const file = await client.getFile('dev', 'bitcoin/bitcoin.conf');
console.log(`Fichier: ${file.filename}`);
console.log(`Taille: ${file.size} caractères`);
console.log(`Contenu: ${file.content}`);
} catch (error) {
console.error('Erreur:', error.message);
}
getFiles(requests: FileRequest[]): Promise<VaultFile[]>
Récupère plusieurs fichiers en parallèle.
Paramètres :
interface FileRequest {
env: string;
filePath: string;
}
Exemple :
const files = await client.getFiles([
{ env: 'dev', filePath: 'bitcoin/bitcoin.conf' },
{ env: 'dev', filePath: 'tor/torrc' },
{ env: 'dev', filePath: 'sdk_relay/sdk_relay.conf' }
]);
files.forEach(file => {
console.log(`${file.filename}: ${file.size} caractères`);
});
health(): Promise<VaultHealth>
Vérifie l'état de santé de l'API.
Retour :
interface VaultHealth {
status: string; // "healthy" ou "unhealthy"
service: string; // Nom du service
encryption: string; // Type de chiffrement
algorithm: string; // Algorithme utilisé
}
Exemple :
const health = await client.health();
console.log(`Statut: ${health.status}`);
console.log(`Chiffrement: ${health.encryption}`);
info(): Promise<VaultInfo>
Récupère les informations sur l'API.
Retour :
interface VaultInfo {
name: string; // Nom de l'API
version: string; // Version
domain: string; // Domaine
port: number; // Port
protocol: string; // Protocole
encryption: string; // Type de chiffrement
endpoints: Record<string, string>; // Endpoints disponibles
}
Exemple :
const info = await client.info();
console.log(`API: ${info.name} v${info.version}`);
console.log(`Domaine: ${info.domain}:${info.port}`);
ping(): Promise<boolean>
Teste la connectivité à l'API.
Retour : true
si connecté, false
sinon
Exemple :
const isConnected = await client.ping();
if (isConnected) {
console.log('✅ API accessible');
} else {
console.log('❌ API inaccessible');
}
searchFiles(env: string, pattern?: RegExp): Promise<string[]>
Recherche des fichiers par pattern (non implémenté côté serveur).
Note : Cette méthode retourne toujours un tableau vide car l'endpoint de recherche n'est pas encore implémenté côté serveur.
Classe VaultCrypto
Utilitaires pour la gestion des clés de chiffrement.
generateKey(): string
Génère une clé de déchiffrement aléatoire de 32 bytes (déprécié).
Retour : Clé de 32 caractères UTF-8
Note : Cette méthode est dépréciée car le système utilise maintenant des clés dynamiques générées automatiquement par le serveur.
hashToKey(password: string): string
Dérive une clé de 32 bytes depuis un mot de passe (déprécié).
Paramètres :
password
: Mot de passe source
Retour : Clé de 32 bytes dérivée avec SHA-256
Note : Cette méthode est dépréciée car le système utilise maintenant des clés dynamiques générées automatiquement par le serveur.
validateKey(key: string): boolean
Vérifie qu'une clé fait exactement 32 bytes (déprécié).
Paramètres :
key
: Clé à valider
Retour : true
si la clé est valide, false
sinon
Note : Cette méthode est dépréciée car le système utilise maintenant des clés dynamiques générées automatiquement par le serveur.
Gestion d'erreurs
Classes d'erreurs
VaultApiError
Erreurs liées aux requêtes HTTP vers l'API.
class VaultApiError extends Error {
constructor(
message: string,
public statusCode?: number,
public endpoint?: string
);
}
Propriétés :
message
: Message d'erreurstatusCode
: Code HTTP d'erreurendpoint
: Endpoint qui a échoué
Exemple :
try {
await client.getFile('dev', 'fichier-inexistant.conf');
} catch (error) {
if (error instanceof VaultApiError) {
console.error(`Erreur API: ${error.message}`);
console.error(`Code: ${error.statusCode}`);
console.error(`Endpoint: ${error.endpoint}`);
}
}
VaultDecryptionError
Erreurs liées au déchiffrement des fichiers.
class VaultDecryptionError extends Error {
constructor(message: string);
}
Exemple :
try {
const file = await client.getFile('dev', 'config.conf');
} catch (error) {
if (error instanceof VaultDecryptionError) {
console.error(`Erreur de déchiffrement: ${error.message}`);
}
}
Gestion d'erreurs complète
async function handleFileRequest(env: string, filePath: string) {
try {
const file = await client.getFile(env, filePath);
return file;
} catch (error) {
if (error instanceof VaultApiError) {
switch (error.statusCode) {
case 404:
console.error(`Fichier non trouvé: ${filePath}`);
break;
case 403:
console.error(`Accès non autorisé: ${filePath}`);
break;
case 500:
console.error(`Erreur serveur pour: ${filePath}`);
break;
default:
console.error(`Erreur API: ${error.message}`);
}
} else if (error instanceof VaultDecryptionError) {
console.error(`Erreur de déchiffrement: ${error.message}`);
} else {
console.error(`Erreur inconnue: ${error.message}`);
}
throw error;
}
}
Exemples d'utilisation
Exemple basique
import { createVaultClient } from '@4nk/vault-sdk';
async function basicExample() {
// Création du client (plus de clé de déchiffrement nécessaire)
const client = createVaultClient('https://vault.4nkweb.com:6666');
// Test de connectivité
const isConnected = await client.ping();
if (!isConnected) {
throw new Error('Impossible de se connecter à l\'API');
}
// Récupération d'un fichier
const file = await client.getFile('dev', 'bitcoin/bitcoin.conf');
console.log(`Fichier: ${file.filename}`);
console.log(`Taille: ${file.size} caractères`);
console.log(`Contenu: ${file.content.substring(0, 100)}...`);
}
Exemple avancé avec gestion d'erreurs
import { VaultClient, VaultApiError, VaultDecryptionError } from '@4nk/vault-sdk';
async function advancedExample() {
const client = new VaultClient({
baseUrl: 'https://vault.4nkweb.com:6666',
timeout: 10000,
});
// Informations sur l'API
try {
const info = await client.info();
console.log(`API: ${info.name} v${info.version}`);
} catch (error) {
console.error('Erreur info:', error.message);
}
// Récupération de plusieurs fichiers
const requests = [
{ env: 'dev', filePath: 'bitcoin/bitcoin.conf' },
{ env: 'dev', filePath: 'tor/torrc' },
{ env: 'dev', filePath: 'sdk_relay/sdk_relay.conf' }
];
try {
const files = await client.getFiles(requests);
console.log(`${files.length} fichiers récupérés`);
files.forEach((file, index) => {
console.log(`${index + 1}. ${file.filename}: ${file.size} chars`);
});
} catch (error) {
if (error instanceof VaultApiError) {
console.error(`Erreur API: ${error.statusCode} - ${error.message}`);
} else if (error instanceof VaultDecryptionError) {
console.error(`Erreur de déchiffrement: ${error.message}`);
}
}
}
Exemple avec retry automatique
async function retryOperation<T>(
operation: () => Promise<T>,
maxRetries: number = 3,
delay: number = 1000
): Promise<T> {
let lastError: Error;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
lastError = error as Error;
console.log(`Tentative ${attempt}/${maxRetries} échouée: ${lastError.message}`);
if (attempt < maxRetries) {
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
throw lastError!;
}
// Utilisation
const file = await retryOperation(
() => client.getFile('dev', 'bitcoin/bitcoin.conf'),
3,
500
);
Configuration TypeScript
tsconfig.json recommandé
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020", "DOM"],
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": true,
"sourceMap": true
}
}
Types personnalisés
// Extension des types existants
interface CustomVaultFile extends VaultFile {
metadata?: {
lastModified: Date;
checksum: string;
};
}
// Types pour vos applications
interface ConfigFile {
environment: string;
services: string[];
variables: Record<string, string>;
}
Tests
Tests unitaires avec Jest
import { VaultClient, VaultCrypto } from '@4nk/vault-sdk';
describe('VaultClient', () => {
let client: VaultClient;
beforeEach(() => {
client = new VaultClient({
baseUrl: 'https://vault.4nkweb.com:6666'
});
});
it('devrait récupérer un fichier', async () => {
const file = await client.getFile('dev', 'bitcoin/bitcoin.conf');
expect(file).toBeDefined();
expect(file.filename).toBe('bitcoin.conf');
expect(file.content).toBeTruthy();
});
it('devrait gérer les erreurs 404', async () => {
await expect(client.getFile('dev', 'fichier-inexistant.conf'))
.rejects
.toThrow('Fichier non trouvé');
});
});
Tests d'intégration
describe('Intégration API', () => {
it('devrait fonctionner end-to-end', async () => {
const client = createVaultClient('https://vault.4nkweb.com:6666');
// Test de santé
const health = await client.health();
expect(health.status).toBe('healthy');
// Test de fichier
const file = await client.getFile('dev', 'bitcoin/bitcoin.conf');
expect(file.content).toContain('bitcoin');
});
});
Performance et optimisation
Récupération parallèle
// ✅ Bon : Récupération parallèle
const files = await client.getFiles(requests);
// ❌ Mauvais : Récupération séquentielle
const files = [];
for (const request of requests) {
const file = await client.getFile(request.env, request.filePath);
files.push(file);
}
Cache local
class CachedVaultClient extends VaultClient {
private cache = new Map<string, VaultFile>();
async getFile(env: string, filePath: string): Promise<VaultFile> {
const key = `${env}/${filePath}`;
if (this.cache.has(key)) {
return this.cache.get(key)!;
}
const file = await super.getFile(env, filePath);
this.cache.set(key, file);
return file;
}
}
Dépannage
Problèmes courants
Erreur de clé de déchiffrement
Error: La clé de déchiffrement doit faire exactement 32 bytes
Solution : Vérifiez que votre clé fait exactement 32 caractères UTF-8.
Erreur de connectivité
Error: fetch failed
Solutions :
- Vérifiez que l'API est démarrée
- Vérifiez l'URL de base
- Désactivez la validation SSL si nécessaire (
verifySsl: false
)
Erreur de déchiffrement
VaultDecryptionError: Erreur de déchiffrement
Solutions :
- Vérifiez que la clé correspond à celle utilisée côté serveur
- Vérifiez que le fichier n'est pas corrompu
Debug
// Activation des logs détaillés
const client = new VaultClient({
baseUrl: 'https://vault.4nkweb.com:6666',
timeout: 30000
});
// Test de connectivité
const isConnected = await client.ping();
console.log('Connecté:', isConnected);
// Test d'information
try {
const info = await client.info();
console.log('Info API:', info);
} catch (error) {
console.error('Erreur info:', error);
}
Support
- Documentation : docs/README.md
- API Specification : docs/api-specification.md
- Issues : Git Issues
- Email : sdk-support@4nkweb.com
Version SDK : 1.0.0 Compatibilité API : 1.0.0+