Steuerkram/scripts/container/encrypt-bank-secrets.php

64 lines
1.9 KiB
PHP

<?php
/**
* Verschlüsselt die nach Migration 068 noch im Klartext in bank_sources liegenden
* Felder (client_id_enc, secret_enc, pin_enc) mit dem APP_KEY.
*
* Das Skript ist idempotent: bereits verschlüsselte Werte (Magic-Prefix "enc:v1:")
* werden übersprungen. Nach Ausführung kann es gefahrlos erneut aufgerufen werden.
*
* Aufruf:
* docker compose exec web php scripts/container/encrypt-bank-secrets.php
*
* Voraussetzung: APP_KEY in .env gesetzt (64-stellige Hex-Zeichenkette).
*/
declare(strict_types=1);
require __DIR__ . '/../../vendor/autoload.php';
use Steuerkram\Config;
use Steuerkram\Database;
use Steuerkram\Services\Crypto;
Config::load();
if ((string)Config::get('app_key', '') === '') {
fwrite(STDERR, "FEHLER: APP_KEY ist nicht gesetzt. Bitte zuerst in .env hinterlegen.\n");
fwrite(STDERR, "Generieren mit: php -r \"echo bin2hex(random_bytes(32));\"\n");
exit(1);
}
$rows = Database::fetchAll('SELECT id, client_id_enc, secret_enc, pin_enc FROM bank_sources');
$touched = 0;
$skipped = 0;
foreach ($rows as $row) {
$update = [];
foreach (['client_id_enc', 'secret_enc', 'pin_enc'] as $field) {
$value = $row[$field] ?? null;
if ($value === null || $value === '') {
continue;
}
if (Crypto::isEncrypted((string)$value)) {
continue;
}
$update[$field] = Crypto::encrypt((string)$value);
}
if (empty($update)) {
$skipped++;
continue;
}
$sets = implode(', ', array_map(fn($k) => "$k = ?", array_keys($update)));
$params = array_values($update);
$params[] = (int)$row['id'];
Database::execute("UPDATE bank_sources SET $sets WHERE id = ?", $params);
$touched++;
echo "Verschlüsselt: bank_sources.id={$row['id']} (Felder: " . implode(', ', array_keys($update)) . ")\n";
}
echo "\n";
echo "Fertig: {$touched} Zeile(n) aktualisiert, {$skipped} bereits verschlüsselt oder leer.\n";