| Server IP : 202.61.199.114 / Your IP : 216.73.217.139 Web Server : nginx/1.22.1 System : Linux de.arni-solutions.de 6.1.0-49-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.174-1 (2026-05-26) x86_64 User : web20 ( 1018) PHP Version : 8.4.23 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /var/www/clients/client2/web31/web/crm/cli/ |
Upload File : |
<?php
/**
* CLI: API-Token verwalten (nur Kommandozeile).
*
* php cli/api_token.php create --name="control-center-prod" \
* --scopes="server:read fail2ban:read vpn:read backup:read cron:read domains:read ispconfig:read audit:read" \
* [--expires="2027-06-19"] [--ip="10.0.0.5/32,10.0.0.6/32"] [--rate=120]
*
* php cli/api_token.php list
* php cli/api_token.php revoke --id=3
*
* Das Klartext-Token wird NUR EINMAL bei Erstellung angezeigt; gespeichert wird
* ausschließlich der sha256-Hash.
*/
if (PHP_SAPI !== 'cli') { fwrite(STDERR, "Nur über die Kommandozeile.\n"); exit(1); }
require dirname(__DIR__) . '/app/bootstrap.php';
// --- Argumente parsen ---
$cmd = isset($argv[1]) && substr($argv[1], 0, 2) !== '--' ? $argv[1] : 'create';
$opt = array();
foreach ($argv as $a) {
if (preg_match('/^--([a-z_]+)=(.*)$/s', $a, $m)) { $opt[$m[1]] = $m[2]; }
elseif (preg_match('/^--([a-z_]+)$/', $a, $m)) { $opt[$m[1]] = true; }
}
$T = tbl('api_tokens');
function ensure_table($T) {
$ok = db()->query('SHOW TABLES LIKE ' . db()->quote($T))->fetch();
if (!$ok) {
fwrite(STDERR, "Tabelle $T fehlt. Bitte zuerst database/schema_api.sql importieren.\n");
exit(1);
}
}
ensure_table($T);
if ($cmd === 'list') {
$rows = db()->query('SELECT id,name,token_prefix,scopes,active,revoked,expires_at,last_used_at,last_ip,rate_limit_per_min FROM ' . $T . ' ORDER BY id')->fetchAll(PDO::FETCH_ASSOC);
if (!$rows) { echo "Keine Tokens.\n"; exit; }
foreach ($rows as $r) {
printf("#%d %-22s prefix=%s %s%s rate=%d\n scopes: %s\n last: %s %s expires: %s\n",
$r['id'], $r['name'], $r['token_prefix'],
$r['active'] ? 'aktiv' : 'inaktiv', $r['revoked'] ? '/widerrufen' : '',
$r['rate_limit_per_min'], $r['scopes'],
$r['last_used_at'] ?: '-', $r['last_ip'] ?: '', $r['expires_at'] ?: '-');
}
exit;
}
if ($cmd === 'revoke') {
$id = (int)(isset($opt['id']) ? $opt['id'] : 0);
if ($id <= 0) { fwrite(STDERR, "--id=<n> erforderlich.\n"); exit(1); }
db()->prepare('UPDATE ' . $T . ' SET revoked=1, active=0, updated_at=NOW() WHERE id=?')->execute(array($id));
echo "Token #$id widerrufen.\n";
exit;
}
if ($cmd === 'create') {
$name = isset($opt['name']) ? trim($opt['name']) : '';
if ($name === '') { fwrite(STDERR, "--name=\"...\" erforderlich.\n"); exit(1); }
$scopes = isset($opt['scopes']) ? trim(preg_replace('/[\s,]+/', ' ', $opt['scopes'])) : 'server:read';
$expires = isset($opt['expires']) && $opt['expires'] !== true ? date('Y-m-d H:i:s', strtotime($opt['expires'])) : null;
$ips = isset($opt['ip']) && $opt['ip'] !== true ? trim($opt['ip']) : null;
$rate = isset($opt['rate']) ? (int)$opt['rate'] : (int)cfg('api.rate_limit_default', 120);
$prefixRaw = bin2hex(random_bytes(4)); // 8 hex
$secret = bin2hex(random_bytes(20)); // 40 hex
$token = 'acc_live_' . $prefixRaw . '.' . $secret;
$hash = hash('sha256', $token);
$display = 'acc_live_' . $prefixRaw;
$signing = bin2hex(random_bytes(24)); // HMAC-Signaturschlüssel (für Write-Härtung)
db()->prepare(
'INSERT INTO ' . $T . ' (name, token_prefix, token_hash, signing_secret_enc, scopes, allowed_ips, rate_limit_per_min,
active, revoked, expires_at, created_by, created_at)
VALUES (?,?,?,?,?,?,?,1,0,?,?,NOW())'
)->execute(array($name, $display, $hash, crm_encrypt($signing), $scopes, $ips, $rate, $expires, 'cli'));
$id = (int)db()->lastInsertId();
echo "\n================ API-TOKEN ERSTELLT (#$id) ================\n";
echo "Name: $name\n";
echo "Scopes: $scopes\n";
echo "IP: " . ($ips ?: 'alle') . " Rate: $rate/min Ablauf: " . ($expires ?: 'nie') . "\n";
echo "----------------------------------------------------------\n";
echo "TOKEN (einmalig – sicher speichern, z.B. in CC-Vault):\n\n $token\n\n";
echo "HMAC-SIGNATURSCHLÜSSEL (nur falls api.hmac_required_for_writes=true; einmalig):\n\n $signing\n\n";
echo " Signatur: X-CRM-Signature = HMAC_SHA256(secret, ts.\"\\n\".METHOD.\"\\n\".pfad.\"\\n\".body)\n";
echo " Header: X-CRM-Timestamp: <unixzeit> (Skew <= 300s)\n\n";
echo "Beispiel:\n";
echo " curl -H 'Authorization: Bearer $token' \\\n";
echo " 'https://arni-solutions.de/crm/public/api.php?r=v1/ping'\n";
echo "==========================================================\n";
exit;
}
fwrite(STDERR, "Unbekanntes Kommando: $cmd (create|list|revoke)\n");
exit(1);