Wazuh Agents Limit

75 views
Skip to first unread message

Saad khattak

unread,
Feb 13, 2026, 11:44:15 PMFeb 13
to Wazuh | Mailing List
Hi! I am working on limiting Wazuh agents. Currently, the process I am implementing is using the Wazuh Key agent request to limit the number of agents that can be registered on the Wazuh Manager. The issue I am getting is that the Wazuh agent key request is being executed, but the response of the agent key request is return code 1. authd just falls back to the default, and it registered the agent through auto enrollment. What I simply want is that everything should work fine until the limit is reached, so when the limit is reached, no agents should get connected to that manager. How can I fix this, or are there any alternative solutions to this other than:
  • Creating a script to manually remove the agents through managing agent
  • blocking the port after port 1515 after the limit is reached
I have listed. All of the information is below any help will be much appreciated

I get this in the ossec.log

 wazuh-authd: WARNING: Key request integration (/var/ossec/lic/license.py) returned code 1.
wazuh-remoted: WARNING: (1213): Message from '192.168.18.5' not allowed. Cannot find the ID of the agent. Source agent ID is unknown.
wazuh-authd: INFO: New connection from 192.168.18.5
 wazuh-authd: INFO: Received request for a new agent (DESKTOP-I5GA80N) from: 192.168.18.5
 wazuh-authd: INFO: Agent key generated for 'DESKTOP-I5GA80N' (requested by 192.168.18.5)```
the script log

the logs of the script
 === ENROLLMENT REQUEST ===
Args: ['/var/ossec/lic/license.py', 'ip', '192.168.18.21']
License check: 1/1
 DENIED: License limit reached (1/1)

the script  check limit in   /var/ossec/etc/client.keys and blocks enrollment if limit is reached  but the issue is when it return code 1 the authd fall back

#!/usr/bin/env python3
import sys
import json
import os
import requests
import urllib3
from datetime import datetime

# Disable SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# ---------------- CONFIG ---------------- #
LICENSE_LIMIT = 1
CLIENT_KEYS = "/var/ossec/etc/client.keys"
WAZUH_API_URL = "https://localhost:55000"
WAZUH_API_USER = "admin"
WAZUH_API_PASSWORD = "admin-123"  # Change this!
# ---------------------------------------- #

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
LOG_FILE = os.path.join(SCRIPT_DIR, "license_key_request.log")

def log_message(message):
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    with open(LOG_FILE, "a") as f:
        f.write(f"[{timestamp}] {message}\n")

def get_agent_count():
    try:
        with open(CLIENT_KEYS, "r") as f:
            count = sum(1 for line in f if line.strip() and not line.startswith("000"))
        return count
    except:
        return 0

def get_api_token():
    """Get JWT token from Wazuh API."""
    try:
        response = requests.post(
            f"{WAZUH_API_URL}/security/user/authenticate",
            auth=(WAZUH_API_USER, WAZUH_API_PASSWORD),
            verify=False,
            timeout=10
        )
        if response.status_code == 200:
            return response.json()['data']['token']
        else:
            raise Exception(f"API auth failed: {response.status_code}")
    except Exception as e:
        log_message(f"API authentication error: {str(e)}")
        raise

def create_agent_via_api(agent_name, agent_ip, token):
    """Create agent using Wazuh API."""
    try:
        headers = {
            'Authorization': f'Bearer {token}',
            'Content-Type': 'application/json'
        }

        agent_data = {
            "name": agent_name,
            "ip": agent_ip
        }

        response = requests.post(
            f"{WAZUH_API_URL}/agents",
            headers=headers,
            json=agent_data,
            verify=False,
            timeout=10
        )

        if response.status_code == 200:
            data = response.json()['data']
            return data['id'], data['key']
        else:
            raise Exception(f"API error: {response.status_code} - {response.text}")

    except Exception as e:
        log_message(f"API error: {str(e)}")
        raise

def main():
    log_message(f"=== ENROLLMENT REQUEST ===")
    log_message(f"Args: {sys.argv}")

    if len(sys.argv) < 3:
        print(json.dumps({"error": 1, "message": "Too few arguments"}))
        sys.exit(1)

    request_type = sys.argv[1]
    request_value = sys.argv[2]

    if request_type != "ip":
        print(json.dumps({"error": 1, "message": "Only IP requests supported"}))
        sys.exit(1)

    agent_ip = request_value
    current_count = get_agent_count()

    log_message(f"License check: {current_count}/{LICENSE_LIMIT}")

    if current_count >= LICENSE_LIMIT:
        msg = f"License limit reached ({current_count}/{LICENSE_LIMIT})"
        log_message(f"DENIED: {msg}")
        print(json.dumps({"error": 1, "message": msg}))
        sys.exit(1)

    # Create agent via API
    try:
        agent_name = f"agent-{agent_ip.replace('.', '-')}"
        token = get_api_token()
        agent_id, agent_key = create_agent_via_api(agent_name, agent_ip, token)

        log_message(f"ALLOWED: Created agent ID={agent_id}")

        # Return agent data in the format authd expects
        print(json.dumps({
            "error": 0,
            "data": {
                "id": agent_id,
                "name": agent_name,
                "ip": agent_ip,
                "key": agent_key
            }
        }))
        sys.exit(0)

    except Exception as e:
        log_message(f"ERROR: {str(e)}")
        print(json.dumps({"error": 1, "message": str(e)}))
        sys.exit(1)

if __name__ == "__main__":
    main()

Nikhil Gurjar

unread,
Feb 15, 2026, 11:37:46 PMFeb 15
to Wazuh | Mailing List
Hi  Saad Khattak,

Kindly allow me some time to investigate this issue. I will update you as soon as possible with my findings and next steps.

Best regards,
Nikhil

Nikhil Gurjar

unread,
Feb 16, 2026, 5:01:12 AMFeb 16
to Wazuh | Mailing List
Hi  Saad Khattak,

Thank you for your patience. I have investigated your issue in detail and tested a script that can help enforce limitations on agent enrollment. Kindly refer to the steps below:

Steps to implement
  1. Download the script provided below and update the LICENSE_LIMIT variable to define the maximum number of agents allowed to remain in an active state.

  2. Install the required dependencies using the following command:

           apt install inotify-tools
  1. Make the script executable:

          chmod +x enforce_limit_agent_communication.py
  1. Run the script as a background service (recommended):

    a. Create a systemd service file:

                 nano /etc/systemd/system/wazuh-license.service

            b. Add the following example configuration:

            [Unit] 
            Description=Wazuh Agent Enforcer 
           
           [Service] 
           ExecStart=/usr/bin/python3 /var/ossec/integrations/enforce_limit_agent_communication.py 
           Restart=always
   
          [Install] 
         WantedBy=multi-user.target

         c. Apply the changes using: 

          systemctl daemon-reload 

         systemctl enable --now wazuh-license

Note: If you prefer to run the script manually, uncomment the last two lines and comment out the watch_client_keys() function (as shown in the reference image): Then run:
python3 enforce_limit_agent_communication.py
enforce_limit_agent_communication.png

You can validate the logs at: /var/ossec/logs/license_enforcer.log
logs.png

Reference examples:

  • Before (active agents limit = 0): 
    active_before.png

  • After: 
    active_after.png

Additionally, could you please clarify your exact requirement? You mentioned limiting agent enrollment based on the number of connected agents — could you explain the specific use case for this limitation? If your goal is to allow only specific agents to enroll on the Wazuh manager, you may consider enabling enrollment passwords instead. This allows only agents with the correct password to register. You can refer to the following documentation: https://documentation.wazuh.com/current/user-manual/agent/agent-enrollment/security-options/index.html . This way is more reliable and recommended over the script to limit the number of agents connected.

Hope this information is helpful. We look forward to your update, and please let us know if you have any further questions or require additional assistance.

Best regards,
Nikhil

enforce_limit_agent_communication.py
Reply all
Reply to author
Forward
0 new messages