Wazuh agents move through all the stages of their life cycle, sometimes leaving the agents permanently disconnected (i.e: terminated instances) or never connected (i.e: firewall issues). This post describes how to purge these kinds of agents from the manager’s agent list by using the Wazuh API.

Understanding agent dates

If we use the API to retrieve the agent list, we will see two date fields:

  • dateAdd: Agent registration date.
  • lastKeepAlive: Last date the agent sent a keep alive.

For disconnected agents, we are interested in the lastKeepAlive date, since it is the last time the agent was connected to the manager. Although, for never connected agents, we need to look into the dateAdd date because the agent never reported to the manager (there is no a keep alive).

# curl -u foo:bar -k -XGET 'https://localhost:55000/agents?select=name,status,dateAdd,lastKeepAlive&pretty'
{
   "error": 0,
   "data": {
      "totalItems": 4,
      "items": [
         {
            "status": "Active",
            "dateAdd": "2019-01-01 00:00:00",
            "name": "Springfield",
            "lastKeepAlive": "9999-12-31 23:59:59",
            "id": "000"
         },
         {
            "status": "Active",
            "dateAdd": "2019-04-11 12:00:00",
            "name": "Homer-01",
            "lastKeepAlive": "2019-04-11 13:00:00",
            "id": "001"
         },
         {
            "status": "Never connected",
            "dateAdd": "2019-03-01 12:00:00",
            "name": "Maggie-01",
            "id": "002"
         },
         {
            "status": "Disconnected",
            "dateAdd": "2019-03-01 12:00:01",
            "name": "Bart-01",
            "lastKeepAlive": "2019-03-11 10:00:00",
            "id": "003"
         },
      ]
   }
}

Purging agents using the API

Our API allows for easy managment of the Wazuh agents. The DELETE /agents request will allow us to purge the agents by using the following parameters:

  • status: Select agents according to their status (active, disconnected, neverconnected). You can use commas to enter multiple statuses.
  • older_than: Select disconnected agents for longer than specified (using the lastKeepAlive date) and never connected agents that are older than specified (using the dateAdd date).

So, combining both parameters, we can easily purge the agents that haven’t reported in the last older_than days or the registered agents that have never reported. Here’s some examples:

Example 1: Purging never connected agents older than 21 days

Assuming the current date is 2019-04-11, the agent 002 is removed because its status is never connected and the dateAdd was more than 21 days ago (2019-03-01). In other words, the agent was registered but it has never reported to the manager.

# curl -u foo:bar -k -XDELETE 'https://localhost:55000/agents?status=neverconnected&older_than=21d&pretty'
{
   "error": 0,
   "data": {
      "msg": "All selected agents were removed",
      "older_than": "21d",
      "affected_agents": [
         "002"
      ],
      "total_affected_agents": 1
   }
}

Example 2: Purging disconnected agents older than 21 days

Assuming the current date is 2019-04-11, the agent 003 is removed because its status is disconnected and the lastKeepAlive was more than 21 days ago (2019-03-11). In other words, the agent hasn’t reported in 21 days.

# curl -u foo:bar -k -XDELETE 'https://localhost:55000/agents?status=disconnected&older_than=21d&pretty'
{
   "error": 0,
   "data": {
      "msg": "All selected agents were removed",
      "older_than": "21d",
      "affected_agents": [
         "003"
      ],
      "total_affected_agents": 1
   }
}

Conclusion

The agent coverage is an important metric in our environments, but we need to update the manager’s agent list regularly by removing agents that have not been active for a certain amount of time. That way the manager’s agent list matches the current server inventory or indicates that you have to troubleshoot the missing servers.