- Move 12 markdown files from root to docs/ subdirectories - Organize documentation by category: • docs/troubleshooting/ (1 file) - Technical troubleshooting guides • docs/deployment/ (4 files) - Deployment and security documentation • docs/guides/ (3 files) - Feature-specific guides • docs/planning/ (4 files) - Planning and improvement proposals Root directory cleanup: - Reduced from 16 to 4 markdown files in root - Only essential project files remain: • CLAUDE.md (AI instructions) • README.md (Main project readme) • CLEANUP_PLAN.md (Current cleanup plan) • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements) This improves: ✅ Documentation discoverability ✅ Logical organization by purpose ✅ Clean root directory ✅ Better maintainability
8.6 KiB
Vault System - Secure Secrets Management
Modernes, sicheres Secrets Management System für das Custom PHP Framework.
Features
✅ Libsodium Encryption - Authenticated encryption (AEAD) ✅ Database-backed Storage - Transaktionale Sicherheit ✅ Audit Logging - Vollständiges Audit Trail aller Operations ✅ Metadata Tracking - Access Counts, Last Access, etc. ✅ Key Rotation - Hot Key Rotation ohne Downtime ✅ CLI Management - Vollständige Console Commands ✅ Type Safety - Value Objects für alle Daten ✅ Framework Integration - Native DI Container Support
Installation & Setup
1. Migration ausführen
docker exec php php console.php db:migrate
Dies erstellt die drei Vault-Tabellen:
vault_secrets- Encrypted secrets storagevault_audit_log- Audit trailvault_encryption_keys- Key version tracking
2. Encryption Key generieren
docker exec php php console.php vault:generate-key
Dies generiert einen kryptographisch sicheren Encryption Key:
VAULT_ENCRYPTION_KEY=aGVsbG8gd29ybGQgdGhpcyBpcyBhIHRlc3Qga2V5IQ==
3. Key in .env speichern
Füge den generierten Key zu deiner .env Datei hinzu:
# Vault Configuration
VAULT_ENCRYPTION_KEY=aGVsbG8gd29ybGQgdGhpcyBpcyBhIHRlc3Qga2V5IQ==
⚠️ WICHTIG: Niemals den Key committen! Die .env Datei ist in .gitignore.
CLI Commands
Secret speichern
# Mit Value als Argument
docker exec php php console.php vault:set database.password "super-secret"
# Value wird interaktiv abgefragt (versteckt)
docker exec php php console.php vault:set database.password
Secret abrufen
docker exec php php console.php vault:get database.password
Secret löschen
docker exec php php console.php vault:delete database.password
Alle Secrets auflisten
docker exec php php console.php vault:list
Zeigt alle Secret Keys mit Metadata:
🔐 Vault Secrets:
• database.password
Accessed: 15 times, Last: 2024-01-15 14:30:45
• api.stripe.secret_key
Accessed: 3 times, Last: 2024-01-14 10:20:30
Total: 2 secrets
Audit Log anzeigen
# Letzte 50 Einträge
docker exec php php console.php vault:audit
# Letzte 100 Einträge
docker exec php php console.php vault:audit 100
# Audit Log für spezifischen Secret Key
docker exec php php console.php vault:audit 50 database.password
Key Rotation
docker exec php php console.php vault:rotate-key
⚠️ KRITISCHE OPERATION:
- Generiert neuen Encryption Key
- Re-encrypted alle Secrets
- Gibt neuen Key aus
- Alte Key aufbewahren bis Rotation verifiziert!
Programmatische Verwendung
In Controller/Services
use App\Framework\Vault\Vault;
use App\Framework\Vault\ValueObjects\SecretKey;
use App\Framework\Vault\ValueObjects\SecretValue;
final readonly class PaymentService
{
public function __construct(
private Vault $vault
) {}
public function processPayment(Order $order): PaymentResult
{
// Secret aus Vault abrufen
$apiKey = $this->vault->get(
SecretKey::from('api.stripe.secret_key')
);
// Secret verwenden (reveal() erforderlich!)
$stripe = new StripeClient($apiKey->reveal());
return $stripe->charge($order->getTotal());
}
}
Secret speichern
public function updateApiKey(string $newKey): void
{
$this->vault->set(
SecretKey::from('api.stripe.secret_key'),
new SecretValue($newKey)
);
}
Secret prüfen
public function hasApiKey(): bool
{
return $this->vault->has(
SecretKey::from('api.stripe.secret_key')
);
}
Metadata abrufen
public function getSecretInfo(string $keyName): array
{
$metadata = $this->vault->getMetadata(
SecretKey::from($keyName)
);
return [
'created_at' => $metadata->createdAt,
'updated_at' => $metadata->updatedAt,
'access_count' => $metadata->accessCount,
'last_accessed' => $metadata->lastAccessedAt
];
}
Value Objects
SecretKey
Typsicherer Secret Identifier mit Validation:
use App\Framework\Vault\ValueObjects\SecretKey;
// ✅ Gültig
$key = SecretKey::from('database.password');
$key = SecretKey::from('api.stripe.secret-key_2024');
// ❌ Ungültig
$key = SecretKey::from(''); // InvalidArgumentException
$key = SecretKey::from('invalid key!'); // Nur a-zA-Z0-9._- erlaubt
SecretValue
Verhindert accidental Exposure:
use App\Framework\Vault\ValueObjects\SecretValue;
$secret = new SecretValue('my-password');
// ✅ Explizit enthüllen
$password = $secret->reveal();
// ✅ Sichere Checks
if ($secret->isEmpty()) { ... }
$length = $secret->length();
// ✅ Verhindert Logging
echo $secret; // Ausgabe: [SECRET]
// ✅ Verhindert var_dump Exposure
var_dump($secret); // ['value' => '[REDACTED]', 'length' => 11]
Sicherheit
Encryption
- Algorithmus: Libsodium
sodium_crypto_secretbox(XSalsa20 + Poly1305) - Authenticated Encryption: Schutz gegen Tampering
- Random Nonce: Eindeutig pro Secret
- 256-bit Keys: SODIUM_CRYPTO_SECRETBOX_KEYBYTES (32 bytes)
Audit Logging
Alle Vault-Operationen werden geloggt:
SELECT * FROM vault_audit_log
WHERE secret_key = 'database.password'
ORDER BY timestamp DESC;
Geloggte Informationen:
- Secret Key (nicht der Value!)
- Action (read, write, delete, rotate, export)
- Timestamp
- User ID (wenn verfügbar)
- IP Address
- User Agent
- Success/Failure Status
- Error Message (bei Fehlern)
Best Practices
✅ DO:
- Encryption Key in
.envspeichern (gitignored) - Unterschiedliche Keys für Environments
- Regelmäßige Key Rotation (quartalsweise)
- Audit Logs monitoren
- Secrets mit beschreibenden Namen (
api.service.key)
❌ DON'T:
- Encryption Key committen
- Secrets in Code hardcoden
- Gleichen Key für Dev/Staging/Production
- Audit Logs ignorieren
- Secrets ohne Namespace (
password)
Migration von .env zu Vault
Schritt 1: Secrets identifizieren
Identifiziere alle sensiblen Werte in .env:
- Passwörter
- API Keys
- Client Secrets
- Private Keys
- Tokens
Schritt 2: In Vault migrieren
# Für jeden Secret:
docker exec php php console.php vault:set api.stripe.secret_key "sk_live_..."
docker exec php php console.php vault:set database.password "prod-password"
docker exec php php console.php vault:set oauth.spotify.client_secret "abc123..."
Schritt 3: Code aktualisieren
Vorher (.env):
$apiKey = $_ENV['STRIPE_SECRET_KEY']; // ❌ Unsicher
Nachher (Vault):
$apiKey = $this->vault
->get(SecretKey::from('api.stripe.secret_key'))
->reveal(); // ✅ Sicher
Schritt 4: .env bereinigen
Nach Migration Secrets aus .env entfernen:
- STRIPE_SECRET_KEY=sk_live_...
- DATABASE_PASSWORD=prod-password
+ # Secrets now in Vault - use vault:get to retrieve
Troubleshooting
"Vault not available"
Problem: VAULT_ENCRYPTION_KEY nicht gesetzt
Lösung:
# Key generieren
docker exec php php console.php vault:generate-key
# Key in .env hinzufügen
echo "VAULT_ENCRYPTION_KEY=generated_key_here" >> .env
"Sodium extension required"
Problem: PHP Sodium Extension fehlt
Lösung: Sodium ist in PHP 7.2+ standardmäßig verfügbar. Prüfe PHP Version:
docker exec php php -m | grep sodium
"Decryption failed"
Problem: Falscher Encryption Key oder korrupte Daten
Mögliche Ursachen:
- Encryption Key geändert ohne Re-Encryption
- Database Corruption
- Falsche Encoding (base64)
Lösung:
- Richtigen Key aus Backup wiederherstellen
- Oder Key Rotation durchführen
"Secret not found"
Problem: Secret Key existiert nicht
Lösung:
# Alle Keys auflisten
docker exec php php console.php vault:list
# Secret neu erstellen
docker exec php php console.php vault:set your-key "your-value"
Performance
Benchmarks
- Read Operation: ~5ms (inkl. Decryption)
- Write Operation: ~10ms (inkl. Encryption + DB Insert)
- Key Rotation: ~100ms pro Secret
Optimierungen
Für High-Performance Scenarios:
- Secrets cachen (mit TTL)
- Batch-Operations für Multiple Secrets
- Read Replicas für Read-Heavy Workloads
Testing
# Unit Tests ausführen
docker exec php ./vendor/bin/pest tests/Framework/Vault/
Tests validieren:
- Value Object Validierung
- Encryption/Decryption
- Key Generation
- Audit Logging
Weitere Informationen
- Libsodium Dokumentation: https://www.php.net/manual/en/book.sodium.php
- Best Practices: https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html