NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky
Sentinel for Laravel

Správa kľúčov

Kľúče žijú v pomenovaných kruhoch: default pre pečate, denník a kontrolné body; http pre podpisy správ; a vaše vlastné — napríklad kruh financial so silnejšími kľúčmi, ktorý pečať zvolí cez ring(). Id kľúča sa hľadá len v jeho kruhu a algoritmus vždy určuje kľúč — nikdy uložený riadok ani prijatý parameter.

DriverOdkiaľ sú kľúčeRotácia
config (kruh default)SENTINEL_KEY_ID / SENTINEL_KEY (+ SENTINEL_PREVIOUS_KEYS pre kľúče len na overovanie)sentinel:key:rotate vypíše nové riadky env
database (kruh http)Riadky sentinel_keys: AES-256-GCM pod kľúčom odvodeným z APP_KEY len pre obálky (nikdy nie aplikačný encrypter), každé pole viazané — upravený, skopírovaný či podstrčený riadok sa odmietnesentinel:key:rotate uloží nový kľúč; starý je potom len na overovanie
chainDrivery v poradí (vyhráva prvý podpisový kľúč)podľa drivera

Algoritmy a materiál

AlgoritmusMateriálPečateHTTP
hmac-sha256Koreňové tajomstvo 32–1024 bajtov; HKDF podkľúče 32 bajtovánoáno (surové zdieľané tajomstvo)
hmac-sha384Koreň ≥ 32 bajtov; podkľúče 48 bajtováno—
hmac-sha512Koreň ≥ 32 bajtov; podkľúče 64 bajtováno—
ed2551964-bajtový tajný kľúč libsodium / 32-bajtový verejný kľúčánoáno
ecdsa-p256-sha256PKCS#8 / SPKI PEM, P-256ánoáno
ecdsa-p384-sha384PKCS#8 / SPKI PEM, P-384ánoáno

Materiál je vždy v tvare base64:<štandardné base64> — holý reťazec sa odmietne, čo blokuje heslá. Koreň HMAC má 32–1024 náhodných bajtov (nikdy PEM, nikdy jeden opakovaný bajt); Ed25519 je 64-bajtový tajný kľúč a/alebo 32-bajtový verejný kľúč; ECDSA je base64 textu PEM s krivkou overenou voči algoritmu. Materiál sa nikdy neobjaví vo výnimkách, logoch, udalostiach, about, var_dump() ani v serializovaných dátach.

API

use RoundlyConsulting\Sentinel\Enums\Algorithm;
use RoundlyConsulting\Sentinel\Enums\KeyDestination;

Sentinel::keys()->rings();                                  // ['default', 'http']
Sentinel::keys()->all();                                    // KeyInfo of every key in every ring — never material
Sentinel::keys()->ring()->current();                        // KeyInfo of the default ring's signing key

$ring = Sentinel::keys()->ring('http');                     // KeyRingHandle; a kid of another ring is unknown here
$ring->name();                                              // 'http'
$ring->find('acme-2026-10');                                // ?KeyInfo
$ring->all();
$ring->generate(Algorithm::Ed25519, keyId: 'acme-2026-11', activatesAt: now()->addWeek());   // stored, pending until then
$ring->import('acme-2026-10', Algorithm::EcdsaP256Sha256, $pem, owner: $partner);
$ring->rotate();                                            // RotationResult: current, previous (now verify-only)
$ring->revoke('acme-2026-10', reason: 'Partner offboarded', actor: $admin);
$ring->retire('acme-2025-10');

$lines = Sentinel::keys()->ring()->generate(Algorithm::HmacSha256, destination: KeyDestination::Config)->envSnippet;
  • Predvolené hodnoty sa líšia zámerne. generate() uloží kľúč do databázového úložiska kruhu (KeyDestination::Database; kruh bez neho vyhodí KeyDriverException::readOnly), kým KeyDestination::Config vráti riadky env v envSnippet a nič neuloží. sentinel:key:generate robí opak: riadky env, pokiaľ nezadáte --database.
  • rotate() rotuje v úložisku, kde žije aktuálny podpisový kľúč; signs_until predošlého kľúča sa nastaví na aktiváciu nového, takže sa prekrývajú bez medzery.
  • revoke() a retire() menia len kľúče v databáze. Kľúč z konfigurácie vyhodí KeyDriverException::notStoredInDatabase: odvoláte ho pridaním ring:kid do SENTINEL_REVOKED_KEYS a vyradíte odstránením zo zoznamu kľúčov kruhu len na overovanie — sentinel:key:revoke a sentinel:key:retire namiesto chyby vypíšu presne tento postup.
  • Dôvod odvolania je povinný (1–1 000 znakov); retire() ukončí obdobie overovania kľúča okamžite, takže pečate, ktoré ho stále používajú, hlásia RetiredKey.
use RoundlyConsulting\Sentinel\DataTransferObjects\GenerateKeyRequest;
use RoundlyConsulting\Sentinel\DataTransferObjects\RevokeKeyRequest;
use RoundlyConsulting\Sentinel\DataTransferObjects\RotateKeyRequest;

$key = Sentinel::generateKey(new GenerateKeyRequest('http', Algorithm::Ed25519, keyId: 'acme-2027-01', owner: $partner));
$rotation = Sentinel::rotateKey(new RotateKeyRequest('http'));
Sentinel::revokeKey(new RevokeKeyRequest('http', 'acme-2027-01', 'Partner offboarded', $admin));
Sentinel::retireKey('http', 'acme-2025-10');
Sentinel::listKeys('http');                                 // null = every ring
Sentinel::findKey('http', 'acme-2027-01');                  // ?KeyInfo
Sentinel::currentKey();                                     // null = keys.default_ring

Stavy

Stavy zodpovedajú NIST SP 800-57 — pending → active → verify-only → retired, plus revoked — a efektívny stav sa určuje v tomto poradí:

StavKedyPodpisujeOveruje
Revokedring:kid v keys.revoked (vždy vyhráva), alebo odvolanýnienie
Retireduplynulo verifies_until, alebo vyradenýnienie (dôkazy v denníku sa stále overia)
Pendingactivates_at v budúcnostinienie
VerifyOnlyuplynulo signs_until, kľúč previous v konfigurácii, alebo len verejný materiálnieáno
Activeinakáno (so súkromným/tajným materiálom)áno

SENTINEL_REVOKED_KEYS (ring:kid,…) odvolá kľúč bez ohľadu na to, čo hovorí jeho driver — obnovený riadok v databáze odvolanie nikdy nezruší.

Import kľúčov

Pridajte partnera za behu — bez nasadenia, s kľúčom viazaným na model partnera:

$ring->import('acme-2026-10', Algorithm::Ed25519, $publicKeyPemOrBase64, owner: $partner, label: 'ACME');
Sentinel::importKey(new ImportKeyRequest('http', 'acme-2026-10', Algorithm::Ed25519, $pem, owner: $partner));
php artisan sentinel:key:import acme-2026-10 --ring=http --algorithm=ed25519 --file=acme.pem \
    --owner-type=partner --owner-id=7

import() uloží existujúci materiál do databázového úložiska kruhu: verejný kľúč partnera (Ed25519 surový alebo SPKI PEM, ECDSA PEM) alebo dohodnuté tajomstvo HMAC, viazaný na model vlastníka a len na overovanie — nikdy nepodpisuje, ani ako aktuálny kľúč kruhu, ani cez Http::withSignature() — pokiaľ nie je importovaný so signing: true (vlastný pár kľúčov presúvaný z prostredia do databázy; bez toho sa súkromný materiál odmietne). Stav je viazaný v zašifrovanej obálke, kid musí byť voľný v celom kruhu a odošle sa KeyImported.

Rotácia

  • Databázový kruh: rotate() vytvorí nový aktívny kľúč (voliteľne s neskoršou aktiváciou cez activatesAt); predošlý kľúč je po aktivácii nového len na overovanie. Staré pečate ostanú Intact, nové používajú nový kid.
  • Kruh z konfigurácie: sentinel:key:rotate vypíše nové SENTINEL_KEY_ID / SENTINEL_KEY a aktualizované SENTINEL_PREVIOUS_KEYS so starým kľúčom len na overovanie.
  • Potom presuňte staré pečate na nový kľúč cez sentinel:reseal — nikdy potichu nelegalizuje zmenu a --from-key= ho obmedzí na jeden starý kid.
  • Kľúč vyraďte, keď ho už nič nepoužíva (sentinel:key:retire odmietne, kým ho pečate na ktoromkoľvek pripojení denníka používajú, pokiaľ nezadáte --force); kompromitovaný kľúč okamžite odvolajte.

Drivery config a database

Driver config drží kľúče mimo databázy — odporúčané nastavenie pre pečate:

SENTINEL_KEY_ID=default-20261002-k3f9qa
SENTINEL_ALGORITHM=hmac-sha256
SENTINEL_KEY="base64:…"
SENTINEL_PUBLIC_KEY="base64:…"                  # asymmetric keys; alone = verify-only
SENTINEL_PREVIOUS_KEYS="default-20250901-a1b2c3|hmac-sha256|base64:…"   # verify-only, comma-separated

Driver database ukladá riadky sentinel_keys, ktorých autoritatívna obálka je AES-256-GCM pod kľúčom odvodeným z APP_KEY len pre obálky (s podporou rotácie cez APP_PREVIOUS_KEYS). Viaže každé pole — kruh, kid, algoritmus, materiál, verejný kľúč, stav, dátumy, vlastníka — takže riadok, ktorého nešifrované stĺpce nesúhlasia s obálkou, vyvolá KeyIntegrityException, spustí KeyIntegrityViolated a považuje sa za neznámy. Kľúče v databáze sú len také bezpečné ako APP_KEY, preto pre predvolený kruh uprednostnite driver config. chain číta svoje drivery v poradí — vyhráva prvý podpisový kľúč.

Uzly len na overovanie

Servery, ktoré majú overovať, no nikdy nepečatiť, nakonfigurujú len verejnú polovicu (SENTINEL_KEY_ID, SENTINEL_ALGORITHM, SENTINEL_PUBLIC_KEY, bez SENTINEL_KEY) a SENTINEL_AUTO_SEAL=false. Overia všetko; explicitné seal() vyhodí NoSigningKeyException.

Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

Ďalšie spôsoby podpory vrátane kryptomien

Odoslaním daru súhlasíte s našimi podmienkami prijímania darov.

Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.