tis-wazuh-plugin-import-from-wazuh
26-10
Plugin for importing wazuh breaches in wapt data audit
1070 downloads
Download
See build result See VirusTotal scan

tis-wazuh-plugin-import-from-wazuh
This package allows CVEs detected by Wazuh to be reported in the audit data of the affected machines in WAPT.
The audit is performed automatically every hour.
The result is saved in the audit data under the key wazuh.
Two types of results are possible:
- ✅ OK → The data transfer from Wazuh to WAPT is working correctly.
- ❌ ERROR → A package configuration error is preventing proper operation.
To benefit from the latest updates, it is recommended to:
- Clone the package from Tranquil IT's WAPT repository.
How the package works:
- Deploy the package on the Wazuh server
- Go to /opt/wapt/private
- Modify the files "elastic_wazuh_api.ini" and "wapt_api.ini" with your information
- Run the package audit to verify everything is working correctly
elastic_wazuh_api.ini :
[elastic]
username = account to connect to elastic_search
password = account password
instance_name = name of the elastic_search instance (Wazuh instance or cluster name)
verify_cert = False/True
url = https://127.0.0.1:9200 - URL to connect to elastic_search
wazuh_url = https://srvwazuh.mydomain.lan - Wazuh server URL
wapt_api.ini :
[wapt]
username = waptapi - WAPT account to read and store audit data
password = password - Account password
url = https://mywapt.mydomain.lan - WAPT server URL
- package : tis-wazuh-plugin-import-from-wazuh
- name : Plugin Import Wazuh
- version : 26-10
- categories :
- maintainer : Simon Fonteneau ,Tranquil IT
- editor :
- licence :
- locale :
- target_os : all
- impacted_process :
- architecture : all
- signature_date : 2025-06-08 14:01
- size : 8.99 Ko
package : tis-wazuh-plugin-import-from-wazuh
version : 26-10
architecture : all
section : base
priority : optional
name : Plugin Import Wazuh
categories :
maintainer : Simon Fonteneau ,Tranquil IT
description : Plugin for importing wazuh breaches in wapt data audit
depends :
conflicts :
maturity : PROD
locale :
target_os : all
min_wapt_version :
sources :
installed_size :
impacted_process :
description_fr :
description_pl :
description_de :
description_es :
description_pt :
description_it :
description_nl :
description_ru :
audit_schedule : 1h
editor :
keywords :
licence :
homepage :
package_uuid : 48c20188-1ffb-4fc5-bcf3-9a5085a9f664
valid_from :
valid_until :
forced_install_on :
changelog :
min_os_version :
max_os_version :
icon_sha256sum : ab03226aa75b0f33fcb7fe327fa164535e5410d0b5cbe02fdd5e124a017f9cb9
signer : Tranquil IT
signer_fingerprint: 8c5127a75392be9cc9afd0dbae1222a673072c308c14d88ab246e23832e8c6bb
signature_date : 2025-06-08T14:01:13.000000
signed_attributes : package,version,architecture,section,priority,name,categories,maintainer,description,depends,conflicts,maturity,locale,target_os,min_wapt_version,sources,installed_size,impacted_process,description_fr,description_pl,description_de,description_es,description_pt,description_it,description_nl,description_ru,audit_schedule,editor,keywords,licence,homepage,package_uuid,valid_from,valid_until,forced_install_on,changelog,min_os_version,max_os_version,icon_sha256sum,signer,signer_fingerprint,signature_date,signed_attributes
signature : ZKS0/hP6fI4jVGJLae5/Eii23HKFsXluRlWYgUADw+0zug7iY0FJEj6Jb1qJEGbfJQipqKDFAyZOfrahlNasEzqS8KDaL+wzi0qGEs4oTslUNhaO2gcir7oda+oWd+DjViyhSoiC8trcVXwfTxiLrMcksEmSlKE3tEet1qjS97uA20uxjWv/6NaFD61WVgPn0EIzFY0qZtOXj0doD7CewNyYyB05jity+VauDPdXeupX4SYJCRaNVXGzUmhXYqiRdwXEmJuh8Ykxt4CWTjlPEXcCvZxeC7zWgoJnWHxEA3iL8f4rlMH3caTevCKhDvwDUccylVSdc+/7HyQqTh3MIQ==
# -*- coding: utf-8 -*-
from setuphelpers import *
from configparser import ConfigParser
from waptutils import get_verify_cert
from common import get_requests_client_cert_session
import platform
import waptlicences
import json
import concurrent.futures
import requests
from requests.auth import HTTPBasicAuth
import datetime
simultaneous_maximum_send=10
def audit():
CONFWAPT = ConfigParser()
CONFWAPT.read(makepath(WAPT.private_dir, "wapt_api.ini"))
username_wapt = CONFWAPT.get("wapt", "username")
password_wapt = CONFWAPT.get("wapt", "password")
srvwapt_url = CONFWAPT.get("wapt", "url")
t = waptlicences.waptserver_login(WAPT.config_filename,username_wapt,password_wapt)
if not 'session' in t['session_cookies']:
session_cookies = [u for u in t['session_cookies'] if u['Domain'] == WAPT.waptserver.server_url.split('://')[-1]][0]
else:
session_cookies = t['session_cookies']['session']
session_cookies['Name'] = 'session'
sessionwapt = get_requests_client_cert_session(WAPT.waptserver.server_url,cert=(t['client_certificate'],t['client_private_key'],t['client_private_key_password']),verify=WAPT.waptserver.verify_cert)
sessionwapt.cookies.set(session_cookies['Name'], session_cookies['Value'], domain=session_cookies['Domain'])
sessionwapt.verify = WAPT.waptserver.verify_cert
CONFWAZUH = ConfigParser()
CONFWAZUH.read(makepath(WAPT.private_dir, "elastic_wazuh_api.ini"))
url_elastic = CONFWAZUH.get("elastic", "url")
username_elastic = CONFWAZUH.get("elastic", "username")
password_elastic = CONFWAZUH.get("elastic", "password")
instance_name_elastic = CONFWAZUH.get("elastic", "instance_name")
wazuh_url = CONFWAZUH.get("elastic", "wazuh_url")
if CONFWAZUH.has_option("elastic", 'verify_cert'):
verify_cert_wz = get_verify_cert(CONFWAZUH.get("elastic", 'verify_cert'))
else:
verify_cert_wz = True
dict_hostname_uuid = {}
for pc in json.loads(sessionwapt.get("%s/api/v3/hosts?&limit=1000000" % WAPT.waptserver.server_url).content)["result"]:
dict_hostname_uuid[str(pc["computer_name"]).lower()] = pc["uuid"]
list_error = []
list_run = []
for hostname, uuid in dict_hostname_uuid.items():
list_run.append({
"sessionwapt": sessionwapt,
"dict_hostname_uuid": {hostname: uuid},
"WAPT": WAPT,
"hostname":hostname,
"list_error":list_error,
"url_elastic": url_elastic,
"username_elastic" : username_elastic,
"password_elastic" : password_elastic,
"instance_name_elastic" : instance_name_elastic,
"verify_cert_wz" : verify_cert_wz,
"wazuh_url" : wazuh_url
})
results = []
with concurrent.futures.ThreadPoolExecutor(simultaneous_maximum_send) as executor:
futures = {executor.submit(import_from_wazuh, **g): g for g in list_run}
for future in concurrent.futures.as_completed(futures):
results.append(future.result())
waptlicences.waptserver_logout(WAPT.config_filename)
if list_error:
print(" \n".join(list_error))
return "ERROR"
else:
return "OK"
def import_from_wazuh(sessionwapt=None,url_elastic=None,username_elastic=None,password_elastic=None,instance_name_elastic=None,dict_hostname_uuid=None,WAPT=None,hostname=None,list_error=None,verify_cert_wz=True,wazuh_url=None):
waptdata = []
try:
# URL d'accès à l'index Elasticsearch pour les vulnérabilités
url = f"{url_elastic}/wazuh-states-vulnerabilities-{instance_name_elastic}/_search"
# Construction de la requête avec un filtre sur l'agent si nécessaire
query = {
"_source": [
"agent.id",
"agent.name",
"vulnerability.id",
"vulnerability.severity",
"vulnerability.reference",
"vulnerability.score.base",
"package.name",
"package.version"
],
"size": 100,
"sort": [
{
"_score": {
"order": "desc"
}
}
],
"query": {
"wildcard": {
"agent.name": {
"value": hostname,
"case_insensitive": True
}
}
}
}
# Envoi de la requête GET à Elasticsearch
response = requests.get(url, auth=HTTPBasicAuth(username_elastic, password_elastic), headers={'Content-Type': 'application/json'}, json=query, verify=verify_cert_wz)
response.raise_for_status()
data = response.json()
vulnerabilities = data.get('hits', {}).get('hits', [])
result = {"cve":{},"max_score_base":0,"status":"compliant" ,"list_patch": {},"wazuh_url":wazuh_url,"agent_id": {}}
for vuln in vulnerabilities:
source = vuln["_source"]
cve_id = source.get("vulnerability", {}).get("id")
score_base = source.get("vulnerability", {}).get("score").get("base")
package_name = source.get("package", {}).get("name")
agent_id = source.get("agent", {}).get("id")
result['cve'][cve_id] = {
"agent_name": source.get("agent", {}).get("name"),
"score_base": score_base,
"vulnerability_id": cve_id,
"package_name": package_name,
"package_version": source.get("package", {}).get("version"),
"severity": source.get("vulnerability", {}).get("severity"),
"reference": source.get("vulnerability", {}).get("reference")
}
if package_name :
result['list_patch'][package_name.replace(' ','_')] = package_name
if agent_id :
result['agent_id'] = agent_id
result['status'] = 'vulnerable'
if score_base > result['max_score_base']:
result['max_score_base'] = score_base
result['list_patch_list'] = list(result['list_patch'])
##################################################################
waptdata.append(
{
"host_id": dict_hostname_uuid[str(hostname).lower()],
"value_id": int(time.monotonic() * 1000),
"value_date": datetime2isodate(datetime.datetime.utcnow()),
"value_section": "wazuh",
"value_key": "wazuh",
"value": result,
"expiration_date": datetime2isodate(datetime.datetime.utcnow() + datetime.timedelta(minutes=1440)),
}
)
print("Get %s from wazuh" % str(hostname).lower())
time.sleep(0.0000001)
except Exception as e:
list_error.append("Error %s %s" % (str(hostname).lower(), str(e)))
sessionwapt.post("%s/api/v3/update_hosts_audit_data" % WAPT.waptserver.server_url, data=json.dumps(waptdata))
def install():
if not isfile(makepath(WAPT.private_dir, "elastic_wazuh_api.ini")):
filecopyto("elastic_wazuh_api.ini", makepath(WAPT.private_dir, "elastic_wazuh_api.ini"))
if not isfile(makepath(WAPT.private_dir, "wapt_api.ini")):
filecopyto("wapt_api.ini", makepath(WAPT.private_dir, "wapt_api.ini"))
def list_to_dict(newkey=None, listconvert=None):
newdict = {}
for p in listconvert:
newdict[p[newkey]] = p
return newdict
e638e8deaf15d5e322d4d253534d72c3602fa6e46fb1f400fdea89abf3de0720 : WAPT/README.md
a1d2da32f4483edd53ab2cdeaca6185d1776bd5baf549e1d67abe013831999ae : WAPT/README_fr.md
38d056ab130f7bf7c481c12636a4e9959de36561d3dfcbe54c6e3571bc0c1dc3 : WAPT/certificate.crt
ee9b56b7c5ff90b37e408fb490510044ef8741bc3163c9839726887aa50b3ffd : WAPT/control
ab03226aa75b0f33fcb7fe327fa164535e5410d0b5cbe02fdd5e124a017f9cb9 : WAPT/icon.png
b41d8970d1fd0d06f9be052f55ee3544e9d6cdbce6d348f669e3791d77dedec7 : elastic_wazuh_api.ini
a64128c7f86be1ffbe257b8de4d91b85b57226aa5d46f9e38d72104ba483b387 : luti.json
f52601023fac6b0c0a3f55625c19773c3015b87f15861e33ee3c68cd6a97d432 : setup.py
cb302f842cf1695f553389a436898f9e580d7d866a6726789dca1994a55e9c3c : wapt_api.ini