While developing a solution for the client, two tasks arose that I wanted to address beautifully and using the native functionality of Zabbix.
Task 1. Monitoring the current firmware version on Mikrotik routers.
This task can be easily solved by adding it to the HTTP agent template. The agent retrieves the latest version from the Mikrotik website, and the trigger compares the current version with the latest one, issuing an alert if there is a discrepancy.
When you have 10 routers, this approach is not critical, but what about 3,000 routers? Sending 3,000 requests to the server? It will work, but the sheer number of requests coming from a single IP could be perceived as a DoS attack, and might lead to being banned.
Task 2. Using an authorization session across different HTTP agents.
When information needs to be retrieved from 'closed' pages via an HTTP agent, an authorization cookie is required. This typically involves a standard login/password authorization form and setting the session ID in the cookie.
However, there is a problem: you cannot access data from one HTTP agent item to substitute this value in the Header of another.
There is also a 'Web Scenario', which has a different limitation; it does not allow obtaining content for analysis and further storage. You can only check for the presence of necessary variables on the pages or transfer previously obtained variables between steps of the web scenario.
After some thought on these tasks, I decided to use macros, which are easily visible in any part of the monitoring system: in templates, hosts, triggers, or items. Macros can be updated through the web interface API.
Zabbix has good and detailed documentation on the API. Data is exchanged using the Json format. You can read more in .
The sequence of actions to obtain the required data and record it in the macro is presented in the diagram below.

Step 1
The very first step may consist of one action or many actions. The entire main logic is laid out in the initial steps, with the last three steps being the most crucial.
In my example, the first step involved obtaining the authorization cookie from the PBX for the first task. For the second task, I retrieved the current firmware version number of Mikrotik.
URL of the latest firmware versions for Mikrotik
- — URL for the latest Stable version
- — URL for the latest LTS version
These addresses are accessed by Mikrotik equipment when retrieving the latest available firmware version.
The first step is completely individual for each case, and the logic of its operation may vary. It all depends on your task.
When working with web scripts, monitor which method of response you need. Headers HTTP response or just the body of the response without headers?
If cookies for authorization are needed, set the response method Headers as in the case with Asterisk.If data is needed, as in the case with the Mikrotik server response, set it to Body the response without headers.
Step 2
Now we move to the second step. Obtaining the authorization session:
POST http://company.com/zabbix/api_jsonrpc.php HTTP/1.1
Content-Type: application/json-rpc
{
"jsonrpc": "2.0",
"method": "user.login",
"params": {
"user": "Admin",
"password": "zabbix"
},
"id": 1,
"auth": null
}jsonrpc — the version of the JSON-RPC protocol being used;
Zabbix implements JSON-RPC version 2.0;
- method — the method that is being called;
- params — the parameters being passed by the method;
- id — an arbitrary identifier for the request;
- auth — the user's authentication key; since we do not have it yet, we will set it to null.
To work with the API, I created a separate account with limited rights. First, you should not give access where it is not needed. Secondly, before version 5.0, the password set via the macro could be read. Accordingly, if you use the Zabbix administrator password, the admin account can be easily stolen.
This will be particularly relevant when working with the API through third-party scripts and storing credentials on that side.
Starting from version 5.0, there is an option to hide the password saved in the macro.

When creating a separate account for updating data through the API, always check if the necessary data is available through the web interface, and whether it can be updated. I didn’t check and then couldn’t understand for a long time why my macro wasn’t visible via the API.

After obtaining authorization in the API, we proceed to obtain the list of macros.
Step 3
The API interface does not allow updating the host macro by name; it is necessary to first obtain the macro ID. Moreover, to obtain a list of macros for a specific host, you must know the ID of that host, which adds an extra request. Use a standard macro {HOST.ID} in the request is not possible. I decided to bypass the limitation this way:

I created a local macro with the ID of this host. Getting the host ID is very easy from the web interface.
The response containing the list of all macros for this host can be filtered by pattern:
regex:{"hostmacroid":"([0-9]+)"[A-z0-9,":]+"{$MIKROTIK_VERSION}" 
Thus, we obtain the ID of the desired macro, where MIKROTIK_VERSION is the name of the macro we are looking for. In my case, the macro being sought is MIKROTIK_VERSION, which was assigned to the host.
The request looks like this:
POST http://company.com/zabbix/api_jsonrpc.php HTTP/1.1
Content-Type: application/json-rpc
{
"jsonrpc":"2.0",
"method":"usermacro.get",
"params":{
"output":"extend",
"hostids":"{$HOST_ID}"
},
"auth":"{sid}",
"id":1
}
The variable {sid} obtained in the second step and will be used continuously wherever API interface interaction is needed.
Final STEP 4 — updating the macro
Now we know the ID of the macro we need to update, the authorization cookie, or the version of the router firmware. It is possible to update the macro itself.
POST http://company.com/zabbix/api_jsonrpc.php HTTP/1.1
Content-Type: application/json-rpc
{
"jsonrpc":"2.0",
"method":"usermacro.update",
"params":{
"hostmacroid":"{hostmacroid}",
"value":"{mikrotik_version}"
},
"auth":"{sid}",
"id":1
}
{mikrotik_version} is the value obtained in the first step. In my example, it is the version of the current Mikrotik firmware.
{hostmacroid} is the value obtained in the third step — the ID of the macro being updated.
Conclusions
The approach to solving the task with standard functionality is significantly more complex and time-consuming. Especially if you know programming and can quickly outline the necessary logic in a script.
An obvious advantage of this approach is the "portability" of the solution between different servers.
Personally, I find it strange that there is no option to reference data from another item in the HTTP agent and insert it into the body of the request or headers [ ].
The finished template can be .
Source: habr.com
