Skip to content

Instantly share code, notes, and snippets.

@spy86
Last active February 21, 2025 17:54
Show Gist options
  • Save spy86/1a084c5670b0029b10310ef307ff5543 to your computer and use it in GitHub Desktop.
Save spy86/1a084c5670b0029b10310ef307ff5543 to your computer and use it in GitHub Desktop.
zabbix_export:
version: '6.4'
media_types:
-
name: 'MS Teams Workflows'
type: WEBHOOK
parameters:
-
name: alert_message
value: '{ALERT.MESSAGE}'
-
name: alert_subject
value: '{ALERT.SUBJECT}'
-
name: event_date
value: '{EVENT.DATE}'
-
name: event_id
value: '{EVENT.ID}'
-
name: event_nseverity
value: '{EVENT.NSEVERITY}'
-
name: event_opdata
value: '{EVENT.OPDATA}'
-
name: event_recovery_date
value: '{EVENT.RECOVERY.DATE}'
-
name: event_recovery_time
value: '{EVENT.RECOVERY.TIME}'
-
name: event_severity
value: '{EVENT.SEVERITY}'
-
name: event_source
value: '{EVENT.SOURCE}'
-
name: event_status
value: '{EVENT.STATUS}'
-
name: event_tags
value: '{EVENT.TAGS}'
-
name: event_time
value: '{EVENT.TIME}'
-
name: event_update_action
value: '{EVENT.UPDATE.ACTION}'
-
name: event_update_date
value: '{EVENT.UPDATE.DATE}'
-
name: event_update_message
value: '{EVENT.UPDATE.MESSAGE}'
-
name: event_update_status
value: '{EVENT.UPDATE.STATUS}'
-
name: event_update_time
value: '{EVENT.UPDATE.TIME}'
-
name: event_update_user
value: '{USER.FULLNAME}'
-
name: event_value
value: '{EVENT.VALUE}'
-
name: host_ip
value: '{HOST.IP}'
-
name: host_name
value: '{HOST.NAME}'
-
name: teams_endpoint
value: '<PLACE WEBHOOK URL HERE>'
-
name: trigger_description
value: '{TRIGGER.DESCRIPTION}'
-
name: trigger_id
value: '{TRIGGER.ID}'
-
name: use_default_message
value: 'false'
-
name: zabbix_url
value: '{$ZABBIX.URL}'
status: DISABLED
script: |
var SEVERITY_COLORS = [
'emphasis', // Not classified.
'accent', // Information.
'warning', // Warning.
'warning', // Average.
'attention', // High.
'attention', // Disaster.
'good', // Resolved.
'default' // Default.
];
try {
var params = JSON.parse(value);
if (typeof params.teams_endpoint !== 'string' || params.teams_endpoint.trim() === '') {
throw 'Cannot get teams_endpoint';
}
else if (!params.teams_endpoint.startsWith('http')) {
throw 'Invalid MS Teams webhook URL: ' + params.teams_endpoint;
}
params.zabbix_url = (params.zabbix_url.endsWith('/'))
? params.zabbix_url.slice(0, -1) : params.zabbix_url;
if ([0, 1, 2, 3, 4].indexOf(parseInt(params.event_source)) === -1) {
throw 'Incorrect "event_source" parameter given: "' + params.event_source + '".\nMust be 0-4.';
}
// Set "use_default_message" to true for non trigger-based events.
if (params.event_source !== '0') {
params.use_default_message = 'true';
}
// Check {EVENT.VALUE} for trigger-based and internal events.
if (params.event_value !== '0' && params.event_value !== '1'
&& (params.event_source === '0' || params.event_source === '3')) {
throw 'Incorrect "event_value" parameter given: "' + params.event_value + '".\nMust be 0 or 1.';
}
// Check {EVENT.UPDATE.STATUS} only for trigger-based events.
if (params.event_update_status !== '0' && params.event_update_status !== '1' && params.event_source === '0') {
throw 'Incorrect "event_update_status" parameter given: "' + params.event_update_status + '".\nMust be 0 or 1.';
}
if (params.event_value == 0) {
params.event_nseverity = '6';
}
if (!SEVERITY_COLORS[params.event_nseverity]) {
params.event_nseverity = '7';
}
var request = new HttpRequest(),
factset = {
type: 'FactSet',
facts: []
}
adaptivecard = {
'$schema': 'http://adaptivecards.io/schemas/adaptive-card.json',
type: 'AdaptiveCard',
version: '1.4',
body: [
{
type: 'Container',
items: [
{
type: 'TextBlock',
size: 'Medium',
weight: 'Bolder',
text: params.alert_subject
}
],
style: SEVERITY_COLORS[params.event_nseverity],
bleed: true
},
{
type: 'RichTextBlock',
inlines: [
(params.use_default_message.toLowerCase() == 'true')
? params.alert_message
: params.trigger_description,
]
}
],
actions: [
{
type: 'Action.OpenUrl',
title: (params.event_source === '0')
? 'Event Info'
: 'Zabbix Home',
url: (params.event_source === '0')
? params.zabbix_url + '/tr_events.php?triggerid=' +
params.trigger_id + '&eventid=' + params.event_id
: params.zabbix_url
}
]
}
body = {
type: 'message',
attachments: [
{
contentType: 'application/vnd.microsoft.card.adaptive',
contentUrl: null,
}
]
};
if (params.use_default_message.toLowerCase() !== 'true') {
// Problem message.
if (params.event_value === '1' && params.event_update_status === '0') {
factset.facts.push({
title: 'Event time',
value: params.event_time + ' ' + params.event_date
});
factset.facts.push({
title: 'Host',
value: params.host_name + ' [' + params.host_ip + ']'
});
}
// Update message.
else if (params.event_update_status === '1') {
adaptivecard.body[1].text = params.event_update_user + ' ' + params.event_update_action + '.';
if (params.event_update_message) {
adaptivecard.body[1].text += '<br>Message:<br>' + params.event_update_message;
}
factset.facts.push({
title: 'Event update time',
value: params.event_update_time + ' ' + params.event_update_date
});
factset.facts.push({
title: 'Host',
value: params.host_name + ' [' + params.host_ip + ']'
});
}
// Resolved message.
else {
factset.facts.push({
title: 'Recovery time',
value: params.event_recovery_time + ' ' + params.event_recovery_date
});
factset.facts.push({
title: 'Host',
value: params.host_name + ' [' + params.host_ip + ']'
});
}
if (params.event_severity && params.event_severity !== '{EVENT.SEVERITY}') {
factset.facts.push({
title: 'Severity',
value: params.event_severity
});
}
if (params.event_opdata && params.event_opdata !== '{EVENT.OPDATA}') {
factset.facts.push({
title: 'Operational data',
value: params.event_opdata
});
}
if (params.event_tags && params.event_tags !== '{EVENT.TAGS}') {
factset.facts.push({
title: 'Event tags',
value: params.event_tags
});
}
Object.keys(params)
.forEach(function (key) {
if (key.startsWith('fact_') && params[key] !== '') {
factset.facts.push({
title: key.substring(5),
value: params[key]
});
}
else if (key.startsWith('openUri_') && params[key] !== '' && !params[key].startsWith('{')) {
adaptivecard.actions.push({
type: 'Action.OpenUrl',
title: key.substring(8),
url: params[key]
});
}
});
adaptivecard.body.push(factset);
}
body.attachments[0].content = adaptivecard;
request.addHeader('Content-Type: application/json');
if (typeof params.HTTPProxy === 'string' && params.HTTPProxy !== '') {
request.setProxy(params.HTTPProxy);
}
Zabbix.log(4, '[ MS Teams Webhook ] JSON: ' + JSON.stringify(body));
var response = request.post(params.teams_endpoint, JSON.stringify(body));
Zabbix.log(4, '[ MS Teams Webhook ] Response: ' + response);
var responsecode = request.getStatus();
if (responsecode === 202) {
return 'OK';
}
else {
Zabbix.log(4, '[ MS Teams Webhook ] FAILED with response code: ' + responsecode);
throw 'Response code: ' + responsecode;
}
}
catch (error) {
Zabbix.log(3, '[ MS Teams Webhook ] ERROR: ' + error);
throw 'Sending failed: ' + error;
}
message_templates:
-
event_source: TRIGGERS
operation_mode: PROBLEM
subject: 'Problem: {EVENT.NAME}'
message: |
Problem started at {EVENT.TIME} on {EVENT.DATE}
Problem name: {EVENT.NAME}
Host: {HOST.NAME}
Severity: {EVENT.SEVERITY}
Operational data: {EVENT.OPDATA}
Original problem ID: {EVENT.ID}
{TRIGGER.URL}
-
event_source: TRIGGERS
operation_mode: RECOVERY
subject: 'Resolved: {EVENT.NAME}'
message: |
Problem has been resolved in {EVENT.DURATION} at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
Problem name: {EVENT.NAME}
Host: {HOST.NAME}
Severity: {EVENT.SEVERITY}
Original problem ID: {EVENT.ID}
{TRIGGER.URL}
-
event_source: TRIGGERS
operation_mode: UPDATE
subject: 'Updated problem: {EVENT.NAME}'
message: |
{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
{EVENT.UPDATE.MESSAGE}
Current problem status is {EVENT.STATUS}, acknowledged: {EVENT.ACK.STATUS}.
-
event_source: DISCOVERY
operation_mode: PROBLEM
subject: 'Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}'
message: |
Discovery rule: {DISCOVERY.RULE.NAME}
Device IP: {DISCOVERY.DEVICE.IPADDRESS}
Device DNS: {DISCOVERY.DEVICE.DNS}
Device status: {DISCOVERY.DEVICE.STATUS}
Device uptime: {DISCOVERY.DEVICE.UPTIME}
Device service name: {DISCOVERY.SERVICE.NAME}
Device service port: {DISCOVERY.SERVICE.PORT}
Device service status: {DISCOVERY.SERVICE.STATUS}
Device service uptime: {DISCOVERY.SERVICE.UPTIME}
-
event_source: AUTOREGISTRATION
operation_mode: PROBLEM
subject: 'Autoregistration: {HOST.HOST}'
message: |
Host name: {HOST.HOST}
Host IP: {HOST.IP}
Agent port: {HOST.PORT}
-
event_source: SERVICE
operation_mode: PROBLEM
subject: 'Service "{SERVICE.NAME}" problem: {EVENT.NAME}'
message: |
Service problem started at {EVENT.TIME} on {EVENT.DATE}
Service problem name: {EVENT.NAME}
Service: {SERVICE.NAME}
Severity: {EVENT.SEVERITY}
Original problem ID: {EVENT.ID}
Service description: {SERVICE.DESCRIPTION}
{SERVICE.ROOTCAUSE}
-
event_source: SERVICE
operation_mode: RECOVERY
subject: 'Service "{SERVICE.NAME}" resolved in {EVENT.DURATION}: {EVENT.NAME}'
message: |
Service "{SERVICE.NAME}" has been resolved at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
Problem name: {EVENT.NAME}
Problem duration: {EVENT.DURATION}
Severity: {EVENT.SEVERITY}
Original problem ID: {EVENT.ID}
Service description: {SERVICE.DESCRIPTION}
-
event_source: SERVICE
operation_mode: UPDATE
subject: 'Changed "{SERVICE.NAME}" service status to {EVENT.UPDATE.SEVERITY} in {EVENT.AGE}'
message: |
Changed "{SERVICE.NAME}" service status to {EVENT.UPDATE.SEVERITY} at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
Current problem age is {EVENT.AGE}.
Service description: {SERVICE.DESCRIPTION}
{SERVICE.ROOTCAUSE}
@may7cry8
Copy link

Hi,
Does this code allow you to have the problem title in the notification header instead of "Card"?
Thanks

@spy86
Copy link
Author

spy86 commented Feb 21, 2025

This code does not allow the issue title to be placed in the notification header instead of "Card"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment