Pilotez Zedmos depuis n'importe où.
Chaque capacité Zedmos exposée par l'interface de la console est un point de terminaison REST. Ce guide couvre les deux façons sûres pour un système distant de les atteindre — une clé d'API directe, ou le proxy WebSocket zedmos-console — ainsi qu'une référence complète par catégorie.
API directe, ou proxy WebSocket
Les deux voies aboutissent aux mêmes contrôleurs /api/zedmos/* — seuls le transport et les identifiants diffèrent. Choisissez-en une par intégration.
- Expose
- Le pare-feu OPNsense lui-même (son serveur web). Sur pfSense, la protection équivalente est limitée à la boucle locale — utilisez plutôt le proxy WebSocket.
- Transport
- HTTPS directement vers l'interface d'administration du pare-feu.
- Identifiant
- Clé d'API OPNsense + secret (authentification HTTP Basic). pfSense utilise une clé + un secret générés localement, acceptés uniquement sur la boucle locale.
- Délimitation
- Une seule ACL OPNsense — page-services-zedmos — contrôle tous les points de terminaison (lecture ET écriture). Aucune portée en lecture seule intégrée. Sur pfSense, la protection équivalente est le privilège d'ACL Zedmos.
- Idéal pour
- Un partenaire sur un segment de confiance ou un VPN site à site, ou que vous pouvez restreindre par IP.
- Expose
- Le hub cloud Zedmos (zedmos-backend). Le pare-feu s'y connecte en sortie.
- Transport
- Le pare-feu ouvre un tunnel wss:// sortant vers le hub ; le partenaire appelle l'API REST du hub.
- Identifiant
- Jeton de session de la console du hub (Bearer). Le pare-feu est enrôlé avec tenant_id + node_id + agent_secret (HMAC).
- Délimitation
- Liste d'autorisation par chemin sur l'agent, PLUS l'ACL de la clé d'API locale, PLUS l'isolation des locataires du hub.
- Idéal pour
- Gestion SaaS / multi-locataire, pare-feu derrière NAT, ou tout ce que vous ne devez pas exposer en entrée.
Démarrage rapide
Sur OPNsense, l'API directe utilise une clé d'API OPNsense + un secret via HTTP Basic. Les appels non authentifiés reçoivent un HTTP 302 (redirection vers la connexion), pas un 401. Les appels par clé d'API sont exemptés de CSRF. Sur pfSense, la protection de l'API locale est limitée à la boucle locale : les intégrations distantes passent donc par le proxy WebSocket.
# OPNsense only - on pfSense use the WebSocket-proxy example below
# 1) Create an API key in OPNsense: System > Access > Users > API keys
# The user must hold the "Services: Zedmos" privilege (page-services-zedmos).
KEY='....' # OPNsense API key
SECRET='....' # OPNsense API secret
# Read — list policy groups
curl -s -u "$KEY:$SECRET" \
https://fw.example.com/api/zedmos/policies/groups
# -> {"groups":[{"name":"Default","status":true}, ...]}
# Write — block a domain globally (POST, JSON body)
curl -s -u "$KEY:$SECRET" -H 'Content-Type: application/json' \
-d '{"type":"host","value":"badsite.com","global":true}' \
https://fw.example.com/api/zedmos/policies/block
# -> {"status":"ok"}const base = "https://fw.example.com";
const auth =
"Basic " + Buffer.from(`${process.env.ZED_KEY}:${process.env.ZED_SECRET}`).toString("base64");
async function zed(path, { method = "GET", body } = {}) {
const r = await fetch(`${base}/api/zedmos${path}`, {
method,
headers: { Authorization: auth, ...(body ? { "Content-Type": "application/json" } : {}) },
body: body ? JSON.stringify(body) : undefined,
});
if (r.status === 302) throw new Error("auth failed (redirect to login)");
return r.json();
}
const groups = await zed("/policies/groups");
await zed("/policies/block", {
method: "POST",
body: { type: "category", value: "AdultContent", group: "Strict" },
});# The partner never talks to the firewall directly — it calls the hub,
# which routes the call down the firewall's outbound socket.
curl -s -X POST https://www.zedmos.com/api/agent/proxy/http \
-H "Authorization: Bearer $CONSOLE_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"tenant_id": "69fb...",
"node_id": "6a0d...",
"method": "GET",
"url": "/api/zedmos/policies/groups"
}'
# -> {"status":"ok","response":{"status":200,"body":"{\"groups\":[...]}","error":null}}La façon la plus sûre de l'exposer
Pour une entreprise extérieure que vous ne contrôlez pas entièrement, préférez le proxy WebSocket : aucun port entrant, liste d'autorisation par chemin, isolation des locataires, révocation centralisée. N'utilisez l'API directe que sur un segment de confiance ou un VPN, toujours durcie.
Une seule ACL contrôle tout
page-services-zedmos couvre chaque point de terminaison /api/zedmos/*, en lecture comme en écriture. Il n'existe pas de privilège Zedmos par point de terminaison ni en lecture seule. Délimitez plutôt un partenaire par des règles réseau ou par la liste d'autorisation du proxy WS.
Les clés d'API contournent le CSRF
Les appels par clé d'API sont exemptés du jeton anti-CSRF (seules les sessions navigateur en ont besoin hors GET). Certains points de terminaison modifient aussi l'état sur GET sans protection de méthode — sans risque avec des clés, mais verrouillez les méthodes sur un proxy inverse si vous les exposez.
Toujours en HTTPS, toujours restreint par IP
L'API écoute sur toutes les interfaces (*:80 en laboratoire). Pour un usage distant, passez l'interface web en HTTPS avec un certificat valide et limitez le port d'administration par une règle de pare-feu aux IP source du partenaire.
Préférez le proxy WS pour les tiers
Il n'ouvre aucun port entrant, restreint exactement les chemins que le partenaire peut appeler (liste d'autorisation), isole les locataires et se révoque depuis un point central (pierre tombale signée). C'est le canal recommandé pour les intégrateurs non fiables.
Recommandation
Proxy WS pour les tiers non fiables. API directe uniquement derrière HTTPS et une règle de pare-feu sur le port d'administration limitée aux IP source du partenaire, avec un compte de service dédié ne détenant que page-services-zedmos.
Le schéma policies.json
Chaque clé que le partenaire peut lire par /policies/get et écrire par /policies/groupsave ou /policies/save. Schéma 1.1.0. Les valeurs admises et les valeurs par défaut viennent de la documentation intégrée du document lui-même.
Structure du document
eval — ordre d'évaluation
evalgroups[] — l'objet groupe de politique
Identity
groups[]Selectors — who the group applies to
groups[].selectorsA flow joins this group when its selectors match. Empty arrays = no constraint on that axis.
Overrides
groups[].overridesExclusions
groups[].exclusionsAllow-list overrides that exempt matching traffic from this group's blocks.
Security catalogs (threat categories)
groups[].securityEach boolean enables blocking of one threat-intel catalog. basic_mode/advanced_mode are convenience presets; the `essential{}` and `advanced{}` objects mirror the flat booleans.
Application control (L7 app-ID)
groups[].appsEncrypted-transport control
groups[].transportFirst-install default: all 'allow'. Switch to 'block' to enforce.
TLS inspection (MITM)
groups[].tlsNetwork (L3/L4) blocks
groups[].networkHard early-drops via fast-reject before rules[] runs. Use a rule with is_exception+action:allow to punch a hole.
Web filtering
groups[].webAI Security & DLP
groups[].web.dlpPer-group only — globals.web.dlp is a TEMPLATE the engine ignores. First-install default: OFF.
File / AV scanning
groups[].file.scanDNS control
groups[].dnsETA · Identity · Geo · Risk · TI · IDS
groups[].{eta,identity,geo,risk,ti,ids}Action handlers
groups[].actionsConfigured at group level; a rule references them via its `action`. Most fire only on a DROP-class decision (pair with action:drop). Placeholders $src, $dst, $rule_id.
App Routing
groups[].routingRules (ordered, fine-grained)
groups[].rules[]Optional per-group ordered rule list evaluated after early-drops. Each rule matches on fields and fires one action.
// POST /api/zedmos/policies/groupsave — Content-Type: application/json
// Upsert one group (only the keys you send are changed; rest is preserved).
{
"name": "Strict",
"status": true,
"description": "Locked-down VLAN",
"selectors": { "vlans": [30], "direction": "any" },
"overrides": { "block_all": false, "block_untrusted": true, "schedule": "work-hours" },
"security": { "basic_mode": "high", "malware_virus": true, "phishing": true },
"apps": { "categories_block": ["adultcontent", "gaming"] },
"transport":{ "quic_strategy": "block", "doh_strategy": "block" },
"tls": { "enable_inspection": true, "bump_mode": "force", "min_version": "1.2" },
"dns": { "block_domains": ["coin-hive.com"], "dga": "block", "tunnel": "block" },
"web": { "dlp": { "enable": true, "mode": "regex_only", "action": "block",
"presets": ["cc_luhn","iban","email_pii"] } },
"file": { "scan": { "mode": "block", "action": "block", "engines": ["clamav"] } },
"ids": { "mode": "prevent", "block_max_priority": 2 },
"rules": [
{ "is_exception": true, "action": "allow", "mode": "any",
"dst_domain": ["intranet.corp"], "comment": "always allow intranet" }
]
}globals — valeurs par défaut, catalogues, réglages du moteur
Engine knob registry
globals.engineOperator-tunable hot-path knobs. Precedence: value here > env DG_* > hardcoded default. Atomic publish on policy reload.
Global catalogs & defaults
globals.{security,ti,quarantine,schedules,exclusions}// POST /api/zedmos/policies/globals — set global blacklists / actions
{
"exclusions": { "domains": ["windowsupdate.com"], "src_cidrs": ["10.0.0.0/8"] },
"ti": { "domain_block": ["evil.example"], "ip_block": ["203.0.113.7"] },
"schedules": [
{ "name": "work-hours", "start": "08:00", "end": "18:00",
"days": ["Mon","Tue","Wed","Thu","Fri"] }
]
}Toutes les catégories
Regroupées exactement comme dans la console : Politiques d'abord, puis Réglages, Notifications, Rapports, Direct et le reste. Les chemins sont relatifs à la base de chaque catégorie.
/api/zedmos/policiesLa surface principale. Pilote policies.json — groupes, réglages globaux, catalogue de sécurité, catégories d'applications, préréglages DLP et renseignement sur les menaces.
/api/zedmos/settingsLa plus grande surface (environ 62 actions) : TLS/CA, interfaces et processus, IDS/ETA/TI, writerd et stockage, AD/identité, console cloud, reconnaissance des appareils et contrôle du trafic.
/api/zedmos/notificationsFlux d'alertes + répartiteur. Le seul contrôleur doté de sa propre barrière d'autorisation (canModify : utilisateur de session, ou boucle locale / même hôte). Configuration dans notifications.json.
/api/zedmos/reportsPoints de terminaison de graphiques en lecture seule sur la base de flux. Tous forcés en POST dans dispatch() pour que l'interface puisse les appeler en XHR-GET ; avec une clé d'API, l'une ou l'autre méthode fonctionne. Paramètres courants : hours(1-168), since/until(ms), mode(session/packet/volume). La plupart renvoient {labels, values}.
/api/zedmos/liveFlux quasi temps réel. Interrogez avec un curseur since (l'interface fait du sondage — il n'y a ni WebSocket ni SSE sur la machine). Paramètres courants : hours(6), since(ms), limit(1000, 10-2000), plus des filtres intelligents (filters_<ep>, sf_*).
/api/zedmos/dashboardIndicateurs agrégés, télémétrie système (CPU/température/disque), état des fonctionnalités, et contrôle des services et des mises à jour.
/api/zedmos/deviceInventaire des appareils et cycle de vie. Utilise des arguments de chemin positionnels pour les actions <id>, par exemple /device/trust/42.
/api/zedmosContrôleurs supplémentaires, résumés. Chacun suit la même convention /api/zedmos/<slug>/<command> et la même authentification.
La voie B, en détail
Le pare-feu se connecte vers le hub ; le partenaire appelle l'API REST du hub, qui relaie l'appel dans la socket. L'agent applique une liste d'autorisation par requête avant de toucher à l'API locale.
API REST du hub — ce que le partenaire appelle
Préréglages de liste d'autorisation (la frontière par requête)
core-read-onlyEnviron 364 points de terminaison GET en lecture seule répartis sur 24 modules. Valeur par défaut sûre.firewall-adminfirewall/* en lecture et écriture complètes + core/diag/interfaces en lecture seule.network-admininterfaces/*, routes/*, routing/* complets + core/diag en lecture seule.vpn-adminipsec/*, openvpn/*, wireguard/* complets (sur disque ; à sélectionner via personnalisé).ids-monitorids/* complet + core/diag en lecture seule (sur disque ; à sélectionner via personnalisé).full-adminTout, tous les modules. « Équivaut à un contournement. » Ne le donnez pas à des partenaires.Aucun des préréglages livrés n'inclut /api/zedmos/*. Pour une intégration aux politiques, utilisez une liste d'autorisation personnalisée :
# Custom allowlist for a policies integration (config.json patterns / preset=custom)
/api/zedmos/policies/*
/api/zedmos/settings/*
# optional read-only telemetry
/api/zedmos/dashboard/*
/api/zedmos/live/*
/api/zedmos/reports/*Protocole de messages (référence)
Hub → agent : {"type":"http","requestId","method","url","body","timeoutMs"}
Agent → hub : {"type":"httpResponse","requestId","status","body","error"}
Établissement de session : le hub envoie un nonce de défi ; l'agent répond par HMAC-SHA256(agent_secret, "tenant|node|ts|nonce") ; le hub répond hello_ack. Révocation par une pierre tombale signée.Référence rédigée complète, avec chaque point de terminaison et chaque paramètre : docs/ZEDMOS_API_REFERENCE.md dans le dépôt.