Skip to content

Commit 7206ea4

Browse files
committed
Add webhook mediatype for Zabbix 6.0 or higher
1 parent 5dfbc6f commit 7206ea4

File tree

10 files changed

+412
-64
lines changed

10 files changed

+412
-64
lines changed

.circleci/config.yml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@ executors:
2020
tag:
2121
type: string
2222
default: latest
23+
mysql_tag:
24+
type: string
25+
default: '5.7'
2326
docker:
2427
- image: circleci/ruby:2.7.2-buster
25-
- image: mysql:5.7
28+
- image: mysql:<< parameters.mysql_tag >>
2629
environment:
2730
MYSQL_DATABASE: zabbix
2831
MYSQL_USER: zabbix
@@ -60,6 +63,19 @@ jobs:
6063
steps:
6164
- integration_test_with_zabbix
6265

66+
integration_test_with_zabbix_60:
67+
executor:
68+
name: zabbix
69+
mysql_tag: '8.2'
70+
tag: ubuntu-6.0-latest
71+
working_directory: ~/repo
72+
environment:
73+
ZABBIX_API: http://localhost:8080/
74+
ZABBIX_USER: Admin
75+
ZABBIX_DISPATCHER_MEDIA_TYPE: webhook
76+
steps:
77+
- integration_test_with_zabbix
78+
6379
circleci_is_disabled_job:
6480
docker:
6581
- image: cimg/base:stable
@@ -74,6 +90,7 @@ workflows:
7490
jobs:
7591
- integration_test_with_zabbix_32
7692
- integration_test_with_zabbix_40
93+
- integration_test_with_zabbix_60
7794
circleci_is_disabled:
7895
jobs:
7996
- circleci_is_disabled_job

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Change Log
22

3+
## 1.1.0
4+
5+
- Add webhook media_type for Zabbix 6.0 or higher
6+
37
## 1.0.0
48

59
- Drop python 2.7 support.

README.md

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,14 @@ This README explains how this integration works, and how to configure it.
66
![Internal construction of this pack](./images/internal_construction.png)
77

88
# Requirements
9+
## st2 pack
10+
* Zabbix >=3.0. It has been tested with v3.0, v3.2 and v4.0.
911

10-
* Zabbix >3.0. It has been tested with v3.0, v3.2 and v4.0.
12+
## script type distpacher
13+
* Zabbix >=3.0. It has been tested with v3.0, v3.2 and v4.0.
14+
15+
## webhook type dispatcher
16+
* Zabbix >=6.0. It has been tested with v6.0.
1117

1218
# Installation
1319
Install the pack:
@@ -34,6 +40,13 @@ Options:
3440
-s Z_SENDTO, --sendto=Z_SENDTO
3541
Address, user name or other identifier of the
3642
recipient
43+
-s Z_DISPATCHERTYPE, --type=Z_DISPATCHERTYPE
44+
Type of way to dispatch. If you select script,
45+
the Zabbix will use st2_dispatcher. On the
46+
other hand, if you select webhook, this command
47+
will import a webhook dispathcer mediatype which
48+
is defined in media_stackstorm.yml
49+
3750
```
3851
3952
Example execution:
@@ -58,9 +71,12 @@ After executing the `register_st2_config_to_zabbix.py` command, you can notice t
5871
You see following page, and you have to fill out with parameters for your st2 environment (the endpoint URLs of st2-api and st2-auth, and authentication information).
5972
![](./images/configuration_for_mediatype2.png)
6073
74+
If you setup webhook dispatcher, you see following page.
75+
![](./images/configuration_for_mediatype3.png)
76+
6177
You can specify additional parameters and you can handle them from the payload of the StackStorm's Trigger(`zabbix.event_handler`).
6278
63-
### Deploy the AlertScript
79+
### Deploy the AlertScript for script dispatcher
6480
6581
The script `st2_dispatch.py` sends Zabbix events to the StackStorm server. Copy this script to the directory which Zabbix MediaType refers to. The directory is specified by the parameter of `AlertScriptsPath` in the Zabbix configuration file on the node which zabbix was installed.
6682
```shell
@@ -253,6 +269,12 @@ Starting procedure to run the test is also simple, all you have to do is executi
253269
$ bundle exec rspec
254270
```
255271
272+
When you want to run test for webhook type, you have to execute following command.
273+
274+
```
275+
$ ZABBIX_DISPATCHER_MEDIA_TYPE=webhook bundle exec rspec
276+
```
277+
256278
# Advanced Usage
257279
If you would prefer to use an API Key for auth in place of user/pass, you can do so by passing a JSON Dict as the first positional argument in your `Media Type` in place of:
258280
```
@@ -277,6 +299,8 @@ This dict has the following valid keys
277299
`api_key` will cause `st2_userid` and `st2_passwd` to be ignored (API Key prefered)
278300
`trigger` allows you to specify your own trigger on st2 to send messages to. Default is `zabbix.event_handler`
279301
302+
> WARNING: webhook type dispatcher does NOT support user/pass auth, please use API Key.
303+
280304
### JSON Examples
281305
API Key for Auth - `{"api_url":"https://stackstorm.yourdomain.com/api/v1", "api_key":"aaabbbccc111222333"}`
282306
User/Pass for auth - `{"api_url":"https://stackstorm.yourdomain.com/api/v1", "auth_url":"https://stackstorm.yourdomain.com/auth", "st2_userid":"st2admin", "st2_passwd":"st2pass"}`
54.9 KB
Loading

media_stackstorm.yml

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
zabbix_export:
2+
version: '6.0'
3+
media_types:
4+
-
5+
name: StackStorm
6+
type: WEBHOOK
7+
description: StackStorm
8+
parameters:
9+
-
10+
name: alert_message
11+
value: '{ALERT.MESSAGE}'
12+
-
13+
name: alert_subject
14+
value: '{ALERT.SUBJECT}'
15+
-
16+
name: alert_sendto
17+
value: '{ALERT.SENDTO}'
18+
-
19+
name: event_source
20+
value: '{EVENT.SOURCE}'
21+
-
22+
name: st2_api_url
23+
value: '<PLACE ST2 API URL>'
24+
-
25+
name: st2_api_key
26+
value: '<PLACE ST2 API Key>'
27+
-
28+
name: st2_trigger
29+
value: zabbix.event_handler
30+
script: |
31+
var St2 = {
32+
params: {},
33+
34+
setParams: function (params) {
35+
if (typeof params !== 'object') {
36+
return;
37+
}
38+
St2.params = params;
39+
},
40+
41+
setProxy: function (HTTPProxy) {
42+
St2.HTTPProxy = HTTPProxy;
43+
},
44+
45+
urlCheckFormat: function (api_url) {
46+
if (typeof api_url === 'string' && !api_url.endsWith('/')) {
47+
api_url += '/';
48+
}
49+
50+
if (api_url.indexOf('http://') === -1 && api_url.indexOf('https://') === -1) {
51+
api_url = 'https://' + api_url;
52+
}
53+
54+
return api_url;
55+
},
56+
57+
request: function (api_url, data) {
58+
if (typeof St2.params !== 'object' || typeof St2.params['api_key'] === 'undefined' || St2.params['api_key'] === '') {
59+
throw 'Required St2 param is not set: "api_key".';
60+
}
61+
62+
var response,
63+
request = new HttpRequest();
64+
65+
request.addHeader('Content-Type: application/json');
66+
request.addHeader('St2-Api-Key: ' + St2.params.api_key);
67+
68+
const webhook_url = api_url + 'webhooks/st2';
69+
70+
if (typeof St2.HTTPProxy !== 'undefined' && St2.HTTPProxy !== '') {
71+
request.setProxy(St2.HTTPProxy);
72+
}
73+
74+
if (typeof data !== 'undefined') {
75+
data = JSON.stringify(data);
76+
}
77+
78+
Zabbix.log(4, '[ StackStorm Webhook ] Sending request: ' + webhook_url + ((typeof data === 'string')
79+
? ('\n' + data)
80+
: ''));
81+
82+
response = request.post(webhook_url, data);
83+
84+
Zabbix.log(4, '[ StackStorm Webhook ] Received response with status code ' +
85+
request.getStatus() + '\n' + response);
86+
87+
if (response !== null) {
88+
try {
89+
response = JSON.parse(response);
90+
}
91+
catch (error) {
92+
Zabbix.log(4, '[ StackStorm Webhook ] Failed to parse response received from StackStorm');
93+
response = null;
94+
}
95+
}
96+
97+
if (typeof response !== 'object') {
98+
throw 'Failed to process response received from StackStorm. Check debug log for more information.';
99+
}
100+
101+
if (request.getStatus() < 200 || request.getStatus() >= 300) {
102+
var message = 'Request failed with status code ' + request.getStatus();
103+
104+
if (response.message) {
105+
message += ': ' + response.message;
106+
}
107+
108+
throw message + ' Check debug log for more information.';
109+
}
110+
111+
return response;
112+
}
113+
};
114+
115+
try {
116+
var params = JSON.parse(value),
117+
st2 = {},
118+
data = {},
119+
result
120+
required_params = [
121+
'alert_subject', 'alert_message',
122+
'st2_api_url', 'st2_api_key', 'st2_trigger'
123+
];
124+
125+
Object.keys(params)
126+
.forEach(function (key) {
127+
if (key.startsWith('st2_')) {
128+
st2[key.substring(4)] = params[key];
129+
}
130+
else if (required_params.indexOf(key) !== -1 && params[key] === '') {
131+
throw 'Parameter "' + key + '" can\'t be empty.';
132+
}
133+
});
134+
135+
// Check type of event. Possible values: 0 - Trigger
136+
if (params.event_source != 0) {
137+
throw ('Incorrect "event_source" parameter given: ' + params.event_source
138+
+ '\nOnly trigger-based events are supported');
139+
}
140+
141+
// Check for backslash in the end of url and schema.
142+
st2.api_url = St2.urlCheckFormat(st2.api_url);
143+
144+
145+
data.trigger = st2.trigger;
146+
data.payload = {
147+
alert_sendto: params.alert_sendto,
148+
alert_subject: params.alert_subject,
149+
alert_message: params.alert_message
150+
}
151+
152+
St2.setParams(st2);
153+
St2.setProxy(params.HTTPProxy);
154+
155+
var response = St2.request(st2.api_url, data);
156+
157+
Zabbix.log(4, '[ StackStorm Webhook ] Response: ' + JSON.stringify(response));
158+
return JSON.stringify(response);
159+
}
160+
catch (error) {
161+
Zabbix.log(4, '[ StackStorm Webhook ] ERROR: ' + error);
162+
throw 'Sending failed: ' + error;
163+
}
164+
message_templates:
165+
-
166+
event_source: TRIGGERS
167+
operation_mode: PROBLEM
168+
subject: '[{TRIGGER.STATUS}] {TRIGGER.NAME}'
169+
message: |
170+
{
171+
"event": {
172+
"id": "{EVENT.ID}",
173+
"time": "{EVENT.TIME}"
174+
},
175+
"trigger": {
176+
"id": "{TRIGGER.ID}",
177+
"name": "{TRIGGER.NAME}",
178+
"status": "{TRIGGER.STATUS}"
179+
},
180+
"items": [
181+
{
182+
"name": "{ITEM.NAME1}",
183+
"host": "{HOST.NAME1}",
184+
"key": "{ITEM.KEY1}",
185+
"value": "{ITEM.VALUE1}"
186+
},
187+
{
188+
"name": "{ITEM.NAME2}",
189+
"host": "{HOST.NAME2}",
190+
"key": "{ITEM.KEY2}",
191+
"value": "{ITEM.VALUE2}"
192+
},
193+
{
194+
"name": "{ITEM.NAME3}",
195+
"host": "{HOST.NAME3}",
196+
"key": "{ITEM.KEY3}",
197+
"value": "{ITEM.VALUE3}"
198+
},
199+
{
200+
"name": "{ITEM.NAME4}",
201+
"host": "{HOST.NAME4}",
202+
"key": "{ITEM.KEY4}",
203+
"value": "{ITEM.VALUE4}"
204+
},
205+
{
206+
"name": "{ITEM.NAME5}",
207+
"host": "{HOST.NAME5}",
208+
"key": "{ITEM.KEY5}",
209+
"value": "{ITEM.VALUE5}"
210+
},
211+
{
212+
"name": "{ITEM.NAME6}",
213+
"host": "{HOST.NAME6}",
214+
"key": "{ITEM.KEY6}",
215+
"value": "{ITEM.VALUE6}"
216+
},
217+
{
218+
"name": "{ITEM.NAME7}",
219+
"host": "{HOST.NAME7}",
220+
"key": "{ITEM.KEY7}",
221+
"value": "{ITEM.VALUE7}"
222+
},
223+
{
224+
"name": "{ITEM.NAME8}",
225+
"host": "{HOST.NAME8}",
226+
"key": "{ITEM.KEY8}",
227+
"value": "{ITEM.VALUE8}"
228+
},
229+
{
230+
"name": "{ITEM.NAME9}",
231+
"host": "{HOST.NAME9}",
232+
"key": "{ITEM.KEY9}",
233+
"value": "{ITEM.VALUE9}"
234+
}
235+
]
236+
}

pack.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description: Zabbix Monitoring System
55
keywords:
66
- zabbix
77
- monitoring
8-
version: 1.0.0
8+
version: 1.1.0
99
author: Hiroyasu OHYAMA
1010
1111
python_versions:

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ py-zabbix==1.1.3
22
st2client
33
pytz
44
tzlocal
5+
pyyaml

spec/localhost/tools_register_config_for_st2_spec.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
ZABBIX_SENDTO = ENV['ZABBIX_SENDTO'] || 'admin'
66
ZABBIX_PASSWORD = ENV['ZABBIX_PASSWORD'] || 'zabbix'
77
ZABBIX_API_ENDPOINT = ENV['ZABBIX_API'] || 'http://localhost/'
8+
ZABBIX_DISPATCHER_MEDIA_TYPE = ENV['ZABBIX_DISPATCHER_MEDIA_TYPE'] || 'script'
89

910
describe 'Tests for registering Zabbix for StackStorm' do
1011
before(:all) do
@@ -18,7 +19,8 @@
1819
"-u #{ ZABBIX_USER } " \
1920
"-s #{ ZABBIX_SENDTO } " \
2021
"-p #{ ZABBIX_PASSWORD } " \
21-
"-z #{ ZABBIX_API_ENDPOINT }") do
22+
"-z #{ ZABBIX_API_ENDPOINT } " \
23+
"-t #{ ZABBIX_DISPATCHER_MEDIA_TYPE }") do
2224
its(:exit_status) { should eq 0 }
2325
its(:stdout) do
2426
should match /^Success to register the configurations for StackStorm to the Zabbix Server./
@@ -38,7 +40,7 @@
3840
# This method wait to start and initialize Zabbix-server and Zabbix-Web
3941
def try_to_login(retry_count = 0)
4042
begin
41-
return @client.login('admin', 'zabbix')
43+
return @client.login(ZABBIX_USER, ZABBIX_PASSWORD)
4244
rescue => e
4345
if retry_count < 60
4446
# make a delay before retrying

0 commit comments

Comments
 (0)