Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AuditSemKrnl

Système d'audit et de conformité automatisé pour infrastructures critiques, construit avec Semantic Kernel 1.74 en C# / .NET 9.

Ce projet est un cas d'usage industriel qui démontre les trois piliers avancés de Semantic Kernel : l'orchestration multi-agents, le RAG hybride à large échelle, et le routage dynamique multi-LLM.


Vue d'ensemble

Le système analyse des preuves techniques (manifestes Kubernetes, configurations Terraform, scripts Shell) et les compare automatiquement à des référentiels réglementaires (DORA, ACPR, ISO 27001) via un pipeline d'agents IA spécialisés.

Fichiers d'infra (YAML/HCL/Shell)
        │
        ▼
  ┌─────────────┐
  │  LLM Router │ ──→ Simple → Synthese (Mistral local)
  └─────────────┘
        │ Complex
        ▼
  ┌─────────────────────────────────────────────┐
  │              AgentGroupChat                  │
  │                                             │
  │  AuditeurTech  →  OfficerConformite  →  Synthese  │
  │  (GPT-4o)         (Claude 3.5)        (Mistral)  │
  └─────────────────────────────────────────────┘
        │                    ▲
        └────── RAG ─────────┘
               (Qdrant)
        │
        ▼
  Rapport d'audit : APPROUVÉ / ALERTE

Fonctionnalités

  • Orchestration multi-agents via AgentGroupChat (Semantic Kernel Agents Framework)
  • Stratégie de terminaison automatique sur les mots-clés APPROUVÉ / ALERTE (max 5 itérations)
  • RAG hybride : recherche dense (embeddings) + re-ranking TF-IDF sparse en mémoire
  • Router LLM : classification heuristique + méta-prompt SLM pour aiguiller les requêtes
  • Connecteur Anthropic custom : implémentation de IChatCompletionService pour Claude
  • Télémétrie complète : traces OpenTelemetry, métriques de tokens et coûts par modèle
  • API REST ASP.NET Core avec DI complète et resilience (Polly via Microsoft.Extensions.Http.Resilience)

Architecture

Le projet suit une architecture en couches inspirée de Clean Architecture :

audit-sem-krnl/
├── src/
│   ├── AuditSemKrnl.Domain/            # Entités, enums, value objects (aucune dépendance externe)
│   ├── AuditSemKrnl.Application/       # Interfaces, use cases, contrats de données
│   ├── AuditSemKrnl.Infrastructure/    # Implémentations : agents SK, RAG, routing, telemetry
│   └── AuditSemKrnl.Api/               # Hôte ASP.NET Core, controllers, Program.cs
├── prompts/                             # Templates de prompts SK au format YAML
│   ├── auditeur_tech/
│   ├── officer_conformite/
│   └── synthese/
└── docker/                             # docker-compose.yml + config OTel Collector

Dépendances entre projets

Api → Infrastructure → Application → Domain
Api →                  Application

Stack technique

Composant Technologie Version
Framework IA Microsoft Semantic Kernel 1.74.0
Agent Framework Microsoft.SemanticKernel.Agents.Core 1.74.0
LLM frontier Azure OpenAI (GPT-4o) via SK connector
LLM conformité Anthropic Claude 3.5 Sonnet Anthropic.SDK 5.10.0
LLM local Mistral via Ollama SK connector 1.74.0-alpha
Base vectorielle Qdrant Client 1.17.0
Observabilité OpenTelemetry 1.15.1
Résilience HTTP Microsoft.Extensions.Http.Resilience 10.4.0
Runtime .NET 9.0

Les trois agents

AuditeurTech (GPT-4o)

Analyse les fichiers d'infrastructure à la recherche de non-conformités de sécurité :

  • Conteneurs Kubernetes s'exécutant en root (securityContext absent ou runAsRoot: true)
  • privileged: true, hostPID, hostNetwork, hostIPC
  • Buckets S3 publics, politiques IAM avec wildcard *
  • Clés d'accès hardcodées dans Terraform
  • Groupes de sécurité ouverts sur 0.0.0.0/0

Plugins disponibles : FileAnalysisPlugin (lecture/listage des fichiers), ComplianceRagPlugin (requêtes RAG), ReportPlugin (accumulation des findings).

OfficerConformite (Claude 3.5 Sonnet)

Expert juridique en réglementation financière et cybersécurité. À partir des findings de l'AuditeurTech :

  • Cite les articles précis de DORA (Art. 5-44), ACPR, ISO 27001
  • Évalue la gravité réglementaire de chaque non-conformité
  • Rend un verdict APPROUVÉ ou ALERTE

Note d'architecture : Claude est intégré via un IChatCompletionService custom (AnthropicChatCompletionService) car il n'existe pas de connecteur SK officiel pour Anthropic.

Synthese (Mistral via Ollama)

Produit un résumé exécutif en 3 paragraphes maximum, compréhensible par un RSSI non-technique. Fonctionne entièrement en local (Ollama).

Important : aucun plugin n'est enregistré sur ce kernel. Les données sensibles (fichiers de configuration) ne quittent jamais ce modèle vers le cloud.


RAG hybride

La base réglementaire (textes DORA, ACPR, ISO 27001) est indexée dans Qdrant et interrogée lors de chaque audit.

Ingestion (DocumentIngestionService)

  1. Découpage en chunks de 512 mots avec overlap de 128
  2. Génération des embeddings denses (text-embedding-3-large via Azure OpenAI)
  3. Fit de l'encodeur TF-IDF sparse sur le document
  4. Upsert dans Qdrant avec métadonnées : framework, version, audit_date, chunk_index

Recherche (HybridSearchService)

  1. Embedding dense de la requête
  2. Recherche Qdrant SearchAsync (vecteurs denses)
  3. Re-ranking hybride en mémoire : score_final = 0.7 × score_dense + 0.3 × boost_sparse
  4. Filtrage au-dessus du seuil de pertinence (défaut : 0.70)

Pour un corpus > 10k documents, remplacer SparseVectorEncoder par un modèle SPLADE via ONNX Runtime. L'interface IHybridSearchService isole ce changement.


Router LLM

Le LlmRouter classifie chaque requête avant de décider si le groupe complet d'agents est nécessaire :

Longueur > 2000 tokens   ──→ Complex (AgentGroupChat complet)
      │
Mot-clé de risque détecté ──→ Complex
      │
Appel méta-prompt Mistral ──→ SIMPLE ou COMPLEX

Mots-clés configurables (dans appsettings.json) : privilege escalation, RBAC, ClusterRoleBinding, IAM, cross-account, hostPID, hostNetwork.


Télémétrie

Chaque invocation de fonction kernel est instrumentée via SkFunctionInvocationFilter (IFunctionInvocationFilter) :

Signal OTel Nom Dimensions
Trace agent.<name>.<function> llm.model_id, sk.function
Counter audit.llm.tokens.total model, agent, direction
Histogram audit.llm.latency_ms model, agent
Counter audit.rag.hits framework
Histogram audit.rag.score framework

Les traces sont exportées vers Jaeger via l'OTel Collector (OTLP gRPC port 4317).

Coût par modèle

Configuré dans appsettings.json (section TokenCost) :

"TokenCost": {
  "Models": {
    "gpt-4o": { "InputPer1k": 0.0025, "OutputPer1k": 0.010 },
    "claude-3-5-sonnet-20241022": { "InputPer1k": 0.003, "OutputPer1k": 0.015 },
    "mistral": { "InputPer1k": 0.0, "OutputPer1k": 0.0 }
  }
}

Prérequis

  • .NET 9 SDK
  • Docker Desktop (pour Qdrant, Ollama, Jaeger)
  • Un déploiement Azure OpenAI avec gpt-4o et text-embedding-3-large
  • Une clé API Anthropic

Installation et démarrage

1. Démarrer l'infrastructure locale

cd docker
docker compose up -d

# Télécharger le modèle Mistral dans Ollama (première fois uniquement, ~4 GB)
docker exec audit-ollama ollama pull mistral

Les services démarrent sur :

  • Qdrant REST : http://localhost:6333
  • Qdrant gRPC : localhost:6334
  • Ollama : http://localhost:11434
  • Jaeger UI : http://localhost:16686
  • OTel Collector : localhost:4317

2. Configurer les secrets

Ne jamais committer les clés API. Utilisez dotnet user-secrets :

cd src/AuditSemKrnl.Api

dotnet user-secrets init
dotnet user-secrets set "SemanticKernel:AzureOpenAI:Endpoint"            "https://<votre-ressource>.openai.azure.com/"
dotnet user-secrets set "SemanticKernel:AzureOpenAI:ApiKey"              "<votre-clé-azure-openai>"
dotnet user-secrets set "SemanticKernel:AzureOpenAI:DeploymentName"      "gpt-4o"
dotnet user-secrets set "SemanticKernel:AzureOpenAI:EmbeddingDeploymentName" "text-embedding-3-large"
dotnet user-secrets set "SemanticKernel:Anthropic:ApiKey"                "<votre-clé-anthropic>"

3. Lancer l'API

cd src/AuditSemKrnl.Api
dotnet run

L'API écoute sur https://localhost:7xxx (voir Properties/launchSettings.json).


Utilisation de l'API

Ingérer un document réglementaire

Avant de lancer un audit, indexez les textes réglementaires dans Qdrant :

curl -X POST https://localhost:7xxx/api/v1/documents/ingest \
  -H "Content-Type: application/json" \
  -d '{
    "title": "DORA - Règlement UE 2022/2554",
    "textContent": "Article 5 : Les entités financières disposent...",
    "framework": "DORA",
    "version": "2024"
  }'

Réponse :

{
  "documentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "chunkCount": 42,
  "title": "DORA - Règlement UE 2022/2554"
}

Lancer un audit

curl -X POST https://localhost:7xxx/api/v1/audit \
  -H "Content-Type: application/json" \
  -d '{
    "files": {
      "deployment.yaml": "apiVersion: apps/v1\nkind: Deployment\nspec:\n  template:\n    spec:\n      containers:\n      - name: app\n        image: myapp:latest\n        securityContext:\n          privileged: true",
      "main.tf": "resource \"aws_s3_bucket\" \"data\" {\n  bucket = \"mon-bucket\"\n  acl    = \"public-read\"\n}"
    },
    "framework": "DORA",
    "infraVersion": "1.4.2"
  }'

Réponse :

{
  "correlationId": "a1b2c3d4-...",
  "status": "ALERTE",
  "findings": [
    {
      "description": "Conteneur 'app' s'exécute avec privileged: true",
      "risk": "CRITICAL",
      "framework": "DORA",
      "lineReference": "securityContext.privileged",
      "regulatoryReference": "DORA Art. 9 - Sécurité des systèmes ICT"
    },
    {
      "description": "Bucket S3 'mon-bucket' accessible publiquement (acl: public-read)",
      "risk": "HIGH",
      "framework": "DORA",
      "regulatoryReference": "DORA Art. 9 - Protection des données"
    }
  ],
  "summary": "L'audit de l'infrastructure version 1.4.2 a révélé deux non-conformités...",
  "tokensConsumed": 3847,
  "estimatedCostUsd": 0.048
}

Health check

curl https://localhost:7xxx/health
# {"status":"healthy","service":"audit-sem-krnl"}

Référentiels supportés

Valeur framework Description
DORA Digital Operational Resilience Act (UE 2022/2554)
ACPR Autorité de Contrôle Prudentiel et de Résolution
ISO27001 ISO/IEC 27001:2022 — Sécurité de l'information
All Tous les référentiels indexés

Prompts SK

Les instructions des agents sont externalisées dans prompts/ au format YAML Semantic Kernel :

prompts/
├── auditeur_tech/
│   ├── analyze_kubernetes.yaml   # Détection de privilèges excessifs K8s
│   ├── analyze_terraform.yaml    # Détection de mauvaises configs cloud
│   └── analyze_shell.yaml        # Analyse de scripts Shell
├── officer_conformite/
│   ├── check_dora.yaml           # Comparaison avec articles DORA
│   ├── check_acpr.yaml           # Comparaison avec directives ACPR
│   └── check_iso27001.yaml       # Comparaison avec contrôles ISO 27001
└── synthese/
    └── summarize_findings.yaml   # Résumé exécutif pour RSSI

Tous les prompts utilisent temperature: 0.1 pour maximiser le déterminisme des résultats d'audit.


Configuration complète

src/AuditSemKrnl.Api/appsettings.json :

{
  "SemanticKernel": {
    "AzureOpenAI": {
      "Endpoint": "",
      "ApiKey": "",
      "DeploymentName": "gpt-4o",
      "EmbeddingDeploymentName": "text-embedding-3-large"
    },
    "Anthropic": {
      "ApiKey": "",
      "Model": "claude-3-5-sonnet-20241022"
    },
    "Ollama": {
      "Endpoint": "http://localhost:11434",
      "Model": "mistral"
    }
  },
  "Qdrant": {
    "QdrantEndpoint": "http://localhost:6333",
    "QdrantGrpcPort": 6334,
    "CollectionName": "regulatory_docs",
    "DenseVectorSize": 3072,
    "RelevanceThreshold": 0.70,
    "ChunkSize": 512,
    "ChunkOverlap": 128
  },
  "Routing": {
    "ComplexityTokenThreshold": 2000,
    "ComplexKeywords": ["privilege escalation", "RBAC", "ClusterRoleBinding", "IAM"]
  }
}

Décisions d'architecture notables

Pourquoi un connecteur Anthropic custom ?

Il n'existe pas de Microsoft.SemanticKernel.Connectors.Anthropic officiel sur NuGet. AnthropicChatCompletionService implémente IChatCompletionService en wrappant Anthropic.SDK et s'intègre nativement dans le système de services SK.

Pourquoi un kernel par agent ?

Chaque agent nécessite un modèle différent (GPT-4o, Claude, Mistral). SK ne permet pas de mixer les providers sur un kernel unique de manière fiable. KernelFactory crée trois kernels isolés, chacun avec ses propres plugins.

Pourquoi AgentOrchestrator est Scoped et non Singleton ?

AgentGroupChat maintient l'historique de conversation en mémoire. L'enregistrer comme Singleton ferait partager l'historique entre toutes les requêtes HTTP concurrentes. La durée de vie Scoped garantit une instance propre par requête.

Pourquoi le kernel Synthese n'a aucun plugin ?

Sécurité by design : le modèle Mistral tourne en local (Ollama). Sans plugin, il ne peut pas appeler d'outils externes. Les données sensibles (fichiers de config Terraform, YAML) ne quittent jamais ce kernel vers des services cloud.


Pistes d'évolution

  • Streaming : implémenter GetStreamingChatMessageContentsAsync dans AnthropicChatCompletionService pour les réponses en temps réel
  • Sparse vectoriel natif : remplacer SparseVectorEncoder (TF-IDF) par SPLADE via ONNX Runtime pour > 10k documents
  • Persistance des rapports : brancher IDistributedCache (Redis) ou une base SQL pour GET /api/v1/audit/{correlationId}
  • GraphRAG : intégrer une base de graphes (Neo4j) pour modéliser les relations entre ressources infra
  • Nouveaux référentiels : NIS2, PCI-DSS — il suffit d'ingérer les documents et d'ajouter les valeurs dans l'enum ComplianceFramework
  • Tests d'intégration : brancher un Qdrant en mémoire et un serveur OpenAI mock pour les tests CI

About

Automated conformance audit systems for criticals infrastructures, built on **Semantic Kernel 1.74** and **C# / .NET 9**.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages