Architecture
Frontière produit
SIEM / EDR / SOAR / agent non fiable
|
| proposition typée + preuves référencées
v
API AEGIS (mTLS/RBAC)
|
approbateur humain distinct
reçu court lié à l'intention
|
+---------+---------+
| |
OPA / AuthZEN dual PostgreSQL autoritaire
| |
+---- capacité -----+
|
Temporal programme d’abord
|
ExecutionProof + grant borné
|
v
exécuteur typé en mTLS
| \
| +--> observateur mTLS lecture seule
admission indépendante (profil strict)
|
Kubernetes réel (opt-in)
simulateur durable (défaut)
|
reçus SCITT-like --> WORM externe
L’agent et son raisonnement restent hors de la base de confiance. Ils peuvent mentir, rejouer, courir contre l’état ou inventer des preuves ; ces comportements doivent réduire leur pouvoir ou provoquer un refus.
Composants du profil complet
| Composant | Responsabilité | Interdit |
|---|---|---|
AegisKernel |
missions, preuves, politique, capacités, reçus | interpréter du texte libre ou posséder un secret cible |
PostgresStore |
autorité transactionnelle, one-shot, nonces, checkpoints, audit, arrêt | décider seul d’une autorisation ou partager les rôles migration/application/exécuteur |
| OPA/AuthZEN + évaluateur embarqué | décision reproductible en double; réponse externe signée et liée à la requête | exécuter un outil ou modifier sa politique |
| Temporal | conserver et déclencher l’obligation de restauration | inventer une cible ou contourner le noyau |
MtlsExecutorClient |
transporter trois opérations typées | accepter URL, shell, manifest ou verbe arbitraire |
| service exécuteur | vérifier grant et ExecutionProof, anti-rejeu, préconditions fraîches, CAS, postconditions |
recevoir un token OpenBao, la clé TLS de l’API ou lire missions/preuves/audit |
| vérificateur d’admission | recalculer preuve, autorité, état et restauration avec des clés publiques | posséder un credential Kubernetes d’écriture ou une clé de signature |
| service observateur indépendant | revérifier preuve/reçu, relire pod/policy sans écriture et signer les faits | devenir une nouvelle voie de mutation ou partager la clé exécuteur |
| transparence + WORM | chaîner les reçus et retenir leurs versions hors contrôle | réécrire un objet existant ou prétendre à une conformité SCITT non testée |
| OpenBao Transit | signer/vérifier sans exporter la clé active | livrer la clé privée aux processus AEGIS |
| métriques | état opérationnel à faible cardinalité | exposer sujet, mission, pod ou contenu de preuve |
SQLite et le simulateur en processus restent disponibles pour la console simple.
Le service admission-verifier-service est conçu comme une seconde base de
décision : il ne fait confiance ni au verdict AEGIS, ni aux annotations seules.
Il vérifie les signatures et recalcule localement la mission, l'autorité, la
politique embarquée, l'état préparé et l'obligation de restauration. Il reste
un profil opt-in jusqu'à sa qualification sur la matrice Kubernetes cible.
Transaction d’autorité
- Une identité de contrôle crée une mission signée et bornée.
- Des collecteurs admis signent des enveloppes fraîches avec la clé de leur certificat ; PostgreSQL/SQLite revendique le nonce avant d’écrire une preuve immuable dont la racine et le domaine de faute sont configurés hors de l’agent. Un collecteur ne peut donc pas s'auto-déclarer indépendant.
- Une identité d’approbation distincte de l’opérateur accepte l’action, sa durée et l’ensemble exact des preuves techniques. AEGIS signe un reçu court, l’enregistre comme preuve humaine immuable et refuse toute modification de l’intention.
- Le proposal recharge les preuves, vérifie ce reçu humain, calcule leurs domaines de faute, demande un état frais à l’exécuteur, exige l’accord de la politique embarquée et du PDP externe, puis émet une capacité one-shot liée à une autorité atténuée et un contrat de réversibilité.
- Le commit recharge mission et preuves, revérifie l’approbation, réévalue la politique, relit la cible et vérifie le même hash d’état.
- En mode
shadow, AEGIS s’arrête ici après avoir signé une décisionwould_execute: le ticket n’est pas consommé et la cible reste inchangée. - En mode d’action, PostgreSQL consomme atomiquement la capacité. Une course perdante n’atteint jamais l’exécuteur.
- AEGIS signe une obligation de restauration liée au job, au hash de l’état antérieur, à l’audience et à sa fenêtre ; le job est persisté puis accepté par Temporal avant la mutation.
- AEGIS émet un grant d’exécution Ed25519 de 15 secondes au plus, lié à la capacité, l’identité, l’audience, l’intention, l’état, les preuves et la décision de politique.
- AEGIS construit et persiste une
ExecutionProofautonome contenant mission, décision recalculable, preuves causales, état frais, autorité et restauration. - L’exécuteur vérifie grant et preuve avec des clés publiques épinglées, revendique atomiquement l’ID dans PostgreSQL, puis seulement demande le CAS.
- Dans le profil strict, Kubernetes appelle un vérificateur distinct sans droit d’écriture avant d’admettre le pod/NetworkPolicy porteur de la preuve.
- AEGIS lie le reçu au grant et à la preuve, le signe et l’audite.
- Un service mTLS distinct revérifie preuve et reçu, relit Kubernetes avec un compte sans écriture et signe une attestation de postcondition.
- Les artefacts peuvent recevoir un reçu de transparence chaîné puis être conservés comme versions S3 Object Lock COMPLIANCE.
- À l’échéance, le worker revendique exactement le job et présente son grant de restauration ; une modification plus récente produit un conflit signé.
Une panne du policy engine, du signer, du scheduler, du stockage ou de l’exécuteur refuse l’autorisation ou produit un résultat ambigu explicite. Une capacité consommée n’est jamais réactivée.
Identité et séparation des secrets
Le profil applicatif Windows utilise des certificats courts issus d’une CA locale et exige exactement une URI SPIFFE dans le SAN. Le profil SOTA déploie SPIRE et exerce réellement TLS 1.3 dans les deux sens entre deux workloads qui récupèrent leurs X.509-SVID par le socket CSI. La cible production doit appliquer ce modèle, avec rotation continue, à tous les services plutôt que juxtaposer les deux profils de laboratoire.
Le lanceur évite deux fuites inter-processus : l’exécuteur ne reçoit ni token
OpenBao ni clé privée de signature, seulement le bundle public de la clé active,
et le worker Temporal ne reçoit pas la clé privée TLS du serveur API. OpenBao
reçoit seulement les données canoniques à signer, jamais les secrets de la cible.
Le rôle PostgreSQL aegis_executor ne peut pas lire missions, preuves,
capacités, reçus, jobs ou audit, ni modifier l’arrêt d’urgence. Une fonction
SECURITY DEFINER étroite conserve l’atomicité stop/CAS du simulateur sans lui
accorder UPDATE sur le stop.
Signature et migration
OpenBao Transit est la clé active. Un KeyringSigner route la vérification selon
le signingKeyId, ce qui maintient la vérifiabilité de l’historique signé avec
l’ancienne clé locale sans permettre à celle-ci de signer de nouveaux records.
La signature Transit contient sa version de clé ; la rotation future doit
conserver les versions nécessaires à la rétention d’audit.
OPA ne charge pas directement le fichier Rego : le bootstrap construit un bundle
RSA signé avec un scope aegis/action, puis le runtime exige la clé publique,
l’identifiant et le scope avant toute activation. La clé de signature de
politique reste locale au labo ; une cible de production doit la placer dans un
domaine d’administration et de publication séparé.
Le transport OPA du profil durci impose TLS 1.3 et un certificat client signé
par une CA OPA dédiée. Le client vérifie aussi le nom d’hôte et l’unique URI SAN
spiffe://aegis.local/policy/opa. Cette séparation empêche un certificat
opérateur AEGIS valide d’appeler directement le policy engine.
Le journal peut produire un checkpoint aegis.audit-checkpoint.v1 qui lie la
séquence, le hash de tête, le store autoritaire et l’heure. Son hash est signé
par la clé active, persisté séparément puis référencé par un nouvel événement du
journal. Il peut être exporté et revérifié sans exporter toute la base.
aegis.audit-export.v1 regroupe exactement les événements couverts par le
checkpoint et les clés publiques nécessaires. Le vérificateur hors ligne
recalcule chaque hash/signature, l’ancre et l’enveloppe d’export ; il expose les
empreintes des clés pour leur épinglage par un canal indépendant.
Les restaurations classent les conflits d’état comme définitifs. Une panne transitoire est remise en file cinq fois au maximum avec backoff exponentiel ; l’épuisement produit un reçu d’échec signé et un événement d’escalade.
Exécuteur Kubernetes
Le service hors processus utilise le simulateur PostgreSQL par défaut. En mode
réel explicitement confirmé, KubernetesNetworkPolicyExecutor charge seulement
un kubeconfig absolu et un contexte nommés, refuse les plugins d’authentification
exécutables, impose une allowlist de namespaces, vérifie UID/resourceVersion
et deux pods frères prêts, crée une NetworkPolicy deny-all, puis ajoute son label
réservé par JSON Patch conditionnel. La restauration supprime uniquement la
policy et le label liés au même UID.
Kubernetes RBAC ne limite pas les champs d’un patch : les
ValidatingAdmissionPolicy de lab/kubernetes/ bornent donc le ServiceAccount
au label et à la forme de policy prévus. La forme vérifiée est qualifiée sur le
cluster local Kubernetes 1.36.1 avec Cilium 1.20.1, mais doit encore l’être sur
la matrice de production ; l’arrêt PostgreSQL et la mutation Kubernetes ne
forment pas une transaction atomique distribuée.
La qualification utilise aussi aegis-kubernetes-observer, un ServiceAccount
distinct limité à get/list sur pods et NetworkPolicies. Un service séparé,
authentifié en TLS 1.3 mutuel et doté d'une clé propre, revérifie la preuve et le
reçu avant de signer l'état d'exécution puis de restauration. La sonde réseau
Cilium confirme séparément l’effet puis le retour du trafic. Cela prouve le
patron local ; la haute disponibilité, le multi-cluster et l’indépendance
administrative restent à industrialiser.
Le module de transparence signe des déclarations JSON et des reçus chaînés. Le
sink S3 exige Object Lock COMPLIANCE, un checksum et une confirmation de
rétention sur la version exacte. Il s'agit d'un profil inspiré de SCITT, pas
d'une revendication d'interopérabilité COSE/SCITT.
Depuis la 0.15.0, le journal accepte aussi une racine de relevé MAIVAR
(POST /v1/posture/roots, type d'artefact posture-root). MAIVAR est un autre
programme, dans un autre dépôt, qui relève l'état d'un poste Windows sans rien
y écrire ; ce qui traverse la frontière est la racine de Merkle de son relevé,
la racine précédente, l'heure, le nom de machine et le nombre de constats — pas
un constat. AEGIS atteste avoir reçu cette racine à cet instant de ce
collecteur, et rien de la vérité des constats qu'elle résume : il n'a pas vu la
machine. C'est la même frontière que pour toute preuve entrante, tenue au plus
étroit.
Voir kubernetes-executor.md.
Invariants production
- Tout write passe par un contrat typé non-LLM.
- Tout commit réautorise selon une politique signée et épinglée.
- Toute capacité et preuve lient identité, audience, action, ressource, arguments, domaines de faute, état, mission, politique, temps, autorité atténuée, restauration et invocation.
- Consommation et idempotence sont transactionnelles et fail-closed.
- Les agents ne reçoivent aucun credential d’écriture.
- La provenance survit aux transformations ; les données ne deviennent jamais une autorité par simple copie.
- Les postconditions sont observées indépendamment de l’agent proposant.
- La compensation survit aux pannes de l’agent, du worker et du scheduler.
- Clés et administration de politique vivent hors de leurs domaines de confiance.
- L’arrêt d’urgence fonctionne sans LLM ni agent.