# 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
