tis-wazuh-plugin-import-from-wazuh

26-10
Plugin for importing wazuh breaches in wapt data audit
1070 téléchargements
Télécharger
Voir le résultat de la construction Voir l'analyse de VirusTotal
tis-wazuh-plugin-import-from-wazuh icon

tis-wazuh-plugin-import-from-wazuh

Ce paquet permet de faire remonté les CVE détéctées par Wazuh dans les données d'audit des machines concernées dans WAPT

L’audit est effectué automatiquement tous les 1 heures.

Le résultat est enregistré dans les données d’audit sous la clé wazuh.

Deux types de résultats sont possibles :

  • OK → La remontée des données de Wazuh vers WAPT fonctionne correctement.
  • ERROR → Une erreur de configuration du paquet empêche le bon fonctionnement.

Pour bénéficier des dernières mises à jour, il est recommandé de :

  • Cloner le paquet depuis le dépôt WAPT de Tranquil IT.

Comment fonctionne le paquet :

  • Déployer le paquet sur le serveur Wazuh
  • Se rendre dans /opt/wapt/private
  • Mofifier les fichiers "elastic_wazuh_api.ini" et "wapt_api.ini" avec vos informations.
  • Lancer l'audit du paquet afin de vérifier le bon fonctionnement.

elastic_wazuh_api.ini :

[elastic]
username = compte pour se connecter à élastic_search
password = mot de passe du compte
instance_name = nom de l'instance elastic_search (nom de l'instance Wazuh ou du cluster)
verify_cert = False/True
url = https://127.0.0.1:9200 - URL de connexion à élastic_search
wazuh_url = https://srvwazuh.mydomain.lan - URL du serveur Wazuh

wapt_api.ini :

[wapt]
username = waptapi - Compte WAPT pour lire et enregister les données d'audit
password = password - Mot de passe du compte 
url = https://mywapt.mydomain.lan - URL du serveur WAPT
  • 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