Wazuh Agent Management - Enrollment and Configuration

Wazuh agents are installed on endpoints and handle log collection, file system monitoring, system inventory, and security assessments. Agent management encompasses the entire lifecycle - from enrollment and group assignment through centralized configuration, upgrades, and decommissioning. At scale, automating enrollment and configuration through Ansible, GPO, or cloud-init becomes critical. This guide covers all aspects of managing Wazuh 4.14 agents.

Agent Lifecycle

Every Wazuh agent progresses through defined states during operation.

Agent states

StateDescription
PendingAgent is registered but has not yet connected to the manager
ActiveAgent is connected and transmitting data
DisconnectedAgent has lost communication with the manager (default: 10 minutes without heartbeat)
Never connectedAgent is registered but has never established a connection

Lifecycle diagram

Installation -> Enrollment -> Pending -> Active <-> Disconnected
                                                        |
                                                     Removed

Checking agent status

Through the API:

TOKEN=$(curl -sk -u wazuh-wui:$PASSWORD \
  -X POST "https://localhost:55000/security/user/authenticate?raw=true")

curl -sk -H "Authorization: Bearer $TOKEN" \
  "https://localhost:55000/agents?status=active&limit=10" | jq '.data.affected_items[] | {id,name,status,ip}'

Through the CLI on the manager:

/var/ossec/bin/agent_control -l

# Detailed information about a specific agent
/var/ossec/bin/agent_control -i 001

Through the state file on the agent:

cat /var/ossec/var/run/wazuh-agentd.state

Configuring disconnection time

By default, an agent is considered disconnected after 600 seconds (10 minutes). To change this in ossec.conf on the manager:

<ossec_config>
  <global>
    <agents_disconnection_time>300</agents_disconnection_time>
    <agents_disconnection_alert_time>60</agents_disconnection_alert_time>
  </global>
</ossec_config>

Enrollment Methods

Enrollment via agent configuration

The most common method. The agent registers automatically on its first connection to the manager.

On a Linux agent:

<!-- /var/ossec/etc/ossec.conf -->
<ossec_config>
  <client>
    <server>
      <address>192.168.1.5</address>
      <port>1514</port>
      <protocol>tcp</protocol>
    </server>
    <enrollment>
      <enabled>yes</enabled>
      <manager_address>192.168.1.5</manager_address>
      <port>1515</port>
      <agent_name>web-server-01</agent_name>
      <groups>linux,web-servers</groups>
    </enrollment>
  </client>
</ossec_config>

On a Windows agent (during installation):

Invoke-WebRequest -Uri https://packages.wazuh.com/4.x/windows/wazuh-agent-4.14.4-1.msi -OutFile wazuh-agent.msi

msiexec.exe /i wazuh-agent.msi /q `
  WAZUH_MANAGER="192.168.1.5" `
  WAZUH_AGENT_NAME="win-server-01" `
  WAZUH_AGENT_GROUP="windows,servers" `
  WAZUH_REGISTRATION_SERVER="192.168.1.5"

Password-based enrollment

To protect the enrollment process, you can configure password authentication.

On the manager, create a password file:

echo "MySecurePassword" > /var/ossec/etc/authd.pass
chmod 640 /var/ossec/etc/authd.pass
chown root:wazuh /var/ossec/etc/authd.pass

Enable password authentication in ossec.conf:

<ossec_config>
  <auth>
    <use_password>yes</use_password>
  </auth>
</ossec_config>

On the agent, specify the password:

<enrollment>
  <enabled>yes</enabled>
  <manager_address>192.168.1.5</manager_address>
  <authorization_pass_path>/var/ossec/etc/authd.pass</authorization_pass_path>
</enrollment>

Certificate-based enrollment

Certificate authentication provides mutual verification between agent and manager.

On the manager:

<ossec_config>
  <auth>
    <ssl_agent_ca>/var/ossec/etc/rootCA.pem</ssl_agent_ca>
    <ssl_verify_host>yes</ssl_verify_host>
  </auth>
</ossec_config>

On the agent:

<enrollment>
  <enabled>yes</enabled>
  <manager_address>192.168.1.5</manager_address>
  <agent_certificate_path>/var/ossec/etc/agent.cert</agent_certificate_path>
  <agent_key_path>/var/ossec/etc/agent.key</agent_key_path>
  <server_ca_path>/var/ossec/etc/rootCA.pem</server_ca_path>
</enrollment>

API-based enrollment

A two-step process: request a key through the API and import it on the agent.

# Step 1: Obtain the key via API
TOKEN=$(curl -sk -u wazuh-wui:$PASSWORD \
  -X POST "https://localhost:55000/security/user/authenticate?raw=true")

KEY=$(curl -sk -H "Authorization: Bearer $TOKEN" \
  -X POST "https://localhost:55000/agents" \
  -H "Content-Type: application/json" \
  -d '{"name":"api-agent-01","ip":"any"}' | jq -r '.data.key')

# Step 2: Import the key on the agent
/var/ossec/bin/manage_agents -i "$KEY"

# Step 3: Start the agent
systemctl start wazuh-agent

Enrollment via authd

The authd daemon automatically handles enrollment requests. It is enabled by default and listens on port 1515/TCP.

# On the agent - request enrollment
/var/ossec/bin/agent-auth -m 192.168.1.5

# With a custom name and group
/var/ossec/bin/agent-auth -m 192.168.1.5 -A "custom-agent-name" -G "linux,production"

# With password
/var/ossec/bin/agent-auth -m 192.168.1.5 -P "MySecurePassword"

Agent Groups

Groups allow logical organization of agents and centralized configuration management.

Default group

All newly registered agents are automatically assigned to the default group. The group configuration is located at /var/ossec/etc/shared/default/agent.conf.

Creating a group

Through the CLI:

/var/ossec/bin/agent_groups -a -g web-servers -q

Through the API:

curl -sk -H "Authorization: Bearer $TOKEN" \
  -X POST "https://localhost:55000/groups" \
  -H "Content-Type: application/json" \
  -d '{"group_id": "web-servers"}'

Through the Dashboard: Agents management - Groups - Add new group.

Assigning an agent to a group

# Through CLI
/var/ossec/bin/agent_groups -a -i 001 -g web-servers -q

# Through API
curl -sk -H "Authorization: Bearer $TOKEN" \
  -X PUT "https://localhost:55000/agents/001/group/web-servers"

Assignment during enrollment

# Using agent-auth
/var/ossec/bin/agent-auth -m 192.168.1.5 -G "web-servers,linux"

# During Windows installation
msiexec.exe /i wazuh-agent.msi /q WAZUH_AGENT_GROUP="windows,production"

Multi-group membership

An agent can belong to multiple groups simultaneously. When parameters conflict, the last assigned group takes precedence.

# Assign to multiple groups
curl -sk -H "Authorization: Bearer $TOKEN" \
  -X PUT "https://localhost:55000/agents/001/group/web-servers"

curl -sk -H "Authorization: Bearer $TOKEN" \
  -X PUT "https://localhost:55000/agents/001/group/production"

Priority order (lowest to highest): default - web-servers - production. Configuration from the production group overrides conflicting parameters from web-servers and default.

Viewing agent groups

# Groups for a specific agent
curl -sk -H "Authorization: Bearer $TOKEN" \
  "https://localhost:55000/agents/001/group" | jq '.data.affected_items'

# All agents in a group
curl -sk -H "Authorization: Bearer $TOKEN" \
  "https://localhost:55000/groups/web-servers/agents" | jq '.data.affected_items[] | {id,name,status}'

Centralized Configuration (agent.conf)

The agent.conf file enables centralized management of agent configuration through the manager. Each group has its own agent.conf at /var/ossec/etc/shared/<GROUP_NAME>/agent.conf.

Structure of agent.conf

<!-- /var/ossec/etc/shared/web-servers/agent.conf -->
<agent_config>

  <!-- Web server log collection -->
  <localfile>
    <log_format>apache</log_format>
    <location>/var/log/apache2/access.log</location>
  </localfile>

  <localfile>
    <log_format>apache</log_format>
    <location>/var/log/apache2/error.log</location>
  </localfile>

  <!-- File integrity monitoring -->
  <syscheck>
    <directories check_all="yes" realtime="yes">/var/www/html</directories>
    <directories check_all="yes">/etc/apache2</directories>
  </syscheck>

  <!-- Active Response -->
  <active-response>
    <disabled>no</disabled>
  </active-response>

</agent_config>

OS-based filtering

<agent_config os="Linux">
  <localfile>
    <log_format>syslog</log_format>
    <location>/var/log/auth.log</location>
  </localfile>
</agent_config>

<agent_config os="Windows">
  <localfile>
    <log_format>eventchannel</log_format>
    <location>Security</location>
    <query>Event/System[EventID=4625 or EventID=4624]</query>
  </localfile>
</agent_config>

Profile-based filtering

<agent_config profile="database">
  <localfile>
    <log_format>syslog</log_format>
    <location>/var/log/postgresql/postgresql-*.log</location>
  </localfile>
</agent_config>

Shared files

In addition to agent.conf, the group directory can contain supplementary files that are automatically synchronized to agents:

  • CDB lists for rootcheck
  • CIS Benchmark files
  • Custom configuration files
# Place a file for the group
cp custom-rootcheck.txt /var/ossec/etc/shared/web-servers/

# Check synchronization status
/var/ossec/bin/agent_groups -S -i 001

Configuration merging (merged.mg)

The manager automatically generates a merged.mg file that combines configurations from all groups assigned to an agent. This file is sent to the agent and determines the final working configuration.

Agent Upgrades

Upgrading via WPK

WPK (Wazuh Package) files are signed packages for remote agent upgrades.

Through the API:

# Upgrade a single agent
curl -sk -H "Authorization: Bearer $TOKEN" \
  -X PUT "https://localhost:55000/agents/001/upgrade" | jq '.'

# Upgrade multiple agents
curl -sk -H "Authorization: Bearer $TOKEN" \
  -X PUT "https://localhost:55000/agents/upgrade" \
  -H "Content-Type: application/json" \
  -d '{"agents_list": ["001", "002", "003"]}'

Checking upgrade status

curl -sk -H "Authorization: Bearer $TOKEN" \
  "https://localhost:55000/agents/upgrade_result" | jq '.data.affected_items'

Upgrading through Dashboard

  1. Navigate to Agents management
  2. Select agents for upgrade
  3. Click Upgrade
  4. Confirm the version and start the process

Staged upgrades

To minimize impact on production systems, upgrade agents in batches:

# Upgrade agents in the staging group
AGENTS=$(curl -sk -H "Authorization: Bearer $TOKEN" \
  "https://localhost:55000/groups/staging/agents?limit=500" | \
  jq -r '.data.affected_items[].id' | tr '\n' ',' | sed 's/,$//')

curl -sk -H "Authorization: Bearer $TOKEN" \
  -X PUT "https://localhost:55000/agents/upgrade" \
  -H "Content-Type: application/json" \
  -d "{\"agents_list\": [\"${AGENTS}\"]}"

Custom WPK packages

To build custom WPK packages:

# Download the build tools
git clone https://github.com/wazuh/wazuh.git
cd wazuh/src/wazuh_modules/agent_upgrade/

# Build a custom WPK (requires a GPG key for signing)

Agent Labels

Labels allow attaching custom metadata to agents. Labels are included in every alert, simplifying filtering and routing.

Configuring labels

On the agent in ossec.conf:

<ossec_config>
  <labels>
    <label key="environment">production</label>
    <label key="datacenter">us-east-1</label>
    <label key="team">platform</label>
    <label key="cost-center">CC-1234</label>
  </labels>
</ossec_config>

Through centralized configuration in agent.conf:

<agent_config>
  <labels>
    <label key="compliance">pci-dss</label>
    <label key="tier">tier-1</label>
  </labels>
</agent_config>

Hidden labels

Labels prefixed with _ are not included in alerts but remain accessible through the API:

<labels>
  <label key="_internal.ticket">JIRA-12345</label>
</labels>

Using labels in queries

GET wazuh-alerts-*/_search
{
  "query": {
    "term": { "agent.labels.environment": "production" }
  }
}

Key Management

Exporting an agent key

/var/ossec/bin/manage_agents -e 001

Importing a key on the agent

/var/ossec/bin/manage_agents -i "<KEY_STRING>"

Listing registered agents

/var/ossec/bin/manage_agents -l

Removing an agent

# Through CLI
/var/ossec/bin/manage_agents -r 001

# Through API
curl -sk -H "Authorization: Bearer $TOKEN" \
  -X DELETE "https://localhost:55000/agents?agents_list=001&status=all&older_than=0s"

Mass Deployment Strategies

Ansible

# playbook.yml
---
- name: Deploy Wazuh agents
  hosts: all
  become: yes
  vars:
    wazuh_manager: "192.168.1.5"
    wazuh_version: "4.14.4"
    wazuh_group: "{{ group_names | join(',') }}"

  tasks:
    - name: Add Wazuh repository
      apt_repository:
        repo: "deb https://packages.wazuh.com/4.x/apt/ stable main"
        state: present
      when: ansible_os_family == "Debian"

    - name: Install Wazuh agent
      apt:
        name: "wazuh-agent={{ wazuh_version }}-1"
        state: present
      when: ansible_os_family == "Debian"

    - name: Configure agent
      template:
        src: ossec.conf.j2
        dest: /var/ossec/etc/ossec.conf
        owner: root
        group: wazuh
        mode: '0640'

    - name: Start Wazuh agent
      systemd:
        name: wazuh-agent
        state: started
        enabled: yes

GPO with MSI (Windows)

For mass deployment on Windows through Group Policy:

  1. Download the MSI package: wazuh-agent-4.14.4-1.msi
  2. Place it in a network share accessible to domain computers
  3. Create a GPO for Software Installation:
    • Computer Configuration - Policies - Software Settings - Software Installation
    • Add the MSI package
  4. Configure installation parameters through an MST (transform) file:
WAZUH_MANAGER=192.168.1.5
WAZUH_AGENT_GROUP=windows,production
WAZUH_REGISTRATION_SERVER=192.168.1.5
WAZUH_REGISTRATION_PASSWORD=MySecurePassword

cloud-init

#cloud-config
package_update: true

runcmd:
  - curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | gpg --dearmor -o /usr/share/keyrings/wazuh.gpg
  - echo "deb [signed-by=/usr/share/keyrings/wazuh.gpg] https://packages.wazuh.com/4.x/apt/ stable main" > /etc/apt/sources.list.d/wazuh.list
  - apt-get update
  - WAZUH_MANAGER="192.168.1.5" WAZUH_AGENT_GROUP="cloud,auto-provisioned" apt-get install -y wazuh-agent
  - systemctl daemon-reload
  - systemctl enable wazuh-agent
  - systemctl start wazuh-agent

Docker

FROM ubuntu:22.04

ENV WAZUH_MANAGER="192.168.1.5"
ENV WAZUH_AGENT_GROUP="docker,containers"

RUN apt-get update && \
    apt-get install -y curl gnupg && \
    curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | \
      gpg --dearmor -o /usr/share/keyrings/wazuh.gpg && \
    echo "deb [signed-by=/usr/share/keyrings/wazuh.gpg] https://packages.wazuh.com/4.x/apt/ stable main" \
      > /etc/apt/sources.list.d/wazuh.list && \
    apt-get update && \
    apt-get install -y wazuh-agent && \
    apt-get clean

ENTRYPOINT ["/var/ossec/bin/wazuh-control", "start"]

Auto-removal of Disconnected Agents

To automatically clean up agents that have been offline for an extended period:

# Remove agents disconnected for more than 30 days
curl -sk -H "Authorization: Bearer $TOKEN" \
  -X DELETE "https://localhost:55000/agents?status=disconnected&older_than=30d" | jq '.'

To automate this, add a cron job:

# /etc/cron.daily/wazuh-cleanup-agents
#!/bin/bash
TOKEN=$(curl -sk -u wazuh-wui:$PASSWORD \
  -X POST "https://localhost:55000/security/user/authenticate?raw=true")
curl -sk -H "Authorization: Bearer $TOKEN" \
  -X DELETE "https://localhost:55000/agents?status=disconnected&older_than=30d"

Comparison with Other SIEM Platforms

FeatureWazuh AgentSplunk Universal ForwarderElastic Agent (Fleet)QRadar Log Sources
Deployment modelAgent per hostForwarder per hostAgent per hostAgentless + WinCollect
Group managementGroups with agent.confServer classesPoliciesLog Source Groups
Centralized configagent.conf via managerDeployment appsFleet policiesNone (per-source)
Remote upgradeWPK via APIDeployment serverFleet upgradeWinCollect update
Built-in FIMYesNo (addon)Yes (integration)No (addon)
Vulnerability scanYesNoYesNo
Mass deploymentAnsible, GPO, cloud-initAnsible, GPO, SCCMFleet enrollment tokensWinCollect MSI
LicensingFreePer data volumePer data volumePer EPS

Troubleshooting

Agent not connecting

Symptom: agent remains in never_connected or disconnected status.

Diagnostics on the agent:

# Check configuration
cat /var/ossec/etc/ossec.conf | grep -A5 "<server>"

# Check agent logs
tail -50 /var/ossec/logs/ossec.log

# Test network connectivity
nc -zv 192.168.1.5 1514
nc -zv 192.168.1.5 1515

Diagnostics on the manager:

# Check enrollment logs
tail -50 /var/ossec/logs/ossec.log | grep -i "agent"

# Verify authd is listening
ss -tlnp | grep 1515

# Verify remoted is listening
ss -tlnp | grep 1514

Solutions:

  • Verify that ports 1514/TCP and 1515/TCP are open on the firewall
  • Check that the manager address is correct in the agent configuration
  • When using password enrollment, ensure the password matches on both sides
  • Restart wazuh-authd on the manager

Key mismatch

Symptom: Invalid key or Agent key mismatch messages in the logs.

# On the manager - export the key for the agent
/var/ossec/bin/manage_agents -e 001

# On the agent - remove the old key and import the new one
/var/ossec/bin/manage_agents -r
/var/ossec/bin/manage_agents -i "<NEW_KEY>"

# Restart the agent
systemctl restart wazuh-agent

Version incompatibility

Symptom: agent connects but functionality is limited or errors appear.

Wazuh supports backward compatibility within the major version. Agent 4.x can connect to manager 4.y where y >= x. Upgrade the agent to match the manager version for full compatibility.

# Check version on the agent
/var/ossec/bin/wazuh-control info | grep VERSION

# Check version on the manager
/var/ossec/bin/wazuh-control info | grep VERSION

Duplicate agents

Symptom: a single host is registered multiple times with different IDs.

# Search for duplicates by IP or name
curl -sk -H "Authorization: Bearer $TOKEN" \
  "https://localhost:55000/agents?name=web-server-01" | jq '.data.affected_items[] | {id,name,ip,status}'

# Remove the duplicate agent
curl -sk -H "Authorization: Bearer $TOKEN" \
  -X DELETE "https://localhost:55000/agents?agents_list=002&status=all&older_than=0s"

Prevention: use force.enabled in the authd configuration:

<ossec_config>
  <auth>
    <force>
      <enabled>yes</enabled>
      <key_mismatch>yes</key_mismatch>
      <disconnected_time enabled="yes">1h</disconnected_time>
      <after_registration_time>1h</after_registration_time>
    </force>
  </auth>
</ossec_config>

This allows an agent with the same IP or name to replace an existing registration if the old agent has been disconnected for more than 1 hour.

Agent not receiving group configuration

Symptom: changes to agent.conf are not applied on the agent.

# Check synchronization status
/var/ossec/bin/agent_groups -S -i 001

# Check the merged.mg file on the agent
cat /var/ossec/etc/shared/merged.mg

# Force synchronization - restart the agent
systemctl restart wazuh-agent

Ensure that agent.conf is valid XML - malformed XML blocks synchronization entirely.

Additional Resources

Last updated on