Hitelesítés

KernelHost API

Kötelező kérésfejlécek

Minden kérésnek (kivéve /v1/health) tartalmaznia kell ezt a négy fejlécet. Ha bármelyik hiányzik vagy érvénytelen, a szerver HTTP 401 hibával utasítja vissza.

HeaderFormatJelentés
KH-Keykh_live_[A-Z0-9]{32}Nyilvános kulcsazonosító. Nem titok, megjelenhet naplókban.
KH-TimestampUnix-másodperc (10 számjegy)Aktuális időbélyeg. Tűréshatár +-300 másodperc.
KH-Nonce22-44 base64url karakterKérésenként egyszer használatos érték. 600 másodpercig tárolva, utána újrahasználható.
KH-Signature64 hexHMAC-SHA256(secret, signing_string), hex kódolással.

Az aláírási karakterlánc felépítése

Az aláírandó karakterlánc öt komponensből áll, sortöréssel (\n) elválasztva.

signing_string = METHOD + "\n"
               + PATH    + "\n"
               + TIMESTAMP + "\n"
               + NONCE   + "\n"
               + SHA256_HEX(BODY)

signature = HEX( HMAC_SHA256(secret, signing_string) )

A PATH a /v1 előtaggal kezdődő útvonal, például /v1/orders, nem pedig /cp/kernelhost_api/v1/orders. Ha a kérés lekérdezési karakterláncot is tartalmaz, az a PATH része (például /v1/services?limit=10&offset=0). A BODY a nyers kéréstörzs; törzs nélküli kéréseknél a BODY üres karakterlánc, amelynek SHA256 értéke a jól ismert konstans e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.

Referenciaimplementációk

PHP:

$method = 'POST';
$path   = '/v1/orders';
$body   = json_encode(['product_id' => 42, 'billing_cycle' => 'monthly', 'hostname' => 'web01.example.com']);
$idem   = 'order-web01-' . date('Ymd');
$ts     = (string) time();
$nonce  = bin2hex(random_bytes(16));

$signing = "{$method}\n{$path}\n{$ts}\n{$nonce}\n" . hash('sha256', $body);
$sig = hash_hmac('sha256', $signing, getenv('KH_SECRET'));

$ch = curl_init('https://www.kernelhost.com/cp/kernelhost_api/v1/orders');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'POST',
    CURLOPT_POSTFIELDS     => $body,
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
        'KH-Key: ' . getenv('KH_KEY'),
        "KH-Timestamp: {$ts}",
        "KH-Nonce: {$nonce}",
        "KH-Signature: {$sig}",
        "Idempotency-Key: {$idem}",
    ],
]);
$res = curl_exec($ch);

Node.js:

import crypto from 'node:crypto';

const method = 'POST';
const path   = '/v1/orders';
const body   = JSON.stringify({ product_id: 42, billing_cycle: 'monthly', hostname: 'web01.example.com' });
const idem   = 'order-web01-' + new Date().toISOString().slice(0, 10).replaceAll('-', '');
const ts     = Math.floor(Date.now() / 1000).toString();
const nonce  = crypto.randomBytes(16).toString('hex');

const bodyHash = crypto.createHash('sha256').update(body).digest('hex');
const signing  = `${method}\n${path}\n${ts}\n${nonce}\n${bodyHash}`;
const sig      = crypto.createHmac('sha256', process.env.KH_SECRET).update(signing).digest('hex');

const res = await fetch('https://www.kernelhost.com/cp/kernelhost_api/v1/orders', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'KH-Key': process.env.KH_KEY,
        'KH-Timestamp': ts,
        'KH-Nonce': nonce,
        'KH-Signature': sig,
        'Idempotency-Key': idem,
    },
    body,
});

Visszajátszás-védelem

Egy sikeresen aláírt kérést NEM lehet újra elküldeni. A szerver minden nonce-ot 600 másodpercig tárol az adatbázisban; egy második kérés ugyanazzal a nonce-szal replay_detected hibával elutasításra kerül. Hasonlóképpen elutasításra kerül minden olyan kérés, amelynek időbélyege több mint 300 másodperccel eltér a szerver idejétől.

Jogosultsági modell

Minden kulcsnak van egy kifejezett jogosultsági listája. Az útvonalak ellenőrzik a szükséges jogosultságot; ha hiányzik, HTTP 403 forbidden_scope a válasz. Az íráshoz és érzékeny adatokhoz tartozó jogosultságokat kifejezetten engedélyezni kell a kulcs létrehozásakor.

  • read:products, read:orders, read:services, read:billing, read:webhooks
  • read:credentials (Szolgáltatási hozzáférési adatok olvasása (hosztnév, IP-címek, felhasználónév, jelszó). Hívásonként egy további credentials.read audit-bejegyzést hoz létre.)
  • write:orders (Megrendelések leadása és fizetése.)
  • write:services (Szolgáltatási műveletek futtatása (start, stop, reboot, valamint felmondás a számlázási időszak végére és annak visszavonása).)
  • write:webhooks (Webhook URL beállítása.)