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 appreciatedI 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 logthe 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()