- 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
402 lines
8.6 KiB
Markdown
402 lines
8.6 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
docker exec php php console.php db:migrate
|
|
```
|
|
|
|
Dies erstellt die drei Vault-Tabellen:
|
|
- `vault_secrets` - Encrypted secrets storage
|
|
- `vault_audit_log` - Audit trail
|
|
- `vault_encryption_keys` - Key version tracking
|
|
|
|
### 2. Encryption Key generieren
|
|
|
|
```bash
|
|
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:
|
|
|
|
```env
|
|
# Vault Configuration
|
|
VAULT_ENCRYPTION_KEY=aGVsbG8gd29ybGQgdGhpcyBpcyBhIHRlc3Qga2V5IQ==
|
|
```
|
|
|
|
⚠️ **WICHTIG**: Niemals den Key committen! Die `.env` Datei ist in `.gitignore`.
|
|
|
|
## CLI Commands
|
|
|
|
### Secret speichern
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
docker exec php php console.php vault:get database.password
|
|
```
|
|
|
|
### Secret löschen
|
|
|
|
```bash
|
|
docker exec php php console.php vault:delete database.password
|
|
```
|
|
|
|
### Alle Secrets auflisten
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
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
|
|
|
|
```php
|
|
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
|
|
|
|
```php
|
|
public function updateApiKey(string $newKey): void
|
|
{
|
|
$this->vault->set(
|
|
SecretKey::from('api.stripe.secret_key'),
|
|
new SecretValue($newKey)
|
|
);
|
|
}
|
|
```
|
|
|
|
### Secret prüfen
|
|
|
|
```php
|
|
public function hasApiKey(): bool
|
|
{
|
|
return $this->vault->has(
|
|
SecretKey::from('api.stripe.secret_key')
|
|
);
|
|
}
|
|
```
|
|
|
|
### Metadata abrufen
|
|
|
|
```php
|
|
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:
|
|
|
|
```php
|
|
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:
|
|
|
|
```php
|
|
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:
|
|
|
|
```sql
|
|
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 `.env` speichern (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
|
|
|
|
```bash
|
|
# 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)**:
|
|
```php
|
|
$apiKey = $_ENV['STRIPE_SECRET_KEY']; // ❌ Unsicher
|
|
```
|
|
|
|
**Nachher (Vault)**:
|
|
```php
|
|
$apiKey = $this->vault
|
|
->get(SecretKey::from('api.stripe.secret_key'))
|
|
->reveal(); // ✅ Sicher
|
|
```
|
|
|
|
### Schritt 4: .env bereinigen
|
|
|
|
Nach Migration Secrets aus `.env` entfernen:
|
|
|
|
```diff
|
|
- 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**:
|
|
```bash
|
|
# 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:
|
|
```bash
|
|
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**:
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|