
Eine kleine, überprüfbare, terminierende, deterministische Mikro-Policy-Engine
Eine kleine, prüfbare, terminierende, deterministische Mikro-Policy-Engine.
Ich habe Gate0 gebaut, weil ich es leid war, regex-basierte Richtlinien in der Produktion zu debuggen. Ich wollte etwas, das langweilig, begrenzt und unmöglich zum Absturz zu bringen ist. Wenn Sie eine flexible, universelle Policy-Engine wünschen, sollten Sie OPA verwenden. Wenn Sie eine Policy-Engine wollen, die bei sub-50µs Evaluierung und null Allokationen für sicherheitskritische Pfade testet, dann ist Gate0 das Richtige.
Gate0 ist für Hochsicherheitsumgebungen konzipiert, in denen die Richtlinienauswertung deterministisch und ressourcenbegrenzt sein muss. Siehe die Sicherheitsrichtlinie für die Meldung von Schwachstellen und das Sicherheitsmodell für das vollständige Bedrohungsmodell und die mechanischen Garantien.
Gate0 verwendet eine lineare Deny-Overrides-Evaluierungsstrategie. Jede Regel besteht aus einem Target (Fast-Path-Match) und einer optionalen Condition (tiefe Logik).
+----------+ +-------------+ +--------+
| Ephemera | ----> | GateBridge | ----> | Gate0 |
| (Legacy) | | (Normalize) | | (Core) |
+----------+ +-------------+ +--------+
| ^
| |
+----(Shadow Log)----+
Die Korrektheit und Sicherheit von Gate0 werden mechanisch verifiziert durch Unit-Tests, die Kernlogik und Grenzfälle abdecken, durch eigenschaftsbasiertes Testen mit proptest mit Hunderten von generierten Szenarien und durch MIRI-Verifikation für panikfreien und undefiniertem Verhalten freien Betrieb. Es werden Worst-Case-Eingaben getestet, um eine begrenzte Terminierung sicherzustellen.
cargo test
cargo +nightly miri test --lib
Der Evaluator von Gate0 verwendet feste, stack-allozierte Puffer, um während der Auswertung keine Heap-Allokationen zu garantieren. Die Standardimplementierung verwendet MaybeUninit, um die Initialisierung ungenutzter Slots zu vermeiden, was zu O(used) Initialisierungskosten führt und nicht zu O(capacity).
Der unsichere Code ist auf ein einzelnes Modul (fixed_stack.rs) mit einfachen Invarianten beschränkt: Elemente 0..len sind initialisiert, Elemente len..N nicht. Alle unsicheren Pfade werden mit MIRI verifiziert.
Für Benutzer, die einen Code ohne unsafe bevorzugen, bietet Gate0 SafeFixedStack hinter dem Feature-Flag safe-stack. Diese Variante verwendet [T; N] mit T: Default + Copy und initialisiert alle Slots im Voraus. Der Nachteil sind O(capacity) Initialisierungskosten bei jedem Evaluierungsaufruf.
cargo build --features safe-stack
Beide Implementierungen bieten identische Semantik und die gleiche Null-Allokations-Garantie während der Auswertung. Die Wahl liegt zwischen Leistung (O(used)) und absoluter Sicherheit (O(capacity)). Für kleine Stacks mit billigen Default-Typen wie bool ist der Unterschied vernachlässigbar.
Gate0 ist so konzipiert, dass es als Policy Decision Point (PDP) innerhalb einer größeren Host-Anwendung fungiert. Um Determiniertheit und strenge Grenzen zu wahren, übernimmt Gate0 kein I/O, Netzwerk oder Objektlebenszyklen.
Das empfohlene Integrationsmuster trennt die Verantwortlichkeiten in drei Schichten. Die Host-Anwendung (API-Gateway, SSH-Server usw.) verwaltet Zustand, Identität und Nebeneffekte. Eine Adapterschicht normalisiert diesen komplexen Zustand in Primitive, die Gate0 versteht (Strings, Booleans, Ints). Gate0 wertet den flachen Kontext rein aus und gibt eine Decision zurück.
Host Application (User Request)
│
▼
[Adapter Layer] → Pre-computes context (time, IP ranges, MFA status)
│ Converts "complex" to "primitive"
▼
[Gate0 Engine] → Pure evaluation (0 allocations, bounded stack)
│
▼
Decision::Allow / Deny
Diese Trennung erklärt, warum Gate0 keine komplexen Matcher wie IP-Bereichsprüfungen oder Regex enthält. Die Adapterschicht übernimmt domänenspezifische Logik und präsentiert Gate0 vorberechnete boolesche oder String-Attribute. Gate0 bleibt klein, prüfbar und deterministisch.
use gate0::{Policy, Rule, Target, Request, ReasonCode};
let policy = Policy::builder()
.rule(Rule::allow(Target::any(), ReasonCode(1)))
.build()?;
let decision = policy.evaluate(&Request::new("alice", "read", "doc"))?;
assert!(decision.is_allow());
Das Verzeichnis examples/ enthält anschauliche Szenarien, die typische Verwendungsmuster von Gate0 demonstrieren:
SaaS API: Standard RBAC/Multi-Tenancy-Logik. Zero Trust Network: Attributbasierte Zugriffskontrolle (ABAC) mit MFA und Standortprüfungen. Complex Overrides: Demonstriert Deny-Overrides-Konfliktlösung.
Führen Sie sie aus mit:
cargo run --example saas_api
cargo run --example zero_trust_network
cargo run --example complex_overrides
Gate0 ist bewusst eingeschränkt, um vorhersagbar und leistungsfähig zu bleiben.
Keine komplexen Matcher: Logik wie vollständige Bit-Mask-CIDR oder fortgeschrittenes Regex bleibt der Adapterschicht überlassen. Gate0 wertet vorverarbeitete Primitive aus.
Kein natives Multithreading: Die aktuelle FFI-Implementierung für Python ist nicht threadsicher. Benutzer mit hohen Nebenläufigkeitsanforderungen sollten Multiprocessing verwenden oder auf die Phase-4-FFI-Stabilisierung warten, die globale Sperren adressieren wird.
Keine überlappenden Entscheidungen: Innerhalb einer einzelnen Effektklasse (Allow/Deny) wird nur die erste passende Regel zurückgegeben. Die Konfliktlösung erfolgt strikt in der Reihenfolge.
Die folgenden Projekte erweitern die Gate0-Engine für spezialisierte Anwendungsfälle.
gate0_dsl: Eine rust-native domänenspezifische Sprache für Gate0, entwickelt von hardliner66. Sie nutzt Rust-Makros, um eine saubere und lesbare Syntax zur Definition von Richtlinien direkt im Code zu bieten. Die Implementierung und Dokumentation finden Sie unter hardliner66/gate0_dsl.
MIT