diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md
new file mode 100644
index 0000000..d02cfc4
--- /dev/null
+++ b/ARCHITECTURE.md
@@ -0,0 +1,63 @@
+# Zabbix PostgreSQL Partitioning Architecture
+
+This document provides a brief technical overview of the components, logic, and dynamic querying mechanisms that power the PostgreSQL partitioning solution for Zabbix.
+
+## Schema-Agnostic Design
+
+A core architectural principle of this solution is its **schema-agnostic design**. It does not assume that your Zabbix database is installed in the default `public` schema.
+
+When the procedures need to create, drop, or manipulate a partitioned table (e.g., `history`), they do not hardcode the schema. Instead, they dynamically query PostgreSQL's internal system catalogs (`pg_class` and `pg_namespace`) to locate exactly which schema the target table belongs to:
+
+```sql
+SELECT n.nspname INTO v_schema
+FROM pg_class c
+JOIN pg_namespace n ON n.oid = c.relnamespace
+WHERE c.relname = v_table;
+```
+
+This ensures that the partitioning scripts will work flawlessly, even in custom Zabbix deployments where tables are housed in alternative schemas.
+
+## File Structure & Queries
+
+The solution is divided into a series of SQL scripts that must be executed sequentially to set up the environment.
+
+### 1. `00_partitions_init.sql`
+* **Purpose:** Initializes the foundation for the partitioning system.
+* **Actions:**
+ * Creates the isolated `partitions` schema to keep everything separate from Zabbix's own structure.
+ * Creates the `partitions.config` table (which stores retention policies).
+ * Creates the `partitions.version` table for tracking the installed version.
+
+### 2. `01_auditlog_prep.sql`
+* **Purpose:** Prepares the Zabbix `auditlog` table for partitioning.
+* **Actions:**
+ * PostgreSQL range partitioning requires the partition key (in this case, `clock`) to be part of the Primary Key.
+ * This script dynamically locates the existing Primary Key (usually just `auditid`) and alters it to a composite key `(auditid, clock)`.
+
+### 3. `02_maintenance.sql`
+* **Purpose:** Contains the core PL/pgSQL procedural logic that manages the lifecycle of the partitions.
+* **Key Functions/Procedures:**
+ * `partition_exists()`: Queries `pg_class` to verify if a specific child partition partition exists.
+ * `create_partition()`: Executes the DDL `CREATE TABLE ... PARTITION OF ... FOR VALUES FROM (x) TO (y)` to generate a new time-bound chunk.
+ * `drop_old_partitions()`: Iterates over existing child partitions (using `pg_inherits`) and calculates their age based on their suffix. Drops those older than the defined `keep_history` policy.
+ * `maintain_table()`: The orchestrator for a single table. It calculates the necessary UTC timestamps, calls `create_partition()` to build the future buffer, calls `create_partition()` recursively backward to cover the retention period, and finally calls `drop_old_partitions()`.
+ * `run_maintenance()`: The global loop that iterates through `partitions.config` and triggers `maintain_table()` for every configured Zabbix table.
+
+### 4. `03_enable_partitioning.sql`
+* **Purpose:** The migration script that actually executes the partition conversion on the live database.
+* **Actions:**
+ * It takes the original Zabbix table (e.g., `history`) and renames it to `history_old` (`ALTER TABLE ... RENAME TO ...`).
+ * It immediately creates a new partitioned table with the original name, inheriting the exact structure of the old table (`CREATE TABLE ... (LIKE ... INCLUDING ALL) PARTITION BY RANGE (clock)`).
+ * It triggers the first maintenance run so new incoming data has immediate partitions to land in.
+
+### 5. `04_monitoring_view.sql`
+* **Purpose:** Provides an easy-to-read observability layer.
+* **Actions:**
+ * Creates the `partitions.monitoring` view by joining `pg_class`, `pg_inherits`, `pg_tablespace`, and `pg_size_pretty`.
+ * This view aggregates the total size of each partitioned family and calculates how many "future partitions" exist as a safety buffer.
+
+## Automated Scheduling (`pg_cron`)
+
+While `systemd` timers or standard `cron` can be used to trigger the maintenance, the recommended approach (especially for AWS RDS/Aurora deployments) is using the `pg_cron` database extension.
+
+`pg_cron` allows you to schedule the `CALL partitions.run_maintenance();` procedure directly within PostgreSQL, ensuring the database autonomously manages its own housekeeping without requiring external OS-level access or triggers.
diff --git a/postgresql/docker/init_scripts/01_30_maintenance.sql b/postgresql/docker/init_scripts/01_30_maintenance.sql
index 2e2008f..9d47026 100644
--- a/postgresql/docker/init_scripts/01_30_maintenance.sql
+++ b/postgresql/docker/init_scripts/01_30_maintenance.sql
@@ -11,7 +11,6 @@ BEGIN
SELECT 1 FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname = p_partition_name
- AND n.nspname = 'public'
);
END;
$$ LANGUAGE plpgsql;
@@ -28,7 +27,17 @@ DECLARE
v_start_ts bigint;
v_end_ts bigint;
v_suffix text;
+ v_parent_schema text;
BEGIN
+ -- Determine the schema of the parent table
+ SELECT n.nspname INTO v_parent_schema
+ FROM pg_class c
+ JOIN pg_namespace n ON n.oid = c.relnamespace
+ WHERE c.relname = p_parent_table;
+
+ IF NOT FOUND THEN
+ RAISE EXCEPTION 'Parent table % not found', p_parent_table;
+ END IF;
-- (No changes needed for time here as passed params are already UTC-adjusted in caller)
v_start_ts := extract(epoch from p_start_time)::bigint;
v_end_ts := extract(epoch from p_end_time)::bigint;
@@ -43,8 +52,8 @@ BEGIN
IF NOT partitions.partition_exists(v_partition_name) THEN
EXECUTE format(
- 'CREATE TABLE public.%I PARTITION OF public.%I FOR VALUES FROM (%s) TO (%s)',
- v_partition_name, p_parent_table, v_start_ts, v_end_ts
+ 'CREATE TABLE %I.%I PARTITION OF %I.%I FOR VALUES FROM (%s) TO (%s)',
+ v_parent_schema, v_partition_name, v_parent_schema, p_parent_table, v_start_ts, v_end_ts
);
END IF;
END;
@@ -61,16 +70,19 @@ DECLARE
v_partition record;
v_partition_date timestamp with time zone;
v_suffix text;
+ v_partition_schema text;
BEGIN
-- Calculate cutoff timestamp
v_cutoff_ts := extract(epoch from (now() - p_retention))::bigint;
FOR v_partition IN
SELECT
- child.relname AS partition_name
+ child.relname AS partition_name,
+ n.nspname AS partition_schema
FROM pg_inherits
JOIN pg_class parent ON pg_inherits.inhparent = parent.oid
JOIN pg_class child ON pg_inherits.inhrelid = child.oid
+ JOIN pg_namespace n ON child.relnamespace = n.oid
WHERE parent.relname = p_parent_table
LOOP
-- Parse partition suffix to determine age
@@ -85,14 +97,14 @@ BEGIN
-- To be safe, adding 1 month to check vs cutoff.
IF extract(epoch from (v_partition_date + '1 month'::interval)) < v_cutoff_ts THEN
RAISE NOTICE 'Dropping old partition %', v_partition.partition_name;
- EXECUTE format('DROP TABLE public.%I', v_partition.partition_name);
+ EXECUTE format('DROP TABLE %I.%I', v_partition.partition_schema, v_partition.partition_name);
COMMIT; -- Release lock immediately
END IF;
ELSIF length(v_suffix) = 8 THEN -- YYYYMMDD
v_partition_date := to_timestamp(v_suffix, 'YYYYMMDD') AT TIME ZONE 'UTC';
IF extract(epoch from (v_partition_date + '1 day'::interval)) < v_cutoff_ts THEN
RAISE NOTICE 'Dropping old partition %', v_partition.partition_name;
- EXECUTE format('DROP TABLE public.%I', v_partition.partition_name);
+ EXECUTE format('DROP TABLE %I.%I', v_partition.partition_schema, v_partition.partition_name);
COMMIT; -- Release lock immediately
END IF;
END IF;
diff --git a/postgresql/docker/init_scripts/01_40_enable.sql b/postgresql/docker/init_scripts/01_40_enable.sql
index cd6147b..42570fe 100644
--- a/postgresql/docker/init_scripts/01_40_enable.sql
+++ b/postgresql/docker/init_scripts/01_40_enable.sql
@@ -10,27 +10,35 @@ DECLARE
v_table text;
v_old_table text;
v_pk_sql text;
+ v_schema text;
BEGIN
FOR v_row IN SELECT * FROM partitions.config LOOP
v_table := v_row.table_name;
v_old_table := v_table || '_old';
+ -- Determine schema
+ SELECT n.nspname INTO v_schema
+ FROM pg_class c
+ JOIN pg_namespace n ON n.oid = c.relnamespace
+ WHERE c.relname = v_table;
+
+
-- Check if table exists and is NOT already partitioned
IF EXISTS (SELECT 1 FROM pg_class WHERE relname = v_table AND relkind = 'r') THEN
RAISE NOTICE 'Converting table % to partitioned table...', v_table;
-- 1. Rename existing table
- EXECUTE format('ALTER TABLE public.%I RENAME TO %I', v_table, v_old_table);
+ EXECUTE format('ALTER TABLE %I.%I RENAME TO %I', v_schema, v_table, v_old_table);
-- 2. Create new partitioned table (copying structure)
- EXECUTE format('CREATE TABLE public.%I (LIKE public.%I INCLUDING ALL) PARTITION BY RANGE (clock)', v_table, v_old_table);
+ EXECUTE format('CREATE TABLE %I.%I (LIKE %I.%I INCLUDING ALL) PARTITION BY RANGE (clock)', v_schema, v_table, v_schema, v_old_table);
-- 3. Create initial partitions
RAISE NOTICE 'Creating initial partitions for %...', v_table;
CALL partitions.maintain_table(v_table, v_row.period, v_row.keep_history, v_row.future_partitions);
-- Optional: Migrate existing data
- -- EXECUTE format('INSERT INTO public.%I SELECT * FROM public.%I', v_table, v_old_table);
+ -- EXECUTE format('INSERT INTO %I.%I SELECT * FROM %I.%I', v_schema, v_table, v_schema, v_old_table);
ELSIF EXISTS (SELECT 1 FROM pg_class WHERE relname = v_table AND relkind = 'p') THEN
RAISE NOTICE 'Table % is already partitioned. Skipping conversion.', v_table;
diff --git a/postgresql/procedures/02_maintenance.sql b/postgresql/procedures/02_maintenance.sql
index 2e2008f..9d47026 100644
--- a/postgresql/procedures/02_maintenance.sql
+++ b/postgresql/procedures/02_maintenance.sql
@@ -11,7 +11,6 @@ BEGIN
SELECT 1 FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname = p_partition_name
- AND n.nspname = 'public'
);
END;
$$ LANGUAGE plpgsql;
@@ -28,7 +27,17 @@ DECLARE
v_start_ts bigint;
v_end_ts bigint;
v_suffix text;
+ v_parent_schema text;
BEGIN
+ -- Determine the schema of the parent table
+ SELECT n.nspname INTO v_parent_schema
+ FROM pg_class c
+ JOIN pg_namespace n ON n.oid = c.relnamespace
+ WHERE c.relname = p_parent_table;
+
+ IF NOT FOUND THEN
+ RAISE EXCEPTION 'Parent table % not found', p_parent_table;
+ END IF;
-- (No changes needed for time here as passed params are already UTC-adjusted in caller)
v_start_ts := extract(epoch from p_start_time)::bigint;
v_end_ts := extract(epoch from p_end_time)::bigint;
@@ -43,8 +52,8 @@ BEGIN
IF NOT partitions.partition_exists(v_partition_name) THEN
EXECUTE format(
- 'CREATE TABLE public.%I PARTITION OF public.%I FOR VALUES FROM (%s) TO (%s)',
- v_partition_name, p_parent_table, v_start_ts, v_end_ts
+ 'CREATE TABLE %I.%I PARTITION OF %I.%I FOR VALUES FROM (%s) TO (%s)',
+ v_parent_schema, v_partition_name, v_parent_schema, p_parent_table, v_start_ts, v_end_ts
);
END IF;
END;
@@ -61,16 +70,19 @@ DECLARE
v_partition record;
v_partition_date timestamp with time zone;
v_suffix text;
+ v_partition_schema text;
BEGIN
-- Calculate cutoff timestamp
v_cutoff_ts := extract(epoch from (now() - p_retention))::bigint;
FOR v_partition IN
SELECT
- child.relname AS partition_name
+ child.relname AS partition_name,
+ n.nspname AS partition_schema
FROM pg_inherits
JOIN pg_class parent ON pg_inherits.inhparent = parent.oid
JOIN pg_class child ON pg_inherits.inhrelid = child.oid
+ JOIN pg_namespace n ON child.relnamespace = n.oid
WHERE parent.relname = p_parent_table
LOOP
-- Parse partition suffix to determine age
@@ -85,14 +97,14 @@ BEGIN
-- To be safe, adding 1 month to check vs cutoff.
IF extract(epoch from (v_partition_date + '1 month'::interval)) < v_cutoff_ts THEN
RAISE NOTICE 'Dropping old partition %', v_partition.partition_name;
- EXECUTE format('DROP TABLE public.%I', v_partition.partition_name);
+ EXECUTE format('DROP TABLE %I.%I', v_partition.partition_schema, v_partition.partition_name);
COMMIT; -- Release lock immediately
END IF;
ELSIF length(v_suffix) = 8 THEN -- YYYYMMDD
v_partition_date := to_timestamp(v_suffix, 'YYYYMMDD') AT TIME ZONE 'UTC';
IF extract(epoch from (v_partition_date + '1 day'::interval)) < v_cutoff_ts THEN
RAISE NOTICE 'Dropping old partition %', v_partition.partition_name;
- EXECUTE format('DROP TABLE public.%I', v_partition.partition_name);
+ EXECUTE format('DROP TABLE %I.%I', v_partition.partition_schema, v_partition.partition_name);
COMMIT; -- Release lock immediately
END IF;
END IF;
diff --git a/postgresql/procedures/03_enable_partitioning.sql b/postgresql/procedures/03_enable_partitioning.sql
index cd6147b..42570fe 100644
--- a/postgresql/procedures/03_enable_partitioning.sql
+++ b/postgresql/procedures/03_enable_partitioning.sql
@@ -10,27 +10,35 @@ DECLARE
v_table text;
v_old_table text;
v_pk_sql text;
+ v_schema text;
BEGIN
FOR v_row IN SELECT * FROM partitions.config LOOP
v_table := v_row.table_name;
v_old_table := v_table || '_old';
+ -- Determine schema
+ SELECT n.nspname INTO v_schema
+ FROM pg_class c
+ JOIN pg_namespace n ON n.oid = c.relnamespace
+ WHERE c.relname = v_table;
+
+
-- Check if table exists and is NOT already partitioned
IF EXISTS (SELECT 1 FROM pg_class WHERE relname = v_table AND relkind = 'r') THEN
RAISE NOTICE 'Converting table % to partitioned table...', v_table;
-- 1. Rename existing table
- EXECUTE format('ALTER TABLE public.%I RENAME TO %I', v_table, v_old_table);
+ EXECUTE format('ALTER TABLE %I.%I RENAME TO %I', v_schema, v_table, v_old_table);
-- 2. Create new partitioned table (copying structure)
- EXECUTE format('CREATE TABLE public.%I (LIKE public.%I INCLUDING ALL) PARTITION BY RANGE (clock)', v_table, v_old_table);
+ EXECUTE format('CREATE TABLE %I.%I (LIKE %I.%I INCLUDING ALL) PARTITION BY RANGE (clock)', v_schema, v_table, v_schema, v_old_table);
-- 3. Create initial partitions
RAISE NOTICE 'Creating initial partitions for %...', v_table;
CALL partitions.maintain_table(v_table, v_row.period, v_row.keep_history, v_row.future_partitions);
-- Optional: Migrate existing data
- -- EXECUTE format('INSERT INTO public.%I SELECT * FROM public.%I', v_table, v_old_table);
+ -- EXECUTE format('INSERT INTO %I.%I SELECT * FROM %I.%I', v_schema, v_table, v_schema, v_old_table);
ELSIF EXISTS (SELECT 1 FROM pg_class WHERE relname = v_table AND relkind = 'p') THEN
RAISE NOTICE 'Table % is already partitioned. Skipping conversion.', v_table;
diff --git a/postgresql/sql-scripts-80/data.sql b/postgresql/sql-scripts-80/data.sql
new file mode 100644
index 0000000..deb0e2b
--- /dev/null
+++ b/postgresql/sql-scripts-80/data.sql
@@ -0,0 +1,319788 @@
+START TRANSACTION;
+INSERT INTO role (roleid,name,type,readonly) VALUES ('1','User role','1','0'),
+('2','Admin role','2','0'),
+('3','Super admin role','3','1'),
+('4','Guest role','1','0');
+INSERT INTO ugset (ugsetid,hash) VALUES ('1','b21d61561974b06cbeb97a71ca880e92f0fc06d49ac3246280afb88dfa6050a6');
+INSERT INTO users (userid,username,name,surname,passwd,url,autologin,autologout,refresh,rows_per_page,roleid) VALUES ('1','Admin','Zabbix','Administrator','$2y$10$92nDno4n0Zm7Ej7Jfsz8WukBfgSS/U0QkIuu8WkJPihXBb2A1UrEK','','1','0','30s','50','3'),
+('2','guest','','','$2y$10$89otZrRNmde97rIyzclecuk6LwKAsHN0BcvoOKGjbT.BwMBfm7G06','','0','15m','30s','50','4');
+INSERT INTO hstgrp (groupid,name,flags,uuid,type) VALUES ('1','Templates','0','7df96b18c230490a9a0a9e2307226338','1'),
+('2','Linux servers','0','dc579cd7a1a34222933f24f52a68bcd8','0'),
+('4','Zabbix servers','0','6f6799aa69e844b4b3918f779f2abf08','0'),
+('5','Discovered hosts','0','f2481361f99448eea617b7b1d4765566','0'),
+('6','Virtual machines','0','137f19e6e2dc4219b33553b812627bc2','0'),
+('7','Hypervisors','0','1b837a3c078647049a0c00c61b4d57b5','0'),
+('9','Templates/Network devices','0','36bff6c29af64692839d077febfc7079','1'),
+('10','Templates/Operating systems','0','846977d1dfed4968bc5f8bdb363285bc','1'),
+('11','Templates/Server hardware','0','e960332b3f6c46a1956486d4f3f99fce','1'),
+('12','Templates/Applications','0','a571c0d144b14fd4a87a9d9b2aa9fcd6','1'),
+('13','Templates/Databases','0','748ad4d098d447d492bb935c907f652f','1'),
+('14','Templates/Virtualization','0','02e4df4f20b848e79267641790f241da','1'),
+('15','Templates/Telephony','0','1d12408342854fd5a4436dd6d5d1bd4a','1'),
+('16','Templates/SAN','0','7c2cb727f85b492d88cd56e17127c64d','1'),
+('17','Templates/Video surveillance','0','d37f71c7e3f7469bab645852a69a2018','1'),
+('18','Templates/Power','0','3dcd5bbe90534f9e8eb5c2d53756af63','1'),
+('19','Applications','0','a571c0d144b14fd4a87a9d9b2aa9fcd6','0'),
+('20','Databases','0','748ad4d098d447d492bb935c907f652f','0'),
+('21','Templates/Cloud','0','c2c162144c2d4c5491c8801193af4945','1');
+INSERT INTO drules (druleid,proxyid,name,iprange,delay,status,concurrency_max) VALUES ('2',NULL,'Local network','192.168.0.1-254','1h','1','0');
+INSERT INTO dchecks (dcheckid,druleid,type,key_,snmp_community,ports,snmpv3_securityname,snmpv3_securitylevel,snmpv3_authpassphrase,snmpv3_privpassphrase,uniq,snmpv3_authprotocol,snmpv3_privprotocol,snmpv3_contextname,host_source,name_source,allow_redirect) VALUES ('2','2','9','system.uname','','10050','','0','','','0','0','0','','1','0','0');
+INSERT INTO media_type (mediatypeid,type,name,smtp_server,smtp_helo,smtp_email,exec_path,gsm_modem,username,passwd,smtp_port,smtp_security,smtp_verify_peer,smtp_verify_host,smtp_authentication,maxsessions,maxattempts,attempt_interval,message_format,script,timeout,process_tags,show_event_menu,event_menu_url,event_menu_name,description,provider) VALUES ('1','0','Email','mail.example.com','example.com','zabbix@example.com','','','','','25','0','0','0','0','1','3','10s','0','','30s','0','0','','','','0'),
+('3','2','SMS','','','','','/dev/ttyS0','','','25','0','0','0','0','1','3','10s','1','','30s','0','0','','','','0'),
+('4','0','Email (HTML)','mail.example.com','example.com','zabbix@example.com','','','','','25','0','0','0','0','1','3','10s','1','','30s','0','0','','','','0'),
+('34','0','Gmail','smtp.gmail.com','example.com','zabbix@example.com','','','','','587','1','0','0','1','1','3','10s','1','','30s','0','0','','','','1'),
+('35','0','Gmail relay','smtp-relay.gmail.com','example.com','zabbix@example.com','','','','','587','1','0','0','0','1','3','10s','1','','30s','0','0','','','','2'),
+('36','0','Office365','smtp.office365.com','example.com','zabbix@example.com','','','','','587','1','0','0','1','1','3','10s','1','','30s','0','0','','','','3'),
+('37','0','Office365 relay','example-com.mail.protection.outlook.com','example.com','zabbix@example.com','','','','','25','1','0','0','0','1','3','10s','1','','30s','0','0','','','','4'),
+('70','4','Brevis.one','','','','','','','','25','0','0','0','0','1','3','10s','1',E'var BrevisOne = {
+ params: [],
+
+ addParam: function (name, value) {
+ BrevisOne.params.push(name + ''='' + encodeURIComponent(value));
+ },
+
+ setProxy: function (HTTPProxy) {
+ BrevisOne.HTTPProxy = HTTPProxy;
+ },
+
+ setPayload: function (params) {
+ var parts = params.send_to.split('':''),
+ defaultValues = {
+ ring: ''true'',
+ flash: ''true'',
+ telauto: ''false''
+ };
+
+ BrevisOne.addParam(''username'', params.username);
+ BrevisOne.addParam(''password'', params.password);
+ BrevisOne.addParam(''text'', params.text);
+
+ if (parts.length > 1) {
+ BrevisOne.addParam(''mode'', parts[0]);
+ BrevisOne.addParam(''to'', parts[1]);
+ }
+ else {
+ BrevisOne.addParam(''to'', parts[0]);
+ }
+
+ Object.keys(defaultValues)
+ .forEach(function (key) {
+ if (params[key] && params[key].trim() && params[key].toLowerCase() === defaultValues[key]) {
+ BrevisOne.addParam(key, defaultValues[key]);
+ }
+ });
+ },
+
+ request: function () {
+ var response,
+ request = new HttpRequest(),
+ data = ''?'' + BrevisOne.params.join(''&'');
+
+ request.addHeader(''Content-Type: multipart/form-data'');
+
+ if (typeof BrevisOne.HTTPProxy !== ''undefined'' && BrevisOne.HTTPProxy !== '''') {
+ request.setProxy(BrevisOne.HTTPProxy);
+ }
+
+ Zabbix.log(4, ''[ BrevisOne Webhook ] Sending request.'');
+
+ response = request.post(params.endpoint + data);
+
+ Zabbix.log(4, ''[ BrevisOne Webhook ] Received response with status code '' +
+ request.getStatus() + ''\\n'' + response);
+
+ if (request.getStatus() < 200 || request.getStatus() >= 300) {
+ var message = ''Request failed with status code '' + request.getStatus();
+
+ if (response) {
+ message += '': '' + response;
+ }
+
+ throw message + ''. Check debug log for more information.'';
+ }
+ }
+};
+
+try {
+ var params = JSON.parse(value);
+
+ [''endpoint'', ''password'', ''username'', ''text'', ''send_to''].forEach(function (field) {
+ if (typeof params !== ''object'' || typeof params[field] === ''undefined''
+ || !params[field].trim()) {
+ throw ''Required parameter is not set: "'' + field + ''".'';
+ }
+ });
+
+ if (params.send_to === ''{ALERT.SENDTO}'') {
+ throw ''Required parameter is not set: "send_to".'';
+ }
+
+ BrevisOne.setProxy(params.HTTPProxy);
+ BrevisOne.setPayload(params);
+ BrevisOne.request();
+
+ return ''OK'';
+}
+catch (error) {
+ Zabbix.log(3, ''[ BrevisOne Webhook ] ERROR: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','0','0','','','','0'),
+('71','4','Discord','','','','','','','','25','0','0','0','0','1','3','10s','1',E'const CLogger = function(serviceName) {
+ this.serviceName = serviceName;
+ this.INFO = 4
+ this.WARN = 3
+ this.ERROR = 2
+ this.log = function(level, msg) {
+ Zabbix.log(level, ''['' + this.serviceName + ''] '' + msg);
+ }
+}
+
+const CWebhook = function(value) {
+ try {
+ params = JSON.parse(value);
+
+ if ([''0'', ''1'', ''2'', ''3'', ''4''].indexOf(params.event_source) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''.\\nMust be 0-4.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1 && [''0'', ''1''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0 or 1.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1) {
+ if (params.event_source === ''1'' && [''0'', ''1'', ''2'', ''3''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0-3.'';
+ }
+
+ if (params.event_source === ''0'' && [''0'', ''1''].indexOf(params.event_update_status) === -1) {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''.\\nMust be 0 or 1.'';
+ }
+
+ if (params.event_source === ''4'') {
+ if ([''0'', ''1'', ''2'', ''3'', ''4'', ''5''].indexOf(params.event_update_nseverity) !== -1 && params.event_update_nseverity != params.event_nseverity) {
+ params.event_nseverity = params.event_update_nseverity;
+ params.event_severity = params.event_update_severity;
+ params.event_update_status = ''1'';
+ }
+ }
+ }
+
+ this.runCallback = function(name, params) {
+ if (typeof this[name] === ''function'') {
+ return this[name].apply(this, [params]);
+ }
+ }
+
+ this.handleEvent = function(source, event) {
+ const alert = { source: source, event: event };
+ return [
+ this.runCallback(''on'' + source + event, alert),
+ this.runCallback(''on'' + event, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.handleEventless = function(source) {
+ const alert = { source: source, event: null };
+ return [
+ this.runCallback(''on'' + source, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.run = function() {
+ var results = [];
+ if (typeof this.httpProxy === ''string'' && this.httpProxy.trim() !== '''') {
+ this.request.setProxy(this.httpProxy);
+ }
+ const types = { ''0'': ''Trigger'', ''1'': ''Discovery'', ''2'': ''Autoreg'', ''3'': ''Internal'', ''4'': ''Service'' };
+
+ if ([''0'', ''3'', ''4''].indexOf(this.params.event_source) !== -1) {
+ var event = (this.params.event_update_status === ''1'')
+ ? ''Update''
+ : ((this.params.event_value === ''1'') ? ''Problem'' : ''Resolve'');
+
+ results = this.handleEvent(types[this.params.event_source], event);
+ }
+ else if (typeof types[this.params.event_source] !== ''undefined'') {
+ results = this.handleEventless(types[this.params.event_source]);
+ }
+ else {
+ throw ''Unexpected "event_source": '' + this.params.event_source;
+ }
+
+ for (idx in results) {
+ if (typeof results[idx] !== ''undefined'') {
+ return JSON.stringify(results[idx]);
+ }
+ }
+ }
+ this.httpProxy = params.http_proxy;
+ this.params = params;
+ this.runCallback(''onCheckParams'', {});
+ } catch (error) {
+ throw ''Webhook processing failed: '' + error;
+ }
+}
+
+const CParamValidator = {
+
+ isType: function(value, type) {
+ if (type === ''array'') {
+ return Array.isArray(value);
+ }
+ if (type === ''integer'') {
+ return CParamValidator.isInteger(value);
+ }
+ if (type === ''float'') {
+ return CParamValidator.isFloat(value);
+ }
+
+ return (typeof value === type);
+ },
+
+ isInteger: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseInt(value));
+ },
+
+ isFloat: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+\\.\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseFloat(value));
+ },
+
+ isDefined: function(value) {
+ return !CParamValidator.isType(value, ''undefined'');
+ },
+
+ isEmpty: function(value) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be checked for emptiness.'';
+ }
+
+ return (value.trim() === '''');
+ },
+
+ isMacroSet: function(value, macro) {
+ if (CParamValidator.isDefined(macro)) {
+ return !(CParamValidator.ifMatch(value, ''^\\{'' + macro + ''\\}$''))
+ }
+
+ return !(CParamValidator.ifMatch(value, ''^\\{[$#]{0,1}[A-Z_\\.]+[\\:]{0,1}["]{0,1}.*["]{0,1}\\}$'') || value === ''*UNKNOWN*'')
+ },
+
+ withinRange: function(value, min, max) {
+ if (!CParamValidator.isType(value, ''number'')) {
+ throw ''Value "'' + value + ''" must be a number to be checked for range.'';
+ }
+ if (value < ((CParamValidator.isDefined(min)) ? min : value)
+ || value > ((CParamValidator.isDefined(max)) ? max : value)) {
+ return false;
+ }
+
+ return true;
+ },
+
+ inArray: function(value, array) {
+ if (!CParamValidator.isType(array, ''array'')) {
+ throw ''The array must be an array to check the value for existing in it.'';
+ }
+
+ return (array.indexOf((typeof value === ''string'') ? value.toLowerCase() : value) !== -1);
+ },
+
+ ifMatch: function(value, regex) {
+ return (new RegExp(regex)).test(value);
+ },
+
+ match: function(value, regex) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be matched with the regular expression.'';
+ }
+
+ return value.match(new RegExp(regex));
+ },
+
+ checkURL: function(value) {
+ if (CParamValidator.isEmpty(value)) {
+ throw ''URL value "'' + value + ''" must be a non-empty string.'';
+ }
+ if (!CParamValidator.ifMatch(value, ''^(http|https):\\/\\/.+'')) {
+ throw ''URL value "'' + value + ''" must contain a schema.'';
+ }
+
+ return value.endsWith(''/'') ? value.slice(0, -1) : value;
+ },
+
+ check: function(key, rule, params) {
+ if (!CParamValidator.isDefined(rule.type)) {
+ throw ''Mandatory attribute "type" has not been defined for parameter "'' + key + ''".'';
+ }
+ if (!CParamValidator.isDefined(params[key])) {
+ throw ''Checked parameter "'' + key + ''" was not found in the list of input parameters.'';
+ }
+ var value = params[key],
+ error_message = null;
+ switch (rule.type) {
+ case ''string'':
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + key + ''" must be a string.'';
+ }
+ if (CParamValidator.isEmpty(value)) {
+ error_message = ''Value "'' + key + ''" must be a non-empty string'';
+ break;
+ }
+ if (CParamValidator.isDefined(rule.len) && value.length < rule.len) {
+ error_message = ''Value "'' + key + ''" must be a string with a length > '' + rule.len;
+ }
+ if (CParamValidator.isDefined(rule.regex) && !CParamValidator.ifMatch(value, rule.regex)) {
+ error_message = ''Value "'' + key + ''" must match the regular expression "'' + rule.regex + ''"'';
+ }
+ if (CParamValidator.isDefined(rule.url) && rule.url === true) {
+ value = CParamValidator.checkURL(value);
+ }
+ break;
+ case ''integer'':
+ if (!CParamValidator.isInteger(value)) {
+ error_message = ''Value "'' + key + ''" must be an integer'';
+ break;
+ }
+ value = parseInt(value);
+ break;
+ case ''float'':
+ if (!CParamValidator.isFloat(value)) {
+ error_message = ''Value "'' + key + ''" must be a floating-point number'';
+ break;
+ }
+ value = parseFloat(value);
+ break;
+ case ''boolean'':
+ if (CParamValidator.inArray(value, [''1'', ''true'', ''yes'', ''on''])) {
+ value = true;
+ }
+ else if (CParamValidator.inArray(value, [''0'', ''false'', ''no'', ''off''])) {
+ value = false;
+ }
+ else {
+ error_message = ''Value "'' + key + ''" must be a boolean-like.'';
+ }
+ break;
+ case ''array'':
+ try {
+ value = JSON.parse(value);
+ } catch (error) {
+ throw ''Value "'' + key + ''" contains invalid JSON.'';
+ }
+ if (!CParamValidator.isType(value, ''array'')) {
+ error_message = ''Value "'' + key + ''" must be an array.'';
+ }
+ if (CParamValidator.isDefined(rule.tags) && rule.tags === true) {
+ value = value.reduce(function(acc, obj) {
+ acc[obj.tag] = obj.value || null;
+ return acc;
+ }, {});
+ }
+ break;
+ case ''object'':
+ value = JSON.parse(value);
+ if (!CParamValidator.isType(value, ''object'')) {
+ error_message = ''Value "'' + key + ''" must be an object.'';
+ }
+ break;
+ default:
+ throw ''Unexpected attribute type "'' + rule.type + ''" for value "'' + key + ''". Available: '' +
+ [''integer'', ''float'', ''string'', ''boolean'', ''array'', ''object''].join('', '');
+ }
+ params[key] = value;
+ if (CParamValidator.inArray(rule.type, [''integer'', ''float'']) && error_message === null && (CParamValidator.isDefined(rule.min)
+ || CParamValidator.isDefined(rule.max)) && !CParamValidator.withinRange(value, rule.min, rule.max)) {
+ error_message = ''Value "'' + key + ''" must be a number '' + ((CParamValidator.isDefined(rule.min) && CParamValidator.isDefined(rule.max))
+ ? (rule.min + ''..'' + rule.max) : ((CParamValidator.isDefined(rule.min)) ? ''>'' + rule.min : ''<'' + rule.max));
+ }
+ else if (CParamValidator.isDefined(rule.array) && !CParamValidator.inArray(value, rule.array)) {
+ error_message = ''Value "'' + key + ''" must be in the array '' + JSON.stringify(rule.array);
+ }
+ else if (CParamValidator.isDefined(rule.macro) && !CParamValidator.isMacroSet(value.toString(), rule.macro)) {
+ error_message = ''The macro '' + ((CParamValidator.isDefined(rule.macro)) ? ''{'' + rule.macro + ''} '' : '' '') + ''is not set'';
+ }
+ if (error_message !== null) {
+ if (CParamValidator.isDefined(rule.default) && CParamValidator.isType(rule.default, rule.type)) {
+ params[key] = rule.default;
+ }
+ else {
+ Zabbix.log(4, ''Default value for "'' + key + ''" must be a '' + rule.type + ''. Skipped.'');
+ throw ''Incorrect value for variable "'' + key + ''". '' + error_message;
+ }
+ }
+
+ return this;
+ },
+
+ validate: function(rules, params) {
+ if (!CParamValidator.isType(params, ''object'') || CParamValidator.isType(params, ''array'')) {
+ throw ''Incorrect parameters value. The value must be an object.'';
+ }
+ for (var key in rules) {
+ CParamValidator.check(key, rules[key], params);
+ }
+ }
+}
+
+const CHttpRequest = function(logger) {
+ this.request = new HttpRequest();
+ if (typeof logger !== ''object'' || logger === null) {
+ this.logger = Zabbix;
+ }
+ else {
+ this.logger = logger;
+ }
+
+ this.clearHeader = function() {
+ this.request.clearHeader();
+ }
+
+ this.addHeaders = function(value) {
+ var headers = [];
+
+ if (typeof value === ''object'' && value !== null) {
+ if (!Array.isArray(value)) {
+ Object.keys(value).forEach(function(key) {
+ headers.push(key + '': '' + value[key]);
+ });
+ }
+ else {
+ headers = value;
+ }
+ }
+ else if (typeof value === ''string'') {
+ value.split(''\\r\\n'').forEach(function(header) {
+ headers.push(header);
+ });
+ }
+
+ for (var idx in headers) {
+ this.request.addHeader(headers[idx]);
+ }
+ }
+
+ this.setProxy = function(proxy) {
+ this.request.setProxy(proxy);
+ }
+
+ this.plainRequest = function(method, url, data) {
+ var resp = null;
+ method = method.toLowerCase();
+ this.logger.log(4, ''Sending '' + method + '' request:'' + JSON.stringify(data));
+ if ([''get'', ''post'', ''put'', ''patch'', ''delete'', ''trace''].indexOf(method) !== -1) {
+ resp = this.request[method](url, data);
+ }
+ else if ([''connect'', ''head'', ''options''].indexOf(method) !== -1) {
+ resp = this.request[method](url);
+ }
+ else {
+ throw ''Unexpected method. Method '' + method + '' is not supported.'';
+ }
+ this.logger.log(4, ''Response has been received: '' + resp);
+
+ return resp;
+ }
+
+ this.jsonRequest = function(method, url, data) {
+ this.addHeaders(''Content-Type: application/json'');
+ var resp = this.plainRequest(method, url, JSON.stringify(data));
+ try {
+ resp = JSON.parse(resp);
+ }
+ catch (error) {
+ throw ''Failed to parse response: not well-formed JSON was received'';
+ }
+
+ return resp;
+ }
+
+ this.getStatus = function() {
+ return this.request.getStatus();
+ }
+}
+
+const CWebhookHelper = {
+
+ createProblemURL: function(event_source, zabbix_url, trigger_id, event_id) {
+ if (event_source === ''0'') {
+ return zabbix_url + ''/tr_events.php?triggerid='' + trigger_id + ''&eventid='' + event_id;
+ } else if (event_source === ''4'') {
+ return zabbix_url + ''/zabbix.php?action=service.list'';
+ }
+
+ return zabbix_url;
+ },
+
+};
+
+var SEVERITY_COLORS = [
+ ''#97AAB3'',
+ ''#7499FF'',
+ ''#FFC859'',
+ ''#FFA059'',
+ ''#E97659'',
+ ''#E45959'',
+ ''#009900''
+],
+ serviceLogName = ''Discord Webhook'',
+ Logger = new CLogger(serviceLogName),
+ Discord = CWebhook;
+
+function stringTruncate(str, len) {
+ return str.length > len ? str.substring(0, len - 3) + ''...'' : str;
+}
+
+Discord.prototype.onCheckParams = function () {
+ CParamValidator.validate({discord_endpoint: {type: ''string'', url: true}, zabbix_url: {type: ''string'', url: true}, alert_message: {type: ''string''},
+ alert_subject: {type: ''string''}, event_nseverity: {type: ''integer'', default: 1}, user_agent: {type: ''string''}}, this.params);
+
+ this.params.discord_endpoint = this.params.discord_endpoint.replace(''/api/'', ''/api/v10/'') + ''?wait=True'';
+
+ if (this.params.event_source === ''3'' && this.params.event_value === ''1'') {
+ this.params.event_nseverity = 4;
+ }
+
+ if (this.params.event_value === ''0'') {
+ this.params.event_nseverity = 6;
+ }
+
+ if (this.params.event_source === ''0'') {
+ CParamValidator.validate({event_id: {type: ''integer''}, trigger_id: {type: ''integer''}}, this.params);
+ }
+
+ this.data = {
+ embeds: [
+ {
+ color: parseInt(SEVERITY_COLORS[this.params.event_nseverity].replace(''#'', ''''), 16),
+ url: CWebhookHelper.createProblemURL(this.params.event_source, this.params.zabbix_url, this.params.trigger_id, this.params.event_id),
+ title: stringTruncate(this.params.alert_subject, 256),
+ description: stringTruncate(this.params.alert_message, 4096)
+ }
+ ]
+ };
+};
+
+Discord.prototype.onEvent = function (alert) {
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+
+ this.request.addHeaders({"User-Agent": this.params.user_agent});
+ const response = this.request.jsonRequest(''POST'', this.params.discord_endpoint, this.data);
+
+ if (!response.id) {
+ const error_message = CParamValidator.isType(response.message, ''string'') ? response.message : ''Unknown error'';
+
+ throw error_message + ''. For more details check the Zabbix server log.'';
+ }
+
+ return ''OK'';
+};
+
+
+try {
+ var hook = new Discord(value);
+ hook.request = new CHttpRequest(Logger);
+ return hook.run();
+}
+catch (error) {
+ Logger.log(Logger.WARN, ''notification failed: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','0','0','','','This media type integrates your Zabbix installation with your Discord server using the Zabbix webhook feature.
+
+Discord configuration:
+
+1. Go to `https://discord.com/app` or open the Discord desktop application. Open your *Server Settings* and head to the *Integrations* tab.
+2. Press the *Create Webhook* button to create a new webhook.
+3. Click on the webhook that has been created and edit the details if needed.
+4. After setting up your Discord webhook press "Save Changes". Now you can copy Discord webhook URL now by pressing "Copy Webhook URL" or you can view it later.
+
+Zabbix configuration:
+
+1. Before you can start using Discord webhook, set up the global macro "{$ZABBIX.URL}":
+- In the Zabbix web interface, go to "Administration" → "Macros" section in the dropdown menu in the top left corner.
+- Set up the global macro "{$ZABBIX.URL}" which will contain the URL to the Zabbix frontend. The URL should be either an IP address, a fully qualified domain name, or localhost.
+- Specifying a protocol is mandatory, whereas the port is optional. Depending on the web server configuration you might also need to append "/zabbix" to the end of URL. Good examples:
+ - http://zabbix.com
+ - https://zabbix.lan/zabbix
+ - http://server.zabbix.lan/
+ - http://localhost
+ - http://127.0.0.1:8080
+- Bad examples:
+ - zabbix.com
+ - http://zabbix/
+
+2. Create a Zabbix user and add media:
+- If you want to create a new user, go to the "Users" → "Users" section, click the "Create user" button in the top right corner. In the "User" tab, fill in all required fields (marked with red asterisks).
+- In the "Media" tab, add a new media and select "Discord" type from the drop-down list. The "Send to" field must contain the URL of the Discord webhook created before.
+- Make sure this user has access to all hosts for which you would like problem notifications to be sent to Discord.
+
+3. Great! You can now start using this media type in actions and receive alerts!
+
+You can find the latest version of this media and additional information in the official Zabbix repository:
+https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/templates/media/discord','0'),
+('72','4','Event-Driven Ansible','','','','','','','','25','0','0','0','0','1','3','10s','1',E'var Eda = {
+ params: {},
+
+ setParams: function (params) {
+ var required_params = [
+ ''send_to'',
+ ''event_source'',
+ ''event_value'',
+ ''event_date'',
+ ''event_time''],
+ integer_fields = [
+ ''event_id'',
+ ''event_nseverity'',
+ ''event_object'',
+ ''event_source'',
+ ''event_value'',
+ ''host_id'',
+ ''trigger_id''];
+
+ required_params.forEach(function (field) {
+ if (typeof params !== ''object'' || typeof params[field] === ''undefined'' || params[field] === '''') {
+ throw ''Required param is not set: "'' + field + ''".'';
+ }
+ });
+
+ Eda.params = params;
+
+ integer_fields.forEach(function (key) {
+ if (typeof Eda.params[key] !== ''undefined'') {
+ if (isNaN(Eda.params[key])) {
+ throw ''Parameter "'' + key + ''" must be integer. Given value: '' + Eda.params[key];
+ }
+ Eda.params[key] = parseInt(Eda.params[key]);
+ }
+ });
+
+ // Check type of event. Possible values: 0 - Trigger
+ if (params.event_source != 0) {
+ throw (''Incorrect "event_source" parameter given: '' + params.event_source
+ + ''\\nOnly trigger-based events are supported'');
+ }
+
+ // Check trigger update and trigger resolve events
+ if (params.event_source == 0 && params.event_value != 1) {
+ throw (''Incorrect "event_value" parameter given: "'' + params.event_value
+ + ''".\\nOnly trigger-based events of problem are supported'');
+ }
+
+ // Check endpoint
+ Eda.params.endpoint = (Eda.params.endpoint.startsWith(''/''))
+ ? Eda.params.endpoint : ''/'' + Eda.params.endpoint;
+ // Prepare groups
+ Eda.params.host_groups = (typeof Eda.params[''host_groups''] !== ''undefined'')
+ ? this.prepareHostgroups(Eda.params.host_groups): []
+ // Prepare tags
+ Eda.params.event_tags = (typeof Eda.params[''event_tags''] !== ''undefined'')
+ ? this.transformTags(Eda.params.event_tags): {}
+ // Prepare timestamp
+ Eda.params.event_datetime_timestamp = this.getTimestamp(
+ Eda.params.event_date, Eda.params.event_time)
+ },
+
+ setProxy: function (HTTPProxy) {
+ Eda.HTTPProxy = HTTPProxy;
+ },
+
+ prepareHostgroups: function (hostgroups) {
+ var host_groups = [];
+ hostgroups.split('','').forEach(function (group) {
+ group = group.trim();
+ if (group.length > 0) {
+ host_groups.push(group);
+ }
+ });
+ return host_groups;
+ },
+
+ getTimestamp: function (date, time) {
+ try {
+ return Date.parse(date.split(''.'').join(''-'') + ''T'' + time + ''.000Z'') / 1000 + new Date().getTimezoneOffset() * 60;
+ } catch (_) {}
+
+ throw (''Failed to parse event time.'');
+ },
+
+ transformTags: function (event_tags) {
+ var tags = {};
+ if (event_tags) {
+ try {
+ JSON.parse(event_tags).forEach(function (object) {
+ var tag = object[''tag''];
+ tags[tag] = tags[tag] || [];
+ tags[tag].push(object[''value'']);
+ });
+ } catch (error) {
+ throw ''Event tags format is invalid.'';
+ }
+ }
+
+ return tags;
+ },
+
+ sendMessage: function () {
+ var response, request = new HttpRequest();
+ var url = Eda.params[''send_to''] + Eda.params[''endpoint''];
+ var data = JSON.stringify(Eda.params);
+ Zabbix.log(4, ''[ Event-Driven Ansible webhook ] URL: '' + url + '' data: '' + data);
+
+ if (typeof Eda.HTTPProxy !== ''undefined'' && Eda.HTTPProxy !== '''') {
+ request.setProxy(Eda.HTTPProxy);
+ }
+ request.addHeader(''Content-Type: application/json'');
+ response = request.post(url, data);
+
+ Zabbix.log(4, ''[ Event-Driven Ansible webhook ] HTTP code: '' + request.getStatus()
+ + '' response: '' + response);
+
+ if (request.getStatus() !== 200) {
+ throw ''Request failed with status code '' + request.getStatus() + '': '' + response;
+ }
+ }
+};
+
+
+try {
+ var params = JSON.parse(value);
+
+ Eda.setParams(params);
+ Eda.setProxy(params.HTTPProxy);
+ Eda.sendMessage();
+ return true;
+}
+catch (error) {
+ Zabbix.log(3, ''[ Event-Driven Ansible webhook ] notification failed: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','0','0','','','','0'),
+('73','4','Express.ms','','','','','','','','25','0','0','0','0','1','3','10s','1',E'var Express = {
+ params: [],
+
+ setParams: function (params) {
+ if (typeof params !== ''object'') {
+ return;
+ }
+
+ Express.params = params;
+
+ if (typeof Express.params.url === ''string'' && !Express.params.url.endsWith(''/'')) {
+ Express.params.url += ''/'';
+ }
+ },
+
+ setProxy: function (HTTPProxy) {
+ Express.HTTPProxy = HTTPProxy;
+ },
+
+ request: function (query, data) {
+ var response,
+ url = Express.params.url + query,
+ request = new HttpRequest();
+
+ request.addHeader(''Content-Type: application/json'');
+ request.addHeader(''Authorization: Bearer '' + Express.params.token);
+
+ if (typeof Express.HTTPProxy !== ''undefined'' && Express.HTTPProxy !== '''') {
+ request.setProxy(Express.HTTPProxy);
+ }
+
+ if (typeof data !== ''undefined'') {
+ data = JSON.stringify(data);
+ }
+
+ Zabbix.log(4, ''[ Express Webhook ] Sending request: '' + url +
+ ((typeof data === ''string'') ? (''\\n'' + data) : ''''));
+
+ response = request.post(url, data);
+
+ Zabbix.log(4, ''[ Express Webhook ] Received response with status code '' +
+ request.getStatus() + ''\\n'' + response);
+
+ if (response !== null) {
+ try {
+ response = JSON.parse(response);
+ }
+ catch (error) {
+ Zabbix.log(4, ''[ Express Webhook ] Failed to parse response received from Express'');
+ response = {};
+ }
+ }
+
+ if (response.status !== ''ok'') {
+ var message = ''Request failed with status code '' + request.getStatus();
+
+ if (typeof response.reason !== ''undefined'') {
+ message += '': '' + JSON.stringify(response.reason);
+ }
+
+ throw message + ''. Check debug log for more information.'';
+ }
+
+ return response.result;
+ },
+
+ postMessage: function (is_problem) {
+ var data,
+ url,
+ result = {tags: {}},
+ response;
+
+ if (is_problem) {
+ data = {
+ group_chat_id: Express.params.send_to,
+ notification: {
+ status: ''ok'',
+ body: Express.params.message
+ }
+ };
+ url = ''api/v4/botx/notifications/direct'';
+ }
+ else {
+ data = {
+ reply: {
+ status: ''ok'',
+ body: Express.params.message
+ }
+ };
+ url = ''api/v3/botx/events/reply_event'';
+
+ try {
+ var tags = JSON.parse(Express.params.tags);
+ }
+ catch (error) {
+ throw ''Value of "express_tags" is not JSON. Value: '' + Express.params.tags + ''.'';
+ }
+
+ tags.forEach(function(tag) {
+ if (tag.tag === ''__zbx_ex_sync_id_'' + Express.params.send_to) {
+ data.source_sync_id = tag.value;
+ }
+ });
+
+ if (!data.source_sync_id) {
+ throw ''Cannot update data. sync_id for the provided sender is unknown.'';
+ }
+ }
+
+ response = Express.request(url, data);
+
+ if (is_problem && response.sync_id) {
+ result.tags[''__zbx_ex_sync_id_'' + Express.params.send_to] = response.sync_id;
+
+ return JSON.stringify(result);
+ }
+ else {
+ return ''OK'';
+ }
+ }
+};
+
+try {
+ var params = JSON.parse(value),
+ express = {},
+ required_params = [
+ ''express_url'', ''express_send_to'', ''express_message'', ''express_tags'', ''express_token'',
+ ''event_source'', ''event_value'', ''event_update_status''
+ ];
+
+ Object.keys(params)
+ .forEach(function (key) {
+ if (key.startsWith(''express_'')) {
+ express[key.substring(8)] = params[key];
+ }
+
+ if (required_params.indexOf(key) !== -1
+ && (params[key].trim() === '''' || params[key] === ''{ALERT.SENDTO}'')) {
+ throw ''Parameter "'' + key + ''" can\\''t be empty.'';
+ }
+ });
+
+ if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''\\nMust be 0-3.'';
+ }
+
+ // Forcing event_value and event_update_status for non trigger-based events.
+ if (params.event_source !== ''0'' ) {
+ params.event_value = ''1'';
+ params.event_update_status = ''0'';
+ }
+
+ if (params.event_value !== ''0'' && params.event_value !== ''1'') {
+ 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.'';
+ }
+
+ Express.setParams(express);
+ Express.setProxy(params.HTTPProxy);
+
+ return Express.postMessage(params.event_value === ''1'' && params.event_update_status === ''0'');
+}
+catch (error) {
+ Zabbix.log(3, ''[ Express Webhook ] ERROR: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','0','','','','0'),
+('74','4','GitHub','','','','','','','','25','0','0','0','0','1','3','10s','1',E'const CLogger = function(serviceName) {
+ this.serviceName = serviceName;
+ this.INFO = 4
+ this.WARN = 3
+ this.ERROR = 2
+ this.log = function(level, msg) {
+ Zabbix.log(level, ''['' + this.serviceName + ''] '' + msg);
+ }
+}
+
+const CWebhook = function(value) {
+ try {
+ params = JSON.parse(value);
+
+ if ([''0'', ''1'', ''2'', ''3'', ''4''].indexOf(params.event_source) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''.\\nMust be 0-4.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1 && [''0'', ''1''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0 or 1.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1) {
+ if (params.event_source === ''1'' && [''0'', ''1'', ''2'', ''3''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0-3.'';
+ }
+
+ if (params.event_source === ''0'' && [''0'', ''1''].indexOf(params.event_update_status) === -1) {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''.\\nMust be 0 or 1.'';
+ }
+
+ if (params.event_source === ''4'') {
+ if ([''0'', ''1'', ''2'', ''3'', ''4'', ''5''].indexOf(params.event_update_nseverity) !== -1 && params.event_update_nseverity != params.event_nseverity) {
+ params.event_nseverity = params.event_update_nseverity;
+ params.event_severity = params.event_update_severity;
+ params.event_update_status = ''1'';
+ }
+ }
+ }
+
+ this.runCallback = function(name, params) {
+ if (typeof this[name] === ''function'') {
+ return this[name].apply(this, [params]);
+ }
+ }
+
+ this.handleEvent = function(source, event) {
+ const alert = { source: source, event: event };
+ return [
+ this.runCallback(''on'' + source + event, alert),
+ this.runCallback(''on'' + event, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.handleEventless = function(source) {
+ const alert = { source: source, event: null };
+ return [
+ this.runCallback(''on'' + source, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.run = function() {
+ var results = [];
+ if (typeof this.httpProxy === ''string'' && this.httpProxy.trim() !== '''') {
+ this.request.setProxy(this.httpProxy);
+ }
+ const types = { ''0'': ''Trigger'', ''1'': ''Discovery'', ''2'': ''Autoreg'', ''3'': ''Internal'', ''4'': ''Service'' };
+
+ if ([''0'', ''3'', ''4''].indexOf(this.params.event_source) !== -1) {
+ var event = (this.params.event_update_status === ''1'')
+ ? ''Update''
+ : ((this.params.event_value === ''1'') ? ''Problem'' : ''Resolve'');
+
+ results = this.handleEvent(types[this.params.event_source], event);
+ }
+ else if (typeof types[this.params.event_source] !== ''undefined'') {
+ results = this.handleEventless(types[this.params.event_source]);
+ }
+ else {
+ throw ''Unexpected "event_source": '' + this.params.event_source;
+ }
+
+ for (idx in results) {
+ if (typeof results[idx] !== ''undefined'') {
+ return JSON.stringify(results[idx]);
+ }
+ }
+ }
+ this.httpProxy = params.http_proxy;
+ this.params = params;
+ this.runCallback(''onCheckParams'', {});
+ } catch (error) {
+ throw ''Webhook processing failed: '' + error;
+ }
+}
+
+const CParamValidator = {
+
+ isType: function(value, type) {
+ if (type === ''array'') {
+ return Array.isArray(value);
+ }
+ if (type === ''integer'') {
+ return CParamValidator.isInteger(value);
+ }
+ if (type === ''float'') {
+ return CParamValidator.isFloat(value);
+ }
+
+ return (typeof value === type);
+ },
+
+ isInteger: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseInt(value));
+ },
+
+ isFloat: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+\\.\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseFloat(value));
+ },
+
+ isDefined: function(value) {
+ return !CParamValidator.isType(value, ''undefined'');
+ },
+
+ isEmpty: function(value) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be checked for emptiness.'';
+ }
+
+ return (value.trim() === '''');
+ },
+
+ isMacroSet: function(value, macro) {
+ if (CParamValidator.isDefined(macro)) {
+ return !(CParamValidator.ifMatch(value, ''^\\{'' + macro + ''\\}$''))
+ }
+
+ return !(CParamValidator.ifMatch(value, ''^\\{[$#]{0,1}[A-Z_\\.]+[\\:]{0,1}["]{0,1}.*["]{0,1}\\}$'') || value === ''*UNKNOWN*'')
+ },
+
+ withinRange: function(value, min, max) {
+ if (!CParamValidator.isType(value, ''number'')) {
+ throw ''Value "'' + value + ''" must be a number to be checked for range.'';
+ }
+ if (value < ((CParamValidator.isDefined(min)) ? min : value)
+ || value > ((CParamValidator.isDefined(max)) ? max : value)) {
+ return false;
+ }
+
+ return true;
+ },
+
+ inArray: function(value, array) {
+ if (!CParamValidator.isType(array, ''array'')) {
+ throw ''The array must be an array to check the value for existing in it.'';
+ }
+
+ return (array.indexOf((typeof value === ''string'') ? value.toLowerCase() : value) !== -1);
+ },
+
+ ifMatch: function(value, regex) {
+ return (new RegExp(regex)).test(value);
+ },
+
+ match: function(value, regex) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be matched with the regular expression.'';
+ }
+
+ return value.match(new RegExp(regex));
+ },
+
+ checkURL: function(value) {
+ if (CParamValidator.isEmpty(value)) {
+ throw ''URL value "'' + value + ''" must be a non-empty string.'';
+ }
+ if (!CParamValidator.ifMatch(value, ''^(http|https):\\/\\/.+'')) {
+ throw ''URL value "'' + value + ''" must contain a schema.'';
+ }
+
+ return value.endsWith(''/'') ? value.slice(0, -1) : value;
+ },
+
+ check: function(key, rule, params) {
+ if (!CParamValidator.isDefined(rule.type)) {
+ throw ''Mandatory attribute "type" has not been defined for parameter "'' + key + ''".'';
+ }
+ if (!CParamValidator.isDefined(params[key])) {
+ throw ''Checked parameter "'' + key + ''" was not found in the list of input parameters.'';
+ }
+ var value = params[key],
+ error_message = null;
+ switch (rule.type) {
+ case ''string'':
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + key + ''" must be a string.'';
+ }
+ if (CParamValidator.isEmpty(value)) {
+ error_message = ''Value "'' + key + ''" must be a non-empty string'';
+ break;
+ }
+ if (CParamValidator.isDefined(rule.len) && value.length < rule.len) {
+ error_message = ''Value "'' + key + ''" must be a string with a length > '' + rule.len;
+ }
+ if (CParamValidator.isDefined(rule.regex) && !CParamValidator.ifMatch(value, rule.regex)) {
+ error_message = ''Value "'' + key + ''" must match the regular expression "'' + rule.regex + ''"'';
+ }
+ if (CParamValidator.isDefined(rule.url) && rule.url === true) {
+ value = CParamValidator.checkURL(value);
+ }
+ break;
+ case ''integer'':
+ if (!CParamValidator.isInteger(value)) {
+ error_message = ''Value "'' + key + ''" must be an integer'';
+ break;
+ }
+ value = parseInt(value);
+ break;
+ case ''float'':
+ if (!CParamValidator.isFloat(value)) {
+ error_message = ''Value "'' + key + ''" must be a floating-point number'';
+ break;
+ }
+ value = parseFloat(value);
+ break;
+ case ''boolean'':
+ if (CParamValidator.inArray(value, [''1'', ''true'', ''yes'', ''on''])) {
+ value = true;
+ }
+ else if (CParamValidator.inArray(value, [''0'', ''false'', ''no'', ''off''])) {
+ value = false;
+ }
+ else {
+ error_message = ''Value "'' + key + ''" must be a boolean-like.'';
+ }
+ break;
+ case ''array'':
+ try {
+ value = JSON.parse(value);
+ } catch (error) {
+ throw ''Value "'' + key + ''" contains invalid JSON.'';
+ }
+ if (!CParamValidator.isType(value, ''array'')) {
+ error_message = ''Value "'' + key + ''" must be an array.'';
+ }
+ if (CParamValidator.isDefined(rule.tags) && rule.tags === true) {
+ value = value.reduce(function(acc, obj) {
+ acc[obj.tag] = obj.value || null;
+ return acc;
+ }, {});
+ }
+ break;
+ case ''object'':
+ value = JSON.parse(value);
+ if (!CParamValidator.isType(value, ''object'')) {
+ error_message = ''Value "'' + key + ''" must be an object.'';
+ }
+ break;
+ default:
+ throw ''Unexpected attribute type "'' + rule.type + ''" for value "'' + key + ''". Available: '' +
+ [''integer'', ''float'', ''string'', ''boolean'', ''array'', ''object''].join('', '');
+ }
+ params[key] = value;
+ if (CParamValidator.inArray(rule.type, [''integer'', ''float'']) && error_message === null && (CParamValidator.isDefined(rule.min)
+ || CParamValidator.isDefined(rule.max)) && !CParamValidator.withinRange(value, rule.min, rule.max)) {
+ error_message = ''Value "'' + key + ''" must be a number '' + ((CParamValidator.isDefined(rule.min) && CParamValidator.isDefined(rule.max))
+ ? (rule.min + ''..'' + rule.max) : ((CParamValidator.isDefined(rule.min)) ? ''>'' + rule.min : ''<'' + rule.max));
+ }
+ else if (CParamValidator.isDefined(rule.array) && !CParamValidator.inArray(value, rule.array)) {
+ error_message = ''Value "'' + key + ''" must be in the array '' + JSON.stringify(rule.array);
+ }
+ else if (CParamValidator.isDefined(rule.macro) && !CParamValidator.isMacroSet(value.toString(), rule.macro)) {
+ error_message = ''The macro '' + ((CParamValidator.isDefined(rule.macro)) ? ''{'' + rule.macro + ''} '' : '' '') + ''is not set'';
+ }
+ if (error_message !== null) {
+ if (CParamValidator.isDefined(rule.default) && CParamValidator.isType(rule.default, rule.type)) {
+ params[key] = rule.default;
+ }
+ else {
+ Zabbix.log(4, ''Default value for "'' + key + ''" must be a '' + rule.type + ''. Skipped.'');
+ throw ''Incorrect value for variable "'' + key + ''". '' + error_message;
+ }
+ }
+
+ return this;
+ },
+
+ validate: function(rules, params) {
+ if (!CParamValidator.isType(params, ''object'') || CParamValidator.isType(params, ''array'')) {
+ throw ''Incorrect parameters value. The value must be an object.'';
+ }
+ for (var key in rules) {
+ CParamValidator.check(key, rules[key], params);
+ }
+ }
+}
+
+const CHttpRequest = function(logger) {
+ this.request = new HttpRequest();
+ if (typeof logger !== ''object'' || logger === null) {
+ this.logger = Zabbix;
+ }
+ else {
+ this.logger = logger;
+ }
+
+ this.clearHeader = function() {
+ this.request.clearHeader();
+ }
+
+ this.addHeaders = function(value) {
+ var headers = [];
+
+ if (typeof value === ''object'' && value !== null) {
+ if (!Array.isArray(value)) {
+ Object.keys(value).forEach(function(key) {
+ headers.push(key + '': '' + value[key]);
+ });
+ }
+ else {
+ headers = value;
+ }
+ }
+ else if (typeof value === ''string'') {
+ value.split(''\\r\\n'').forEach(function(header) {
+ headers.push(header);
+ });
+ }
+
+ for (var idx in headers) {
+ this.request.addHeader(headers[idx]);
+ }
+ }
+
+ this.setProxy = function(proxy) {
+ this.request.setProxy(proxy);
+ }
+
+ this.plainRequest = function(method, url, data) {
+ var resp = null;
+ method = method.toLowerCase();
+ this.logger.log(4, ''Sending '' + method + '' request:'' + JSON.stringify(data));
+ if ([''get'', ''post'', ''put'', ''patch'', ''delete'', ''trace''].indexOf(method) !== -1) {
+ resp = this.request[method](url, data);
+ }
+ else if ([''connect'', ''head'', ''options''].indexOf(method) !== -1) {
+ resp = this.request[method](url);
+ }
+ else {
+ throw ''Unexpected method. Method '' + method + '' is not supported.'';
+ }
+ this.logger.log(4, ''Response has been received: '' + resp);
+
+ return resp;
+ }
+
+ this.jsonRequest = function(method, url, data) {
+ this.addHeaders(''Content-Type: application/json'');
+ var resp = this.plainRequest(method, url, JSON.stringify(data));
+ try {
+ resp = JSON.parse(resp);
+ }
+ catch (error) {
+ throw ''Failed to parse response: not well-formed JSON was received'';
+ }
+
+ return resp;
+ }
+
+ this.getStatus = function() {
+ return this.request.getStatus();
+ }
+}
+
+const CWebhookHelper = {
+
+ createProblemURL: function(event_source, zabbix_url, trigger_id, event_id) {
+ if (event_source === ''0'') {
+ return zabbix_url + ''/tr_events.php?triggerid='' + trigger_id + ''&eventid='' + event_id;
+ } else if (event_source === ''4'') {
+ return zabbix_url + ''/zabbix.php?action=service.list'';
+ }
+
+ return zabbix_url;
+ },
+
+};
+
+var serviceLogName = ''GitHub Webhook'',
+ Logger = new CLogger(serviceLogName),
+ GitHub = CWebhook;
+
+GitHub.prototype.onCheckParams = function () {
+ CParamValidator.validate({
+ alert_message: {type: ''string''},
+ alert_subject: {type: ''string''},
+ github_api_version: {type: ''string''},
+ github_repo: {type: ''string''},
+ github_token: {type: ''string''},
+ github_url: {type: ''string'', url: true},
+ github_user_agent: {type: ''string''},
+ github_zabbix_event_priority_label_prefix: {type: ''string'', default: ''Zabbix Event Priority: ''},
+ github_zabbix_event_source_label_prefix: {type: ''string'', default: ''Zabbix Event Source: ''},
+ github_zabbix_event_status_label_prefix: {type: ''string'', default: ''Zabbix Event Status: ''},
+ github_zabbix_generic_label: {type: ''string'', default: ''Zabbix GitHub Webhook''},
+ zabbix_url: {type: ''string'', url: true}
+ }, this.params);
+
+ this.request_headers = {
+ ''User-Agent'': this.params.github_user_agent,
+ ''Accept'': ''application/vnd.github+json'',
+ ''X-GitHub-Api-Version'': this.params.github_api_version,
+ ''Authorization'': ''Bearer '' + this.params.github_token
+ };
+
+ this.payload_data = {
+ title: this.params.alert_subject,
+ labels: [
+ {
+ name: this.params.github_zabbix_generic_label
+ }
+ ]
+ };
+
+ this.result = {tags: {}};
+};
+
+function checkResponse(response, received_code, required_code, response_field, error_message) {
+ if (received_code != required_code || !CParamValidator.isDefined(response[response_field])) {
+ var message = error_message + '' Request failed with status code '' + received_code;
+
+ if (CParamValidator.isDefined(response.message) && Object.keys(response.message).length > 0) {
+ message += '': '' + response.message;
+ }
+
+ throw message + '' Check debug log for more information.'';
+ }
+}
+
+GitHub.prototype.createIssue = function () {
+ this.payload_data.body = this.params.alert_message + ''\\n'' + CWebhookHelper.createProblemURL(this.params.event_source, this.params.zabbix_url, this.params.trigger_id, this.params.event_id);
+
+ this.request.addHeaders(this.request_headers);
+
+ const response = this.request.jsonRequest(''POST'', this.params.github_url + ''/repos/'' + this.params.github_repo + ''/issues'', this.payload_data);
+
+ checkResponse(response, this.request.getStatus(), 201, ''number'', ''Cannot create GitHub issue.'');
+
+ return response;
+}
+
+GitHub.prototype.updateIssue = function () {
+ this.request.addHeaders(this.request_headers);
+
+ const response = this.request.jsonRequest(''PATCH'', this.params.github_url + ''/repos/'' + this.params.github_repo + ''/issues/'' + this.params.github_issue_number, this.payload_data);
+
+ checkResponse(response, this.request.getStatus(), 200, ''number'', ''Cannot update GitHub issue.'');
+
+ return response;
+}
+
+GitHub.prototype.addIssueComment = function () {
+ this.payload_data = {
+ body: this.params.alert_message
+ };
+
+ this.request.addHeaders(this.request_headers);
+
+ const response = this.request.jsonRequest(''POST'', this.params.github_url + ''/repos/'' + this.params.github_repo + ''/issues/'' + this.params.github_issue_number + ''/comments'', this.payload_data);
+
+ checkResponse(response, this.request.getStatus(), 201, ''id'', ''Cannot add comment for GitHub issue.'');
+
+ return response;
+}
+
+GitHub.prototype.onProblem = function (alert) {
+ if (CParamValidator.isMacroSet(this.params.github_issue_number)) {
+ return this.onUpdate(alert);
+ }
+
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+
+ if (this.params.event_source === ''0'') {
+ CParamValidator.validate({event_id: {type: ''integer''}, trigger_id: {type: ''integer''}}, this.params);
+ }
+
+ this.payload_data.labels.push({name: this.params.github_zabbix_event_source_label_prefix + alert.source});
+
+ this.payload_data.labels.push({name: this.params.github_zabbix_event_status_label_prefix + ''Problem''});
+
+ if (!CParamValidator.isEmpty(this.params.event_severity) && CParamValidator.isMacroSet(this.params.event_severity, ''EVENT.SEVERITY'')) {
+ this.payload_data.labels.push({name: this.params.github_zabbix_event_priority_label_prefix + this.params.event_severity});
+ }
+
+ const response = this.createIssue();
+
+ this.result.tags = {
+ __zbx_github_issue_number: response.number,
+ __zbx_github_repo: this.params.github_repo,
+ __zbx_github_link: response.html_url
+ };
+
+ return this.result;
+}
+
+GitHub.prototype.onUpdate = function (alert) {
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+
+ if (!CParamValidator.isMacroSet(this.params.github_issue_number)) {
+ throw "Failed to update the existing issue: no issue number was received."
+ }
+
+ this.payload_data.labels.push({name: this.params.github_zabbix_event_source_label_prefix + alert.source});
+
+ if (this.params.event_value === ''0'') {
+ this.payload_data.labels.push({name: this.params.github_zabbix_event_status_label_prefix + ''Resolved''});
+ } else {
+ this.payload_data.labels.push({name: this.params.github_zabbix_event_status_label_prefix + ''Problem''});
+ }
+
+ if (!CParamValidator.isEmpty(this.params.event_severity) && CParamValidator.isMacroSet(this.params.event_severity, ''EVENT.SEVERITY'')) {
+ this.payload_data.labels.push({name: this.params.github_zabbix_event_priority_label_prefix + this.params.event_severity});
+ }
+
+ this.updateIssue();
+
+ this.request.clearHeader();
+ this.addIssueComment();
+
+ return this.result;
+}
+
+GitHub.prototype.onResolve = function (alert) {
+ return this.onUpdate(alert);
+}
+
+GitHub.prototype.onDiscovery = function (alert) {
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+
+ this.payload_data.labels.push({name: this.params.github_zabbix_event_source_label_prefix + alert.source});
+
+ this.createIssue();
+
+ return this.result;
+}
+
+GitHub.prototype.onAutoreg = function (alert) {
+ return this.onDiscovery(alert);
+}
+
+try {
+ var hook = new GitHub(value);
+ hook.request = new CHttpRequest(Logger);
+ return hook.run();
+}
+catch (error) {
+ Logger.log(Logger.WARN, ''notification failed: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','1','{EVENT.TAGS.__zbx_github_link}','Github: Issue {EVENT.TAGS.__zbx_github_issue_number}','This media type integrates your Zabbix installation with GitHub using the Zabbix webhook feature.
+
+GitHub configuration:
+
+1. Create an access token.
+
+One of the simplest ways to send authenticated requests is to use a personal access token - either a classic or a fine-grained one:
+https://docs.github.com/en/rest/authentication/authenticating-to-the-rest-api?apiVersion=2022-11-28#authenticating-with-a-personal-access-token
+
+Classic personal access token
+
+You can create a new classic personal access token by following the instructions in the official documentation:
+https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic
+
+The token user must have a permission to create issues and issue comments in the desired repositories. For webhook to work on private repositories, the "repo" scope must be set in token settings to have full control of private repositories.
+
+Additional information about OAuth scopes is available in the official documentation:
+https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps#available-scopes
+
+Fine-grained personal access token
+
+Alternatively, you can use a fine-grained personal access token:
+https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token
+
+In order to use fine-grained tokens to monitor organization-owned repositories, organizations must opt in to fine-grained personal access tokens and set up a personal access token policy:
+https://docs.github.com/en/organizations/managing-programmatic-access-to-your-organization/setting-a-personal-access-token-policy-for-your-organization
+
+The fine-grained token needs to have the following permission set to provide access to the repository issues:
+- "Issues" repository permissions (write)
+
+2. Copy and save the created token somewhere, as it will be shown only once for security reasons.
+
+Zabbix configuration:
+
+1. Before you can start using Zammad webhook, set up the global macro "{$ZABBIX.URL}":
+- In the Zabbix web interface, go to "Administration" → "Macros" section in the dropdown menu in the top left corner.
+- Set up the global macro "{$ZABBIX.URL}" which will contain the URL to the Zabbix frontend. The URL should be either an IP address, a fully qualified domain name, or localhost.
+- Specifying a protocol is mandatory, whereas the port is optional. Depending on the web server configuration you might also need to append "/zabbix" to the end of URL. Good examples:
+ - http://zabbix.com
+ - https://zabbix.lan/zabbix
+ - http://server.zabbix.lan/
+ - http://localhost
+ - http://127.0.0.1:8080
+- Bad examples:
+ - zabbix.com
+ - http://zabbix/
+
+2. Set the "github_token" webhook parameter value to the access token that you created previously.
+
+You can also adjust the issue labels created by the webhook in the following parameters:
+- github_zabbix_event_priority_label_prefix - the prefix for the issue label that displays the Zabbix event priority in the supported event sources. It is set to "Zabbix Event Priority: " by default.
+- github_zabbix_event_source_label_prefix - the prefix for the issue label that displays the Zabbix event source. It is set to "Zabbix Event Source: " by default.
+- github_zabbix_event_status_label_prefix - the prefix for the issue label that displays the Zabbix event status. It is set to "Zabbix Event Status: " by default.
+- github_zabbix_generic_label - the label that is added to all issues created by the webhook. It is set to "Zabbix GitHub Webhook" by default.
+
+Note that the webhook will reuse the labels with the same name that already exist in the repository (including the color, so it can changed from the default value for new labels in GitHub, if needed). Also, the labels are replaced when the issue is updated, so any user-added labels will be removed.
+
+4. Create a Zabbix user and add media:
+- If you want to create a new user, go to the "Users" → "Users" section, click the "Create user" button in the top right corner. In the "User" tab, fill in all required fields (marked with red asterisks).
+- In the "Media" tab, add a new media and select "Zammad" type from the drop-down list. In field "Send to" specify the full repo name (owner/project name) e.g. johndoe/example-project.
+- Make sure this user has access to all hosts for which you would like problem notifications to be sent to GitHub.
+
+5. Great! You can now start using this media type in actions and create GitHub issues!
+
+You can find the latest version of this media and additional information in the official Zabbix repository:
+https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/templates/media/github','0'),
+('75','4','GLPi','','','','','','','','25','0','0','0','0','1','1','10s','1',E'const CLogger = function(serviceName) {
+ this.serviceName = serviceName;
+ this.INFO = 4
+ this.WARN = 3
+ this.ERROR = 2
+ this.log = function(level, msg) {
+ Zabbix.log(level, ''['' + this.serviceName + ''] '' + msg);
+ }
+}
+
+const CWebhook = function(value) {
+ try {
+ params = JSON.parse(value);
+
+ if ([''0'', ''1'', ''2'', ''3'', ''4''].indexOf(params.event_source) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''.\\nMust be 0-4.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1 && [''0'', ''1''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0 or 1.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1) {
+ if (params.event_source === ''1'' && [''0'', ''1'', ''2'', ''3''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0-3.'';
+ }
+
+ if (params.event_source === ''0'' && [''0'', ''1''].indexOf(params.event_update_status) === -1) {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''.\\nMust be 0 or 1.'';
+ }
+
+ if (params.event_source === ''4'') {
+ if ([''0'', ''1'', ''2'', ''3'', ''4'', ''5''].indexOf(params.event_update_nseverity) !== -1 && params.event_update_nseverity != params.event_nseverity) {
+ params.event_nseverity = params.event_update_nseverity;
+ params.event_severity = params.event_update_severity;
+ params.event_update_status = ''1'';
+ }
+ }
+ }
+
+ this.runCallback = function(name, params) {
+ if (typeof this[name] === ''function'') {
+ return this[name].apply(this, [params]);
+ }
+ }
+
+ this.handleEvent = function(source, event) {
+ const alert = { source: source, event: event };
+ return [
+ this.runCallback(''on'' + source + event, alert),
+ this.runCallback(''on'' + event, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.handleEventless = function(source) {
+ const alert = { source: source, event: null };
+ return [
+ this.runCallback(''on'' + source, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.run = function() {
+ var results = [];
+ if (typeof this.httpProxy === ''string'' && this.httpProxy.trim() !== '''') {
+ this.request.setProxy(this.httpProxy);
+ }
+ const types = { ''0'': ''Trigger'', ''1'': ''Discovery'', ''2'': ''Autoreg'', ''3'': ''Internal'', ''4'': ''Service'' };
+
+ if ([''0'', ''3'', ''4''].indexOf(this.params.event_source) !== -1) {
+ var event = (this.params.event_update_status === ''1'')
+ ? ''Update''
+ : ((this.params.event_value === ''1'') ? ''Problem'' : ''Resolve'');
+
+ results = this.handleEvent(types[this.params.event_source], event);
+ }
+ else if (typeof types[this.params.event_source] !== ''undefined'') {
+ results = this.handleEventless(types[this.params.event_source]);
+ }
+ else {
+ throw ''Unexpected "event_source": '' + this.params.event_source;
+ }
+
+ for (idx in results) {
+ if (typeof results[idx] !== ''undefined'') {
+ return JSON.stringify(results[idx]);
+ }
+ }
+ }
+ this.httpProxy = params.http_proxy;
+ this.params = params;
+ this.runCallback(''onCheckParams'', {});
+ } catch (error) {
+ throw ''Webhook processing failed: '' + error;
+ }
+}
+
+const CParamValidator = {
+
+ isType: function(value, type) {
+ if (type === ''array'') {
+ return Array.isArray(value);
+ }
+ if (type === ''integer'') {
+ return CParamValidator.isInteger(value);
+ }
+ if (type === ''float'') {
+ return CParamValidator.isFloat(value);
+ }
+
+ return (typeof value === type);
+ },
+
+ isInteger: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseInt(value));
+ },
+
+ isFloat: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+\\.\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseFloat(value));
+ },
+
+ isDefined: function(value) {
+ return !CParamValidator.isType(value, ''undefined'');
+ },
+
+ isEmpty: function(value) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be checked for emptiness.'';
+ }
+
+ return (value.trim() === '''');
+ },
+
+ isMacroSet: function(value, macro) {
+ if (CParamValidator.isDefined(macro)) {
+ return !(CParamValidator.ifMatch(value, ''^\\{'' + macro + ''\\}$''))
+ }
+
+ return !(CParamValidator.ifMatch(value, ''^\\{[$#]{0,1}[A-Z_\\.]+[\\:]{0,1}["]{0,1}.*["]{0,1}\\}$'') || value === ''*UNKNOWN*'')
+ },
+
+ withinRange: function(value, min, max) {
+ if (!CParamValidator.isType(value, ''number'')) {
+ throw ''Value "'' + value + ''" must be a number to be checked for range.'';
+ }
+ if (value < ((CParamValidator.isDefined(min)) ? min : value)
+ || value > ((CParamValidator.isDefined(max)) ? max : value)) {
+ return false;
+ }
+
+ return true;
+ },
+
+ inArray: function(value, array) {
+ if (!CParamValidator.isType(array, ''array'')) {
+ throw ''The array must be an array to check the value for existing in it.'';
+ }
+
+ return (array.indexOf((typeof value === ''string'') ? value.toLowerCase() : value) !== -1);
+ },
+
+ ifMatch: function(value, regex) {
+ return (new RegExp(regex)).test(value);
+ },
+
+ match: function(value, regex) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be matched with the regular expression.'';
+ }
+
+ return value.match(new RegExp(regex));
+ },
+
+ checkURL: function(value) {
+ if (CParamValidator.isEmpty(value)) {
+ throw ''URL value "'' + value + ''" must be a non-empty string.'';
+ }
+ if (!CParamValidator.ifMatch(value, ''^(http|https):\\/\\/.+'')) {
+ throw ''URL value "'' + value + ''" must contain a schema.'';
+ }
+
+ return value.endsWith(''/'') ? value.slice(0, -1) : value;
+ },
+
+ check: function(key, rule, params) {
+ if (!CParamValidator.isDefined(rule.type)) {
+ throw ''Mandatory attribute "type" has not been defined for parameter "'' + key + ''".'';
+ }
+ if (!CParamValidator.isDefined(params[key])) {
+ throw ''Checked parameter "'' + key + ''" was not found in the list of input parameters.'';
+ }
+ var value = params[key],
+ error_message = null;
+ switch (rule.type) {
+ case ''string'':
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + key + ''" must be a string.'';
+ }
+ if (CParamValidator.isEmpty(value)) {
+ error_message = ''Value "'' + key + ''" must be a non-empty string'';
+ break;
+ }
+ if (CParamValidator.isDefined(rule.len) && value.length < rule.len) {
+ error_message = ''Value "'' + key + ''" must be a string with a length > '' + rule.len;
+ }
+ if (CParamValidator.isDefined(rule.regex) && !CParamValidator.ifMatch(value, rule.regex)) {
+ error_message = ''Value "'' + key + ''" must match the regular expression "'' + rule.regex + ''"'';
+ }
+ if (CParamValidator.isDefined(rule.url) && rule.url === true) {
+ value = CParamValidator.checkURL(value);
+ }
+ break;
+ case ''integer'':
+ if (!CParamValidator.isInteger(value)) {
+ error_message = ''Value "'' + key + ''" must be an integer'';
+ break;
+ }
+ value = parseInt(value);
+ break;
+ case ''float'':
+ if (!CParamValidator.isFloat(value)) {
+ error_message = ''Value "'' + key + ''" must be a floating-point number'';
+ break;
+ }
+ value = parseFloat(value);
+ break;
+ case ''boolean'':
+ if (CParamValidator.inArray(value, [''1'', ''true'', ''yes'', ''on''])) {
+ value = true;
+ }
+ else if (CParamValidator.inArray(value, [''0'', ''false'', ''no'', ''off''])) {
+ value = false;
+ }
+ else {
+ error_message = ''Value "'' + key + ''" must be a boolean-like.'';
+ }
+ break;
+ case ''array'':
+ try {
+ value = JSON.parse(value);
+ } catch (error) {
+ throw ''Value "'' + key + ''" contains invalid JSON.'';
+ }
+ if (!CParamValidator.isType(value, ''array'')) {
+ error_message = ''Value "'' + key + ''" must be an array.'';
+ }
+ if (CParamValidator.isDefined(rule.tags) && rule.tags === true) {
+ value = value.reduce(function(acc, obj) {
+ acc[obj.tag] = obj.value || null;
+ return acc;
+ }, {});
+ }
+ break;
+ case ''object'':
+ value = JSON.parse(value);
+ if (!CParamValidator.isType(value, ''object'')) {
+ error_message = ''Value "'' + key + ''" must be an object.'';
+ }
+ break;
+ default:
+ throw ''Unexpected attribute type "'' + rule.type + ''" for value "'' + key + ''". Available: '' +
+ [''integer'', ''float'', ''string'', ''boolean'', ''array'', ''object''].join('', '');
+ }
+ params[key] = value;
+ if (CParamValidator.inArray(rule.type, [''integer'', ''float'']) && error_message === null && (CParamValidator.isDefined(rule.min)
+ || CParamValidator.isDefined(rule.max)) && !CParamValidator.withinRange(value, rule.min, rule.max)) {
+ error_message = ''Value "'' + key + ''" must be a number '' + ((CParamValidator.isDefined(rule.min) && CParamValidator.isDefined(rule.max))
+ ? (rule.min + ''..'' + rule.max) : ((CParamValidator.isDefined(rule.min)) ? ''>'' + rule.min : ''<'' + rule.max));
+ }
+ else if (CParamValidator.isDefined(rule.array) && !CParamValidator.inArray(value, rule.array)) {
+ error_message = ''Value "'' + key + ''" must be in the array '' + JSON.stringify(rule.array);
+ }
+ else if (CParamValidator.isDefined(rule.macro) && !CParamValidator.isMacroSet(value.toString(), rule.macro)) {
+ error_message = ''The macro '' + ((CParamValidator.isDefined(rule.macro)) ? ''{'' + rule.macro + ''} '' : '' '') + ''is not set'';
+ }
+ if (error_message !== null) {
+ if (CParamValidator.isDefined(rule.default) && CParamValidator.isType(rule.default, rule.type)) {
+ params[key] = rule.default;
+ }
+ else {
+ Zabbix.log(4, ''Default value for "'' + key + ''" must be a '' + rule.type + ''. Skipped.'');
+ throw ''Incorrect value for variable "'' + key + ''". '' + error_message;
+ }
+ }
+
+ return this;
+ },
+
+ validate: function(rules, params) {
+ if (!CParamValidator.isType(params, ''object'') || CParamValidator.isType(params, ''array'')) {
+ throw ''Incorrect parameters value. The value must be an object.'';
+ }
+ for (var key in rules) {
+ CParamValidator.check(key, rules[key], params);
+ }
+ }
+}
+
+const CHttpRequest = function(logger) {
+ this.request = new HttpRequest();
+ if (typeof logger !== ''object'' || logger === null) {
+ this.logger = Zabbix;
+ }
+ else {
+ this.logger = logger;
+ }
+
+ this.clearHeader = function() {
+ this.request.clearHeader();
+ }
+
+ this.addHeaders = function(value) {
+ var headers = [];
+
+ if (typeof value === ''object'' && value !== null) {
+ if (!Array.isArray(value)) {
+ Object.keys(value).forEach(function(key) {
+ headers.push(key + '': '' + value[key]);
+ });
+ }
+ else {
+ headers = value;
+ }
+ }
+ else if (typeof value === ''string'') {
+ value.split(''\\r\\n'').forEach(function(header) {
+ headers.push(header);
+ });
+ }
+
+ for (var idx in headers) {
+ this.request.addHeader(headers[idx]);
+ }
+ }
+
+ this.setProxy = function(proxy) {
+ this.request.setProxy(proxy);
+ }
+
+ this.plainRequest = function(method, url, data) {
+ var resp = null;
+ method = method.toLowerCase();
+ this.logger.log(4, ''Sending '' + method + '' request:'' + JSON.stringify(data));
+ if ([''get'', ''post'', ''put'', ''patch'', ''delete'', ''trace''].indexOf(method) !== -1) {
+ resp = this.request[method](url, data);
+ }
+ else if ([''connect'', ''head'', ''options''].indexOf(method) !== -1) {
+ resp = this.request[method](url);
+ }
+ else {
+ throw ''Unexpected method. Method '' + method + '' is not supported.'';
+ }
+ this.logger.log(4, ''Response has been received: '' + resp);
+
+ return resp;
+ }
+
+ this.jsonRequest = function(method, url, data) {
+ this.addHeaders(''Content-Type: application/json'');
+ var resp = this.plainRequest(method, url, JSON.stringify(data));
+ try {
+ resp = JSON.parse(resp);
+ }
+ catch (error) {
+ throw ''Failed to parse response: not well-formed JSON was received'';
+ }
+
+ return resp;
+ }
+
+ this.getStatus = function() {
+ return this.request.getStatus();
+ }
+}
+
+const CWebhookHelper = {
+
+ createProblemURL: function(event_source, zabbix_url, trigger_id, event_id) {
+ if (event_source === ''0'') {
+ return zabbix_url + ''/tr_events.php?triggerid='' + trigger_id + ''&eventid='' + event_id;
+ } else if (event_source === ''4'') {
+ return zabbix_url + ''/zabbix.php?action=service.list'';
+ }
+
+ return zabbix_url;
+ },
+
+};
+
+const serviceLogName = ''GLPi Webhook'',
+ Logger = new CLogger(serviceLogName),
+ GLPi = CWebhook;
+
+GLPi.prototype.onCheckParams = function () {
+ CParamValidator.validate({
+ alert_message: { type: ''string'' },
+ alert_subject: { type: ''string'' },
+ zabbix_url: { type: ''string'', url: true },
+ glpi_url: { type: ''string'', url: true },
+ glpi_user_token: { type: ''string'' }
+ }, this.params);
+
+ this.params.use_app_token = false;
+
+ if (CParamValidator.isDefined(this.params.glpi_app_token) && !CParamValidator.isEmpty(this.params.glpi_app_token)) {
+ this.params.use_app_token = true;
+ }
+
+ if (this.params.event_source === ''0'') {
+ CParamValidator.validate({ trigger_id: { type: ''integer'' }, event_id: { type: ''integer'' } }, this.params);
+ this.params.zabbix_url = CWebhookHelper.createProblemURL(this.params.event_source, this.params.zabbix_url, this.params.trigger_id, this.params.event_id);
+ }
+
+ if (params.event_value != ''0'' && CParamValidator.isMacroSet(this.params.glpi_problem_id)) {
+ this.params.event_update_status = ''1'';
+ }
+
+ this.data = {
+ input: {
+ name: this.params.alert_subject,
+ urgency: (this.params.event_nseverity = isNaN(Number(this.params.event_nseverity)) ? 2 : this.params.event_nseverity)
+ }
+ };
+
+ this.dataFollowup = {
+ input: {
+ items_id: this.params.glpi_problem_id,
+ itemtype: ''Problem'',
+ content: this.params.alert_message + ''
Link to problem in Zabbix'',
+ }
+ };
+
+ this.result = { tags: {} };
+}
+
+GLPi.prototype.getAuthToken = function () {
+
+ this.request.addHeaders(''Authorization: user_token '' + this.params.glpi_user_token);
+ if (this.params.use_app_token) {
+ this.request.addHeaders(''App-Token: '' + this.params.glpi_app_token);
+ }
+ var response = this.request.jsonRequest(''post'', this.params.glpi_url + ''/apirest.php/initSession'');
+
+ if ((this.request.getStatus() !== 200 && this.request.getStatus() !== 201)) {
+ Logger.log(Logger.INFO, ''HTTP code: '' + this.request.getStatus());
+ if (CParamValidator.isType(response.description, ''string'')) {
+ throw response.description;
+ }
+ else {
+ Logger.log(Logger.INFO, ''Request not successful. Received response: '' + JSON.stringify(response));
+ throw ''Unknown INFO. Check debug log for more information.'';
+ }
+ }
+ if (!CParamValidator.isType(response.session_token, ''string'') || CParamValidator.isEmpty(response.session_token)) {
+ Logger.log(Logger.INFO, ''Check getting GLPi sessionToken: '' + response.session_token);
+ throw ''Required GLPi sessionToken is not received.'';
+ }
+
+ return response.session_token;
+}
+
+GLPi.prototype.sendRequest = function (method, path, data) {
+
+ this.request.clearHeader();
+ this.request.addHeaders(''Session-Token:'' + this.params.authToken);
+ if (this.params.use_app_token) {
+ this.request.addHeaders(''App-Token: '' + this.params.glpi_app_token);
+ }
+ var response = this.request.jsonRequest(method, this.params.glpi_url + path, data);
+
+ if ((this.request.getStatus() !== 200 && this.request.getStatus() !== 201)) {
+ Logger.log(Logger.INFO, ''HTTP code: '' + this.request.getStatus());
+ if (CParamValidator.isType(response.description, ''string'')) {
+ throw response.description;
+ }
+ else {
+ Logger.log(Logger.INFO, ''Request not successful. Received response: '' + JSON.stringify(response));
+ throw ''Unknown INFO. Check debug log for more information.'';
+ }
+ }
+
+ return response;
+}
+
+GLPi.prototype.createProblem = function (status) {
+ this.data.input.content = this.params.alert_message + ''
Link to problem in Zabbix'';
+
+ if (CParamValidator.isDefined(status)) {
+ this.data.input.status = status;
+ }
+
+ var response = this.sendRequest(''post'', ''/apirest.php/Problem/'', this.data);
+
+ if (!CParamValidator.isDefined(response.id)) {
+ throw ''Cannot create GPLi problem. Check debug log for more information.'';
+ }
+
+ return response.id
+}
+
+GLPi.prototype.updateProblem = function (status) {
+ CParamValidator.validate({ glpi_problem_id: { type: ''string'' } }, this.params);
+ this.data.id = this.params.glpi_problem_id;
+
+ if (CParamValidator.isDefined(status)) {
+ this.data.input.status = status;
+ }
+
+ this.sendRequest(''put'', ''/apirest.php/Problem/'' + this.params.glpi_problem_id, this.data);
+ this.sendRequest(''post'', ''/apirest.php/Problem/'' + this.params.glpi_problem_id + ''/ITILFollowup'', this.dataFollowup);
+}
+
+GLPi.prototype.onProblem = function (alert) {
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+ const problem_id = this.createProblem(1)
+
+ this.result.tags.__zbx_glpi_problem_id = problem_id;
+ this.result.tags.__zbx_glpi_link = this.params.glpi_url + ''/front/problem.form.php?id='' + problem_id;
+
+ return this.result;
+}
+
+GLPi.prototype.onUpdate = function (alert) {
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+ this.updateProblem();
+
+ return this.result;
+}
+
+GLPi.prototype.onResolve = function (alert) {
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+ this.updateProblem(5);
+
+ return this.result;
+}
+
+GLPi.prototype.onDiscovery = function () {
+ return this.createProblem();
+}
+
+GLPi.prototype.onAutoreg = function () {
+ return this.createProblem();
+}
+
+try {
+ var hook = new GLPi(value);
+ hook.request = new CHttpRequest(Logger);
+ hook.params.authToken = hook.getAuthToken();
+ return hook.run();
+}
+catch (error) {
+ Logger.log(Logger.WARN, ''notification failed: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','1','{EVENT.TAGS.__zbx_glpi_link}','GLPi: Problem {EVENT.TAGS.__zbx_glpi_problem_id}','This media type integrates your Zabbix installation with your GLPi installation using the Zabbix webhook feature.
+
+GLPi configuration:
+
+1. Enable access to the GLPi REST API:
+- In the GLPi web interface, go to "Setup" → "General" → "API".
+- Set the "Enable Rest API" and "Enable Rest API" options to "Yes" and click the "Save" button.
+
+2. Add a new API client:
+- Click the "Add API client" button.
+- Specify the API client name and set the "Active" option to "Yes".
+- For security reasons, you may want to restrict the API client to the IP address of Zabbix server and/or create an additional application token (will be generated by default; you can uncheck the "Regenerate" checkbox if you don''t want to use it).
+- Click the "Add" button.
+- If you''ve opted to create an application token, open the settings of the created API client, and then copy and save the generated application token.
+
+3. Create a new user profile with permissions to create problems and followups (alternatively, you can use an existing profile with sufficient privileges):
+- Go to "Administration" → "Profiles" and click the "Add" button on the top of the page.
+- Specify the profile name and set the "Profile''s Interface" option to "Standard Interface", and then click the "Add" button.
+- Open the created profile and click the "Assistance" tab.
+- Set the "Add followup (requester)" permission for the "Followups" line in the "Followups/Tasks" section.
+- Set the "Update", "Create", and "See all" permissions in the "Problems" section.
+- Click the "Save" button.
+
+4. Create a new user:
+- Go to "Administration" → "Users" and click the "Add User" button on the top of the page.
+- Specify the user login and set the "Profiles" option to the profile that you created in the previous step (or any other existing profile with permissions to create problems and followups).
+- Click the "Add" button.
+- Open the profile of the created user and check the "Regenerate" checkbox of the "API token" option; click "Save".
+- Copy and save the generated user API token.
+
+Zabbix configuration:
+
+1. Before you can start using the GLPi webhook, set the global macro "{$ZABBIX.URL}":
+- In the Zabbix web interface, go to "Administration" → "Macros" in the top-left drop-down menu.
+- Set the global macro "{$ZABBIX.URL}" to the URL of the Zabbix frontend. The URL should be either an IP address, a fully qualified domain name, or localhost.
+- Specifying a protocol is mandatory, whereas the port is optional. Depending on the web server configuration, you might also need to append "/zabbix" to the end of URL. Good examples:
+ - http://zabbix.com
+ - https://zabbix.lan/zabbix
+ - http://server.zabbix.lan/
+ - http://localhost
+ - http://127.0.0.1:8080
+- Bad examples:
+ - zabbix.com
+ - http://zabbix/
+
+2. Set the following webhook parameters:
+- glpi_app_token - if you''ve opted to use an application token during the creation of API client, specify it here; otherwise leave it empty
+- glpi_url - the frontend URL of your GLPi installation
+- glpi_user_token - the user token that was generated during creation of GLPi user
+
+3. Click the "Enabled" checkbox to enable the media type and click the "Update" button to save the webhook settings.
+
+4. Create a Zabbix user and add media:
+- To create a new user, go to the "Users" → "Users" section, click the "Create user" button in the top right corner. In the "User" tab, fill in all required fields (marked with red asterisks).
+- In the "Media" tab, click "Add" and select the type "GLPi" from the drop-down list. Add any value in the "Send to" field: it is not used in the webhook, but is required.
+- Make sure this user has access to all hosts for which you would like problem notifications to be sent to GLPi.
+
+5. Done! You can now start using this media type in actions and create problem items in GLPi.
+
+You can find the latest version of this media and additional information in the official Zabbix repository:
+https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/templates/media/glpi','0'),
+('76','4','iLert','','','','','','','','25','0','0','0','0','1','3','10s','1','try {
+ var result = { tags: {} },
+ params = JSON.parse(value),
+ req = new HttpRequest(),
+ resp = '''';
+
+ if (typeof params.HTTPProxy === ''string'' && params.HTTPProxy.trim() !== '''') {
+ req.setProxy(params.HTTPProxy);
+ }
+ var alertSourceKey = params[''.ILERT.ALERT.SOURCE.KEY''];
+ if (!alertSourceKey || (typeof alertSourceKey === ''string'' && alertSourceKey.trim() === '''')) {
+ throw ''incorrect value for variable "ILERT.ALERT.SOURCE.KEY". The value must be a non-empty string.'';
+ }
+ delete params[''.ILERT.ALERT.SOURCE.KEY''];
+
+ var ilertApiBaseURL = "https://api.ilert.com";
+ var reqURL = encodeURI(ilertApiBaseURL + "/api/v1/events/zabbix-mt/" + alertSourceKey)
+
+ var incidentKey = "zabbix-" + params[''EVENT.ID''];
+ var incidentViewURL = ilertApiBaseURL + "/api/v1/incidents/resolve-ik/" + alertSourceKey + "/" + incidentKey;
+
+ req.addHeader(''Accept: application/json'');
+ req.addHeader(''Content-Type: application/json'');
+
+ Zabbix.log(4, ''[iLert Webhook] Sending request:'' + JSON.stringify(params));
+ resp = req.post(reqURL, JSON.stringify(params));
+ Zabbix.log(4, ''[iLert Webhook] Receiving response:'' + resp);
+
+ try {
+ resp = JSON.parse(resp);
+ }
+ catch (error) {
+ throw ''incorrect response. iLert returned a non-JSON object.'';
+ }
+
+ if (req.getStatus() == 200) {
+ result.tags.__ilert_incident_url = incidentViewURL;
+ return JSON.stringify(result);
+ }
+
+ if (req.getStatus() == 400 && typeof resp === ''object'' && typeof resp.code === ''string'') {
+ if (resp.code === ''NO_OPEN_INCIDENT_WITH_KEY'') {
+ return JSON.stringify(result);
+ }
+ if (resp.code === ''INCIDENT_ALREADY_ACCEPTED'') {
+ result.tags.__ilert_incident_url = incidentViewURL;
+ return JSON.stringify(result);
+ }
+ }
+
+ if (typeof resp === ''object'' && typeof resp.message === ''string'') {
+ throw resp.message;
+ }
+ else {
+ throw ''Unknown error.'';
+ }
+}
+catch (error) {
+ Zabbix.log(3, ''[iLert Webhook] Notification failed : '' + error);
+ throw ''iLert notification failed : '' + error;
+}','30s','1','1','{EVENT.TAGS.__ilert_incident_url}','iLert incident','Please refer to https://docs.ilert.com/integrations/zabbix/native
+
+Set global macro {$ZABBIX.URL} with your Zabbix server URL.
+Add a dedicated user with the media type "iLert". You can also rewrite the incident summary via ".ILERT.INCIDENT.SUMMARY" parameter or leave it empty to use the standard pattern.','0'),
+('77','4','iTop','','','','','','','','25','0','0','0','0','1','3','10s','1',E'var Itop = {
+ params: {},
+
+ setParams: function (params) {
+ if (typeof params !== ''object'') {
+ return;
+ }
+
+ if (params.log !== ''private_log'' && params.log !== ''public_log'') {
+ throw ''Incorrect "itop_log" parameter given: '' + params.log + ''\\nMust be "private_log" or "public_log".'';
+ }
+
+ Itop.params = params;
+ if (typeof Itop.params.url === ''string'') {
+ if (!Itop.params.url.endsWith(''/'')) {
+ Itop.params.url += ''/'';
+ }
+
+ Itop.params.url += ''webservices/rest.php?version='' + encodeURIComponent(Itop.params.api_version);
+ }
+ },
+
+ setProxy: function (HTTPProxy) {
+ Itop.HTTPProxy = HTTPProxy;
+ },
+
+ setCreatePayload: function () {
+ json_data.operation = ''core/create'';
+ json_data.fields.org_id = Itop.params.organization_id;
+ json_data.fields.title = params.alert_subject;
+ json_data.fields.description = params.alert_message.replace(''<'', ''<'')
+ .replace(''>'', ''>'')
+ .replace(/(?:\\r\\n|\\r|\\n)/g, ''
'');
+ },
+
+ setUpdatePayload: function () {
+ json_data.operation = ''core/update'';
+ json_data.key = Itop.params.id;
+ json_data.fields.title = params.alert_subject;
+ json_data.fields[Itop.params.log] = {
+ add_item: {
+ message: params.alert_subject + ''\\n'' + params.alert_message,
+ format: ''text''
+ }
+ };
+ },
+
+ request: function (data) {
+ [''url'', ''user'', ''password'', ''organization_id'', ''class'', ''api_version'', ''id''].forEach(function (field) {
+ if (typeof Itop.params !== ''object'' || typeof Itop.params[field] === ''undefined''
+ || Itop.params[field] === '''' ) {
+ throw ''Required Itop param is not set: "itop_'' + field + ''".'';
+ }
+ });
+
+ var response,
+ url = Itop.params.url,
+ request = new HttpRequest(),
+ object;
+
+ request.addHeader(''Content-Type: multipart/form-data'');
+ request.addHeader(''Authorization: Basic '' + btoa(Itop.params.user + '':'' + Itop.params.password));
+
+ if (Itop.HTTPProxy) {
+ request.setProxy(Itop.HTTPProxy);
+ }
+
+ if (typeof data !== ''undefined'') {
+ data = JSON.stringify(data);
+ }
+
+ Zabbix.log(4, ''[ iTop Webhook ] Sending request: '' + url + ''&json_data='' + data);
+
+ response = request.post(url + ''&json_data='' + encodeURIComponent(data));
+
+ Zabbix.log(4, ''[ iTop Webhook ] Received response with status code '' + request.getStatus() + ''\\n'' + response);
+
+ try {
+ response = JSON.parse(response);
+ }
+ catch (error) {
+ Zabbix.log(4, ''[ iTop Webhook ] Failed to parse response received from iTop'');
+ throw ''Failed to parse response received from iTop.\\nRequest status code '' +
+ request.getStatus() + ''. Check debug log for more information.'';
+ }
+
+ if (request.getStatus() < 200 || request.getStatus() >= 300) {
+ throw ''Request failed with status code '' + request.getStatus() + ''. Check debug log for more information.'';
+ }
+ else if (typeof response.code !== ''undefined'' && response.code !== 0) {
+ throw ''Request failed with iTop code '' + response.code + '': '' +
+ JSON.stringify(response.message) + ''. Check debug log for more information.'';
+ }
+ else {
+ Object.keys(response.objects)
+ .forEach(function (key) {
+ object = response.objects[key];
+ });
+
+ return {
+ status: request.getStatus(),
+ response: object.fields
+ };
+ }
+ }
+};
+
+try {
+ var params = JSON.parse(value),
+ json_data = {},
+ itop_params = {},
+ result = {tags: {}},
+ required_params = [
+ ''alert_subject'', ''summary'', ''event_recovery_value'',
+ ''event_source'', ''event_value'', ''action_name''
+ ];
+
+ Object.keys(params)
+ .forEach(function (key) {
+ if (key.startsWith(''itop_'')) {
+ itop_params[key.substring(5)] = params[key];
+ }
+ else if (required_params.indexOf(key) !== -1 && params[key] === '''') {
+ throw ''Parameter "'' + key + ''" can\\''t be empty.'';
+ }
+ });
+
+ if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''\\nMust be 0-3.'';
+ }
+
+ // 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_source !== ''0'' && params.event_recovery_value === ''0'') {
+ throw ''Recovery operations are supported only for trigger-based actions.'';
+ }
+
+ Itop.setParams(itop_params);
+ Itop.setProxy(params.HTTPProxy);
+
+ json_data.operation = '''';
+ json_data.class = Itop.params.class;
+ json_data.comment = Itop.params.comment;
+ json_data.output_fields = ''id, friendlyname'';
+ json_data.fields = {};
+
+ // Create issue for non trigger-based events.
+ if (params.event_source !== ''0'' && params.event_recovery_value !== ''0'') {
+ Itop.setCreatePayload();
+ Itop.request(json_data);
+ }
+ // Create issue for trigger-based events.
+ else if (params.event_value === ''1'' && params.event_update_status === ''0''
+ && (Itop.params.id === ''{EVENT.TAGS.__zbx_itop_id}'' || Itop.params.id === ''*UNKNOWN*'')) {
+ Itop.setCreatePayload();
+
+ var response = Itop.request(json_data);
+
+ result.tags.__zbx_itop_id = response.response.id;
+ result.tags.__zbx_itop_key = response.response.friendlyname;
+ result.tags.__zbx_itop_link = params.itop_url + (params.itop_url.endsWith(''/'') ? '''' : ''/'') +
+ ''pages/UI.php?operation=details&class='' + encodeURIComponent(Itop.params.class) + ''&id='' +
+ encodeURIComponent(response.response.id);
+ }
+ // Update created issue for trigger-based event.
+ else {
+ if (Itop.params.id === ''{EVENT.TAGS.__zbx_itop_id}'' || Itop.params.id === ''*UNKNOWN*'') {
+ throw ''Incorrect iTop ticket ID given: '' + Itop.params.id;
+ }
+ Itop.setUpdatePayload();
+ Itop.request(json_data);
+ }
+
+ return JSON.stringify(result);
+}
+catch (error) {
+ Zabbix.log(3, ''[ iTop Webhook ] ERROR: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','1','{EVENT.TAGS.__zbx_itop_link}','iTop: {EVENT.TAGS.__zbx_itop_key}','','0'),
+('78','4','Jira','','','','','','','','25','0','0','0','0','1','3','10s','1',E'const CLogger = function(serviceName) {
+ this.serviceName = serviceName;
+ this.INFO = 4
+ this.WARN = 3
+ this.ERROR = 2
+ this.log = function(level, msg) {
+ Zabbix.log(level, ''['' + this.serviceName + ''] '' + msg);
+ }
+}
+
+const CWebhook = function(value) {
+ try {
+ params = JSON.parse(value);
+
+ if ([''0'', ''1'', ''2'', ''3'', ''4''].indexOf(params.event_source) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''.\\nMust be 0-4.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1 && [''0'', ''1''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0 or 1.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1) {
+ if (params.event_source === ''1'' && [''0'', ''1'', ''2'', ''3''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0-3.'';
+ }
+
+ if (params.event_source === ''0'' && [''0'', ''1''].indexOf(params.event_update_status) === -1) {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''.\\nMust be 0 or 1.'';
+ }
+
+ if (params.event_source === ''4'') {
+ if ([''0'', ''1'', ''2'', ''3'', ''4'', ''5''].indexOf(params.event_update_nseverity) !== -1 && params.event_update_nseverity != params.event_nseverity) {
+ params.event_nseverity = params.event_update_nseverity;
+ params.event_severity = params.event_update_severity;
+ params.event_update_status = ''1'';
+ }
+ }
+ }
+
+ this.runCallback = function(name, params) {
+ if (typeof this[name] === ''function'') {
+ return this[name].apply(this, [params]);
+ }
+ }
+
+ this.handleEvent = function(source, event) {
+ const alert = { source: source, event: event };
+ return [
+ this.runCallback(''on'' + source + event, alert),
+ this.runCallback(''on'' + event, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.handleEventless = function(source) {
+ const alert = { source: source, event: null };
+ return [
+ this.runCallback(''on'' + source, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.run = function() {
+ var results = [];
+ if (typeof this.httpProxy === ''string'' && this.httpProxy.trim() !== '''') {
+ this.request.setProxy(this.httpProxy);
+ }
+ const types = { ''0'': ''Trigger'', ''1'': ''Discovery'', ''2'': ''Autoreg'', ''3'': ''Internal'', ''4'': ''Service'' };
+
+ if ([''0'', ''3'', ''4''].indexOf(this.params.event_source) !== -1) {
+ var event = (this.params.event_update_status === ''1'')
+ ? ''Update''
+ : ((this.params.event_value === ''1'') ? ''Problem'' : ''Resolve'');
+
+ results = this.handleEvent(types[this.params.event_source], event);
+ }
+ else if (typeof types[this.params.event_source] !== ''undefined'') {
+ results = this.handleEventless(types[this.params.event_source]);
+ }
+ else {
+ throw ''Unexpected "event_source": '' + this.params.event_source;
+ }
+
+ for (idx in results) {
+ if (typeof results[idx] !== ''undefined'') {
+ return JSON.stringify(results[idx]);
+ }
+ }
+ }
+ this.httpProxy = params.http_proxy;
+ this.params = params;
+ this.runCallback(''onCheckParams'', {});
+ } catch (error) {
+ throw ''Webhook processing failed: '' + error;
+ }
+}
+
+const CWebhookHelper = {
+
+ createProblemURL: function(event_source, zabbix_url, trigger_id, event_id) {
+ if (event_source === ''0'') {
+ return zabbix_url + ''/tr_events.php?triggerid='' + trigger_id + ''&eventid='' + event_id;
+ } else if (event_source === ''4'') {
+ return zabbix_url + ''/zabbix.php?action=service.list'';
+ }
+
+ return zabbix_url;
+ },
+
+};
+
+const CParamValidator = {
+
+ isType: function(value, type) {
+ if (type === ''array'') {
+ return Array.isArray(value);
+ }
+ if (type === ''integer'') {
+ return CParamValidator.isInteger(value);
+ }
+ if (type === ''float'') {
+ return CParamValidator.isFloat(value);
+ }
+
+ return (typeof value === type);
+ },
+
+ isInteger: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseInt(value));
+ },
+
+ isFloat: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+\\.\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseFloat(value));
+ },
+
+ isDefined: function(value) {
+ return !CParamValidator.isType(value, ''undefined'');
+ },
+
+ isEmpty: function(value) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be checked for emptiness.'';
+ }
+
+ return (value.trim() === '''');
+ },
+
+ isMacroSet: function(value, macro) {
+ if (CParamValidator.isDefined(macro)) {
+ return !(CParamValidator.ifMatch(value, ''^\\{'' + macro + ''\\}$''))
+ }
+
+ return !(CParamValidator.ifMatch(value, ''^\\{[$#]{0,1}[A-Z_\\.]+[\\:]{0,1}["]{0,1}.*["]{0,1}\\}$'') || value === ''*UNKNOWN*'')
+ },
+
+ withinRange: function(value, min, max) {
+ if (!CParamValidator.isType(value, ''number'')) {
+ throw ''Value "'' + value + ''" must be a number to be checked for range.'';
+ }
+ if (value < ((CParamValidator.isDefined(min)) ? min : value)
+ || value > ((CParamValidator.isDefined(max)) ? max : value)) {
+ return false;
+ }
+
+ return true;
+ },
+
+ inArray: function(value, array) {
+ if (!CParamValidator.isType(array, ''array'')) {
+ throw ''The array must be an array to check the value for existing in it.'';
+ }
+
+ return (array.indexOf((typeof value === ''string'') ? value.toLowerCase() : value) !== -1);
+ },
+
+ ifMatch: function(value, regex) {
+ return (new RegExp(regex)).test(value);
+ },
+
+ match: function(value, regex) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be matched with the regular expression.'';
+ }
+
+ return value.match(new RegExp(regex));
+ },
+
+ checkURL: function(value) {
+ if (CParamValidator.isEmpty(value)) {
+ throw ''URL value "'' + value + ''" must be a non-empty string.'';
+ }
+ if (!CParamValidator.ifMatch(value, ''^(http|https):\\/\\/.+'')) {
+ throw ''URL value "'' + value + ''" must contain a schema.'';
+ }
+
+ return value.endsWith(''/'') ? value.slice(0, -1) : value;
+ },
+
+ check: function(key, rule, params) {
+ if (!CParamValidator.isDefined(rule.type)) {
+ throw ''Mandatory attribute "type" has not been defined for parameter "'' + key + ''".'';
+ }
+ if (!CParamValidator.isDefined(params[key])) {
+ throw ''Checked parameter "'' + key + ''" was not found in the list of input parameters.'';
+ }
+ var value = params[key],
+ error_message = null;
+ switch (rule.type) {
+ case ''string'':
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + key + ''" must be a string.'';
+ }
+ if (CParamValidator.isEmpty(value)) {
+ error_message = ''Value "'' + key + ''" must be a non-empty string'';
+ break;
+ }
+ if (CParamValidator.isDefined(rule.len) && value.length < rule.len) {
+ error_message = ''Value "'' + key + ''" must be a string with a length > '' + rule.len;
+ }
+ if (CParamValidator.isDefined(rule.regex) && !CParamValidator.ifMatch(value, rule.regex)) {
+ error_message = ''Value "'' + key + ''" must match the regular expression "'' + rule.regex + ''"'';
+ }
+ if (CParamValidator.isDefined(rule.url) && rule.url === true) {
+ value = CParamValidator.checkURL(value);
+ }
+ break;
+ case ''integer'':
+ if (!CParamValidator.isInteger(value)) {
+ error_message = ''Value "'' + key + ''" must be an integer'';
+ break;
+ }
+ value = parseInt(value);
+ break;
+ case ''float'':
+ if (!CParamValidator.isFloat(value)) {
+ error_message = ''Value "'' + key + ''" must be a floating-point number'';
+ break;
+ }
+ value = parseFloat(value);
+ break;
+ case ''boolean'':
+ if (CParamValidator.inArray(value, [''1'', ''true'', ''yes'', ''on''])) {
+ value = true;
+ }
+ else if (CParamValidator.inArray(value, [''0'', ''false'', ''no'', ''off''])) {
+ value = false;
+ }
+ else {
+ error_message = ''Value "'' + key + ''" must be a boolean-like.'';
+ }
+ break;
+ case ''array'':
+ try {
+ value = JSON.parse(value);
+ } catch (error) {
+ throw ''Value "'' + key + ''" contains invalid JSON.'';
+ }
+ if (!CParamValidator.isType(value, ''array'')) {
+ error_message = ''Value "'' + key + ''" must be an array.'';
+ }
+ if (CParamValidator.isDefined(rule.tags) && rule.tags === true) {
+ value = value.reduce(function(acc, obj) {
+ acc[obj.tag] = obj.value || null;
+ return acc;
+ }, {});
+ }
+ break;
+ case ''object'':
+ value = JSON.parse(value);
+ if (!CParamValidator.isType(value, ''object'')) {
+ error_message = ''Value "'' + key + ''" must be an object.'';
+ }
+ break;
+ default:
+ throw ''Unexpected attribute type "'' + rule.type + ''" for value "'' + key + ''". Available: '' +
+ [''integer'', ''float'', ''string'', ''boolean'', ''array'', ''object''].join('', '');
+ }
+ params[key] = value;
+ if (CParamValidator.inArray(rule.type, [''integer'', ''float'']) && error_message === null && (CParamValidator.isDefined(rule.min)
+ || CParamValidator.isDefined(rule.max)) && !CParamValidator.withinRange(value, rule.min, rule.max)) {
+ error_message = ''Value "'' + key + ''" must be a number '' + ((CParamValidator.isDefined(rule.min) && CParamValidator.isDefined(rule.max))
+ ? (rule.min + ''..'' + rule.max) : ((CParamValidator.isDefined(rule.min)) ? ''>'' + rule.min : ''<'' + rule.max));
+ }
+ else if (CParamValidator.isDefined(rule.array) && !CParamValidator.inArray(value, rule.array)) {
+ error_message = ''Value "'' + key + ''" must be in the array '' + JSON.stringify(rule.array);
+ }
+ else if (CParamValidator.isDefined(rule.macro) && !CParamValidator.isMacroSet(value.toString(), rule.macro)) {
+ error_message = ''The macro '' + ((CParamValidator.isDefined(rule.macro)) ? ''{'' + rule.macro + ''} '' : '' '') + ''is not set'';
+ }
+ if (error_message !== null) {
+ if (CParamValidator.isDefined(rule.default) && CParamValidator.isType(rule.default, rule.type)) {
+ params[key] = rule.default;
+ }
+ else {
+ Zabbix.log(4, ''Default value for "'' + key + ''" must be a '' + rule.type + ''. Skipped.'');
+ throw ''Incorrect value for variable "'' + key + ''". '' + error_message;
+ }
+ }
+
+ return this;
+ },
+
+ validate: function(rules, params) {
+ if (!CParamValidator.isType(params, ''object'') || CParamValidator.isType(params, ''array'')) {
+ throw ''Incorrect parameters value. The value must be an object.'';
+ }
+ for (var key in rules) {
+ CParamValidator.check(key, rules[key], params);
+ }
+ }
+}
+
+const CHttpRequest = function(logger) {
+ this.request = new HttpRequest();
+ if (typeof logger !== ''object'' || logger === null) {
+ this.logger = Zabbix;
+ }
+ else {
+ this.logger = logger;
+ }
+
+ this.clearHeader = function() {
+ this.request.clearHeader();
+ }
+
+ this.addHeaders = function(value) {
+ var headers = [];
+
+ if (typeof value === ''object'' && value !== null) {
+ if (!Array.isArray(value)) {
+ Object.keys(value).forEach(function(key) {
+ headers.push(key + '': '' + value[key]);
+ });
+ }
+ else {
+ headers = value;
+ }
+ }
+ else if (typeof value === ''string'') {
+ value.split(''\\r\\n'').forEach(function(header) {
+ headers.push(header);
+ });
+ }
+
+ for (var idx in headers) {
+ this.request.addHeader(headers[idx]);
+ }
+ }
+
+ this.setProxy = function(proxy) {
+ this.request.setProxy(proxy);
+ }
+
+ this.plainRequest = function(method, url, data) {
+ var resp = null;
+ method = method.toLowerCase();
+ this.logger.log(4, ''Sending '' + method + '' request:'' + JSON.stringify(data));
+ if ([''get'', ''post'', ''put'', ''patch'', ''delete'', ''trace''].indexOf(method) !== -1) {
+ resp = this.request[method](url, data);
+ }
+ else if ([''connect'', ''head'', ''options''].indexOf(method) !== -1) {
+ resp = this.request[method](url);
+ }
+ else {
+ throw ''Unexpected method. Method '' + method + '' is not supported.'';
+ }
+ this.logger.log(4, ''Response has been received: '' + resp);
+
+ return resp;
+ }
+
+ this.jsonRequest = function(method, url, data) {
+ this.addHeaders(''Content-Type: application/json'');
+ var resp = this.plainRequest(method, url, JSON.stringify(data));
+ try {
+ resp = JSON.parse(resp);
+ }
+ catch (error) {
+ throw ''Failed to parse response: not well-formed JSON was received'';
+ }
+
+ return resp;
+ }
+
+ this.getStatus = function() {
+ return this.request.getStatus();
+ }
+}
+
+var ZABBIX_SEVERITY_MAP = ["not_classified", "information", "warning", "average", "high", "disaster"];
+
+var serviceLogName = ''Jira Webhook'',
+ Logger = new CLogger(serviceLogName),
+ Jira = CWebhook;
+
+Jira.prototype.onCheckParams = function () {
+ CParamValidator.validate({
+ jira_url: { type: ''string'', url: true},
+ jira_user: { type: ''string'' },
+ jira_password: { type: ''string'' },
+ jira_issue_type: { type: ''string'' },
+ jira_project_key: { type: ''string'' },
+ event_source: { type: ''string'' },
+ alert_subject: { type: ''string'' },
+ alert_message: { type: ''string'' },
+ event_nseverity: { type: ''integer'', default: 0 }
+ }, this.params);
+
+ this.priority = this.params.event_source == 3 ? this.params.jira_priority_internal : this.params[''severity_'' + ZABBIX_SEVERITY_MAP[this.params.event_nseverity]];
+ this.params.event_tags_json = parseTags(this.params.event_tags_json, false);
+
+ if (this.params.event_tags_json.length > 0) {
+ this.labels = setLabels(this.params.event_tags_json);
+ }
+
+ parseOptionalFields();
+
+ this.result = { tags: {} };
+}
+
+function escapeMarkup(str) {
+ var length = str.length,
+ result = '''',
+ markup = [''{'', ''|'', ''}'', ''~'', ''_'', ''\\\\'', ''['', '']'', ''^'', ''<'', ''>'', ''?'', ''!'', ''#'', ''+'', ''*'', ''&''];
+
+ for (var i = 0; i < length; i++) {
+ var char = str[i];
+ result += (markup.indexOf(char) !== -1) ? ('''' + str[i].charCodeAt() + '';'') : char;
+ }
+
+ return result;
+}
+
+function parseOptionalFields() {
+ this.params.customfields = {};
+ this.params.components = [];
+
+ Object.keys(this.params).forEach(function (key) {
+ if (key.startsWith(''customfield_'')) {
+ this.params.customfields[key] = this.params[key];
+ }
+
+ if (key.startsWith(''component_'')) {
+ this.params.components.push({"name": this.params[key]})
+ }
+ });
+}
+
+Jira.prototype.addCustomFields = function (data) {
+ if (typeof this.params.customfields === ''object'' && Object.keys(this.params.customfields).length) {
+ var schemaData = this.sendRequest(''GET'', ''/rest/api/latest/field''),
+ schema = {};
+
+ schemaData.forEach(function (item) {
+ schema[item.id] = item.schema;
+ });
+
+ Object.keys(this.params.customfields).forEach(function (field) {
+ if (typeof schema[field] === ''object'' && schema[field].type) {
+ const type = schema[field].type;
+
+ if (type === ''number'') {
+ data.fields[field] = parseInt(this.params.customfields[field]);
+ }
+ else if (type === ''string'' && schema[field][''custom''].split('':'')[1] === ''url'') {
+ if (this.params.customfields[field] === ''zabbix_url'') {
+ data.fields[field] = CWebhookHelper.createProblemURL(this.params.event_source, this.params.zabbix_url, this.params.trigger_id, this.params.event_id);
+ } else {
+ data.fields[field] = this.params.customfields[field];
+ }
+ }
+ else if (type === ''date'') {
+ if (this.params.customfields[field].match(/\\d+[.-]\\d+[.-]\\d+/) !== null) {
+ data.fields[field] = this.params.customfields[field].replace(/\\./g, ''-'');
+ }
+ }
+ else if (type === ''datetime'') {
+ if (this.params.customfields[field].match(/\\d+[.-]\\d+[.-]\\d+T\\d+:\\d+:\\d+/) !== null) {
+ data.fields[field] = this.params.customfields[field].replace(/\\./g, ''-'');
+ }
+ }
+ else if (type === ''option'') {
+ data.fields[field] = { ''value'': this.params.customfields[field] };
+ }
+ else if (type === ''array'') {
+ if (schema[field].items === ''option'') {
+ const valuesList = this.params.customfields[field].split('','');
+ data.fields[field] = [];
+ valuesList.forEach(function (val) {
+ data.fields[field].push({''value'': val})
+ });
+ }
+ else {
+ data.fields[field] = [this.params.customfields[field]];
+ }
+ }
+ else {
+ data.fields[field] = this.params.customfields[field];
+ }
+ }
+ });
+ }
+ else {
+ Logger.log(Logger.WARN, ''No customfields found.'');
+ }
+
+ return data;
+}
+
+function parseTags(event_tags) {
+ try {
+ return JSON.parse(event_tags);
+ }
+ catch (error) {
+ if (this.params.event_source == 0 || this.params.event_source > 2) {
+ Logger.log(Logger.WARN, ''No event tags were found. Should be an object. Received event tags: "'' + event_tags + ''".'');
+ }
+ return [];
+ }
+}
+
+function getTagValue(tags, key, throw_on_fail) {
+ for (i in tags) {
+ if (tags[i].tag === key) {
+ return tags[i].value
+ }
+ }
+
+ if (!throw_on_fail) {
+ return false;
+ } else {
+ throw ''Tag "'' + key + ''" is not in the event tag list.''
+ }
+};
+
+function setLabels(event_tags_json) {
+ var buffer = [];
+
+ event_tags_json.forEach(function (tag) {
+ if (typeof tag.tag !== ''undefined'' && typeof tag.value !== ''undefined'' && !tag.tag.startsWith(''__zbx'')) {
+ label = (tag.tag + (tag.value ? ('':'' + tag.value) : '''')).replace(/\\s/g, ''_'');
+ if (label.length < 256) {
+ buffer.push(label);
+ }
+ }
+ });
+
+ if (buffer.length === 0) {
+ Logger.log(Logger.WARN, ''No labels were set.'');
+ }
+
+ return buffer;
+}
+
+Jira.prototype.commentIssue = function (issue_key) {
+ var data = {
+ body: this.params.alert_message,
+ };
+ this.sendRequest(''POST'', ''/rest/api/latest/issue/'' + encodeURIComponent(issue_key) + ''/comment'', data);
+}
+
+Jira.prototype.sendRequest = function (method, path, data) {
+ this.request.clearHeader();
+ this.request.addHeaders(''Authorization: Basic '' + btoa(this.params.jira_user + '':'' + this.params.jira_password));
+
+ var response = this.request.jsonRequest(method, this.params.jira_url + path, data);
+
+ if ((this.request.getStatus() !== 200 && this.request.getStatus() !== 201)) {
+ Logger.log(Logger.WARN, ''HTTP code: '' + this.request.getStatus());
+ if (CParamValidator.isType(response.description, ''string'')) {
+ throw response.description;
+ }
+ else {
+ Logger.log(Logger.WARN, ''Request not successful. Received response: '' + JSON.stringify(response));
+ throw ''Unknown error. Check debug log for more information.'';
+ }
+ }
+
+ return response;
+}
+
+Jira.prototype.onProblem = function (alert) {
+ if (this.params.event_tags_json.length > 0 && getTagValue(this.params.event_tags_json, ''__zbx_jira_issuekey'', false) !== false) {
+ return this.onUpdate(alert, true);
+ }
+
+ var data = {
+ fields: {
+ project: {
+ key: this.params.jira_project_key
+ },
+ issuetype: {
+ name: this.params.jira_issue_type
+ },
+ summary: this.params.alert_subject,
+ description: this.params.alert_message,
+ priority: {
+ "name": this.priority
+ }
+ }
+ };
+
+ if (this.labels && this.labels.length > 0) {
+ data.fields.labels = this.labels;
+ }
+
+ if (this.params.components && this.params.components.length > 0) {
+ data.fields.components = this.params.components;
+ }
+
+ var response = this.sendRequest(''POST'', ''/rest/api/latest/issue'', this.addCustomFields(data));
+ this.result.tags = {
+ __zbx_jira_issuekey: response.key,
+ __zbx_jira_issuelink: this.params.jira_url + ''/browse/'' + response.key
+ }
+ return this.result;
+}
+
+Jira.prototype.onUpdate = function (alert, dontUpdatePriority) {
+ var data = {
+ fields: {
+ summary: this.params.alert_subject,
+ priority: {
+ "name": this.priority
+ }
+ }
+ };
+
+ if (dontUpdatePriority && this.params.event_source != 0) {
+ delete data[''fields''][''priority''];
+ }
+
+ var jira_issue_key = getTagValue(this.params.event_tags_json, ''__zbx_jira_issuekey'', true);
+ this.sendRequest(''PUT'', ''/rest/api/latest/issue/'' + encodeURIComponent(jira_issue_key) + ''?returnIssue=true'', this.addCustomFields(data));
+ this.commentIssue(jira_issue_key);
+
+ return this.result;
+}
+
+Jira.prototype.onResolve = function (alert) {
+ return this.onUpdate(alert, true);
+}
+
+Jira.prototype.onDiscovery = function (alert) {
+ this.priority = this.params.jira_priority_discovery;
+ return this.onProblem(alert);
+}
+
+Jira.prototype.onAutoreg = function (alert) {
+ this.priority = this.params.jira_priority_autoregistration;
+ return this.onProblem(alert);
+}
+
+try {
+ var hook = new Jira(value);
+ hook.request = new CHttpRequest(Logger);
+ return hook.run();
+}
+catch (error) {
+ Logger.log(Logger.WARN, ''notification failed: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','1','{EVENT.TAGS.__zbx_jira_issuelink}','Jira: {EVENT.TAGS.__zbx_jira_issuekey}','https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/templates/media/jira
+
+1. To make this integration work, you will need the following from Jira:
+ * Jira instance URL;
+ * Jira project key and issue type that the issues created by Zabbix will use;
+ * Jira username and password or API token. API token is strongly recommended and can be obtained at https://id.atlassian.com/manage/api-tokens.
+2. In the Zabbix web interface, go to Administration → Macros section. Set up the global macro "{$ZABBIX.URL}" which will contain the URL to the Zabbix frontend.
+3. On this page replace the placeholder ''<...>'' values with the ones from the step #1.
+4. In Zabbix, you need to have a Zabbix user and add Media with the Jira media type. Make sure this user has access to all hosts for which you would like problem issues to be created in Jira.','0'),
+('79','4','Jira Service Management','','','','','','','','25','0','0','0','0','1','3','10s','1',E'const CLogger = function(serviceName) {
+ this.serviceName = serviceName;
+ this.INFO = 4
+ this.WARN = 3
+ this.ERROR = 2
+ this.log = function(level, msg) {
+ Zabbix.log(level, ''['' + this.serviceName + ''] '' + msg);
+ }
+}
+
+const CWebhook = function(value) {
+ try {
+ params = JSON.parse(value);
+
+ if ([''0'', ''1'', ''2'', ''3'', ''4''].indexOf(params.event_source) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''.\\nMust be 0-4.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1 && [''0'', ''1''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0 or 1.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1) {
+ if (params.event_source === ''1'' && [''0'', ''1'', ''2'', ''3''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0-3.'';
+ }
+
+ if (params.event_source === ''0'' && [''0'', ''1''].indexOf(params.event_update_status) === -1) {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''.\\nMust be 0 or 1.'';
+ }
+
+ if (params.event_source === ''4'') {
+ if ([''0'', ''1'', ''2'', ''3'', ''4'', ''5''].indexOf(params.event_update_nseverity) !== -1 && params.event_update_nseverity != params.event_nseverity) {
+ params.event_nseverity = params.event_update_nseverity;
+ params.event_severity = params.event_update_severity;
+ params.event_update_status = ''1'';
+ }
+ }
+ }
+
+ this.runCallback = function(name, params) {
+ if (typeof this[name] === ''function'') {
+ return this[name].apply(this, [params]);
+ }
+ }
+
+ this.handleEvent = function(source, event) {
+ const alert = { source: source, event: event };
+ return [
+ this.runCallback(''on'' + source + event, alert),
+ this.runCallback(''on'' + event, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.handleEventless = function(source) {
+ const alert = { source: source, event: null };
+ return [
+ this.runCallback(''on'' + source, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.run = function() {
+ var results = [];
+ if (typeof this.httpProxy === ''string'' && this.httpProxy.trim() !== '''') {
+ this.request.setProxy(this.httpProxy);
+ }
+ const types = { ''0'': ''Trigger'', ''1'': ''Discovery'', ''2'': ''Autoreg'', ''3'': ''Internal'', ''4'': ''Service'' };
+
+ if ([''0'', ''3'', ''4''].indexOf(this.params.event_source) !== -1) {
+ var event = (this.params.event_update_status === ''1'')
+ ? ''Update''
+ : ((this.params.event_value === ''1'') ? ''Problem'' : ''Resolve'');
+
+ results = this.handleEvent(types[this.params.event_source], event);
+ }
+ else if (typeof types[this.params.event_source] !== ''undefined'') {
+ results = this.handleEventless(types[this.params.event_source]);
+ }
+ else {
+ throw ''Unexpected "event_source": '' + this.params.event_source;
+ }
+
+ for (idx in results) {
+ if (typeof results[idx] !== ''undefined'') {
+ return JSON.stringify(results[idx]);
+ }
+ }
+ }
+ this.httpProxy = params.http_proxy;
+ this.params = params;
+ this.runCallback(''onCheckParams'', {});
+ } catch (error) {
+ throw ''Webhook processing failed: '' + error;
+ }
+}
+
+const CWebhookHelper = {
+
+ createProblemURL: function(event_source, zabbix_url, trigger_id, event_id) {
+ if (event_source === ''0'') {
+ return zabbix_url + ''/tr_events.php?triggerid='' + trigger_id + ''&eventid='' + event_id;
+ } else if (event_source === ''4'') {
+ return zabbix_url + ''/zabbix.php?action=service.list'';
+ }
+
+ return zabbix_url;
+ },
+
+};
+
+const CParamValidator = {
+
+ isType: function(value, type) {
+ if (type === ''array'') {
+ return Array.isArray(value);
+ }
+ if (type === ''integer'') {
+ return CParamValidator.isInteger(value);
+ }
+ if (type === ''float'') {
+ return CParamValidator.isFloat(value);
+ }
+
+ return (typeof value === type);
+ },
+
+ isInteger: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseInt(value));
+ },
+
+ isFloat: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+\\.\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseFloat(value));
+ },
+
+ isDefined: function(value) {
+ return !CParamValidator.isType(value, ''undefined'');
+ },
+
+ isEmpty: function(value) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be checked for emptiness.'';
+ }
+
+ return (value.trim() === '''');
+ },
+
+ isMacroSet: function(value, macro) {
+ if (CParamValidator.isDefined(macro)) {
+ return !(CParamValidator.ifMatch(value, ''^\\{'' + macro + ''\\}$''))
+ }
+
+ return !(CParamValidator.ifMatch(value, ''^\\{[$#]{0,1}[A-Z_\\.]+[\\:]{0,1}["]{0,1}.*["]{0,1}\\}$'') || value === ''*UNKNOWN*'')
+ },
+
+ withinRange: function(value, min, max) {
+ if (!CParamValidator.isType(value, ''number'')) {
+ throw ''Value "'' + value + ''" must be a number to be checked for range.'';
+ }
+ if (value < ((CParamValidator.isDefined(min)) ? min : value)
+ || value > ((CParamValidator.isDefined(max)) ? max : value)) {
+ return false;
+ }
+
+ return true;
+ },
+
+ inArray: function(value, array) {
+ if (!CParamValidator.isType(array, ''array'')) {
+ throw ''The array must be an array to check the value for existing in it.'';
+ }
+
+ return (array.indexOf((typeof value === ''string'') ? value.toLowerCase() : value) !== -1);
+ },
+
+ ifMatch: function(value, regex) {
+ return (new RegExp(regex)).test(value);
+ },
+
+ match: function(value, regex) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be matched with the regular expression.'';
+ }
+
+ return value.match(new RegExp(regex));
+ },
+
+ checkURL: function(value) {
+ if (CParamValidator.isEmpty(value)) {
+ throw ''URL value "'' + value + ''" must be a non-empty string.'';
+ }
+ if (!CParamValidator.ifMatch(value, ''^(http|https):\\/\\/.+'')) {
+ throw ''URL value "'' + value + ''" must contain a schema.'';
+ }
+
+ return value.endsWith(''/'') ? value.slice(0, -1) : value;
+ },
+
+ check: function(key, rule, params) {
+ if (!CParamValidator.isDefined(rule.type)) {
+ throw ''Mandatory attribute "type" has not been defined for parameter "'' + key + ''".'';
+ }
+ if (!CParamValidator.isDefined(params[key])) {
+ throw ''Checked parameter "'' + key + ''" was not found in the list of input parameters.'';
+ }
+ var value = params[key],
+ error_message = null;
+ switch (rule.type) {
+ case ''string'':
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + key + ''" must be a string.'';
+ }
+ if (CParamValidator.isEmpty(value)) {
+ error_message = ''Value "'' + key + ''" must be a non-empty string'';
+ break;
+ }
+ if (CParamValidator.isDefined(rule.len) && value.length < rule.len) {
+ error_message = ''Value "'' + key + ''" must be a string with a length > '' + rule.len;
+ }
+ if (CParamValidator.isDefined(rule.regex) && !CParamValidator.ifMatch(value, rule.regex)) {
+ error_message = ''Value "'' + key + ''" must match the regular expression "'' + rule.regex + ''"'';
+ }
+ if (CParamValidator.isDefined(rule.url) && rule.url === true) {
+ value = CParamValidator.checkURL(value);
+ }
+ break;
+ case ''integer'':
+ if (!CParamValidator.isInteger(value)) {
+ error_message = ''Value "'' + key + ''" must be an integer'';
+ break;
+ }
+ value = parseInt(value);
+ break;
+ case ''float'':
+ if (!CParamValidator.isFloat(value)) {
+ error_message = ''Value "'' + key + ''" must be a floating-point number'';
+ break;
+ }
+ value = parseFloat(value);
+ break;
+ case ''boolean'':
+ if (CParamValidator.inArray(value, [''1'', ''true'', ''yes'', ''on''])) {
+ value = true;
+ }
+ else if (CParamValidator.inArray(value, [''0'', ''false'', ''no'', ''off''])) {
+ value = false;
+ }
+ else {
+ error_message = ''Value "'' + key + ''" must be a boolean-like.'';
+ }
+ break;
+ case ''array'':
+ try {
+ value = JSON.parse(value);
+ } catch (error) {
+ throw ''Value "'' + key + ''" contains invalid JSON.'';
+ }
+ if (!CParamValidator.isType(value, ''array'')) {
+ error_message = ''Value "'' + key + ''" must be an array.'';
+ }
+ if (CParamValidator.isDefined(rule.tags) && rule.tags === true) {
+ value = value.reduce(function(acc, obj) {
+ acc[obj.tag] = obj.value || null;
+ return acc;
+ }, {});
+ }
+ break;
+ case ''object'':
+ value = JSON.parse(value);
+ if (!CParamValidator.isType(value, ''object'')) {
+ error_message = ''Value "'' + key + ''" must be an object.'';
+ }
+ break;
+ default:
+ throw ''Unexpected attribute type "'' + rule.type + ''" for value "'' + key + ''". Available: '' +
+ [''integer'', ''float'', ''string'', ''boolean'', ''array'', ''object''].join('', '');
+ }
+ params[key] = value;
+ if (CParamValidator.inArray(rule.type, [''integer'', ''float'']) && error_message === null && (CParamValidator.isDefined(rule.min)
+ || CParamValidator.isDefined(rule.max)) && !CParamValidator.withinRange(value, rule.min, rule.max)) {
+ error_message = ''Value "'' + key + ''" must be a number '' + ((CParamValidator.isDefined(rule.min) && CParamValidator.isDefined(rule.max))
+ ? (rule.min + ''..'' + rule.max) : ((CParamValidator.isDefined(rule.min)) ? ''>'' + rule.min : ''<'' + rule.max));
+ }
+ else if (CParamValidator.isDefined(rule.array) && !CParamValidator.inArray(value, rule.array)) {
+ error_message = ''Value "'' + key + ''" must be in the array '' + JSON.stringify(rule.array);
+ }
+ else if (CParamValidator.isDefined(rule.macro) && !CParamValidator.isMacroSet(value.toString(), rule.macro)) {
+ error_message = ''The macro '' + ((CParamValidator.isDefined(rule.macro)) ? ''{'' + rule.macro + ''} '' : '' '') + ''is not set'';
+ }
+ if (error_message !== null) {
+ if (CParamValidator.isDefined(rule.default) && CParamValidator.isType(rule.default, rule.type)) {
+ params[key] = rule.default;
+ }
+ else {
+ Zabbix.log(4, ''Default value for "'' + key + ''" must be a '' + rule.type + ''. Skipped.'');
+ throw ''Incorrect value for variable "'' + key + ''". '' + error_message;
+ }
+ }
+
+ return this;
+ },
+
+ validate: function(rules, params) {
+ if (!CParamValidator.isType(params, ''object'') || CParamValidator.isType(params, ''array'')) {
+ throw ''Incorrect parameters value. The value must be an object.'';
+ }
+ for (var key in rules) {
+ CParamValidator.check(key, rules[key], params);
+ }
+ }
+}
+
+const CHttpRequest = function(logger) {
+ this.request = new HttpRequest();
+ if (typeof logger !== ''object'' || logger === null) {
+ this.logger = Zabbix;
+ }
+ else {
+ this.logger = logger;
+ }
+
+ this.clearHeader = function() {
+ this.request.clearHeader();
+ }
+
+ this.addHeaders = function(value) {
+ var headers = [];
+
+ if (typeof value === ''object'' && value !== null) {
+ if (!Array.isArray(value)) {
+ Object.keys(value).forEach(function(key) {
+ headers.push(key + '': '' + value[key]);
+ });
+ }
+ else {
+ headers = value;
+ }
+ }
+ else if (typeof value === ''string'') {
+ value.split(''\\r\\n'').forEach(function(header) {
+ headers.push(header);
+ });
+ }
+
+ for (var idx in headers) {
+ this.request.addHeader(headers[idx]);
+ }
+ }
+
+ this.setProxy = function(proxy) {
+ this.request.setProxy(proxy);
+ }
+
+ this.plainRequest = function(method, url, data) {
+ var resp = null;
+ method = method.toLowerCase();
+ this.logger.log(4, ''Sending '' + method + '' request:'' + JSON.stringify(data));
+ if ([''get'', ''post'', ''put'', ''patch'', ''delete'', ''trace''].indexOf(method) !== -1) {
+ resp = this.request[method](url, data);
+ }
+ else if ([''connect'', ''head'', ''options''].indexOf(method) !== -1) {
+ resp = this.request[method](url);
+ }
+ else {
+ throw ''Unexpected method. Method '' + method + '' is not supported.'';
+ }
+ this.logger.log(4, ''Response has been received: '' + resp);
+
+ return resp;
+ }
+
+ this.jsonRequest = function(method, url, data) {
+ this.addHeaders(''Content-Type: application/json'');
+ var resp = this.plainRequest(method, url, JSON.stringify(data));
+ try {
+ resp = JSON.parse(resp);
+ }
+ catch (error) {
+ throw ''Failed to parse response: not well-formed JSON was received'';
+ }
+
+ return resp;
+ }
+
+ this.getStatus = function() {
+ return this.request.getStatus();
+ }
+}
+
+var ZABBIX_SEVERITY_MAP = ["not_classified", "information", "warning", "average", "high", "disaster"];
+
+var serviceLogName = ''Jira Service Management Webhook'',
+ Logger = new CLogger(serviceLogName),
+ Jira = CWebhook;
+
+Jira.prototype.onCheckParams = function () {
+ CParamValidator.validate({
+ jira_url: { type: ''string'', url: true},
+ jira_user: { type: ''string'' },
+ jira_password: { type: ''string'' },
+ jira_request_type_id: { type: ''string'' },
+ jira_servicedesk_id: { type: ''string'' },
+ issue_comments_public: {type: ''boolean'', default: false},
+ event_source: { type: ''string'' },
+ alert_subject: { type: ''string'' },
+ alert_message: { type: ''string'' },
+ event_nseverity: { type: ''integer'', default: 0 }
+ }, this.params);
+
+ this.priority = this.params.event_source == 3 ? this.params.jira_priority_internal : this.params[''severity_'' + ZABBIX_SEVERITY_MAP[this.params.event_nseverity]];
+ this.params.event_tags_json = parseTags(this.params.event_tags_json, false);
+
+ if (this.params.event_tags_json.length > 0) {
+ this.labels = setLabels(this.params.event_tags_json);
+ }
+
+ parseOptionalFields();
+
+ this.result = { tags: {} };
+}
+
+function escapeMarkup(str) {
+ var length = str.length,
+ result = '''',
+ markup = [''{'', ''|'', ''}'', ''~'', ''_'', ''\\\\'', ''['', '']'', ''^'', ''<'', ''>'', ''?'', ''!'', ''#'', ''+'', ''*'', ''&''];
+
+ for (var i = 0; i < length; i++) {
+ var char = str[i];
+ result += (markup.indexOf(char) !== -1) ? ('''' + str[i].charCodeAt() + '';'') : char;
+ }
+
+ return result;
+}
+
+function parseOptionalFields() {
+ this.params.customfields = {};
+ this.params.components = [];
+
+ Object.keys(this.params).forEach(function (key) {
+ if (key.startsWith(''customfield_'')) {
+ this.params.customfields[key] = this.params[key];
+ }
+
+ if (key.startsWith(''component_'')) {
+ this.params.components.push({"name": this.params[key]})
+ }
+ });
+}
+
+Jira.prototype.addCustomFields = function (data, requestFieldValues) {
+ if (typeof this.params.customfields === ''object'' && Object.keys(this.params.customfields).length) {
+ var schemaData = this.sendRequest(''GET'', ''/rest/api/latest/field''),
+ schema = {};
+
+ schemaData.forEach(function (item) {
+ schema[item.id] = item.schema;
+ });
+
+ var placeholder = (requestFieldValues ? ''requestFieldValues'' : ''fields'');
+
+ Object.keys(this.params.customfields).forEach(function (field) {
+ if (typeof schema[field] === ''object'' && schema[field].type) {
+ const type = schema[field].type;
+
+ if (type === ''number'') {
+ data[placeholder][field] = parseInt(this.params.customfields[field]);
+ }
+ else if (type === ''string'' && schema[field][''custom''].split('':'')[1] === ''url'') {
+ if (this.params.customfields[field] === ''zabbix_url'') {
+ data[placeholder][field] = CWebhookHelper.createProblemURL(this.params.event_source, this.params.zabbix_url, this.params.trigger_id, this.params.event_id);
+ } else {
+ data[placeholder][field] = this.params.customfields[field];
+ }
+ }
+ else if (type === ''date'') {
+ if (this.params.customfields[field].match(/\\d+[.-]\\d+[.-]\\d+/) !== null) {
+ data[placeholder][field] = this.params.customfields[field].replace(/\\./g, ''-'');
+ }
+ }
+ else if (type === ''datetime'') {
+ if (this.params.customfields[field].match(/\\d+[.-]\\d+[.-]\\d+T\\d+:\\d+:\\d+/) !== null) {
+ data[placeholder][field] = this.params.customfields[field].replace(/\\./g, ''-'');
+ }
+ }
+ else if (type === ''option'') {
+ data[placeholder][field] = { ''value'': this.params.customfields[field] };
+ }
+ else if (type === ''array'') {
+ if (schema[field].items === ''option'') {
+ const valuesList = this.params.customfields[field].split('','');
+ data[placeholder][field] = [];
+ valuesList.forEach(function (val) {
+ data[placeholder][field].push({''value'': val})
+ });
+ }
+ else {
+ data[placeholder][field] = [this.params.customfields[field]];
+ }
+ }
+ else {
+ data[placeholder][field] = this.params.customfields[field];
+ }
+ }
+ });
+ }
+ else {
+ Logger.log(Logger.WARN, ''No customfields found.'');
+ }
+
+ return data;
+}
+
+function parseTags(event_tags) {
+ try {
+ return JSON.parse(event_tags);
+ }
+ catch (error) {
+ if (this.params.event_source == 0 || this.params.event_source > 2) {
+ Logger.log(Logger.WARN, ''No event tags were found. Should be an object. Received event tags: "'' + event_tags + ''".'');
+ }
+ return [];
+ }
+}
+
+function getTagValue(tags, key, throw_on_fail) {
+ for (i in tags) {
+ if (tags[i].tag === key) {
+ return tags[i].value
+ }
+ }
+
+ if (!throw_on_fail) {
+ return false;
+ } else {
+ throw ''Tag "'' + key + ''" is not in the event tag list.''
+ }
+};
+
+function setLabels(event_tags_json) {
+ var buffer = [];
+
+ event_tags_json.forEach(function (tag) {
+ if (typeof tag.tag !== ''undefined'' && typeof tag.value !== ''undefined'' && !tag.tag.startsWith(''__zbx'')) {
+ label = (tag.tag + (tag.value ? ('':'' + tag.value) : '''')).replace(/\\s/g, ''_'');
+ if (label.length < 256) {
+ buffer.push(label);
+ }
+ }
+ });
+
+ if (buffer.length === 0) {
+ Logger.log(Logger.WARN, ''No labels were set.'');
+ }
+
+ return buffer;
+}
+
+Jira.prototype.commentIssue = function (issue_key) {
+ var data = {
+ body: this.params.alert_message,
+ public: this.params.issue_comments_public
+ };
+ this.sendRequest(''POST'', ''/rest/servicedeskapi/request/'' + encodeURIComponent(issue_key) + ''/comment'', data);
+}
+
+Jira.prototype.sendRequest = function (method, path, data) {
+ this.request.clearHeader();
+ this.request.addHeaders(''Authorization: Basic '' + btoa(this.params.jira_user + '':'' + this.params.jira_password));
+
+ var response = this.request.jsonRequest(method, this.params.jira_url + path, data);
+
+ if ((this.request.getStatus() !== 200 && this.request.getStatus() !== 201)) {
+ Logger.log(Logger.WARN, ''HTTP code: '' + this.request.getStatus());
+ if (CParamValidator.isType(response.description, ''string'')) {
+ throw response.description;
+ }
+ else {
+ Logger.log(Logger.WARN, ''Request not successful. Received response: '' + JSON.stringify(response));
+ throw ''Unknown error. Check debug log for more information.'';
+ }
+ }
+
+ return response;
+}
+
+Jira.prototype.onProblem = function (alert) {
+ if (this.params.event_tags_json.length > 0 && getTagValue(this.params.event_tags_json, ''__zbx_jira_requestkey'', false) !== false) {
+ return this.onUpdate(alert, true);
+ }
+
+ var data = {
+ serviceDeskId: this.params.jira_servicedesk_id,
+ requestTypeId: this.params.jira_request_type_id,
+ requestFieldValues: {
+ summary: this.params.alert_subject,
+ description: this.params.alert_message,
+ priority: {
+ "name": this.priority
+ }
+ }
+ };
+
+ if (this.labels && this.labels.length > 0) {
+ data.requestFieldValues.labels = this.labels;
+ }
+
+ if (this.params.components && this.params.components.length > 0) {
+ data.requestFieldValues.components = this.params.components;
+ }
+
+ var response = this.sendRequest(''POST'', ''/rest/servicedeskapi/request'', this.addCustomFields(data, true));
+ this.result.tags = {
+ __zbx_jira_requestkey: response.issueKey,
+ __zbx_jira_requestlink: this.params.jira_url + ''/browse/'' + response.issueKey
+ }
+ return this.result;
+}
+
+Jira.prototype.onUpdate = function (alert, dontUpdatePriority) {
+ var data = {
+ fields: {
+ summary: this.params.alert_subject,
+ priority: {
+ "name": this.priority
+ }
+ }
+ };
+
+ if (dontUpdatePriority && this.params.event_source != 0) {
+ delete data[''fields''][''priority''];
+ }
+
+ var jira_issue_key = getTagValue(this.params.event_tags_json, ''__zbx_jira_requestkey'', true);
+ this.sendRequest(''PUT'', ''/rest/api/latest/issue/'' + encodeURIComponent(jira_issue_key) + ''?returnIssue=true'', this.addCustomFields(data));
+ this.commentIssue(jira_issue_key);
+
+ return this.result;
+}
+
+Jira.prototype.onResolve = function (alert) {
+ return this.onUpdate(alert, true);
+}
+
+Jira.prototype.onDiscovery = function (alert) {
+ this.priority = this.params.jira_priority_discovery;
+ return this.onProblem(alert);
+}
+
+Jira.prototype.onAutoreg = function (alert) {
+ this.priority = this.params.jira_priority_autoregistration;
+ return this.onProblem(alert);
+}
+
+try {
+ var hook = new Jira(value);
+ hook.request = new CHttpRequest(Logger);
+ return hook.run();
+}
+catch (error) {
+ Logger.log(Logger.WARN, ''notification failed: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','1','{EVENT.TAGS.__zbx_jira_requestlink}','Jira Service Management: {EVENT.TAGS.__zbx_jira_requestkey}','https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/templates/media/jira_service_management
+
+1. To make this integration work, you will need the following from Jira:
+ * Jira instance URL;
+ * Jira service desk id and request type id that the issues created by Zabbix will use;
+ * Jira username and password or API token. API token is strongly recommended and can be obtained at https://id.atlassian.com/manage/api-tokens.
+2. In the Zabbix web interface, go to Administration → Macros section. Set up the global macro "{$ZABBIX.URL}" which will contain the URL to the Zabbix frontend.
+3. On this page replace the placeholder ''<...>'' values with the ones from the step #1.
+4. In Zabbix, you need to have a Zabbix user and add Media with the Jira Service Management media type. Make sure this user has access to all hosts for which you would like problem issues to be created in Jira.','0'),
+('80','4','Line','','','','','','','','25','0','0','0','0','1','3','10s','1',E'function sendMessage(to, messages, params) {
+ var response,
+ request = new HttpRequest();
+
+ if (typeof params.HTTPProxy === ''string'' && params.HTTPProxy.trim() !== '''') {
+ request.setProxy(params.HTTPProxy);
+ }
+
+ request.addHeader(''Content-Type: application/json'');
+ request.addHeader(''Authorization: Bearer '' + params.bot_token);
+
+ response = request.post(''https://api.line.me/v2/bot/message/push'', JSON.stringify({
+ "to": to,
+ "messages": messages
+ }));
+
+ if (request.getStatus() !== 200) {
+ throw response;
+ }
+}
+
+function validateParams(params) {
+ if (typeof params.bot_token !== ''string'' || params.bot_token.trim() === '''') {
+ throw ''Field "bot_token" cannot be empty'';
+ }
+
+ if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
+ throw ''Incorrect "event_source" parameter given: "'' + params.event_source + ''".\\nMust be 0-3.'';
+ }
+
+ if (params.event_source !== ''0'') {
+ params.event_nseverity = ''0'';
+ params.event_severity = ''Not classified'';
+ params.event_update_status = ''0'';
+ }
+
+ if (params.event_source === ''1'' || params.event_source === ''2'') {
+ params.event_value = ''1'';
+ }
+
+ if ([0, 1, 2, 3, 4, 5].indexOf(parseInt(params.event_nseverity)) === -1) {
+ throw ''Incorrect "event_nseverity" parameter given: '' + params.event_nseverity + ''\\nMust be 0-5.'';
+ }
+
+ if (params.event_update_status !== ''0'' && params.event_update_status !== ''1'') {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''\\nMust be 0 or 1.'';
+ }
+
+ if (params.event_value !== ''0'' && params.event_value !== ''1'') {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''\\nMust be 0 or 1.'';
+ }
+
+ if (isNaN(params.trigger_id) && params.event_source === ''0'') {
+ throw ''field "trigger_id" is not a number'';
+ }
+
+ if (typeof params.zabbix_url !== ''string'' || params.zabbix_url.trim() === '''') {
+ throw ''Field "zabbix_url" cannot be empty'';
+ }
+
+ if (!/^(http|https):\\/\\/.+/.test(params.zabbix_url)) {
+ throw ''Field "zabbix_url" must contain a schema'';
+ }
+}
+
+function getZabbixProblemLink(params) {
+ return params.zabbix_url + (params.zabbix_url.endsWith(''/'') ? '''' : ''/'') + ''tr_events.php?triggerid='' + params.trigger_id + ''&eventid='' + params.event_id;
+}
+
+try {
+ var params = JSON.parse(value);
+
+ validateParams(params);
+
+ severity_emoji = [
+ "\\u26AA",
+ "\\uD83D\\uDD35",
+ "\\uD83D\\uDFE4",
+ "\\uD83D\\uDFE1",
+ "\\uD83D\\uDFE0",
+ "\\uD83D\\uDD34",
+ ];
+
+ // If its a trigger and a recovery operation and not an update operation.
+ if (params.event_source === ''0'' && params.event_value === ''0'' && params.event_update_status === ''0'') {
+ var line_message = [
+ {
+ "type": "text",
+ "text": ''\\u2705 '' + params.alert_subject + ''\\n\\n'' + params.alert_message + ''\\n'' + params.trigger_description + ''\\n\\n'' + getZabbixProblemLink(params)
+ }
+ ];
+ }
+ // If its a trigger and its a problem.
+ else if (params.event_source === ''0'' && params.event_value === ''1'') {
+ var line_message = [
+ {
+ "type": "text",
+ "text": severity_emoji[params.event_nseverity] + '' '' + params.alert_subject + ''\\n\\n'' + params.alert_message + ''\\n'' + params.trigger_description + ''\\n\\n'' + getZabbixProblemLink(params)
+ }
+ ];
+ }
+ // If its a trigger and its an update operation.
+ else if (params.event_source === ''0'' && params.event_update_status === ''1'') {
+ var line_message = [
+ {
+ "type": "text",
+ "text": ''\\u2733 '' + severity_emoji[params.event_nseverity] + '' '' + params.alert_subject + ''\\n\\n'' + params.alert_message + ''\\n'' + params.trigger_description + ''\\n\\n'' + getZabbixProblemLink(params)
+ }
+ ];
+ }
+ else {
+ var line_message = [
+ {
+ "type": "text",
+ "text": params.alert_subject + ''\\n\\n'' + params.alert_message + ''\\n''
+ }
+ ];
+ }
+
+ sendMessage(params.send_to, line_message, params);
+
+ return ''OK'';
+}
+catch (err) {
+ Zabbix.log(4, ''[ Line Webhook ] Line notification failed : '' + err);
+ throw ''Line notification failed : '' + err;
+}','30s','0','0','','','Please refer to setup guide here: https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/templates/media/line
+
+Set bot_token parameter to your Line bot token.
+When assigning Line media to the Zabbix user - add the ID of the target recipient. Use a userId, groupId, or roomId value.','0'),
+('81','4','ManageEngine ServiceDesk','','','','','','','','25','0','0','0','0','1','3','10s','1',E'var MEngine = {
+ params: {},
+
+ setParams: function (params) {
+ if (typeof params !== ''object'') {
+ return;
+ }
+
+ MEngine.params = params;
+ if (typeof MEngine.params.url === ''string'') {
+ if (!MEngine.params.url.endsWith(''/'')) {
+ MEngine.params.url += ''/'';
+ }
+
+ MEngine.params.url += ''api/v3/'';
+ }
+
+ if (MEngine.params.on_premise.toLowerCase() !== ''true''
+ && typeof MEngine.params.on_demand_url_auth === ''string'') {
+ if (!MEngine.params.on_demand_url_auth.endsWith(''/'')) {
+ MEngine.params.on_demand_url_auth += ''/'';
+ }
+
+ MEngine.params.on_demand_url_auth += ''oauth/v2/token?'';
+ }
+ },
+
+ setProxy: function (HTTPProxy) {
+ MEngine.HTTPProxy = HTTPProxy;
+ },
+
+ createLink: function (id, url) {
+ return url + (url.endsWith(''/'') ? '''' : ''/'') +
+ ((MEngine.params.on_premise.toLowerCase() === ''true'')
+ ? (''WorkOrder.do?woMode=viewWO&woID='' + id)
+ : (''app/itdesk/ui/requests/'' + id + ''/details'')
+ );
+ },
+
+ refreshAccessToken: function () {
+ [
+ ''on_demand_url_auth'',
+ ''on_demand_refresh_token'',
+ ''on_demand_client_id'',
+ ''on_demand_client_secret''
+ ].forEach(function (field) {
+ if (typeof MEngine.params !== ''object'' || typeof MEngine.params[field] === ''undefined''
+ || MEngine.params[field].trim() === '''' ) {
+ throw ''Required MEngine param is not set: "sd_'' + field + ''".'';
+ }
+ });
+
+ var response,
+ request = new HttpRequest(),
+ url = MEngine.params.on_demand_url_auth +
+ ''refresh_token='' + encodeURIComponent(MEngine.params.on_demand_refresh_token) +
+ ''&grant_type=refresh_token&client_id='' + encodeURIComponent(MEngine.params.on_demand_client_id) +
+ ''&client_secret='' + encodeURIComponent(MEngine.params.on_demand_client_secret) +
+ ''&redirect_uri=https://www.zoho.com&scope=SDPOnDemand.requests.ALL'';
+
+ if (MEngine.HTTPProxy) {
+ request.setProxy(MEngine.HTTPProxy);
+ }
+
+ Zabbix.log(4, ''[ ManageEngine Webhook ] Refreshing access token. Request: '' + url);
+
+ response = request.post(url);
+
+ Zabbix.log(4, ''[ ManageEngine Webhook ] Received response with status code '' +
+ request.getStatus() + ''\\n'' + response);
+
+ try {
+ response = JSON.parse(response);
+ }
+ catch (error) {
+ Zabbix.log(4, ''[ ManageEngine Webhook ] Failed to parse response received from Zoho Accounts'');
+ }
+
+ if ((request.getStatus() < 200 || request.getStatus() >= 300) && !response.access_token) {
+ throw ''Access token refresh failed with HTTP status code '' + request.getStatus() +
+ ''. Check debug log for more information.'';
+ }
+ else {
+ MEngine.params.on_demand_auth_token = response.access_token;
+ }
+ },
+
+ request: function (method, query, data) {
+ var response,
+ url = MEngine.params.url + query,
+ input,
+ request = new HttpRequest(),
+ message;
+
+ if (MEngine.params.on_premise.toLowerCase() === ''true'') {
+ request.addHeader(''TECHNICIAN_KEY: '' + MEngine.params.on_premise_auth_token);
+ }
+ else {
+ request.addHeader(''Authorization: Zoho-oauthtoken '' + MEngine.params.on_demand_auth_token);
+ request.addHeader(''Accept: application/v3+json'');
+ }
+
+ if (MEngine.HTTPProxy) {
+ request.setProxy(MEngine.HTTPProxy);
+ }
+
+ if (typeof data !== ''undefined'') {
+ data = JSON.stringify(data);
+ }
+
+ input = ''input_data='' + encodeURIComponent(data);
+ Zabbix.log(4, ''[ ManageEngine Webhook ] Sending request: '' + url + ''?'' + input);
+
+ switch (method) {
+ case ''post'':
+ response = request.post(url, input);
+ break;
+
+ case ''put'':
+ response = request.put(url, input);
+ break;
+
+ default:
+ throw ''Unsupported HTTP request method: '' + method;
+ }
+
+ Zabbix.log(4, ''[ ManageEngine Webhook ] Received response with status code '' +
+ request.getStatus() + ''\\n'' + response);
+
+ try {
+ response = JSON.parse(response);
+ }
+ catch (error) {
+ Zabbix.log(4, ''[ ManageEngine Webhook ] Failed to parse response received from ManageEngine'');
+ }
+
+ if ((request.getStatus() < 200 || request.getStatus() >= 300)
+ && typeof response.response_status !== ''object'') {
+ throw ''Request failed with HTTP status code '' + request.getStatus() +
+ ''. Check debug log for more information.'';
+ }
+ else if (typeof response.response_status === ''object'' && response.response_status.status === ''failed'') {
+ message = ''Request failed with status_code '';
+
+ if (typeof response.response_status.messages === ''object''
+ && response.response_status.messages[0]
+ && response.response_status.messages[0].message) {
+ message += response.response_status.messages[0].status_code +
+ ''. Message: '' + response.response_status.messages[0].message;
+ }
+ else {
+ message += response.response_status.status_code;
+ }
+
+ message += ''. Check debug log for more information.'';
+ throw message;
+ }
+ else if (response.request) {
+ return response.request.id;
+ }
+ },
+
+ createPaylaod: function (fields, isNote) {
+ var data = {},
+ result;
+
+ if (isNote) {
+ data.description = fields[''field_string:description''].replace(/(?:\\r\\n|\\r|\\n)/g, ''
'');
+ result = {request_note: data};
+ }
+ else {
+ Object.keys(fields)
+ .forEach(function(field) {
+ if (fields[field].trim() === '''') {
+ Zabbix.log(4, ''[ ManageEngine Webhook ] Field "'' + field +
+ ''" can\\''t be empty. The field ignored.'');
+ }
+ else {
+ try {
+ var prefix = field.split('':'')[0],
+ root;
+
+ if (prefix.startsWith(''udf_'') && !data.udf_fields) {
+ data.udf_fields = {};
+ root = data.udf_fields;
+ }
+ else if (prefix.startsWith(''udf_'')) {
+ root = data.udf_fields;
+ }
+ else {
+ root = data;
+ }
+
+ if (prefix.endsWith(''string'')) {
+ root[field.substring(field.indexOf('':'') + 1)
+ .toLowerCase()] = fields[field];
+ }
+ else {
+ root[field.substring(field.indexOf('':'') + 1)
+ .toLowerCase()] = {
+ name: fields[field]
+ };
+ }
+ }
+ catch (error) {
+ Zabbix.log(4, ''[ ManageEngine Webhook ] Can\\''t parse field "'' + field +
+ ''". The field ignored.'');
+ }
+ }
+ });
+ if (data.description) {
+ data.description = data.description.replace(/(?:\\r\\n|\\r|\\n)/g, ''
'');
+ }
+
+ result = {request: data};
+ }
+
+ return result;
+ }
+};
+
+try {
+ var params = JSON.parse(value),
+ fields = {},
+ sd = {},
+ result = {tags: {}},
+ required_params = [
+ ''sd_on_premise'', ''field_string:subject'', ''field_string:description'',
+ ''event_recovery_value'', ''event_source'', ''event_value'', ''event_update_status''
+ ],
+ severities = [
+ {name: ''not_classified'', color: ''#97AAB3''},
+ {name: ''information'', color: ''#7499FF''},
+ {name: ''warning'', color: ''#FFC859''},
+ {name: ''average'', color: ''#FFA059''},
+ {name: ''high'', color: ''#E97659''},
+ {name: ''disaster'', color: ''#E45959''},
+ {name: ''default'', color: ''#000000''}
+ ];
+
+ Object.keys(params)
+ .forEach(function (key) {
+ if (key.startsWith(''sd_'')) {
+ sd[key.substring(3)] = params[key];
+ }
+ else if (key.startsWith(''field_'') || key.startsWith(''udf_field_'')) {
+ fields[key] = params[key];
+ }
+
+ if (required_params.indexOf(key) !== -1 && params[key].trim() === '''') {
+ throw ''Parameter "'' + key + ''" can\\''t be empty.'';
+ }
+ });
+
+ if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''\\nMust be 0-3.'';
+ }
+
+ // 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_source !== ''0'' && params.event_recovery_value === ''0'') {
+ throw ''Recovery operations are supported only for trigger-based actions.'';
+ }
+
+ if ([0, 1, 2, 3, 4, 5].indexOf(parseInt(params.event_nseverity)) === -1) {
+ params.event_nseverity = ''6'';
+ }
+
+ if (params.event_update_status === ''1'' && (typeof params.sd_request_id === ''undefined''
+ || params.sd_request_id.trim() === ''''
+ || params.sd_request_id === ''{EVENT.TAGS.__zbx_sd_request_id}''
+ || params.sd_request_id === ''*UNKNOWN*'')) {
+ throw ''Parameter "sd_request_id" can\\''t be empty for update operation.'';
+ }
+
+ MEngine.setParams(sd);
+ MEngine.setProxy(params.HTTPProxy);
+
+ if (MEngine.params.on_premise.toLowerCase() !== ''true'') {
+ MEngine.refreshAccessToken();
+ }
+
+ // Create issue for non trigger-based events.
+ if (params.event_source !== ''0'' && params.event_recovery_value !== ''0'') {
+ fields[''field_object:priority''] = params[''priority_'' + severities[params.event_nseverity].name]
+ || ''Normal'';
+
+ MEngine.request(''post'', ''requests'', MEngine.createPaylaod(fields));
+ }
+ // Create issue for trigger-based events.
+ else if (params.event_value === ''1'' && params.event_update_status === ''0'') {
+ fields[''field_object:priority''] = params[''priority_'' + severities[params.event_nseverity].name]
+ || ''Normal'';
+
+ var id = MEngine.request(''post'', ''requests'', MEngine.createPaylaod(fields));
+
+ result.tags.__zbx_sd_request_id = id;
+ result.tags.__zbx_sd_request_link = MEngine.createLink(id, params.sd_url);
+ }
+ // Update created issue for trigger-based event.
+ else {
+ if (params.event_update_status === ''1'') {
+ MEngine.request(''post'', ''requests/'' + params.sd_request_id + ''/notes'',
+ MEngine.createPaylaod(fields, true)
+ );
+ }
+ delete fields[''field_string:description''];
+ MEngine.request(''put'', ''requests/'' + params.sd_request_id, MEngine.createPaylaod(fields));
+ }
+
+ return JSON.stringify(result);
+}
+catch (error) {
+ Zabbix.log(3, ''[ ManageEngine Webhook ] ERROR: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','1','{EVENT.TAGS.__zbx_sd_request_link}','ManageEngine: {EVENT.TAGS.__zbx_sd_request_id}','','0'),
+('82','4','MantisBT','','','','','','','','25','0','0','0','0','1','1','10s','1',E'var Mantisbt = {
+ params: {},
+
+ setParams: function (params) {
+ if (typeof params !== ''object'') {
+ return;
+ }
+ Mantisbt.params = params;
+ },
+
+ setProxy: function (HTTPProxy) {
+ Mantisbt.HTTPProxy = HTTPProxy;
+ },
+
+ checkUrlFormat: function (url) {
+ if (typeof url === ''string'' && !url.endsWith(''/'')) {
+ url += ''/'';
+ }
+
+ if (url.indexOf(''http://'') === -1 && url.indexOf(''https://'') === -1) {
+ url = ''https://'' + url;
+ }
+
+ return url;
+ },
+
+ getProblemURL: function (zabbix_url, triggerid, eventid, event_source) {
+ var problem_url = zabbix_url;
+
+ if (event_source === ''0'') {
+ problem_url += ''tr_events.php?triggerid='' + triggerid + ''&eventid='' + eventid;
+ }
+
+ return problem_url;
+ },
+
+ request: function (method, url, data) {
+ [''token'', ''url'', ''category''].forEach(function (field) {
+ if (typeof Mantisbt.params !== ''object'' || typeof Mantisbt.params[field] === ''undefined'' || Mantisbt.params[field] === '''') {
+ throw ''Required MantisBT param is not set: "'' + field + ''".'';
+ }
+ });
+
+ var response,
+ request = new HttpRequest();
+
+ request.addHeader(''Content-Type: application/json'');
+ request.addHeader(''Authorization: '' + Mantisbt.params.token);
+
+ if (typeof Mantisbt.HTTPProxy !== ''undefined'' && Mantisbt.HTTPProxy !== '''') {
+ request.setProxy(Mantisbt.HTTPProxy);
+ }
+
+ if (typeof data !== ''undefined'') {
+ data = JSON.stringify(data);
+ }
+
+ Zabbix.log(4, ''[ MantisBT Webhook ] Sending request: '' + url + ((typeof data === ''string'') ? (''\\n'' + data) : ''''));
+
+ switch (method) {
+ case ''post'':
+ response = request.post(url, data);
+ break;
+
+ case ''patch'':
+ response = request.patch(url, data);
+ break;
+
+ default:
+ throw ''Unsupported HTTP request method: '' + method;
+ }
+
+ Zabbix.log(4, ''[ MantisBT Webhook ] Received response with status code '' + request.getStatus() + ''\\n'' + response);
+
+ if (response !== null) {
+ try {
+ response = JSON.parse(response);
+ }
+ catch (error) {
+ Zabbix.log(4, ''[ MantisBT Webhook ] Failed to parse the response received from MantisBT'');
+ response = null;
+ }
+ }
+
+ if (typeof response !== ''object'') {
+ throw ''Failed to process the response received from MantisBT. Check debug log for more information.'';
+ }
+
+ if (request.getStatus() < 200 || request.getStatus() >= 300) {
+ var message = ''Request failed with status code '' + request.getStatus();
+
+ if (typeof response.message !== ''undefined'') {
+ message += '': '' + response.message;
+ }
+
+ throw message;
+ }
+
+ return response;
+ }
+};
+
+try {
+ var params = JSON.parse(value),
+ mantisbt = {},
+ url = '''',
+ data = {},
+ result = { tags: {} },
+ required_params = [
+ ''alert_subject'', ''alert_message'', ''event_source'', ''event_value'', ''event_update_action'',
+ ''event_update_status'', ''event_recovery_value'', ''event_nseverity'', ''event_tagsjson'',
+ ''event_id'', ''trigger_id'', ''zabbix_url'', ''alert_sendto'',
+ ''mantisbt_token'', ''mantisbt_url'', ''mantisbt_category'', ''mantisbt_issue_number'', ''mantisbt_use_zabbix_tags''
+ ],
+ method,
+ severities = [''none'', ''low'', ''normal'', ''high'', ''urgent'', ''immediate''];
+
+
+ Object.keys(params)
+ .forEach(function (key) {
+ if (key.startsWith(''mantisbt_'')) {
+ mantisbt[key.substring(9)] = params[key];
+ }
+ else if (required_params.indexOf(key) !== -1 && params[key] === '''') {
+ throw ''Parameter "'' + key + ''" cannot be empty.'';
+ }
+ });
+
+ if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''\\nMust be 0-3.'';
+ }
+
+ // 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_source !== ''0'' && params.event_recovery_value === ''0'') {
+ throw ''Recovery operations are supported for trigger-based actions only.'';
+ }
+
+ if (typeof params.zabbix_url !== ''string'' || params.zabbix_url.trim() === '''' || params.zabbix_url === ''{$ZABBIX.URL}'') {
+ throw ''Field "zabbix_url" cannot be empty.'';
+ }
+
+ // Check for backslash in the end of url and schema.
+ mantisbt.url = Mantisbt.checkUrlFormat(mantisbt.url);
+ params.zabbix_url = Mantisbt.checkUrlFormat(params.zabbix_url);
+
+ // In case of resolve event.
+ if (params.event_source === ''0'' && params.event_value === ''0'') {
+ method = "patch";
+ url = mantisbt.url + ''api/rest/issues/'' + mantisbt.issue_number;
+ data = {
+ summary: params.alert_subject,
+ status: {
+ name: "resolved"
+ }
+ };
+ if (/commented/.test(params.event_update_action)) {
+ data.additional_information = params.event_update_message;
+ }
+ process_tags = false;
+ }
+ // In case of update event.
+ else if (params.event_source === ''0'' && params.event_update_status === ''1'') {
+ method = "patch";
+ url = mantisbt.url + ''api/rest/issues/'' + mantisbt.issue_number;
+ data = {
+ status: {},
+ priority: {
+ name: severities[parseInt(params.event_nseverity, 10)]
+ }
+ };
+ if (/commented/.test(params.event_update_action)) {
+ data.additional_information = params.event_update_message;
+ }
+ if (/acknowledged/.test(params.event_update_action)) {
+ data.status.name = "acknowledged";
+ }
+ if (/unacknowledged/.test(params.event_update_action)) {
+ data.status.name = "new";
+ }
+ process_tags = false;
+ }
+ else {
+ method = ''post'';
+ url = mantisbt.url + ''api/rest/issues'';
+
+ data = {
+ summary: params.alert_subject,
+ description: params.alert_message,
+ project: { name: params.alert_sendto },
+ category: { name: mantisbt.category },
+ priority: {
+ name: parseInt(params.event_nseverity, 10) ? severities[parseInt(params.event_nseverity, 10)] : "none"
+ }
+ };
+ if (params.event_source === ''0'') {
+ problem_url = Mantisbt.getProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source);
+ data.description += ''\\n'' + problem_url;
+
+ if (mantisbt.use_zabbix_tags === "true") {
+ var alert_tags = JSON.parse(params.event_tagsjson);
+ data.tags = alert_tags.map(function (t) { return { name: t.value ? (t.tag + '': '' + t.value) : t.tag }; });
+ }
+ }
+ process_tags = true;
+ }
+
+ Mantisbt.setParams(mantisbt);
+ Mantisbt.setProxy(params.HTTPProxy);
+
+ var response = Mantisbt.request(method, url, data);
+
+ if (process_tags) {
+ result.tags.__zbx_mantisbt_issue_number = response.issue.id;
+ result.tags.__zbx_mantisbt_link = mantisbt.url + ''view.php?id='' + response.issue.id;
+ }
+
+ Zabbix.log(4, ''[ MantisBT Webhook ] Result: '' + JSON.stringify(result));
+ return JSON.stringify(result);
+}
+catch (error) {
+ Zabbix.log(4, ''[ MantisBT Webhook ] ERROR: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','1','{EVENT.TAGS.__zbx_mantisbt_link}','MantisBT: Issue ID {EVENT.TAGS.__zbx_mantisbt_issue_number}','','0'),
+('83','4','Mattermost','','','','','','','','25','0','0','0','0','1','1','10s','1',E'var SEVERITY_COLORS = [
+ ''#97AAB3'', ''#7499FF'', ''#FFC859'',
+ ''#FFA059'', ''#E97659'', ''#E45959''
+];
+
+var RESOLVE_COLOR = ''#009900'';
+
+var SEND_MODE_HANDLERS = {
+ alarm: handlerAlarm,
+ event: handlerEvent
+};
+
+if (!String.prototype.format) {
+ String.prototype.format = function() {
+ var args = arguments;
+
+ return this.replace(/{(\\d+)}/g, function(match, number) {
+ return number in args
+ ? args[number]
+ : match
+ ;
+ });
+ };
+}
+
+function isEventProblem(params) {
+ return params.event_value == 1
+ && params.event_update_status == 0
+ ;
+}
+
+function isEventUpdate(params) {
+ return params.event_value == 1
+ && params.event_update_status == 1
+ ;
+}
+
+function isEventResolve(params) {
+ return params.event_value == 0;
+}
+
+function getPermalink(mattermost_url, team_name, postid) {
+ return ''{0}/{1}/pl/{2}''.format(
+ mattermost_url.replace(/\\/+$/, ''''),
+ team_name,
+ postid
+ );
+}
+
+function getChannel(send_to) {
+ switch (true) {
+ case /.+\\/#.+/.test(send_to):
+ return getChannelByName(send_to);
+
+ case /@.+/.test(send_to):
+ return getDirectChannel(send_to);
+
+ default:
+ return getChannelByID(send_to);
+ }
+}
+
+function getChannelByName(send_to) {
+ var team_chan = send_to
+ .trim()
+ .split(''/#'');
+
+ var resp = JSON.parse(req.get(
+ Mattermost.channel_byname.format(team_chan[0], team_chan[1]),
+ JSON.stringify(fields)
+ )
+ );
+
+ if (req.getStatus() != 200) {
+ throw ''[{0}] {1}''.format(resp.status_code, resp.message);
+ }
+
+ return resp;
+}
+
+function getDirectChannel(send_to) {
+ Zabbix.log(5, ''[ Mattermost Webhook ] Call {0}({1})''.format(
+ arguments.callee.name,
+ JSON.stringify(arguments)
+ ));
+
+ var teamUser = send_to
+ .trim()
+ .split(''/@''),
+ bot = getBotUser(),
+ user = getUserByName(teamUser[1]);
+
+ var resp = JSON.parse(req.post(
+ Mattermost.direct_channel,
+ JSON.stringify([bot.id, user.id])
+ )
+ );
+
+ Zabbix.log(5, ''[ Mattermost Webhook ] Result {0}: {1}''.format(
+ arguments.callee.name,
+ JSON.stringify(resp)
+ ));
+
+ if (req.getStatus() != 201) {
+ throw ''[{0}] {1}''.format(resp.status_code, resp.message);
+ }
+
+ resp.team_name = teamUser[0];
+
+ return resp;
+}
+
+function getChannelByID(channelID) {
+ Zabbix.log(5, ''[ Mattermost Webhook ] Call {0}({1})''.format(
+ arguments.callee.name,
+ JSON.stringify(arguments)
+ ));
+
+ var resp = JSON.parse(req.get(
+ Mattermost.get_channel.format(channelID),
+ JSON.stringify(fields)
+ )
+ );
+
+ Zabbix.log(5, ''[ Mattermost Webhook ] Result {0}: {1}''.format(
+ arguments.callee.name,
+ JSON.stringify(resp)
+ ));
+
+ if (req.getStatus() != 200) {
+ throw ''[{0}] {1}''.format(resp.status_code, resp.message);
+ }
+
+ return resp;
+}
+
+function getBotUser() {
+ Zabbix.log(5, ''[ Mattermost Webhook ] Call {0}({1})''.format(
+ arguments.callee.name,
+ JSON.stringify(arguments)
+ ));
+
+ var resp = JSON.parse(req.get(
+ Mattermost.bot_user,
+ JSON.stringify(fields)
+ )
+ );
+
+ Zabbix.log(5, ''[ Mattermost Webhook ] Result {0}: {1}''.format(
+ arguments.callee.name,
+ JSON.stringify(resp)
+ ));
+
+ if (req.getStatus() != 200) {
+ throw ''[{0}] {1}''.format(resp.status_code, resp.message);
+ }
+
+ return resp;
+}
+
+function getUserByName(userName) {
+ Zabbix.log(5, ''[ Mattermost Webhook ] Call {0}({1})''.format(
+ arguments.callee.name,
+ JSON.stringify(arguments)
+ ));
+
+ var resp = JSON.parse(req.get(
+ Mattermost.user_byname.format(userName),
+ JSON.stringify(fields)
+ )
+ );
+
+ Zabbix.log(5, ''[ Mattermost Webhook ] Result {0}: {1}''.format(
+ arguments.callee.name,
+ JSON.stringify(resp)
+ ));
+
+ if (req.getStatus() != 200) {
+ throw ''[{0}] {1}''.format(resp.status_code, resp.message);
+ }
+
+ return resp;
+}
+
+function getTeamByID(teamID) {
+ Zabbix.log(5, ''[ Mattermost Webhook ] Call {0}({1})''.format(
+ arguments.callee.name,
+ JSON.stringify(arguments)
+ ));
+
+ var resp = JSON.parse(req.get(
+ Mattermost.get_team.format(teamID),
+ JSON.stringify(fields)
+ )
+ );
+
+ Zabbix.log(5, ''[ Mattermost Webhook ] Result {0}: {1}''.format(
+ arguments.callee.name,
+ JSON.stringify(resp)
+ ));
+
+ if (req.getStatus() != 200) {
+ throw ''[{0}] {1}''.format(resp.status_code, resp.message);
+ }
+
+ return resp;
+}
+
+function createProblemURL(zabbix_url, triggerid, eventid, event_source) {
+ var problem_url = '''';
+ if (event_source === ''0'') {
+ problem_url = ''{0}/tr_events.php?triggerid={1}&eventid={2}''
+ .format(
+ zabbix_url,
+ triggerid,
+ eventid
+ );
+ }
+ else {
+ problem_url = zabbix_url;
+ }
+
+ return problem_url;
+}
+
+function getTagValue(event_tags, key) {
+ var pattern = new RegExp(''('' + key + '':.+)'');
+ var tagValue = event_tags
+ .split('','')
+ .filter(function (v) {
+ return v.match(pattern);
+ })
+ .map(function (v) {
+ return v.split('':'')[1];
+ })[0]
+ || 0;
+
+ return tagValue;
+}
+
+function handlerAlarm(req, params) {
+ var channel = getChannel(params.send_to);
+ var fields = {
+ channel_id: channel.id,
+ props: {}
+ };
+
+ if (isEventProblem(params)) {
+ var team_name = channel.team_name
+ ? channel.team_name
+ : getTeamByID(channel.team_id).name;
+
+ fields.props.attachments = [
+ createMessage(
+ SEVERITY_COLORS[params.event_nseverity] || 0,
+ params.event_date,
+ params.event_time,
+ createProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source)
+ )
+ ];
+
+ var resp = JSON.parse(req.post(
+ Mattermost.post_message,
+ JSON.stringify(fields)
+ )
+ );
+
+ if (req.getStatus() != 201) {
+ throw ''[{0}] {1}''.format(resp.status_code, resp.message);
+ }
+
+ result.tags.__mattermost_post_id = resp.id;
+ result.tags.__mattermost_channel_id = channel.id;
+ result.tags.__mattermost_channel_name = channel.name;
+ result.tags.__mattermost_message_link = getPermalink(
+ params.mattermost_url,
+ team_name,
+ resp.id
+ );
+
+ }
+ else if (isEventUpdate(params)) {
+ fields.root_id = getTagValue(params.event_tags, ''mattermost_post_id'');
+
+ if (params.event_source === ''0'') {}
+ fields.props.attachments = [
+ createMessage(
+ SEVERITY_COLORS[params.event_nseverity] || 0,
+ params.event_update_date,
+ params.event_update_time,
+ createProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source),
+ true
+ )
+ ];
+
+ resp = JSON.parse(req.post(
+ Mattermost.post_message, JSON.stringify(fields)
+ )
+ );
+
+ if (req.getStatus() != 201) {
+ throw ''[{0}] {1}''.format(resp.status_code, resp.message);
+ }
+
+ }
+ else if (isEventResolve(params)) {
+ fields.channel_id = getTagValue(params.event_tags, ''mattermost_channel_id'');
+ fields.id = getTagValue(params.event_tags, ''mattermost_post_id'');
+ fields.props.attachments = [
+ createMessage(
+ RESOLVE_COLOR,
+ params.event_date,
+ params.event_time,
+ createProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source)
+ )
+ ];
+
+ var post_id = getTagValue(params.event_tags, ''mattermost_post_id'');
+
+ resp = JSON.parse(req.put(
+ Mattermost.chat_update.format(post_id),
+ JSON.stringify(fields)
+ )
+ );
+
+ if (req.getStatus() != 200) {
+ throw ''[{0}] {1}''.format(resp.status_code, resp.message);
+ }
+ }
+}
+
+function handlerEvent(req, params) {
+ var channel = getChannel(params.send_to);
+ var fields = {
+ channel_id: channel.id,
+ props: {}
+ };
+
+ if (isEventProblem(params)) {
+ var team_name = channel.team_name
+ ? channel.team_name
+ : getTeamByID(channel.team_id).name;
+
+ fields.props.attachments = [
+ createMessage(
+ SEVERITY_COLORS[params.event_nseverity] || 0,
+ params.event_date,
+ params.event_time,
+ createProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source)
+ )
+ ];
+
+ var resp = JSON.parse(req.post(Mattermost.post_message, JSON.stringify(fields)));
+
+ if (req.getStatus() != 201) {
+ throw ''[{0}] {1}''.format(resp.status_code, resp.message);
+ }
+
+ result.tags.__mattermost_channel_name = channel.name;
+ result.tags.__mattermost_message_link = getPermalink(
+ params.mattermost_url,
+ team_name,
+ resp.id
+ );
+
+ }
+ else if (isEventUpdate(params)) {
+ fields.props.attachments = [
+ createMessage(
+ SEVERITY_COLORS[params.event_nseverity] || 0,
+ params.event_update_date,
+ params.event_update_time,
+ createProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source),
+ false
+ )
+ ];
+
+ resp = JSON.parse(req.post(Mattermost.post_message, JSON.stringify(fields)));
+
+ if (req.getStatus() != 201) {
+ throw ''[{0}] {1}''.format(resp.status_code, resp.message);
+ }
+
+ }
+ else if (isEventResolve(params)) {
+ fields.props.attachments = [
+ createMessage(
+ RESOLVE_COLOR,
+ params.event_recovery_date,
+ params.event_recovery_time,
+ createProblemURL(params.zabbix_url, params.trigger_id, params.event_id, params.event_source)
+ )
+ ];
+
+ resp = JSON.parse(req.post(Mattermost.post_message, JSON.stringify(fields)));
+
+ if (req.getStatus() != 201) {
+ throw ''[{0}] {1}''.format(resp.status_code, resp.message);
+ }
+ }
+}
+
+function createMessage(
+ event_severity_color,
+ event_date,
+ event_time,
+ problem_url,
+ isShort
+) {
+ var message = {
+ fallbac: params.alert_subject,
+ title: params.alert_subject,
+ color: event_severity_color,
+ title_link: problem_url,
+ footer: problem_url,
+
+ fields: [
+ {
+ title: ''Host'',
+ value: ''{0} [{1}]''.format(params.host_name, params.host_ip),
+ short: true
+ },
+ {
+ title: ''Event time'',
+ value: ''{0} {1}''.format(event_date, event_time),
+ short: true
+ }
+ ],
+ };
+
+
+ if (params.event_source === ''0'') {
+ message.fields.push(
+ {
+ title: ''Severity'',
+ value: params.event_severity,
+ short: true
+ },
+ {
+ title: ''Opdata'',
+ value: params.event_opdata,
+ short: true
+ }
+ );
+ }
+
+ if (!isShort && params.event_source === ''0'') {
+ message.fields.push(
+ {
+ title: ''Event tags'',
+ value: ''`{0}`''.format(params.event_tags.replace(/__.+?:(.+?,|.+)/g, '''') || ''None''),
+ short: true
+ },
+ {
+ title: ''Trigger description'',
+ value: params.trigger_description,
+ short: true
+ }
+ );
+ }
+
+ if (params.event_source !== ''0'' || params.event_update_status === ''1'') {
+ message.fields.push(
+ {
+ title: ''Details'',
+ value: params.alert_message,
+ short: false
+ }
+ );
+ }
+
+ return message;
+}
+
+function validateParams(params) {
+ if (typeof params.bot_token !== ''string'' || params.bot_token.trim() === '''') {
+ throw ''Field "bot_token" cannot be empty'';
+ }
+
+ if (isNaN(params.event_id)) {
+ throw ''Field "event_id" is not a number'';
+ }
+
+ if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
+ throw ''Incorrect "event_source" parameter given: "'' + params.event_source + ''".\\nMust be 0-3.'';
+ }
+
+ if (params.event_source !== ''0'') {
+ params.event_nseverity = ''0'';
+ params.event_severity = ''Not classified'';
+ params.event_update_status = ''0'';
+ params.send_mode = ''event'';
+ }
+
+ if (params.event_source === ''1'' || params.event_source === ''2'') {
+ params.event_value = ''1'';
+ }
+
+ if (params.event_source === ''1'') {
+ params.host_name = params.discovery_host_dns;
+ params.host_ip = params.discovery_host_ip;
+ }
+
+ if ([0, 1, 2, 3, 4, 5].indexOf(parseInt(params.event_nseverity)) === -1) {
+ throw ''Incorrect "event_nseverity" parameter given: '' + params.event_nseverity + ''\\nMust be 0-5.'';
+ }
+
+ if (typeof params.event_severity !== ''string'' || params.event_severity.trim() === '''') {
+ throw ''Field "event_severity" cannot be empty'';
+ }
+
+ if (params.event_update_status !== ''0'' && params.event_update_status !== ''1'') {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''\\nMust be 0 or 1.'';
+ }
+
+ if (params.event_value !== ''0'' && params.event_value !== ''1'') {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''\\nMust be 0 or 1.'';
+ }
+
+ if (typeof params.host_ip !== ''string'' || params.host_ip.trim() === '''') {
+ throw ''Field "host_ip" cannot be empty'';
+ }
+
+ if (typeof params.host_name !== ''string'' || params.host_name.trim() === '''') {
+ throw ''Field "host_name" cannot be empty'';
+ }
+
+ if (typeof params.mattermost_url !== ''string'' || params.mattermost_url.trim() === '''') {
+ throw ''Field "mattermost_url" cannot be empty'';
+ }
+
+ if (!/^(http|https):\\/\\/.+/.test(params.mattermost_url)) {
+ throw ''Field "mattermost_url" must contain a schema'';
+ }
+
+ if ([''alarm'', ''event''].indexOf(params.send_mode) === -1) {
+ throw ''Incorrect "send_mode" parameter given: '' + params.send_mode + ''\\nMust be "alarm" or "event".'';
+ }
+
+ if (typeof params.send_to !== ''string'' || params.send_to.trim() === '''') {
+ throw ''Field "send_to" cannot be empty'';
+ }
+
+ if (isNaN(params.trigger_id) && params.event_source === ''0'') {
+ throw ''field "trigger_id" is not a number'';
+ }
+
+ if (typeof params.zabbix_url !== ''string'' || params.zabbix_url.trim() === '''') {
+ throw ''Field "zabbix_url" cannot be empty'';
+ }
+
+ if (!/^(http|https):\\/\\/.+/.test(params.zabbix_url)) {
+ throw ''Field "zabbix_url" must contain a schema'';
+ }
+
+}
+
+try {
+ var params = JSON.parse(value);
+
+ validateParams(params);
+
+ var req = new HttpRequest(),
+ fields = {},
+ result = {tags: {}};
+
+ if (typeof params.HTTPProxy === ''string'' && params.HTTPProxy.trim() !== '''') {
+ req.setProxy(params.HTTPProxy);
+ }
+
+ req.addHeader(''Content-Type: application/json; charset=utf-8'');
+ req.addHeader(''Authorization: Bearer '' + params.bot_token);
+
+ params.mattermost_url = params.mattermost_url.replace(/\\/+$/, '''');
+ params.zabbix_url = params.zabbix_url.replace(/\\/+$/, '''');
+
+ var APIEndpoint = params.mattermost_url + ''/api/v4/'';
+
+ var Mattermost = {
+ post_message: APIEndpoint + ''posts'',
+ get_channel: APIEndpoint + ''channels/{0}'',
+ get_team: APIEndpoint + ''teams/{0}'',
+ chat_update: APIEndpoint + ''posts/{0}'',
+ direct_channel: APIEndpoint + ''channels/direct'',
+ channel_byname: APIEndpoint + ''teams/name/{0}/channels/name/{1}'',
+ user_byname: APIEndpoint + ''users/username/{0}'',
+ bot_user: APIEndpoint + ''users/me''
+
+ };
+
+ params.send_mode = params.send_mode.toLowerCase();
+ params.send_mode = params.send_mode in SEND_MODE_HANDLERS
+ ? params.send_mode
+ : ''alarm'';
+
+ SEND_MODE_HANDLERS[params.send_mode](req, params);
+
+ if (params.event_source === ''0'') {
+ return JSON.stringify(result);
+ }
+ else {
+ return ''OK'';
+ }
+}
+catch (error) {
+ Zabbix.log(4, ''[ Mattermost Webhook ] Mattermost notification failed: '' + error);
+ throw ''Mattermost notification failed: '' + error;
+}','30s','1','1','{EVENT.TAGS.__mattermost_message_link}','Open in Mattermost: {EVENT.TAGS.__mattermost_channel_name}','','0'),
+('84','4','MS Teams','','','','','','','','25','0','0','0','0','1','3','10s','1',E'const CLogger = function(serviceName) {
+ this.serviceName = serviceName;
+ this.INFO = 4
+ this.WARN = 3
+ this.ERROR = 2
+ this.log = function(level, msg) {
+ Zabbix.log(level, ''['' + this.serviceName + ''] '' + msg);
+ }
+}
+
+const CWebhook = function(value) {
+ try {
+ params = JSON.parse(value);
+
+ if ([''0'', ''1'', ''2'', ''3'', ''4''].indexOf(params.event_source) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''.\\nMust be 0-4.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1 && [''0'', ''1''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0 or 1.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1) {
+ if (params.event_source === ''1'' && [''0'', ''1'', ''2'', ''3''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0-3.'';
+ }
+
+ if (params.event_source === ''0'' && [''0'', ''1''].indexOf(params.event_update_status) === -1) {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''.\\nMust be 0 or 1.'';
+ }
+
+ if (params.event_source === ''4'') {
+ if ([''0'', ''1'', ''2'', ''3'', ''4'', ''5''].indexOf(params.event_update_nseverity) !== -1 && params.event_update_nseverity != params.event_nseverity) {
+ params.event_nseverity = params.event_update_nseverity;
+ params.event_severity = params.event_update_severity;
+ params.event_update_status = ''1'';
+ }
+ }
+ }
+
+ this.runCallback = function(name, params) {
+ if (typeof this[name] === ''function'') {
+ return this[name].apply(this, [params]);
+ }
+ }
+
+ this.handleEvent = function(source, event) {
+ const alert = { source: source, event: event };
+ return [
+ this.runCallback(''on'' + source + event, alert),
+ this.runCallback(''on'' + event, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.handleEventless = function(source) {
+ const alert = { source: source, event: null };
+ return [
+ this.runCallback(''on'' + source, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.run = function() {
+ var results = [];
+ if (typeof this.httpProxy === ''string'' && this.httpProxy.trim() !== '''') {
+ this.request.setProxy(this.httpProxy);
+ }
+ const types = { ''0'': ''Trigger'', ''1'': ''Discovery'', ''2'': ''Autoreg'', ''3'': ''Internal'', ''4'': ''Service'' };
+
+ if ([''0'', ''3'', ''4''].indexOf(this.params.event_source) !== -1) {
+ var event = (this.params.event_update_status === ''1'')
+ ? ''Update''
+ : ((this.params.event_value === ''1'') ? ''Problem'' : ''Resolve'');
+
+ results = this.handleEvent(types[this.params.event_source], event);
+ }
+ else if (typeof types[this.params.event_source] !== ''undefined'') {
+ results = this.handleEventless(types[this.params.event_source]);
+ }
+ else {
+ throw ''Unexpected "event_source": '' + this.params.event_source;
+ }
+
+ for (idx in results) {
+ if (typeof results[idx] !== ''undefined'') {
+ return JSON.stringify(results[idx]);
+ }
+ }
+ }
+ this.httpProxy = params.http_proxy;
+ this.params = params;
+ this.runCallback(''onCheckParams'', {});
+ } catch (error) {
+ throw ''Webhook processing failed: '' + error;
+ }
+}
+
+const CWebhookHelper = {
+
+ createProblemURL: function(event_source, zabbix_url, trigger_id, event_id) {
+ if (event_source === ''0'') {
+ return zabbix_url + ''/tr_events.php?triggerid='' + trigger_id + ''&eventid='' + event_id;
+ } else if (event_source === ''4'') {
+ return zabbix_url + ''/zabbix.php?action=service.list'';
+ }
+
+ return zabbix_url;
+ },
+
+};
+
+const CParamValidator = {
+
+ isType: function(value, type) {
+ if (type === ''array'') {
+ return Array.isArray(value);
+ }
+ if (type === ''integer'') {
+ return CParamValidator.isInteger(value);
+ }
+ if (type === ''float'') {
+ return CParamValidator.isFloat(value);
+ }
+
+ return (typeof value === type);
+ },
+
+ isInteger: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseInt(value));
+ },
+
+ isFloat: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+\\.\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseFloat(value));
+ },
+
+ isDefined: function(value) {
+ return !CParamValidator.isType(value, ''undefined'');
+ },
+
+ isEmpty: function(value) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be checked for emptiness.'';
+ }
+
+ return (value.trim() === '''');
+ },
+
+ isMacroSet: function(value, macro) {
+ if (CParamValidator.isDefined(macro)) {
+ return !(CParamValidator.ifMatch(value, ''^\\{'' + macro + ''\\}$''))
+ }
+
+ return !(CParamValidator.ifMatch(value, ''^\\{[$#]{0,1}[A-Z_\\.]+[\\:]{0,1}["]{0,1}.*["]{0,1}\\}$'') || value === ''*UNKNOWN*'')
+ },
+
+ withinRange: function(value, min, max) {
+ if (!CParamValidator.isType(value, ''number'')) {
+ throw ''Value "'' + value + ''" must be a number to be checked for range.'';
+ }
+ if (value < ((CParamValidator.isDefined(min)) ? min : value)
+ || value > ((CParamValidator.isDefined(max)) ? max : value)) {
+ return false;
+ }
+
+ return true;
+ },
+
+ inArray: function(value, array) {
+ if (!CParamValidator.isType(array, ''array'')) {
+ throw ''The array must be an array to check the value for existing in it.'';
+ }
+
+ return (array.indexOf((typeof value === ''string'') ? value.toLowerCase() : value) !== -1);
+ },
+
+ ifMatch: function(value, regex) {
+ return (new RegExp(regex)).test(value);
+ },
+
+ match: function(value, regex) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be matched with the regular expression.'';
+ }
+
+ return value.match(new RegExp(regex));
+ },
+
+ checkURL: function(value) {
+ if (CParamValidator.isEmpty(value)) {
+ throw ''URL value "'' + value + ''" must be a non-empty string.'';
+ }
+ if (!CParamValidator.ifMatch(value, ''^(http|https):\\/\\/.+'')) {
+ throw ''URL value "'' + value + ''" must contain a schema.'';
+ }
+
+ return value.endsWith(''/'') ? value.slice(0, -1) : value;
+ },
+
+ check: function(key, rule, params) {
+ if (!CParamValidator.isDefined(rule.type)) {
+ throw ''Mandatory attribute "type" has not been defined for parameter "'' + key + ''".'';
+ }
+ if (!CParamValidator.isDefined(params[key])) {
+ throw ''Checked parameter "'' + key + ''" was not found in the list of input parameters.'';
+ }
+ var value = params[key],
+ error_message = null;
+ switch (rule.type) {
+ case ''string'':
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + key + ''" must be a string.'';
+ }
+ if (CParamValidator.isEmpty(value)) {
+ error_message = ''Value "'' + key + ''" must be a non-empty string'';
+ break;
+ }
+ if (CParamValidator.isDefined(rule.len) && value.length < rule.len) {
+ error_message = ''Value "'' + key + ''" must be a string with a length > '' + rule.len;
+ }
+ if (CParamValidator.isDefined(rule.regex) && !CParamValidator.ifMatch(value, rule.regex)) {
+ error_message = ''Value "'' + key + ''" must match the regular expression "'' + rule.regex + ''"'';
+ }
+ if (CParamValidator.isDefined(rule.url) && rule.url === true) {
+ value = CParamValidator.checkURL(value);
+ }
+ break;
+ case ''integer'':
+ if (!CParamValidator.isInteger(value)) {
+ error_message = ''Value "'' + key + ''" must be an integer'';
+ break;
+ }
+ value = parseInt(value);
+ break;
+ case ''float'':
+ if (!CParamValidator.isFloat(value)) {
+ error_message = ''Value "'' + key + ''" must be a floating-point number'';
+ break;
+ }
+ value = parseFloat(value);
+ break;
+ case ''boolean'':
+ if (CParamValidator.inArray(value, [''1'', ''true'', ''yes'', ''on''])) {
+ value = true;
+ }
+ else if (CParamValidator.inArray(value, [''0'', ''false'', ''no'', ''off''])) {
+ value = false;
+ }
+ else {
+ error_message = ''Value "'' + key + ''" must be a boolean-like.'';
+ }
+ break;
+ case ''array'':
+ try {
+ value = JSON.parse(value);
+ } catch (error) {
+ throw ''Value "'' + key + ''" contains invalid JSON.'';
+ }
+ if (!CParamValidator.isType(value, ''array'')) {
+ error_message = ''Value "'' + key + ''" must be an array.'';
+ }
+ if (CParamValidator.isDefined(rule.tags) && rule.tags === true) {
+ value = value.reduce(function(acc, obj) {
+ acc[obj.tag] = obj.value || null;
+ return acc;
+ }, {});
+ }
+ break;
+ case ''object'':
+ value = JSON.parse(value);
+ if (!CParamValidator.isType(value, ''object'')) {
+ error_message = ''Value "'' + key + ''" must be an object.'';
+ }
+ break;
+ default:
+ throw ''Unexpected attribute type "'' + rule.type + ''" for value "'' + key + ''". Available: '' +
+ [''integer'', ''float'', ''string'', ''boolean'', ''array'', ''object''].join('', '');
+ }
+ params[key] = value;
+ if (CParamValidator.inArray(rule.type, [''integer'', ''float'']) && error_message === null && (CParamValidator.isDefined(rule.min)
+ || CParamValidator.isDefined(rule.max)) && !CParamValidator.withinRange(value, rule.min, rule.max)) {
+ error_message = ''Value "'' + key + ''" must be a number '' + ((CParamValidator.isDefined(rule.min) && CParamValidator.isDefined(rule.max))
+ ? (rule.min + ''..'' + rule.max) : ((CParamValidator.isDefined(rule.min)) ? ''>'' + rule.min : ''<'' + rule.max));
+ }
+ else if (CParamValidator.isDefined(rule.array) && !CParamValidator.inArray(value, rule.array)) {
+ error_message = ''Value "'' + key + ''" must be in the array '' + JSON.stringify(rule.array);
+ }
+ else if (CParamValidator.isDefined(rule.macro) && !CParamValidator.isMacroSet(value.toString(), rule.macro)) {
+ error_message = ''The macro '' + ((CParamValidator.isDefined(rule.macro)) ? ''{'' + rule.macro + ''} '' : '' '') + ''is not set'';
+ }
+ if (error_message !== null) {
+ if (CParamValidator.isDefined(rule.default) && CParamValidator.isType(rule.default, rule.type)) {
+ params[key] = rule.default;
+ }
+ else {
+ Zabbix.log(4, ''Default value for "'' + key + ''" must be a '' + rule.type + ''. Skipped.'');
+ throw ''Incorrect value for variable "'' + key + ''". '' + error_message;
+ }
+ }
+
+ return this;
+ },
+
+ validate: function(rules, params) {
+ if (!CParamValidator.isType(params, ''object'') || CParamValidator.isType(params, ''array'')) {
+ throw ''Incorrect parameters value. The value must be an object.'';
+ }
+ for (var key in rules) {
+ CParamValidator.check(key, rules[key], params);
+ }
+ }
+}
+
+const CHttpRequest = function(logger) {
+ this.request = new HttpRequest();
+ if (typeof logger !== ''object'' || logger === null) {
+ this.logger = Zabbix;
+ }
+ else {
+ this.logger = logger;
+ }
+
+ this.clearHeader = function() {
+ this.request.clearHeader();
+ }
+
+ this.addHeaders = function(value) {
+ var headers = [];
+
+ if (typeof value === ''object'' && value !== null) {
+ if (!Array.isArray(value)) {
+ Object.keys(value).forEach(function(key) {
+ headers.push(key + '': '' + value[key]);
+ });
+ }
+ else {
+ headers = value;
+ }
+ }
+ else if (typeof value === ''string'') {
+ value.split(''\\r\\n'').forEach(function(header) {
+ headers.push(header);
+ });
+ }
+
+ for (var idx in headers) {
+ this.request.addHeader(headers[idx]);
+ }
+ }
+
+ this.setProxy = function(proxy) {
+ this.request.setProxy(proxy);
+ }
+
+ this.plainRequest = function(method, url, data) {
+ var resp = null;
+ method = method.toLowerCase();
+ this.logger.log(4, ''Sending '' + method + '' request:'' + JSON.stringify(data));
+ if ([''get'', ''post'', ''put'', ''patch'', ''delete'', ''trace''].indexOf(method) !== -1) {
+ resp = this.request[method](url, data);
+ }
+ else if ([''connect'', ''head'', ''options''].indexOf(method) !== -1) {
+ resp = this.request[method](url);
+ }
+ else {
+ throw ''Unexpected method. Method '' + method + '' is not supported.'';
+ }
+ this.logger.log(4, ''Response has been received: '' + resp);
+
+ return resp;
+ }
+
+ this.jsonRequest = function(method, url, data) {
+ this.addHeaders(''Content-Type: application/json'');
+ var resp = this.plainRequest(method, url, JSON.stringify(data));
+ try {
+ resp = JSON.parse(resp);
+ }
+ catch (error) {
+ throw ''Failed to parse response: not well-formed JSON was received'';
+ }
+
+ return resp;
+ }
+
+ this.getStatus = function() {
+ return this.request.getStatus();
+ }
+}
+
+var SEVERITY_COLORS = [
+ ''#97AAB3'',
+ ''#7499FF'',
+ ''#FFC859'',
+ ''#FFA059'',
+ ''#E97659'',
+ ''#E45959'',
+ ''#009900'',
+ ''#1F1F1F''
+],
+ serviceLogName = ''MS Teams Webhook'',
+ Logger = new CLogger(serviceLogName),
+ MSTeams = CWebhook;
+
+MSTeams.prototype.addBodyFact = function (name, value) {
+ if (!CParamValidator.isDefined(this.data.sections[0].facts)) {
+ this.data.sections[0].facts = [];
+ }
+ this.data.sections[0].facts.push({name: name, value: value});
+}
+
+MSTeams.prototype.onCheckParams = function () {
+ CParamValidator.validate({teams_endpoint: {type: ''string''}, event_source: {type: ''string''}, alert_subject: {type: ''string''},
+ alert_message: {type: ''string''}, host_ip: {type: ''string'', default: ''''}, zabbix_url: {type: ''string'', url: true},
+ use_default_message: {type: ''boolean'', default: false}, event_nseverity: {type: ''integer'', default: 7}}, this.params);
+ var actionName = ''Zabbix Home'';
+ if (!CParamValidator.inArray(this.params.event_source, [''0'',''3'',''4''])
+ || this.params.alert_message.startsWith("NOTE: Escalation canceled:")) {
+ this.params[''use_default_message''] = true;
+ }
+ if (this.params.event_source === ''0'') {
+ CParamValidator.validate({event_id: {type: ''integer''}, trigger_id: {type: ''integer''}}, this.params);
+ actionName = ''Event Info'';
+ }
+ var actionURL = CWebhookHelper.createProblemURL(this.params.event_source, this.params.zabbix_url, this.params.trigger_id, this.params.event_id);
+ if (this.params.event_value === ''0'') {
+ this.params.event_nseverity = 6;
+ }
+ this.data = {
+ themeColor: SEVERITY_COLORS[this.params.event_nseverity].replace(''#'', ''''),
+ summary: this.params.alert_subject,
+ sections: [{
+ markdown: ''false'',
+ activityTitle: this.params.alert_subject,
+ text: (this.params.event_source === ''0'' && !this.params.use_default_message) ? this.params.trigger_description : this.params.alert_message
+ }],
+ potentialAction: [{
+ ''@type'': ''OpenUri'',
+ name: actionName,
+ targets: [{
+ os: ''default'',
+ uri: actionURL
+ }]
+ }]
+ };
+};
+
+MSTeams.prototype.makeUpDefaultMessage = function () {
+ if (!this.params.use_default_message) {
+ if (!CParamValidator.isEmpty(this.params.host_name) && CParamValidator.isMacroSet(this.params.host_name, ''HOST.NAME'')) {
+ this.addBodyFact(''Host'', this.params.host_name + ((!CParamValidator.isEmpty(this.params.host_ip)) ? '' ['' + this.params.host_ip + '']'' : ''''));
+ }
+ if (!CParamValidator.isEmpty(this.params.event_severity) && CParamValidator.isMacroSet(this.params.event_severity, ''EVENT.SEVERITY'')) {
+ this.addBodyFact(''Severity'', this.params.event_severity);
+ }
+ if (!CParamValidator.isEmpty(this.params.event_opdata) && CParamValidator.isMacroSet(this.params.event_opdata, ''EVENT.OPDATA'')) {
+ this.addBodyFact(''Operational data'', this.params.event_opdata);
+ }
+ if (!CParamValidator.isEmpty(this.params.event_tags) && CParamValidator.isMacroSet(this.params.event_tags, ''EVENT.TAGS'')) {
+ this.addBodyFact(''Event tags'', this.params.event_tags);
+ }
+
+ Object.keys(this.params).forEach(function (key) {
+ if (key.startsWith(''fact_'') && this.params[key] !== '''') {
+ this.addBodyFact(key.substring(5), this.params[key]);
+ }
+ else if (key.startsWith(''openUri_'') && this.params[key] !== '''' && !this.params[key].startsWith(''{'')) {
+ this.data.potentialAction.push({
+ ''@type'': ''OpenUri'',
+ name: key.substring(8),
+ targets: [{
+ os: ''default'',
+ uri: this.params[key]
+ }]
+ });
+ }
+ });
+ }
+}
+
+const htmlMultiline = function (text) {
+ return text.replace(/(?:\\r\\n|\\r|\\n)/g, ''
'');
+}
+
+MSTeams.prototype.sendRequest = function () {
+ this.request.addHeaders({"Content-Type": "application/json"});
+ var response = this.request.plainRequest(''POST'', this.params.teams_endpoint, JSON.stringify(this.data));
+
+ if (response !== ''1'') {
+ Logger.log(Logger.WARN, ''FAILED with response: '' + response);
+ throw response;
+ }
+ return ''OK'';
+};
+
+MSTeams.prototype.onProblem = function (alert) {
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+ if (!this.params.use_default_message) {
+ this.addBodyFact(''Event time'', this.params.event_time + '' '' + this.params.event_date);
+ this.makeUpDefaultMessage();
+ }
+ this.data.sections[0].text = htmlMultiline(this.data.sections[0].text);
+
+ return this.sendRequest();
+}
+
+MSTeams.prototype.onUpdate = function (alert) {
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+ if (!this.params.use_default_message) {
+ this.data.sections[0].text = this.params.event_update_user + '' '' + this.params.event_update_action + ''.'';
+ if (this.params.event_update_message) {
+ this.data.sections[0].text += ''
Message:
'' + this.params.event_update_message;
+ }
+ this.addBodyFact(''Event update time'', this.params.event_update_time + '' '' + this.params.event_update_date);
+ this.makeUpDefaultMessage();
+ }
+ this.data.sections[0].text = htmlMultiline(this.data.sections[0].text);
+
+ return this.sendRequest();
+}
+
+MSTeams.prototype.onResolve = function (alert) {
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+ if (!this.params.use_default_message) {
+ this.addBodyFact(''Recovery time'', this.params.event_recovery_time + '' '' + this.params.event_recovery_date);
+ this.makeUpDefaultMessage();
+ }
+ this.data.sections[0].text = htmlMultiline(this.data.sections[0].text);
+
+ return this.sendRequest();
+}
+
+MSTeams.prototype.onDiscovery = function (alert) {
+ return this.onProblem(alert);
+}
+
+MSTeams.prototype.onAutoreg = function (alert) {
+ return this.onProblem(alert);
+}
+
+try {
+ var hook = new MSTeams(value);
+ hook.request = new CHttpRequest(Logger);
+ return hook.run();
+}
+catch (error) {
+ Logger.log(Logger.WARN, ''notification failed: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','0','0','','','https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/templates/media/msteams
+
+1. Add official Zabbix webhook connector from MS Teams apps for the channel, where you want to receive notifications.
+2. Create Incoming webhook for your channel.
+3. In the Zabbix web interface go to Administration → Macros section. Setup the global macro "{$ZABBIX.URL}" which will contain the URL to the Zabbix frontend.
+4. On this page replace placeholder with the incoming webhook URL, created during the webhook setup in MS Teams.
+5. To receive Zabbix notifications in MS Teams, you need to create a Zabbix user and add Media with the MS Teams media type. Make sure this user has access to all hosts for which you would like problem notifications to be sent to MS Teams.','0'),
+('85','4','MS Teams Workflow','','','','','','','','25','0','0','0','0','1','3','10s','1',E'const CLogger = function(serviceName) {
+ this.serviceName = serviceName;
+ this.INFO = 4
+ this.WARN = 3
+ this.ERROR = 2
+ this.log = function(level, msg) {
+ Zabbix.log(level, ''['' + this.serviceName + ''] '' + msg);
+ }
+}
+
+const CWebhook = function(value) {
+ try {
+ params = JSON.parse(value);
+
+ if ([''0'', ''1'', ''2'', ''3'', ''4''].indexOf(params.event_source) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''.\\nMust be 0-4.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1 && [''0'', ''1''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0 or 1.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1) {
+ if (params.event_source === ''1'' && [''0'', ''1'', ''2'', ''3''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0-3.'';
+ }
+
+ if (params.event_source === ''0'' && [''0'', ''1''].indexOf(params.event_update_status) === -1) {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''.\\nMust be 0 or 1.'';
+ }
+
+ if (params.event_source === ''4'') {
+ if ([''0'', ''1'', ''2'', ''3'', ''4'', ''5''].indexOf(params.event_update_nseverity) !== -1 && params.event_update_nseverity != params.event_nseverity) {
+ params.event_nseverity = params.event_update_nseverity;
+ params.event_severity = params.event_update_severity;
+ params.event_update_status = ''1'';
+ }
+ }
+ }
+
+ this.runCallback = function(name, params) {
+ if (typeof this[name] === ''function'') {
+ return this[name].apply(this, [params]);
+ }
+ }
+
+ this.handleEvent = function(source, event) {
+ const alert = { source: source, event: event };
+ return [
+ this.runCallback(''on'' + source + event, alert),
+ this.runCallback(''on'' + event, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.handleEventless = function(source) {
+ const alert = { source: source, event: null };
+ return [
+ this.runCallback(''on'' + source, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.run = function() {
+ var results = [];
+ if (typeof this.httpProxy === ''string'' && this.httpProxy.trim() !== '''') {
+ this.request.setProxy(this.httpProxy);
+ }
+ const types = { ''0'': ''Trigger'', ''1'': ''Discovery'', ''2'': ''Autoreg'', ''3'': ''Internal'', ''4'': ''Service'' };
+
+ if ([''0'', ''3'', ''4''].indexOf(this.params.event_source) !== -1) {
+ var event = (this.params.event_update_status === ''1'')
+ ? ''Update''
+ : ((this.params.event_value === ''1'') ? ''Problem'' : ''Resolve'');
+
+ results = this.handleEvent(types[this.params.event_source], event);
+ }
+ else if (typeof types[this.params.event_source] !== ''undefined'') {
+ results = this.handleEventless(types[this.params.event_source]);
+ }
+ else {
+ throw ''Unexpected "event_source": '' + this.params.event_source;
+ }
+
+ for (idx in results) {
+ if (typeof results[idx] !== ''undefined'') {
+ return JSON.stringify(results[idx]);
+ }
+ }
+ }
+ this.httpProxy = params.http_proxy;
+ this.params = params;
+ this.runCallback(''onCheckParams'', {});
+ } catch (error) {
+ throw ''Webhook processing failed: '' + error;
+ }
+}
+
+const CParamValidator = {
+
+ isType: function(value, type) {
+ if (type === ''array'') {
+ return Array.isArray(value);
+ }
+ if (type === ''integer'') {
+ return CParamValidator.isInteger(value);
+ }
+ if (type === ''float'') {
+ return CParamValidator.isFloat(value);
+ }
+
+ return (typeof value === type);
+ },
+
+ isInteger: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseInt(value));
+ },
+
+ isFloat: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+\\.\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseFloat(value));
+ },
+
+ isDefined: function(value) {
+ return !CParamValidator.isType(value, ''undefined'');
+ },
+
+ isEmpty: function(value) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be checked for emptiness.'';
+ }
+
+ return (value.trim() === '''');
+ },
+
+ isMacroSet: function(value, macro) {
+ if (CParamValidator.isDefined(macro)) {
+ return !(CParamValidator.ifMatch(value, ''^\\{'' + macro + ''\\}$''))
+ }
+
+ return !(CParamValidator.ifMatch(value, ''^\\{[$#]{0,1}[A-Z_\\.]+[\\:]{0,1}["]{0,1}.*["]{0,1}\\}$'') || value === ''*UNKNOWN*'')
+ },
+
+ withinRange: function(value, min, max) {
+ if (!CParamValidator.isType(value, ''number'')) {
+ throw ''Value "'' + value + ''" must be a number to be checked for range.'';
+ }
+ if (value < ((CParamValidator.isDefined(min)) ? min : value)
+ || value > ((CParamValidator.isDefined(max)) ? max : value)) {
+ return false;
+ }
+
+ return true;
+ },
+
+ inArray: function(value, array) {
+ if (!CParamValidator.isType(array, ''array'')) {
+ throw ''The array must be an array to check the value for existing in it.'';
+ }
+
+ return (array.indexOf((typeof value === ''string'') ? value.toLowerCase() : value) !== -1);
+ },
+
+ ifMatch: function(value, regex) {
+ return (new RegExp(regex)).test(value);
+ },
+
+ match: function(value, regex) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be matched with the regular expression.'';
+ }
+
+ return value.match(new RegExp(regex));
+ },
+
+ checkURL: function(value) {
+ if (CParamValidator.isEmpty(value)) {
+ throw ''URL value "'' + value + ''" must be a non-empty string.'';
+ }
+ if (!CParamValidator.ifMatch(value, ''^(http|https):\\/\\/.+'')) {
+ throw ''URL value "'' + value + ''" must contain a schema.'';
+ }
+
+ return value.endsWith(''/'') ? value.slice(0, -1) : value;
+ },
+
+ check: function(key, rule, params) {
+ if (!CParamValidator.isDefined(rule.type)) {
+ throw ''Mandatory attribute "type" has not been defined for parameter "'' + key + ''".'';
+ }
+ if (!CParamValidator.isDefined(params[key])) {
+ throw ''Checked parameter "'' + key + ''" was not found in the list of input parameters.'';
+ }
+ var value = params[key],
+ error_message = null;
+ switch (rule.type) {
+ case ''string'':
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + key + ''" must be a string.'';
+ }
+ if (CParamValidator.isEmpty(value)) {
+ error_message = ''Value "'' + key + ''" must be a non-empty string'';
+ break;
+ }
+ if (CParamValidator.isDefined(rule.len) && value.length < rule.len) {
+ error_message = ''Value "'' + key + ''" must be a string with a length > '' + rule.len;
+ }
+ if (CParamValidator.isDefined(rule.regex) && !CParamValidator.ifMatch(value, rule.regex)) {
+ error_message = ''Value "'' + key + ''" must match the regular expression "'' + rule.regex + ''"'';
+ }
+ if (CParamValidator.isDefined(rule.url) && rule.url === true) {
+ value = CParamValidator.checkURL(value);
+ }
+ break;
+ case ''integer'':
+ if (!CParamValidator.isInteger(value)) {
+ error_message = ''Value "'' + key + ''" must be an integer'';
+ break;
+ }
+ value = parseInt(value);
+ break;
+ case ''float'':
+ if (!CParamValidator.isFloat(value)) {
+ error_message = ''Value "'' + key + ''" must be a floating-point number'';
+ break;
+ }
+ value = parseFloat(value);
+ break;
+ case ''boolean'':
+ if (CParamValidator.inArray(value, [''1'', ''true'', ''yes'', ''on''])) {
+ value = true;
+ }
+ else if (CParamValidator.inArray(value, [''0'', ''false'', ''no'', ''off''])) {
+ value = false;
+ }
+ else {
+ error_message = ''Value "'' + key + ''" must be a boolean-like.'';
+ }
+ break;
+ case ''array'':
+ try {
+ value = JSON.parse(value);
+ } catch (error) {
+ throw ''Value "'' + key + ''" contains invalid JSON.'';
+ }
+ if (!CParamValidator.isType(value, ''array'')) {
+ error_message = ''Value "'' + key + ''" must be an array.'';
+ }
+ if (CParamValidator.isDefined(rule.tags) && rule.tags === true) {
+ value = value.reduce(function(acc, obj) {
+ acc[obj.tag] = obj.value || null;
+ return acc;
+ }, {});
+ }
+ break;
+ case ''object'':
+ value = JSON.parse(value);
+ if (!CParamValidator.isType(value, ''object'')) {
+ error_message = ''Value "'' + key + ''" must be an object.'';
+ }
+ break;
+ default:
+ throw ''Unexpected attribute type "'' + rule.type + ''" for value "'' + key + ''". Available: '' +
+ [''integer'', ''float'', ''string'', ''boolean'', ''array'', ''object''].join('', '');
+ }
+ params[key] = value;
+ if (CParamValidator.inArray(rule.type, [''integer'', ''float'']) && error_message === null && (CParamValidator.isDefined(rule.min)
+ || CParamValidator.isDefined(rule.max)) && !CParamValidator.withinRange(value, rule.min, rule.max)) {
+ error_message = ''Value "'' + key + ''" must be a number '' + ((CParamValidator.isDefined(rule.min) && CParamValidator.isDefined(rule.max))
+ ? (rule.min + ''..'' + rule.max) : ((CParamValidator.isDefined(rule.min)) ? ''>'' + rule.min : ''<'' + rule.max));
+ }
+ else if (CParamValidator.isDefined(rule.array) && !CParamValidator.inArray(value, rule.array)) {
+ error_message = ''Value "'' + key + ''" must be in the array '' + JSON.stringify(rule.array);
+ }
+ else if (CParamValidator.isDefined(rule.macro) && !CParamValidator.isMacroSet(value.toString(), rule.macro)) {
+ error_message = ''The macro '' + ((CParamValidator.isDefined(rule.macro)) ? ''{'' + rule.macro + ''} '' : '' '') + ''is not set'';
+ }
+ if (error_message !== null) {
+ if (CParamValidator.isDefined(rule.default) && CParamValidator.isType(rule.default, rule.type)) {
+ params[key] = rule.default;
+ }
+ else {
+ Zabbix.log(4, ''Default value for "'' + key + ''" must be a '' + rule.type + ''. Skipped.'');
+ throw ''Incorrect value for variable "'' + key + ''". '' + error_message;
+ }
+ }
+
+ return this;
+ },
+
+ validate: function(rules, params) {
+ if (!CParamValidator.isType(params, ''object'') || CParamValidator.isType(params, ''array'')) {
+ throw ''Incorrect parameters value. The value must be an object.'';
+ }
+ for (var key in rules) {
+ CParamValidator.check(key, rules[key], params);
+ }
+ }
+}
+
+const CHttpRequest = function(logger) {
+ this.request = new HttpRequest();
+ if (typeof logger !== ''object'' || logger === null) {
+ this.logger = Zabbix;
+ }
+ else {
+ this.logger = logger;
+ }
+
+ this.clearHeader = function() {
+ this.request.clearHeader();
+ }
+
+ this.addHeaders = function(value) {
+ var headers = [];
+
+ if (typeof value === ''object'' && value !== null) {
+ if (!Array.isArray(value)) {
+ Object.keys(value).forEach(function(key) {
+ headers.push(key + '': '' + value[key]);
+ });
+ }
+ else {
+ headers = value;
+ }
+ }
+ else if (typeof value === ''string'') {
+ value.split(''\\r\\n'').forEach(function(header) {
+ headers.push(header);
+ });
+ }
+
+ for (var idx in headers) {
+ this.request.addHeader(headers[idx]);
+ }
+ }
+
+ this.setProxy = function(proxy) {
+ this.request.setProxy(proxy);
+ }
+
+ this.plainRequest = function(method, url, data) {
+ var resp = null;
+ method = method.toLowerCase();
+ this.logger.log(4, ''Sending '' + method + '' request:'' + JSON.stringify(data));
+ if ([''get'', ''post'', ''put'', ''patch'', ''delete'', ''trace''].indexOf(method) !== -1) {
+ resp = this.request[method](url, data);
+ }
+ else if ([''connect'', ''head'', ''options''].indexOf(method) !== -1) {
+ resp = this.request[method](url);
+ }
+ else {
+ throw ''Unexpected method. Method '' + method + '' is not supported.'';
+ }
+ this.logger.log(4, ''Response has been received: '' + resp);
+
+ return resp;
+ }
+
+ this.jsonRequest = function(method, url, data) {
+ this.addHeaders(''Content-Type: application/json'');
+ var resp = this.plainRequest(method, url, JSON.stringify(data));
+ try {
+ resp = JSON.parse(resp);
+ }
+ catch (error) {
+ throw ''Failed to parse response: not well-formed JSON was received'';
+ }
+
+ return resp;
+ }
+
+ this.getStatus = function() {
+ return this.request.getStatus();
+ }
+}
+
+const CWebhookHelper = {
+
+ createProblemURL: function(event_source, zabbix_url, trigger_id, event_id) {
+ if (event_source === ''0'') {
+ return zabbix_url + ''/tr_events.php?triggerid='' + trigger_id + ''&eventid='' + event_id;
+ } else if (event_source === ''4'') {
+ return zabbix_url + ''/zabbix.php?action=service.list'';
+ }
+
+ return zabbix_url;
+ },
+
+};
+
+
+var serviceLogName = ''MS Teams Webhook'',
+ Logger = new CLogger(serviceLogName),
+ MSTeams = CWebhook;
+
+MSTeams.prototype.onCheckParams = function () {
+ CParamValidator.validate({
+ alert_subject: { type: ''string'' }, alert_message: { type: ''string'' },
+ zabbix_url: { type: ''string'', url: true }, teams_endpoint: { type: ''string'', url: true }
+ }, this.params);
+
+ if (this.params.event_source === ''0'') {
+ CParamValidator.validate({ event_id: { type: ''integer'' }, trigger_id: { type: ''integer'' } }, this.params);
+ }
+
+ this.body = {
+ type: "message",
+ attachments: [
+ {
+ contentType: "application/vnd.microsoft.card.adaptive",
+ contentUrl: null,
+ content: {
+ $schema: "http://adaptivecards.io/schemas/adaptive-card.json",
+ type: "AdaptiveCard",
+ version: "1.4",
+ body: [
+ {
+ type: "Container",
+ items: [
+ {
+ type: "TextBlock",
+ size: "Medium",
+ wrap: "true",
+ weight: "Bolder",
+ text: this.params.alert_subject
+ }
+ ],
+ style: "",
+ bleed: true
+ }
+ ],
+ actions: [
+ {
+ type: "Action.OpenUrl",
+ title: "Event info",
+ url: CWebhookHelper.createProblemURL(this.params.event_source, this.params.zabbix_url, this.params.trigger_id, this.params.event_id)
+ }
+ ]
+ }
+ }
+ ]
+ };
+
+ this.params.alert_message = this.params.alert_message.split(''\\n'');
+
+ for (line in this.params.alert_message) {
+ this.body.attachments[0].content.body.push({
+ type: "TextBlock",
+ wrap: "true",
+ text: this.params.alert_message[line]
+ });
+ }
+
+};
+
+MSTeams.prototype.sendRequest = function (color) {
+ this.body.attachments[0].content.body[0].style = color;
+
+ this.request.addHeaders({ "Content-Type": "application/json" });
+ var response = this.request.plainRequest(''POST'', this.params.teams_endpoint, JSON.stringify(this.body));
+
+ var status = this.request.getStatus();
+ if (status < 200 || status >= 300) {
+ Logger.log(Logger.INFO, ''HTTP code: '' + status + ''. Endpoint response: '' + response);
+ throw ''HTTP code: '' + status + ''. Endpoint response: '' + response;
+ }
+
+ return ''OK'';
+};
+
+MSTeams.prototype.onProblem = function () {
+ return this.sendRequest("attention");
+};
+
+MSTeams.prototype.onResolve = function () {
+ return this.sendRequest("good");
+};
+
+MSTeams.prototype.onUpdate = function () {
+ return this.sendRequest("emphasis");
+};
+
+MSTeams.prototype.onDiscovery = function () {
+ return this.sendRequest("emphasis");
+};
+
+MSTeams.prototype.onAutoreg = function () {
+ return this.sendRequest("emphasis");
+};
+
+try {
+ var hook = new MSTeams(value);
+ hook.request = new CHttpRequest(Logger);
+ return hook.run();
+}
+catch (error) {
+ Logger.log(Logger.WARN, ''notification failed: '' + error);
+ throw ''Sending failed: '' + error;
+};','30s','0','0','','','To set up a webhook, please follow these steps:
+
+- Create a workflow in MS Teams. You can use the "Post a message in a channel when a webhook request is received" template for it.
+- Copy the endpoint URL and place it in the teams_endpoint parameter.
+- Set up the global macro {$ZABBIX.URL}, which will contain the URL to the Zabbix frontend.
+- Create a Zabbix user and add the MS Teams Workflow media to it.
+
+For more detailed instructions, please visit https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/templates/media/.','0'),
+('86','4','Opsgenie','','','','','','','','25','0','0','0','0','1','3','10s','1',E'var method,
+ Media = {
+ params: {},
+ name: '''',
+ labels: [],
+ HTTPProxy: '''',
+
+ setParams: function (params) {
+ if (typeof params !== ''object'') {
+ return;
+ }
+
+ Media.params = params;
+ Media.params.api += Media.params.api.endsWith(''/'') ? '''' : ''/'';
+ Media.params.web += Media.params.web.endsWith(''/'') ? '''' : ''/'';
+ },
+
+ setProxy: function (HTTPProxy) {
+ if (typeof HTTPProxy !== ''undefined'' && HTTPProxy.trim() !== '''') {
+ Media.HTTPProxy = HTTPProxy;
+ }
+ },
+
+ setTags: function(event_tags_json) {
+ if (typeof event_tags_json !== ''undefined'' && event_tags_json !== ''''
+ && event_tags_json !== ''{EVENT.TAGSJSON}'') {
+
+ try {
+ var tags = JSON.parse(event_tags_json),
+ label;
+
+ tags.forEach(function (tag) {
+ if (typeof tag.tag === ''string'') {
+ label = (tag.tag + (typeof tag.value !== ''undefined''
+ && tag.value !== '''' ? ('':'' + tag.value) : '''')).replace(/\\s/g, ''_'');
+ Media.labels.push(label);
+ }
+ });
+ }
+ catch (error) {
+ Zabbix.log(4, ''[ '' + Media.name + '' Webhook ] Failed to parse "event_tags_json" param'');
+ }
+ }
+ },
+
+ request: function (method, query, data, allow_404) {
+ if (typeof(allow_404) === ''undefined'') {
+ allow_404 = false;
+ }
+
+ [''api'', ''token''].forEach(function (field) {
+ if (typeof Media.params !== ''object'' || typeof Media.params[field] === ''undefined''
+ || Media.params[field] === '''') {
+ throw ''Required '' + Media.name + '' param is not set: "'' + field + ''".'';
+ }
+ });
+
+ var response,
+ url = Media.params.api + query,
+ request = new HttpRequest();
+
+ request.addHeader(''Content-Type: application/json'');
+ request.addHeader(''Authorization: '' + Media.params.token);
+ request.setProxy(Media.HTTPProxy);
+
+ if (typeof data !== ''undefined'') {
+ data = JSON.stringify(data);
+ }
+
+ Zabbix.log(4, ''[ '' + Media.name + '' Webhook ] Sending request: '' +
+ url + ((typeof data === ''string'') ? (''\\n'' + data) : ''''));
+
+ switch (method) {
+ case ''get'':
+ response = request.get(url, data);
+ break;
+
+ case ''post'':
+ response = request.post(url, data);
+ break;
+
+ case ''put'':
+ response = request.put(url, data);
+ break;
+
+ default:
+ throw ''Unsupported HTTP request method: '' + method;
+ }
+
+ Zabbix.log(4, ''[ '' + Media.name + '' Webhook ] Received response with status code '' +
+ request.getStatus() + ''\\n'' + response);
+
+ if (response !== null) {
+ try {
+ response = JSON.parse(response);
+ }
+ catch (error) {
+ Zabbix.log(4, ''[ '' + Media.name + '' Webhook ] Failed to parse response.'');
+ response = null;
+ }
+ }
+
+ if ((request.getStatus() < 200 || request.getStatus() >= 300)
+ && (!allow_404 || request.getStatus() !== 404)) {
+ var message = ''Request failed with status code '' + request.getStatus();
+
+ if (response !== null) {
+ if (typeof response.errors === ''object'' && Object.keys(response.errors).length > 0) {
+ message += '': '' + JSON.stringify(response.errors);
+ }
+ else if (typeof response.errorMessages === ''object'' && Object.keys(response.errorMessages).length > 0) {
+ message += '': '' + JSON.stringify(response.errorMessages);
+ }
+ else if (typeof response.message === ''string'') {
+ message += '': '' + response.message;
+ }
+ }
+
+ throw message + '' Check debug log for more information.'';
+ }
+
+ return {
+ status: request.getStatus(),
+ response: response
+ };
+ },
+
+ getAlertId: function (requestId) {
+ status_counter = params.status_counter || 25;
+ do {
+ resp = Media.request(''get'', ''requests/'' + requestId, undefined, true);
+ status_counter -= 1;
+ }
+ while ( status_counter > 0 &&
+ (
+ typeof resp.response !== ''object'' ||
+ typeof resp.response.data === ''undefined'' ||
+ resp.response.data.success === false &&
+ !resp.response.data.status.includes("There is no open alert") &&
+ !resp.response.data.status.includes("Alert is already")
+ )
+ );
+
+ if (typeof resp.response !== ''object'' || typeof resp.response.data === ''undefined'') {
+ throw ''Cannot get '' + Media.name + '' issue ID. Check debug log for more information.'';
+ }
+ else if (resp.response.data.success === false ) {
+ throw Media.name + '': Operation status ('' + resp.response.data.status + '')'';
+ }
+
+ return resp;
+ }
+};
+
+try {
+ var result = {tags: {}},
+ params = JSON.parse(value),
+ media = {},
+ fields = {},
+ resp = {},
+ responders = [],
+ tags = [],
+ required_params = [
+ ''alert_subject'',
+ ''alert_message'',
+ ''event_id'',
+ ''event_source'',
+ ''event_value'',
+ ''event_update_status'',
+ ''opsgenie_api'',
+ ''opsgenie_web'',
+ ''opsgenie_token''
+ ],
+ severities = [
+ ''not_classified'',
+ ''information'',
+ ''warning'',
+ ''average'',
+ ''high'',
+ ''disaster'',
+ ''resolved'',
+ ''default''
+ ],
+ priority;
+
+ Object.keys(params)
+ .forEach(function (key) {
+ if (required_params.indexOf(key) !== -1 && params[key].trim() === '''') {
+ throw ''Parameter "'' + key + ''" cannot be empty.'';
+ }
+ if (key.startsWith(''opsgenie_'')) {
+ media[key.substring(9)] = params[key];
+ }
+ });
+
+ // Possible values of event_source:
+ // 0 - Trigger, 1 - Discovery, 2 - Autoregistration, 3 - Internal.
+ if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
+ throw ''Incorrect "event_source" parameter given: "'' + params.event_source + ''".\\nMust be 0-3.'';
+ }
+
+ // Check event_value for trigger-based and internal events.
+ // Possible values: 1 for problem, 0 for recovering
+ 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.
+ // Possible values: 0 - Webhook was called because of problem/recovery event, 1 - Update operation.
+ if (params.event_source === ''0'' && params.event_update_status !== ''0'' && params.event_update_status !== ''1'') {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''\\nMust be 0 or 1.'';
+ }
+
+ // Check event_id for a numeric value.
+ if (isNaN(parseInt(params.event_id)) || params.event_id < 1) {
+ throw ''Incorrect "event_id" parameter given: '' + params.event_id + ''\\nMust be a positive number.'';
+ }
+
+ if ((params.event_source === ''1'' || params.event_source === ''2'') && params.event_value === ''0'') {
+ throw ''Recovery operations are supported only for Trigger and Internal actions.'';
+ }
+
+ if ([0, 1, 2, 3, 4, 5].indexOf(parseInt(params.event_nseverity)) === -1) {
+ params.event_nseverity = ''7'';
+ }
+
+ if (params.event_value === ''0'') {
+ params.event_nseverity = ''6'';
+ }
+
+ priority = params[''severity_'' + severities[params.event_nseverity]];
+ params.zbxurl = params.zbxurl + (params.zbxurl.endsWith(''/'') ? '''' : ''/'');
+
+ Media.name = ''Opsgenie'';
+ Media.setParams(media);
+ Media.params.token = ''GenieKey '' + Media.params.token;
+ Media.setProxy(params.HTTPProxy);
+ Media.setTags(params.event_tags_json); // Set Media.labels
+
+ // Create an issue.
+ // Numeric value of the event that triggered an action (1 for problem, 0 for recovering).
+ // Numeric value of the problem update status. Possible values:
+ // 0 - Webhook was called because of problem/recovery event, 1 - Update operation.
+ if ((params.event_source == 0 && params.event_value == 1 && params.event_update_status == 0)
+ || (params.event_source == 3 && params.event_value == 1)
+ || params.event_source == 1 || params.event_source == 2) {
+ fields.message = params.alert_subject;
+ fields.alias = params.event_id;
+ fields.description = params.alert_message;
+ fields.priority = priority;
+ fields.source = ''Zabbix'';
+
+ if (params.event_source === ''0'') {
+ fields.details = {
+ ''Zabbix server'': params.zbxurl,
+ Problem: params.zbxurl + ''tr_events.php?triggerid='' + params.trigger_id + ''&eventid='' + params.event_id
+ };
+ }
+ else {
+ fields.details = {''Zabbix server'': params.zbxurl};
+ }
+
+ if (typeof params.opsgenie_teams === ''string'') {
+ responders = params.opsgenie_teams.split('','');
+ fields.responders = responders.map(function(team) {
+ return {type: ''team'', name: team.trim()};
+ });
+ }
+
+ fields.tags = Media.labels;
+ if (typeof params.opsgenie_tags === ''string'') {
+ tags = params.opsgenie_tags.split('','');
+ tags.forEach(function(item) {
+ fields.tags.push(item.trim());
+ });
+ }
+
+ resp = Media.request(''post'', '''', fields);
+ if (typeof resp.response !== ''object'' || typeof resp.response.result === ''undefined'') {
+ throw ''Cannot create '' + Media.name + '' issue. Check debug log for more information.'';
+ }
+
+ if (resp.status === 202) {
+ resp = Media.getAlertId(resp.response.requestId);
+ if (params.event_source == 0 && params.event_value == 1 && params.event_update_status == 0) {
+ result.tags.__zbx_ops_issuekey = resp.response.data.alertId;
+ result.tags.__zbx_ops_issuelink = Media.params.web + ''alert/detail/'' + resp.response.data.alertId;
+ }
+ }
+ else {
+ throw Media.name + '' response code is unexpected. Check debug log for more information.'';
+ }
+ }
+ // Update or close the created issue.
+ else {
+ fields.user = (params.event_value != 0) ? params.zbxuser : '''';
+ fields.note = params.alert_message;
+ if ( [0, 3].indexOf(parseInt(params.event_source)) > -1 && params.event_value == 0 ) {
+ // skip sending of close request from update operation(mandatory when both update & recovery operations are defined in action)
+ method = params.event_update_status == 0 ? "close" : "skip";
+ }
+ else if ( params.event_source == 0 && params.event_value == 1 && params.event_update_status == 1 && params.event_update_action.includes(''acknowledged'')) {
+ method = params.event_update_action.includes(''unacknowledged'') ? "unacknowledge" : "acknowledge";
+ }
+ else {
+ method = "notes";
+ }
+
+ if (method !== "skip") {
+ resp = Media.request(''post'', params.event_id + ''/'' + method +''?identifierType=alias'', fields);
+
+ if (typeof resp.response !== ''object'' || typeof resp.response.result === ''undefined'') {
+ throw ''Cannot update '' + Media.name + '' issue. Check debug log for more information.'';
+ }
+
+ if (resp.status === 202) {
+ resp = Media.getAlertId(resp.response.requestId);
+ }
+ else {
+ throw Media.name + '' response code is unexpected. Check debug log for more information.'';
+ }
+ }
+ }
+ return JSON.stringify(result);
+}
+catch (error) {
+ Zabbix.log(3, ''[ '' + Media.name + '' Webhook ] ERROR: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','1','{EVENT.TAGS.__zbx_ops_issuelink}','Opsgenie: {EVENT.TAGS.__zbx_ops_issuekey}','Please refer to https://docs.opsgenie.com/docs/alert-api and https://www.zabbix.com/documentation/8.0/manual/config/notifications/media/webhook#example_scripts.
+
+Set global macro {$ZABBIX.URL} with your Zabbix server URL.
+Add dedicated user with media type "Opsgenie".
+Change the values of the variables opsgenie_api (https://api.opsgenie.com/v2/alerts or https://api.eu.opsgenie.com/v2/alerts),
+opsgenie_web (for example, https://myzabbix.app.opsgenie.com), opsgenie_token.','0'),
+('87','4','OTRS CE','','','','','','','','25','0','0','0','0','1','3','10s','1',E'const CLogger = function(serviceName) {
+ this.serviceName = serviceName;
+ this.INFO = 4
+ this.WARN = 3
+ this.ERROR = 2
+ this.log = function(level, msg) {
+ Zabbix.log(level, ''['' + this.serviceName + ''] '' + msg);
+ }
+}
+
+const CWebhook = function(value) {
+ try {
+ params = JSON.parse(value);
+
+ if ([''0'', ''1'', ''2'', ''3'', ''4''].indexOf(params.event_source) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''.\\nMust be 0-4.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1 && [''0'', ''1''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0 or 1.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1) {
+ if (params.event_source === ''1'' && [''0'', ''1'', ''2'', ''3''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0-3.'';
+ }
+
+ if (params.event_source === ''0'' && [''0'', ''1''].indexOf(params.event_update_status) === -1) {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''.\\nMust be 0 or 1.'';
+ }
+
+ if (params.event_source === ''4'') {
+ if ([''0'', ''1'', ''2'', ''3'', ''4'', ''5''].indexOf(params.event_update_nseverity) !== -1 && params.event_update_nseverity != params.event_nseverity) {
+ params.event_nseverity = params.event_update_nseverity;
+ params.event_severity = params.event_update_severity;
+ params.event_update_status = ''1'';
+ }
+ }
+ }
+
+ this.runCallback = function(name, params) {
+ if (typeof this[name] === ''function'') {
+ return this[name].apply(this, [params]);
+ }
+ }
+
+ this.handleEvent = function(source, event) {
+ const alert = { source: source, event: event };
+ return [
+ this.runCallback(''on'' + source + event, alert),
+ this.runCallback(''on'' + event, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.handleEventless = function(source) {
+ const alert = { source: source, event: null };
+ return [
+ this.runCallback(''on'' + source, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.run = function() {
+ var results = [];
+ if (typeof this.httpProxy === ''string'' && this.httpProxy.trim() !== '''') {
+ this.request.setProxy(this.httpProxy);
+ }
+ const types = { ''0'': ''Trigger'', ''1'': ''Discovery'', ''2'': ''Autoreg'', ''3'': ''Internal'', ''4'': ''Service'' };
+
+ if ([''0'', ''3'', ''4''].indexOf(this.params.event_source) !== -1) {
+ var event = (this.params.event_update_status === ''1'')
+ ? ''Update''
+ : ((this.params.event_value === ''1'') ? ''Problem'' : ''Resolve'');
+
+ results = this.handleEvent(types[this.params.event_source], event);
+ }
+ else if (typeof types[this.params.event_source] !== ''undefined'') {
+ results = this.handleEventless(types[this.params.event_source]);
+ }
+ else {
+ throw ''Unexpected "event_source": '' + this.params.event_source;
+ }
+
+ for (idx in results) {
+ if (typeof results[idx] !== ''undefined'') {
+ return JSON.stringify(results[idx]);
+ }
+ }
+ }
+ this.httpProxy = params.http_proxy;
+ this.params = params;
+ this.runCallback(''onCheckParams'', {});
+ } catch (error) {
+ throw ''Webhook processing failed: '' + error;
+ }
+}
+
+const CWebhookHelper = {
+
+ createProblemURL: function(event_source, zabbix_url, trigger_id, event_id) {
+ if (event_source === ''0'') {
+ return zabbix_url + ''/tr_events.php?triggerid='' + trigger_id + ''&eventid='' + event_id;
+ } else if (event_source === ''4'') {
+ return zabbix_url + ''/zabbix.php?action=service.list'';
+ }
+
+ return zabbix_url;
+ },
+
+};
+
+const CParamValidator = {
+
+ isType: function(value, type) {
+ if (type === ''array'') {
+ return Array.isArray(value);
+ }
+ if (type === ''integer'') {
+ return CParamValidator.isInteger(value);
+ }
+ if (type === ''float'') {
+ return CParamValidator.isFloat(value);
+ }
+
+ return (typeof value === type);
+ },
+
+ isInteger: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseInt(value));
+ },
+
+ isFloat: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+\\.\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseFloat(value));
+ },
+
+ isDefined: function(value) {
+ return !CParamValidator.isType(value, ''undefined'');
+ },
+
+ isEmpty: function(value) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be checked for emptiness.'';
+ }
+
+ return (value.trim() === '''');
+ },
+
+ isMacroSet: function(value, macro) {
+ if (CParamValidator.isDefined(macro)) {
+ return !(CParamValidator.ifMatch(value, ''^\\{'' + macro + ''\\}$''))
+ }
+
+ return !(CParamValidator.ifMatch(value, ''^\\{[$#]{0,1}[A-Z_\\.]+[\\:]{0,1}["]{0,1}.*["]{0,1}\\}$'') || value === ''*UNKNOWN*'')
+ },
+
+ withinRange: function(value, min, max) {
+ if (!CParamValidator.isType(value, ''number'')) {
+ throw ''Value "'' + value + ''" must be a number to be checked for range.'';
+ }
+ if (value < ((CParamValidator.isDefined(min)) ? min : value)
+ || value > ((CParamValidator.isDefined(max)) ? max : value)) {
+ return false;
+ }
+
+ return true;
+ },
+
+ inArray: function(value, array) {
+ if (!CParamValidator.isType(array, ''array'')) {
+ throw ''The array must be an array to check the value for existing in it.'';
+ }
+
+ return (array.indexOf((typeof value === ''string'') ? value.toLowerCase() : value) !== -1);
+ },
+
+ ifMatch: function(value, regex) {
+ return (new RegExp(regex)).test(value);
+ },
+
+ match: function(value, regex) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be matched with the regular expression.'';
+ }
+
+ return value.match(new RegExp(regex));
+ },
+
+ checkURL: function(value) {
+ if (CParamValidator.isEmpty(value)) {
+ throw ''URL value "'' + value + ''" must be a non-empty string.'';
+ }
+ if (!CParamValidator.ifMatch(value, ''^(http|https):\\/\\/.+'')) {
+ throw ''URL value "'' + value + ''" must contain a schema.'';
+ }
+
+ return value.endsWith(''/'') ? value.slice(0, -1) : value;
+ },
+
+ check: function(key, rule, params) {
+ if (!CParamValidator.isDefined(rule.type)) {
+ throw ''Mandatory attribute "type" has not been defined for parameter "'' + key + ''".'';
+ }
+ if (!CParamValidator.isDefined(params[key])) {
+ throw ''Checked parameter "'' + key + ''" was not found in the list of input parameters.'';
+ }
+ var value = params[key],
+ error_message = null;
+ switch (rule.type) {
+ case ''string'':
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + key + ''" must be a string.'';
+ }
+ if (CParamValidator.isEmpty(value)) {
+ error_message = ''Value "'' + key + ''" must be a non-empty string'';
+ break;
+ }
+ if (CParamValidator.isDefined(rule.len) && value.length < rule.len) {
+ error_message = ''Value "'' + key + ''" must be a string with a length > '' + rule.len;
+ }
+ if (CParamValidator.isDefined(rule.regex) && !CParamValidator.ifMatch(value, rule.regex)) {
+ error_message = ''Value "'' + key + ''" must match the regular expression "'' + rule.regex + ''"'';
+ }
+ if (CParamValidator.isDefined(rule.url) && rule.url === true) {
+ value = CParamValidator.checkURL(value);
+ }
+ break;
+ case ''integer'':
+ if (!CParamValidator.isInteger(value)) {
+ error_message = ''Value "'' + key + ''" must be an integer'';
+ break;
+ }
+ value = parseInt(value);
+ break;
+ case ''float'':
+ if (!CParamValidator.isFloat(value)) {
+ error_message = ''Value "'' + key + ''" must be a floating-point number'';
+ break;
+ }
+ value = parseFloat(value);
+ break;
+ case ''boolean'':
+ if (CParamValidator.inArray(value, [''1'', ''true'', ''yes'', ''on''])) {
+ value = true;
+ }
+ else if (CParamValidator.inArray(value, [''0'', ''false'', ''no'', ''off''])) {
+ value = false;
+ }
+ else {
+ error_message = ''Value "'' + key + ''" must be a boolean-like.'';
+ }
+ break;
+ case ''array'':
+ try {
+ value = JSON.parse(value);
+ } catch (error) {
+ throw ''Value "'' + key + ''" contains invalid JSON.'';
+ }
+ if (!CParamValidator.isType(value, ''array'')) {
+ error_message = ''Value "'' + key + ''" must be an array.'';
+ }
+ if (CParamValidator.isDefined(rule.tags) && rule.tags === true) {
+ value = value.reduce(function(acc, obj) {
+ acc[obj.tag] = obj.value || null;
+ return acc;
+ }, {});
+ }
+ break;
+ case ''object'':
+ value = JSON.parse(value);
+ if (!CParamValidator.isType(value, ''object'')) {
+ error_message = ''Value "'' + key + ''" must be an object.'';
+ }
+ break;
+ default:
+ throw ''Unexpected attribute type "'' + rule.type + ''" for value "'' + key + ''". Available: '' +
+ [''integer'', ''float'', ''string'', ''boolean'', ''array'', ''object''].join('', '');
+ }
+ params[key] = value;
+ if (CParamValidator.inArray(rule.type, [''integer'', ''float'']) && error_message === null && (CParamValidator.isDefined(rule.min)
+ || CParamValidator.isDefined(rule.max)) && !CParamValidator.withinRange(value, rule.min, rule.max)) {
+ error_message = ''Value "'' + key + ''" must be a number '' + ((CParamValidator.isDefined(rule.min) && CParamValidator.isDefined(rule.max))
+ ? (rule.min + ''..'' + rule.max) : ((CParamValidator.isDefined(rule.min)) ? ''>'' + rule.min : ''<'' + rule.max));
+ }
+ else if (CParamValidator.isDefined(rule.array) && !CParamValidator.inArray(value, rule.array)) {
+ error_message = ''Value "'' + key + ''" must be in the array '' + JSON.stringify(rule.array);
+ }
+ else if (CParamValidator.isDefined(rule.macro) && !CParamValidator.isMacroSet(value.toString(), rule.macro)) {
+ error_message = ''The macro '' + ((CParamValidator.isDefined(rule.macro)) ? ''{'' + rule.macro + ''} '' : '' '') + ''is not set'';
+ }
+ if (error_message !== null) {
+ if (CParamValidator.isDefined(rule.default) && CParamValidator.isType(rule.default, rule.type)) {
+ params[key] = rule.default;
+ }
+ else {
+ Zabbix.log(4, ''Default value for "'' + key + ''" must be a '' + rule.type + ''. Skipped.'');
+ throw ''Incorrect value for variable "'' + key + ''". '' + error_message;
+ }
+ }
+
+ return this;
+ },
+
+ validate: function(rules, params) {
+ if (!CParamValidator.isType(params, ''object'') || CParamValidator.isType(params, ''array'')) {
+ throw ''Incorrect parameters value. The value must be an object.'';
+ }
+ for (var key in rules) {
+ CParamValidator.check(key, rules[key], params);
+ }
+ }
+}
+
+const CHttpRequest = function(logger) {
+ this.request = new HttpRequest();
+ if (typeof logger !== ''object'' || logger === null) {
+ this.logger = Zabbix;
+ }
+ else {
+ this.logger = logger;
+ }
+
+ this.clearHeader = function() {
+ this.request.clearHeader();
+ }
+
+ this.addHeaders = function(value) {
+ var headers = [];
+
+ if (typeof value === ''object'' && value !== null) {
+ if (!Array.isArray(value)) {
+ Object.keys(value).forEach(function(key) {
+ headers.push(key + '': '' + value[key]);
+ });
+ }
+ else {
+ headers = value;
+ }
+ }
+ else if (typeof value === ''string'') {
+ value.split(''\\r\\n'').forEach(function(header) {
+ headers.push(header);
+ });
+ }
+
+ for (var idx in headers) {
+ this.request.addHeader(headers[idx]);
+ }
+ }
+
+ this.setProxy = function(proxy) {
+ this.request.setProxy(proxy);
+ }
+
+ this.plainRequest = function(method, url, data) {
+ var resp = null;
+ method = method.toLowerCase();
+ this.logger.log(4, ''Sending '' + method + '' request:'' + JSON.stringify(data));
+ if ([''get'', ''post'', ''put'', ''patch'', ''delete'', ''trace''].indexOf(method) !== -1) {
+ resp = this.request[method](url, data);
+ }
+ else if ([''connect'', ''head'', ''options''].indexOf(method) !== -1) {
+ resp = this.request[method](url);
+ }
+ else {
+ throw ''Unexpected method. Method '' + method + '' is not supported.'';
+ }
+ this.logger.log(4, ''Response has been received: '' + resp);
+
+ return resp;
+ }
+
+ this.jsonRequest = function(method, url, data) {
+ this.addHeaders(''Content-Type: application/json'');
+ var resp = this.plainRequest(method, url, JSON.stringify(data));
+ try {
+ resp = JSON.parse(resp);
+ }
+ catch (error) {
+ throw ''Failed to parse response: not well-formed JSON was received'';
+ }
+
+ return resp;
+ }
+
+ this.getStatus = function() {
+ return this.request.getStatus();
+ }
+}
+
+const SEVERITIES = ["not_classified", "information", "warning", "average", "high", "disaster"],
+ serviceLogName = '' ((OTRS)) CE Webhook '',
+ Logger = new CLogger(serviceLogName),
+ OTRS = CWebhook;
+
+OTRS.prototype.onCheckParams = function () {
+ CParamValidator.validate({alert_subject: {type: ''string''}, alert_message: {type: ''string''},
+ event_nseverity: {type: ''integer'', default: -1}, otrs_url: {type: ''string'', url: true}, otrs_auth_user: {type: ''string''},
+ otrs_auth_password: {type: ''string''}, otrs_customer: {type: ''string''}, otrs_default_priority_id: {type: ''integer'', min: 1, max: 5},
+ otrs_queue: {type: ''string''}, otrs_ticket_type: {type: ''string''}, otrs_ticket_state: {type: ''string''}, otrs_time_unit: {type: ''integer''},
+ otrs_closed_state_id: {type: ''integer'', default: 0}, zabbix_url: {type: ''string'', url: true}}, this.params);
+ this.params.entrypoint = ''/nph-genericinterface.pl/Webservice/ZabbixTicketConnector/Ticket'';
+
+ var priority;
+ if (this.params.event_nseverity >= 0 && this.params.event_nseverity < SEVERITIES.length) {
+ priority = this.params[''severity_'' + SEVERITIES[this.params.event_nseverity]];
+ }
+ this.priority = (CParamValidator.isDefined(priority)) ? priority.trim() : this.params.otrs_default_priority_id;
+
+ if (this.params.event_source === ''0'') {
+ CParamValidator.validate({trigger_id: {type: ''integer''}, event_id: {type: ''integer''}}, this.params);
+ this.params.zabbix_url = CWebhookHelper.createProblemURL(this.params.event_source, this.params.zabbix_url, this.params.trigger_id, this.params.event_id);
+ this.params.alert_message = this.params.alert_subject + ''\\n'' + this.params.alert_message + ''\\n'' +
+ this.params.zabbix_url + ''\\n'';
+ }
+ if (this.params.event_value != ''0'' && CParamValidator.isMacroSet(this.params.otrs_ticket_id)) {
+ this.params.event_update_status = ''1'';
+ }
+ this.dynamicFields = {}
+ Object.keys(this.params).forEach(function (key) {
+ if (key.startsWith(''dynamicfield_'')) {
+ this.dynamicFields[key.substring(13)] = this.params[key];
+ }
+ });
+
+ this.data = {
+ Article: {
+ Subject: this.params.alert_subject,
+ Body: (CParamValidator.isDefined(this.params.alert_message)) ? this.params.alert_message : '''',
+ TimeUnit: this.params.otrs_time_unit.toString(),
+ ContentType: ''text/plain; charset=utf8''
+ }
+ };
+
+ this.result = {tags: {}};
+};
+
+OTRS.prototype.sendRequest = function (method) {
+ var url = this.params.otrs_url + this.params.entrypoint +
+ ''?UserLogin='' + encodeURIComponent(this.params.otrs_auth_user) +
+ ''&Password='' + encodeURIComponent(this.params.otrs_auth_password);
+
+ var response = this.request.jsonRequest(method, url, this.data);
+
+ if (!CParamValidator.isType(response, ''object'')) {
+ Logger.log(Logger.INFO, ''API response ERROR: '' + response);
+ throw ''Unknown error. Check debug log for more information.'';
+ }
+ if (this.request.getStatus() < 200 || this.request.getStatus() >= 300) {
+ var message = ''status code '' + this.request.getStatus();
+ Logger.log(Logger.INFO, ''API response ERROR with '' + message + '': '' + response);
+ throw ''Request failed with '' + message + ''. Check debug log for more information.'';
+ }
+ if (CParamValidator.isDefined(response.Error) && Object.keys(response.Error).length > 0) {
+ Logger.log(Logger.INFO, ''API response ERROR: '' + JSON.stringify(response.Error));
+ throw ''Request failed: '' + JSON.stringify(response.Error);
+ }
+
+ return {
+ status: this.request.getStatus(),
+ response: response
+ };
+};
+
+OTRS.prototype.createTicket = function () {
+ this.data[''Ticket''] = {
+ Title: this.params.alert_subject,
+ Queue: this.params.otrs_queue,
+ Type: this.params.otrs_ticket_type,
+ State: this.params.otrs_ticket_state,
+ PriorityID: this.priority.toString(),
+ CustomerUser: this.params.otrs_customer
+ }
+
+ var result = this.sendRequest(''post'');
+
+ if (!CParamValidator.isDefined(result.response.TicketID) || result.status != 200) {
+ throw ''Cannot create ((OTRS)) CE ticket. Check debug log for more information.'';
+ }
+
+ return result.response.TicketID;
+}
+
+OTRS.prototype.updateTicket = function () {
+ CParamValidator.validate({otrs_ticket_id: {type: ''string''}, entrypoint: {type: ''string''}}, this.params);
+ this.params.entrypoint += ''/'' + encodeURIComponent(this.params.otrs_ticket_id);
+
+ var result = this.sendRequest(''put'');
+
+ if (!CParamValidator.isDefined(result.response.TicketID) || result.status != 200) {
+ throw ''Cannot update ((OTRS)) CE ticket. Check debug log for more information.'';
+ }
+
+ return result.response.TicketID;
+}
+
+OTRS.prototype.onProblem = function (alert) {
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+ if (CParamValidator.isDefined(alert.source) && CParamValidator.inArray(alert.source, [''trigger'', ''service'', ''internal''])) {
+ if (Object.keys(this.dynamicFields).length > 0) {
+ this.data.DynamicField = [];
+ Object.keys(this.dynamicFields).forEach(function(field) {
+ if (field !== undefined) {
+ if (this.dynamicFields[field].match(/^\\d{4}[.-]\\d{2}[.-]\\d{2}$/)) {
+ this.dynamicFields[field] = this.dynamicFields[field].replace(/\\./g, ''-'');
+ }
+
+ this.data.DynamicField.push({Name: field, Value: this.dynamicFields[field]});
+ }
+ });
+ }
+ const ticket_id = this.createTicket(alert);
+ this.result.tags.__zbx_otrs_ticket_id = ticket_id;
+ this.result.tags.__zbx_otrs_ticketlink = this.params.otrs_url + ''index.pl?Action=AgentTicketZoom;TicketID='' + ticket_id;
+
+ return this.result;
+ }
+ return this.createTicket();
+}
+
+OTRS.prototype.onUpdate = function (alert) {
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+ this.updateTicket();
+
+ return this.result;
+}
+
+OTRS.prototype.onResolve = function (alert) {
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+ if (this.params.otrs_closed_state_id > 0) {
+ this.data[''Ticket''] = {
+ StateID: this.params.otrs_closed_state_id
+ }
+ }
+ this.updateTicket();
+
+ return this.result;
+}
+
+OTRS.prototype.onDiscovery = function (alert) {
+ return this.onProblem(alert);
+}
+
+OTRS.prototype.onAutoreg = function (alert) {
+ return this.onProblem(alert);
+}
+
+try {
+ var hook = new OTRS(value);
+ hook.request = new CHttpRequest(Logger);
+ return hook.run();
+}
+catch (error) {
+ Logger.log(Logger.WARN, ''notification failed: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','1','{EVENT.TAGS.__zbx_otrs_ticketlink}','((OTRS)) CE: ticket #{EVENT.TAGS.__zbx_otrs_ticket_id}','This media type integrates your Zabbix installation with your ((OTRS)) CE installation using the Zabbix webhook feature.
+
+((OTRS)) CE configuration:
+
+1. Create a new web service. To do so, navigate to "Admin" → "Web services" and import the "ZabbixTicketConnector.yml" file (it can be found in the official Zabbix repository next to the media type file).
+
+2. Create a new customer.
+
+3. Create a new customer user. Select the ID of the customer that you created in the previous step.
+
+4. Create a new agent. Depending on the ticket queue you want to use for tickets created by the webhook, set the "RW" permission for the group that this ticket queue belongs to. In the example below, if you want to use the "Misc" queue, you must set the "RW" permission for the group "users".
+
+Zabbix configuration:
+
+1. Before you can start using the ((OTRS)) CE webhook, set the global macro "{$ZABBIX.URL}":
+- In the Zabbix web interface, go to "Administration" → "Macros" in the top-left dropdown menu.
+- Set the global macro "{$ZABBIX.URL}" to the URL of the Zabbix frontend. The URL should be either an IP address, a fully qualified domain name, or localhost.
+- Specifying a protocol is mandatory, whereas the port is optional. Depending on the web server configuration, you might also need to append "/zabbix" to the end of URL. Good examples:
+ - http://zabbix.com
+ - https://zabbix.lan/zabbix
+ - http://server.zabbix.lan/
+ - http://localhost
+ - http://127.0.0.1:8080
+- Bad examples:
+ - zabbix.com
+ - http://zabbix/
+
+2. Set the following webhook parameters:
+- otrs_auth_user - the username of the agent
+- otrs_auth_password - the password of the agent
+- otrs_customer - the email of the customer user
+- otrs_queue - the queue that will be used for tickets created by the webhook
+- otrs_url - the frontend URL of your ((OTRS)) CE installation (for example, "https://otrs.example.com/otrs")
+
+3. If you want to prioritize issues according to the severity values in Zabbix, you can define mapping parameters (create them as additional webhook parameters):
+- severity_ - the ((OTRS)) CE priority ID ( in the parameter name can be one of the following values: "not_classified", "information", "warning", "average", "high", "disaster")
+
+4. If you have dynamic fields in ((OTRS)) CE and want them to be filled with values from Zabbix, add webhook parameters in the format "dynamicfield_<((OTRS)) CE dynamic field name>", similarly to the previous step. Dynamic fields can only be of the types "text", "textarea", "checkbox", or "date".
+
+5. If you want the webhook to close tickets related to **resolved** problems in Zabbix, you can change the following parameter value:
+- otrs_closed_state_id - ((OTRS)) CE state ID for closed tasks (possible values: 0 - Disable tickets closing, >0 - State ID from the State Management page).
+
+6. If you use the ticket type feature, you can change the type of the created tickets:
+- otrs_ticket_type - ((OTRS)) CE ticket type (set to "Unclassified" by default; present on fresh installations).
+
+7. Click the "Enabled" checkbox to enable the mediatype and click the "Update" button to save the webhook settings.
+
+8. Create a Zabbix user and add media:
+- To create a new user, go to the "Users" → "Users" section, click the "Create user" button in the top right corner. In the "User" tab, fill in all required fields (marked with red asterisks).
+- In the "Media" tab, click "Add" and select the type "OTRS CE" from the drop-down list. Add any value in the "Send to" field: it is not used in the webhook, but is required.
+- Make sure this user has access to all hosts for which you would like problem notifications to be sent to ((OTRS)) CE.
+
+9. Done! You can now start using this media type in actions and create tickets.
+
+You can find the latest version of this media and additional information in the official Zabbix repository:
+https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/templates/media/otrs_ce','0'),
+('88','4','PagerDuty','','','','','','','','25','0','0','0','0','1','3','10s','1',E'const CLogger = function(serviceName) {
+ this.serviceName = serviceName;
+ this.INFO = 4
+ this.WARN = 3
+ this.ERROR = 2
+ this.log = function(level, msg) {
+ Zabbix.log(level, ''['' + this.serviceName + ''] '' + msg);
+ }
+}
+
+const CWebhook = function(value) {
+ try {
+ params = JSON.parse(value);
+
+ if ([''0'', ''1'', ''2'', ''3'', ''4''].indexOf(params.event_source) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''.\\nMust be 0-4.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1 && [''0'', ''1''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0 or 1.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1) {
+ if (params.event_source === ''1'' && [''0'', ''1'', ''2'', ''3''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0-3.'';
+ }
+
+ if (params.event_source === ''0'' && [''0'', ''1''].indexOf(params.event_update_status) === -1) {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''.\\nMust be 0 or 1.'';
+ }
+
+ if (params.event_source === ''4'') {
+ if ([''0'', ''1'', ''2'', ''3'', ''4'', ''5''].indexOf(params.event_update_nseverity) !== -1 && params.event_update_nseverity != params.event_nseverity) {
+ params.event_nseverity = params.event_update_nseverity;
+ params.event_severity = params.event_update_severity;
+ params.event_update_status = ''1'';
+ }
+ }
+ }
+
+ this.runCallback = function(name, params) {
+ if (typeof this[name] === ''function'') {
+ return this[name].apply(this, [params]);
+ }
+ }
+
+ this.handleEvent = function(source, event) {
+ const alert = { source: source, event: event };
+ return [
+ this.runCallback(''on'' + source + event, alert),
+ this.runCallback(''on'' + event, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.handleEventless = function(source) {
+ const alert = { source: source, event: null };
+ return [
+ this.runCallback(''on'' + source, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.run = function() {
+ var results = [];
+ if (typeof this.httpProxy === ''string'' && this.httpProxy.trim() !== '''') {
+ this.request.setProxy(this.httpProxy);
+ }
+ const types = { ''0'': ''Trigger'', ''1'': ''Discovery'', ''2'': ''Autoreg'', ''3'': ''Internal'', ''4'': ''Service'' };
+
+ if ([''0'', ''3'', ''4''].indexOf(this.params.event_source) !== -1) {
+ var event = (this.params.event_update_status === ''1'')
+ ? ''Update''
+ : ((this.params.event_value === ''1'') ? ''Problem'' : ''Resolve'');
+
+ results = this.handleEvent(types[this.params.event_source], event);
+ }
+ else if (typeof types[this.params.event_source] !== ''undefined'') {
+ results = this.handleEventless(types[this.params.event_source]);
+ }
+ else {
+ throw ''Unexpected "event_source": '' + this.params.event_source;
+ }
+
+ for (idx in results) {
+ if (typeof results[idx] !== ''undefined'') {
+ return JSON.stringify(results[idx]);
+ }
+ }
+ }
+ this.httpProxy = params.http_proxy;
+ this.params = params;
+ this.runCallback(''onCheckParams'', {});
+ } catch (error) {
+ throw ''Webhook processing failed: '' + error;
+ }
+}
+
+const CWebhookHelper = {
+
+ createProblemURL: function(event_source, zabbix_url, trigger_id, event_id) {
+ if (event_source === ''0'') {
+ return zabbix_url + ''/tr_events.php?triggerid='' + trigger_id + ''&eventid='' + event_id;
+ } else if (event_source === ''4'') {
+ return zabbix_url + ''/zabbix.php?action=service.list'';
+ }
+
+ return zabbix_url;
+ },
+
+};
+
+const CParamValidator = {
+
+ isType: function(value, type) {
+ if (type === ''array'') {
+ return Array.isArray(value);
+ }
+ if (type === ''integer'') {
+ return CParamValidator.isInteger(value);
+ }
+ if (type === ''float'') {
+ return CParamValidator.isFloat(value);
+ }
+
+ return (typeof value === type);
+ },
+
+ isInteger: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseInt(value));
+ },
+
+ isFloat: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+\\.\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseFloat(value));
+ },
+
+ isDefined: function(value) {
+ return !CParamValidator.isType(value, ''undefined'');
+ },
+
+ isEmpty: function(value) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be checked for emptiness.'';
+ }
+
+ return (value.trim() === '''');
+ },
+
+ isMacroSet: function(value, macro) {
+ if (CParamValidator.isDefined(macro)) {
+ return !(CParamValidator.ifMatch(value, ''^\\{'' + macro + ''\\}$''))
+ }
+
+ return !(CParamValidator.ifMatch(value, ''^\\{[$#]{0,1}[A-Z_\\.]+[\\:]{0,1}["]{0,1}.*["]{0,1}\\}$'') || value === ''*UNKNOWN*'')
+ },
+
+ withinRange: function(value, min, max) {
+ if (!CParamValidator.isType(value, ''number'')) {
+ throw ''Value "'' + value + ''" must be a number to be checked for range.'';
+ }
+ if (value < ((CParamValidator.isDefined(min)) ? min : value)
+ || value > ((CParamValidator.isDefined(max)) ? max : value)) {
+ return false;
+ }
+
+ return true;
+ },
+
+ inArray: function(value, array) {
+ if (!CParamValidator.isType(array, ''array'')) {
+ throw ''The array must be an array to check the value for existing in it.'';
+ }
+
+ return (array.indexOf((typeof value === ''string'') ? value.toLowerCase() : value) !== -1);
+ },
+
+ ifMatch: function(value, regex) {
+ return (new RegExp(regex)).test(value);
+ },
+
+ match: function(value, regex) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be matched with the regular expression.'';
+ }
+
+ return value.match(new RegExp(regex));
+ },
+
+ checkURL: function(value) {
+ if (CParamValidator.isEmpty(value)) {
+ throw ''URL value "'' + value + ''" must be a non-empty string.'';
+ }
+ if (!CParamValidator.ifMatch(value, ''^(http|https):\\/\\/.+'')) {
+ throw ''URL value "'' + value + ''" must contain a schema.'';
+ }
+
+ return value.endsWith(''/'') ? value.slice(0, -1) : value;
+ },
+
+ check: function(key, rule, params) {
+ if (!CParamValidator.isDefined(rule.type)) {
+ throw ''Mandatory attribute "type" has not been defined for parameter "'' + key + ''".'';
+ }
+ if (!CParamValidator.isDefined(params[key])) {
+ throw ''Checked parameter "'' + key + ''" was not found in the list of input parameters.'';
+ }
+ var value = params[key],
+ error_message = null;
+ switch (rule.type) {
+ case ''string'':
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + key + ''" must be a string.'';
+ }
+ if (CParamValidator.isEmpty(value)) {
+ error_message = ''Value "'' + key + ''" must be a non-empty string'';
+ break;
+ }
+ if (CParamValidator.isDefined(rule.len) && value.length < rule.len) {
+ error_message = ''Value "'' + key + ''" must be a string with a length > '' + rule.len;
+ }
+ if (CParamValidator.isDefined(rule.regex) && !CParamValidator.ifMatch(value, rule.regex)) {
+ error_message = ''Value "'' + key + ''" must match the regular expression "'' + rule.regex + ''"'';
+ }
+ if (CParamValidator.isDefined(rule.url) && rule.url === true) {
+ value = CParamValidator.checkURL(value);
+ }
+ break;
+ case ''integer'':
+ if (!CParamValidator.isInteger(value)) {
+ error_message = ''Value "'' + key + ''" must be an integer'';
+ break;
+ }
+ value = parseInt(value);
+ break;
+ case ''float'':
+ if (!CParamValidator.isFloat(value)) {
+ error_message = ''Value "'' + key + ''" must be a floating-point number'';
+ break;
+ }
+ value = parseFloat(value);
+ break;
+ case ''boolean'':
+ if (CParamValidator.inArray(value, [''1'', ''true'', ''yes'', ''on''])) {
+ value = true;
+ }
+ else if (CParamValidator.inArray(value, [''0'', ''false'', ''no'', ''off''])) {
+ value = false;
+ }
+ else {
+ error_message = ''Value "'' + key + ''" must be a boolean-like.'';
+ }
+ break;
+ case ''array'':
+ try {
+ value = JSON.parse(value);
+ } catch (error) {
+ throw ''Value "'' + key + ''" contains invalid JSON.'';
+ }
+ if (!CParamValidator.isType(value, ''array'')) {
+ error_message = ''Value "'' + key + ''" must be an array.'';
+ }
+ if (CParamValidator.isDefined(rule.tags) && rule.tags === true) {
+ value = value.reduce(function(acc, obj) {
+ acc[obj.tag] = obj.value || null;
+ return acc;
+ }, {});
+ }
+ break;
+ case ''object'':
+ value = JSON.parse(value);
+ if (!CParamValidator.isType(value, ''object'')) {
+ error_message = ''Value "'' + key + ''" must be an object.'';
+ }
+ break;
+ default:
+ throw ''Unexpected attribute type "'' + rule.type + ''" for value "'' + key + ''". Available: '' +
+ [''integer'', ''float'', ''string'', ''boolean'', ''array'', ''object''].join('', '');
+ }
+ params[key] = value;
+ if (CParamValidator.inArray(rule.type, [''integer'', ''float'']) && error_message === null && (CParamValidator.isDefined(rule.min)
+ || CParamValidator.isDefined(rule.max)) && !CParamValidator.withinRange(value, rule.min, rule.max)) {
+ error_message = ''Value "'' + key + ''" must be a number '' + ((CParamValidator.isDefined(rule.min) && CParamValidator.isDefined(rule.max))
+ ? (rule.min + ''..'' + rule.max) : ((CParamValidator.isDefined(rule.min)) ? ''>'' + rule.min : ''<'' + rule.max));
+ }
+ else if (CParamValidator.isDefined(rule.array) && !CParamValidator.inArray(value, rule.array)) {
+ error_message = ''Value "'' + key + ''" must be in the array '' + JSON.stringify(rule.array);
+ }
+ else if (CParamValidator.isDefined(rule.macro) && !CParamValidator.isMacroSet(value.toString(), rule.macro)) {
+ error_message = ''The macro '' + ((CParamValidator.isDefined(rule.macro)) ? ''{'' + rule.macro + ''} '' : '' '') + ''is not set'';
+ }
+ if (error_message !== null) {
+ if (CParamValidator.isDefined(rule.default) && CParamValidator.isType(rule.default, rule.type)) {
+ params[key] = rule.default;
+ }
+ else {
+ Zabbix.log(4, ''Default value for "'' + key + ''" must be a '' + rule.type + ''. Skipped.'');
+ throw ''Incorrect value for variable "'' + key + ''". '' + error_message;
+ }
+ }
+
+ return this;
+ },
+
+ validate: function(rules, params) {
+ if (!CParamValidator.isType(params, ''object'') || CParamValidator.isType(params, ''array'')) {
+ throw ''Incorrect parameters value. The value must be an object.'';
+ }
+ for (var key in rules) {
+ CParamValidator.check(key, rules[key], params);
+ }
+ }
+}
+
+const CHttpRequest = function(logger) {
+ this.request = new HttpRequest();
+ if (typeof logger !== ''object'' || logger === null) {
+ this.logger = Zabbix;
+ }
+ else {
+ this.logger = logger;
+ }
+
+ this.clearHeader = function() {
+ this.request.clearHeader();
+ }
+
+ this.addHeaders = function(value) {
+ var headers = [];
+
+ if (typeof value === ''object'' && value !== null) {
+ if (!Array.isArray(value)) {
+ Object.keys(value).forEach(function(key) {
+ headers.push(key + '': '' + value[key]);
+ });
+ }
+ else {
+ headers = value;
+ }
+ }
+ else if (typeof value === ''string'') {
+ value.split(''\\r\\n'').forEach(function(header) {
+ headers.push(header);
+ });
+ }
+
+ for (var idx in headers) {
+ this.request.addHeader(headers[idx]);
+ }
+ }
+
+ this.setProxy = function(proxy) {
+ this.request.setProxy(proxy);
+ }
+
+ this.plainRequest = function(method, url, data) {
+ var resp = null;
+ method = method.toLowerCase();
+ this.logger.log(4, ''Sending '' + method + '' request:'' + JSON.stringify(data));
+ if ([''get'', ''post'', ''put'', ''patch'', ''delete'', ''trace''].indexOf(method) !== -1) {
+ resp = this.request[method](url, data);
+ }
+ else if ([''connect'', ''head'', ''options''].indexOf(method) !== -1) {
+ resp = this.request[method](url);
+ }
+ else {
+ throw ''Unexpected method. Method '' + method + '' is not supported.'';
+ }
+ this.logger.log(4, ''Response has been received: '' + resp);
+
+ return resp;
+ }
+
+ this.jsonRequest = function(method, url, data) {
+ this.addHeaders(''Content-Type: application/json'');
+ var resp = this.plainRequest(method, url, JSON.stringify(data));
+ try {
+ resp = JSON.parse(resp);
+ }
+ catch (error) {
+ throw ''Failed to parse response: not well-formed JSON was received'';
+ }
+
+ return resp;
+ }
+
+ this.getStatus = function() {
+ return this.request.getStatus();
+ }
+}
+
+var severityMapping = [
+ ''info'',
+ ''info'',
+ ''warning'',
+ ''warning'',
+ ''error'',
+ ''critical''
+],
+ serviceLogName = ''PagerDuty Webhook'',
+ Logger = new CLogger(serviceLogName),
+ PagerDuty = CWebhook;
+
+function getDefaultEventData(data, params) {
+ data.event_action = ''trigger'';
+ data.payload.custom_details = {
+ ''Alert message'': params.alert_message
+ };
+ Object.keys(params).forEach(function (key) {
+ if (key.startsWith(''customdetails_'') && !CParamValidator.isEmpty(params[key])) {
+ data.payload.custom_details[key.substring(14)] = params[key];
+ }
+ });
+ data.client = ''Zabbix'';
+ data.client_url = params.zabbix_url;
+
+ return data;
+};
+
+PagerDuty.prototype.onCheckParams = function () {
+ this.params.url = ''https://events.pagerduty.com/v2/enqueue'';
+ CParamValidator.validate({api_token: {type: ''string''}, event_id: {type: ''integer''},
+ alert_subject: {type: ''string''}, host_ip: {type: ''string'', default: ''''}, zabbix_url: {type: ''string'', url: true},
+ event_nseverity: {type: ''integer'', min: 0, max: 5, default: 0}}, this.params);
+ if (CParamValidator.inArray(this.params.event_source, [''0'',''3'',''4''])) {
+ CParamValidator.validate({host_name: {type: ''string'', default: ''''}}, this.params);
+ if (this.params.event_source === ''0'') {
+ CParamValidator.validate({trigger_id: {type: ''integer''}, event_update_status: {type: ''string'', array: [''0'', ''1'']},
+ event_ack: {type: ''boolean''}}, this.params);
+ }
+ else {
+ CParamValidator.validate({alert_message: {type: ''string''}, event_ack: {type: ''boolean'', default: false}}, this.params);
+ }
+ }
+ this.data = {
+ routing_key: this.params.api_token,
+ dedup_key: String(this.params.event_id),
+ payload: {
+ summary: this.params.alert_subject,
+ source: (!CParamValidator.isEmpty(this.params.host_name)) ? (this.params.host_name +
+ ((!CParamValidator.isEmpty(this.params.host_ip)) ? '' : '' + this.params.host_ip : '''')) : ''Zabbix'',
+ severity: severityMapping[this.params.event_nseverity],
+ }
+ }
+}
+
+PagerDuty.prototype.onProblem = function (alert) {
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+ this.data = getDefaultEventData(this.data, this.params);
+ if (CParamValidator.isDefined(alert.source) && alert.source === ''Trigger'') {
+ this.data.links = [{
+ href: CWebhookHelper.createProblemURL(this.params.event_source, this.params.zabbix_url, this.params.trigger_id, this.params.event_id),
+ text: ''Event link''
+ }];
+ }
+
+ return this.sendRequest();
+}
+
+PagerDuty.prototype.onUpdate = function (alert) {
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+ if (this.params.event_ack === true) {
+ this.data.event_action = ''acknowledge'';
+ return this.sendRequest();
+ }
+ this.data = getDefaultEventData(this.data, this.params);
+
+ return this.sendRequest();
+}
+
+PagerDuty.prototype.onResolve = function (alert) {
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+ this.data = getDefaultEventData(this.data, this.params);
+ this.data.event_action = ''resolve'';
+
+ return this.sendRequest();
+}
+
+PagerDuty.prototype.onDiscovery = function (alert) {
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+ this.data = getDefaultEventData(this.data, this.params);
+ this.data.payload.source = ''Discovery'';
+
+ return this.sendRequest();
+}
+
+PagerDuty.prototype.onAutoreg = function (alert) {
+ return this.onProblem(alert);
+}
+
+PagerDuty.prototype.sendRequest = function () {
+ var response = this.request.jsonRequest(''POST'', this.params.url, this.data);
+ if (!CParamValidator.isType(response, ''object'')) {
+ Logger.log(Logger.INFO, ''API response ERROR: '' + response);
+ throw ''Unknown error. Check debug log for more information.'';
+ }
+ if (this.request.getStatus() != 202) {
+ if (CParamValidator.isType(response.errors, ''array'') && CParamValidator.isType(response.errors[0], ''string'')) {
+ throw response.errors[0];
+ }
+ else {
+ throw ''Unknown error. HTTP status: '' + this.request.getStatus();
+ }
+ }
+ if (response.status != ''success'') {
+ Logger.log(Logger.INFO, ''API response ERROR: '' + response);
+ throw ''Unknown error. Check debug log for more information.'';
+ }
+
+ return ''OK'';
+};
+
+try {
+ var hook = new PagerDuty(value);
+ hook.request = new CHttpRequest(Logger);
+ return hook.run();
+}
+catch (error) {
+ Logger.log(Logger.WARN, ''notification failed: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','0','0','','','Please refer to https://v2.developer.pagerduty.com/docs/send-an-event-events-api-v2 and https://www.zabbix.com/documentation/8.0/manual/config/notifications/media/webhook#example_scripts.
+
+Set global macro {$ZABBIX.URL} with your Zabbix server URL.
+Add a dedicated user with the media type "PagerDuty" and place the integration key in the user''s "Send to" parameter to integrate into the service.','0'),
+('89','4','Pushover','','','','','','','','25','0','0','0','0','0','3','10s','1',E'try {
+ var params = JSON.parse(value),
+ request = new HttpRequest(),
+ data,
+ response,
+ severities = [
+ {name: ''not_classified'', color: ''#97AAB3''},
+ {name: ''information'', color: ''#7499FF''},
+ {name: ''warning'', color: ''#FFC859''},
+ {name: ''average'', color: ''#FFA059''},
+ {name: ''high'', color: ''#E97659''},
+ {name: ''disaster'', color: ''#E45959''},
+ {name: ''resolved'', color: ''#009900''},
+ {name: ''default'', color: ''#000000''}
+ ],
+ priority;
+
+ if (typeof params.HTTPProxy === ''string'' && params.HTTPProxy.trim() !== '''') {
+ request.setProxy(params.HTTPProxy);
+ }
+
+ if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
+ throw ''Incorrect "event_source" parameter given: "'' + params.event_source + ''".\\nMust be 0-3.'';
+ }
+
+ 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.'';
+ }
+
+ if ([0, 1, 2, 3, 4, 5].indexOf(parseInt(params.event_nseverity)) === -1) {
+ params.event_nseverity = ''7'';
+ }
+
+ if (params.event_value === ''0'') {
+ params.event_nseverity = ''6'';
+ }
+
+ priority = params[''priority_'' + severities[params.event_nseverity].name] || params.priority_default;
+
+ if (isNaN(priority) || priority < -2 || priority > 2) {
+ throw ''"priority" should be -2..2'';
+ }
+
+ if (params.event_source === ''0'' && isNaN(params.triggerid)) {
+ throw ''field "triggerid" is not a number'';
+ }
+
+ if (isNaN(params.eventid)) {
+ throw ''field "eventid" is not a number'';
+ }
+
+ if (typeof params.message !== ''string'' || params.message.trim() === '''') {
+ throw ''field "message" cannot be empty'';
+ }
+
+ data = {
+ token: params.token,
+ user: params.user,
+ title: params.title,
+ message: params.message,
+ url: (params.event_source === ''0'')
+ ? params.url + ''/tr_events.php?triggerid='' + params.triggerid + ''&eventid='' + params.eventid
+ : params.url,
+ url_title: params.url_title,
+ priority: priority
+ };
+
+ if (priority == 2) {
+ if (isNaN(params.retry) || params.retry < 30) {
+ throw ''field "retry" should be a number with value of at least 30 if "priority" is set to 2'';
+ }
+
+ if (isNaN(params.expire) || params.expire > 10800) {
+ throw ''field "expire" should be a number with value of at most 10800 if "priority" is set to 2'';
+ }
+
+ data.retry = params.retry;
+ data.expire = params.expire;
+ }
+
+ data = JSON.stringify(data);
+ Zabbix.log(4, ''[ Pushover Webhook ] Sending request: '' + params.endpoint + ''\\n'' + data);
+
+ request.addHeader(''Content-Type: application/json'');
+ response = request.post(params.endpoint, data);
+
+ Zabbix.log(4, ''[ Pushover Webhook ] Received response with status code '' + request.getStatus() + ''\\n'' + response);
+
+ if (response !== null) {
+ try {
+ response = JSON.parse(response);
+ }
+ catch (error) {
+ Zabbix.log(4, ''[ Pushover Webhook ] Failed to parse response received from Pushover'');
+ response = null;
+ }
+ }
+
+ if (request.getStatus() != 200 || response === null || typeof response !== ''object'' || response.status !== 1) {
+ if (response !== null && typeof response === ''object'' && typeof response.errors === ''object''
+ && typeof response.errors[0] === ''string'') {
+ throw response.errors[0];
+ }
+ else {
+ throw ''Unknown error. Check debug log for more information.'';
+ }
+ }
+
+ return ''OK'';
+}
+catch (error) {
+ Zabbix.log(4, ''[ Pushover Webhook ] Pushover notification failed: '' + error);
+ throw ''Pushover notification failed: '' + error;
+}','30s','0','0','','','Please refer to setup guide here: https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/templates/media/pushover
+
+Set token parameter with to your Pushover application key.
+When assigning Pushover media to the Zabbix user - add user key into send to field.','0'),
+('90','4','Redmine','','','','','','','','25','0','0','0','0','1','3','10s','1',E'var Redmine = {
+ params: {},
+
+ setParams: function (params) {
+ if (typeof params !== ''object'') {
+ return;
+ }
+
+ Redmine.params = params;
+ if (typeof Redmine.params.url === ''string'') {
+ if (!Redmine.params.url.endsWith(''/'')) {
+ Redmine.params.url += ''/'';
+ }
+ }
+ },
+
+ addCustomFields: function (data, fields) {
+ if (typeof fields === ''object'' && Object.keys(fields).length) {
+
+ data.issue.custom_fields = [];
+ Object.keys(fields)
+ .forEach(function (field) {
+ var field_value = fields[field];
+
+ if (field_value !== undefined) {
+ data.issue.custom_fields.push({ id: field, value: field_value });
+ }
+ });
+
+ }
+ return data;
+ },
+
+ request: function (method, query, data) {
+ [''url'', ''access_key''].forEach(function (field) {
+ if (typeof Redmine.params !== ''object'' || typeof Redmine.params[field] === ''undefined''
+ || Redmine.params[field] === '''' ) {
+ throw ''Required param is not set: "'' + field + ''".'';
+ }
+ });
+
+ var response,
+ url = Redmine.params.url + query,
+ request = new HttpRequest();
+
+ if (typeof Redmine.HTTPProxy === ''string'' && Redmine.HTTPProxy.trim() !== '''') {
+ request.setProxy(Redmine.HTTPProxy);
+ }
+
+ request.addHeader(''Content-Type: application/json'');
+ request.addHeader(''X-Redmine-API-Key: '' + Redmine.params.access_key);
+
+ if (typeof data !== ''undefined'') {
+ data = JSON.stringify(data);
+ }
+
+ Zabbix.log(4, ''[ Redmine Webhook ] Sending request: '' +
+ url + ((typeof data === ''string'') ? ('' '' + data) : ''''));
+
+ switch (method) {
+ case ''get'':
+ response = request.get(url, data);
+ break;
+
+ case ''post'':
+ response = request.post(url, data);
+ break;
+
+ case ''put'':
+ response = request.put(url, data);
+ break;
+
+ default:
+ throw ''Unsupported HTTP request method: '' + method;
+ }
+
+ Zabbix.log(4, ''[ Redmine Webhook ] Received response with status code '' + request.getStatus() + '': '' + response);
+
+ if (response !== null) {
+ try {
+ response = JSON.parse(response);
+ }
+ catch (error) {
+ Zabbix.log(4, ''[ Redmine Webhook ] Failed to parse response received from Redmine'');
+ response = null;
+ }
+ }
+
+ if (request.getStatus() < 200 || request.getStatus() >= 300) {
+ var message = ''Request failed with status code '' + request.getStatus();
+
+ if (response !== null && typeof response.errors !== ''undefined''
+ && Object.keys(response.errors).length > 0) {
+ message += '': '' + JSON.stringify(response.errors);
+ }
+ else if (response !== null && typeof response.errorMessages !== ''undefined''
+ && Object.keys(response.errorMessages).length > 0) {
+ message += '': '' + JSON.stringify(response.errorMessages);
+ }
+
+ throw message + '' Check debug log for more information.'';
+ }
+
+ return {
+ status: request.getStatus(),
+ response: response
+ };
+ },
+
+ getProjectID: function(name) {
+ var result = Redmine.request(''get'', ''projects.json''),
+ project_id;
+
+ if (result.response) {
+ var projects = result.response.projects || [];
+
+ for (var i in projects) {
+ if (projects[i].name === name) {
+ project_id = projects[i].id;
+ break;
+ }
+ }
+ }
+ else {
+ Zabbix.log(4, ''[ Redmine Webhook ] Failed to retrieve project data.'');
+ }
+
+ if (typeof project_id === ''undefined'') {
+ throw ''Cannot find project with name: '' + name;
+ }
+
+ return project_id;
+ },
+
+ createIssue: function(subject, description, priority, fields) {
+ var project_id = /^\\d+$/.test(Redmine.params.project)
+ ? Redmine.params.project
+ : Redmine.getProjectID(Redmine.params.project),
+ data = {
+ issue: {
+ project_id: project_id,
+ tracker_id: Redmine.params.tracker_id,
+ subject: subject,
+ description: description
+ }
+ },
+ result;
+
+ if (priority) {
+ data.issue.priority_id = priority;
+ }
+
+ result = Redmine.request(''post'', ''issues.json'', Redmine.addCustomFields(data, fields));
+
+ if (typeof result.response !== ''object''
+ || typeof result.response.issue.id === ''undefined''
+ || result.status != 201) {
+ throw ''Cannot create Redmine issue. Check debug log for more information.'';
+ }
+
+ return result.response.issue.id;
+ },
+
+ updateIssue: function (note, fields, status) {
+ var data = {
+ issue: {
+ notes: note || ''''
+ }
+ };
+
+ if (status) {
+ data.issue.status_id = status;
+ }
+
+ Redmine.request(''put'', ''issues/'' + Redmine.params.issue_key + ''.json'', Redmine.addCustomFields(data, fields));
+ }
+
+};
+
+try {
+ var params = JSON.parse(value),
+ params_redmine = {},
+ params_fields = {},
+ params_update = {},
+ result = {tags: {}},
+ required_params = [
+ ''alert_subject'', ''tracker_id'', ''project'',
+ ''event_source'', ''event_value'', ''event_update_status''
+ ],
+ severities = [
+ {name: ''not_classified'', color: ''#97AAB3''},
+ {name: ''information'', color: ''#7499FF''},
+ {name: ''warning'', color: ''#FFC859''},
+ {name: ''average'', color: ''#FFA059''},
+ {name: ''high'', color: ''#E97659''},
+ {name: ''disaster'', color: ''#E45959''},
+ {name: ''resolved'', color: ''#009900''},
+ {name: null, color: ''#000000''}
+ ],
+ priority;
+
+ Object.keys(params)
+ .forEach(function (key) {
+ if (key.startsWith(''redmine_'')) {
+ params_redmine[key.substring(8)] = params[key];
+ }
+ else if (key.startsWith(''customfield_'')) {
+ params_fields[key.substring(12)] = params[key];
+ }
+ else if (key.startsWith(''event_update_'')) {
+ params_update[key.substring(13)] = params[key];
+ }
+ else if (required_params.indexOf(key) !== -1 && params[key].trim() === '''') {
+ throw ''Parameter "'' + key + ''" cannot be empty.'';
+ }
+ });
+
+ if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''\\nMust be 0-3.'';
+ }
+
+ // 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_source === ''0'' && params.event_update_status !== ''0'' && params.event_update_status !== ''1'') {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''\\nMust be 0 or 1.'';
+ }
+
+
+ if (typeof params_redmine.close_status_id === ''string'' && params_redmine.close_status_id.trim() !== '''' && !parseInt(params_redmine.close_status_id, 10)) {
+ throw ''Incorrect "redmine_close_status_id" parameter given! Must be an integer.'';
+ }
+
+ if (params.event_source !== ''0'' && params.event_value === ''0'') {
+ throw ''Recovery operations are supported only for trigger-based actions.'';
+ }
+
+ if (params.event_source === ''0''
+ && ((params.event_value === ''1'' && params.event_update_status === ''1'')
+ || (params.event_value === ''0''
+ && (params.event_update_status === ''0'' || params.event_update_status === ''1'')))
+ && (isNaN(parseInt(params.redmine_issue_key)) || parseInt(params.redmine_issue_key) < 1 )) {
+ throw ''Incorrect "redmine_issue_key" parameter given: '' + params.redmine_issue_key +
+ ''\\nMust be positive integer.'';
+ }
+
+ if ([0, 1, 2, 3, 4, 5].indexOf(parseInt(params.event_nseverity)) === -1) {
+ params.event_nseverity = ''7'';
+ }
+
+ if (params.event_value === ''0'') {
+ params.event_nseverity = ''6'';
+ }
+
+ priority = params[''severity_'' + severities[params.event_nseverity].name];
+ priority = priority && priority.trim() || severities[7].name;
+
+ Redmine.setParams(params_redmine);
+ Redmine.HTTPProxy = params.HTTPProxy;
+
+ // Create issue for non trigger-based events.
+ if (params.event_source !== ''0''
+ && params.event_value !== ''0'') {
+ Redmine.createIssue(params.alert_subject, params.alert_message, priority);
+ }
+ // Create issue for trigger-based events.
+ else if (params.event_value === ''1'' && params_update.status === ''0'') {
+ var issue_id = Redmine.createIssue(params.alert_subject,
+ params.alert_subject + ''\\n'' + params.alert_message + ''\\n'' +
+ params.zabbix_url + (params.zabbix_url.endsWith(''/'') ? '''' : ''/'') +
+ ''tr_events.php?triggerid='' + params.trigger_id + ''&eventid='' + params.event_id + ''\\n'',
+ priority,
+ params_fields);
+
+ result.tags.__zbx_redmine_issue_id = issue_id;
+ result.tags.__zbx_redmine_issuelink = params.redmine_url +
+ (params.redmine_url.endsWith(''/'') ? '''' : ''/'') + ''issues/'' + issue_id;
+ }
+ // Close issue if parameter close_status_id is set and it is a recovery operation
+ else if (params.event_value === ''0'' && typeof params_redmine.close_status_id === ''string'' && params_redmine.close_status_id.trim() !== '''') {
+ Redmine.updateIssue(params.alert_subject + ''\\n'' + params.alert_message, params_fields, params_redmine.close_status_id);
+ }
+ // Update created issue for trigger-based event.
+ else {
+ Redmine.updateIssue(params.alert_subject + ''\\n'' + params.alert_message, params_fields);
+ }
+
+ return JSON.stringify(result);
+}
+catch (error) {
+ Zabbix.log(3, ''[ Redmine Webhook ] ERROR: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','1','{EVENT.TAGS.__zbx_redmine_issuelink}','Redmine: issue #{EVENT.TAGS.__zbx_redmine_issue_id}','','0'),
+('91','4','Rocket.Chat','','','','','','','','25','0','0','0','0','1','3','10s','1',E'var RocketChat = {
+ params: {},
+
+ setParams: function (params) {
+ if (typeof params !== ''object'') {
+ return;
+ }
+
+ RocketChat.params = params;
+ if (RocketChat.params.url && RocketChat.params.api_url) {
+ if (!RocketChat.params.url.endsWith(''/'')) {
+ RocketChat.params.url += ''/'';
+ }
+ if (!RocketChat.params.api_url.endsWith(''/'')) {
+ RocketChat.params.api_url += ''/'';
+ }
+ if (RocketChat.params.api_url.startsWith(''/'')) {
+ RocketChat.params.api_url = RocketChat.params.api_url.substring(1);
+ }
+
+ RocketChat.params.url += RocketChat.params.api_url;
+ }
+ },
+
+ setProxy: function (HTTPProxy) {
+ RocketChat.HTTPProxy = HTTPProxy;
+ },
+
+ addFields: function (fields) {
+ var data = [];
+
+ if (typeof fields === ''object'' && Object.keys(fields).length) {
+ Object.keys(fields)
+ .forEach(function(field) {
+ if (fields[field] === '''') {
+ Zabbix.log(4, ''[ RocketChat Webhook ] Field "'' + field +
+ ''" can\\''t be empty. The field ignored.'');
+ }
+ else {
+ try {
+ var parts = field.split('':''),
+ prefix = parts[0].split(''_'');
+
+ if (typeof prefix[2] === ''undefined''
+ || (prefix[2] === ''p'' && params.event_value === ''1'')
+ || (prefix[2] === ''r'' && params.event_value === ''0'')) {
+ data.push({
+ title: field.substring(field.indexOf('':'') + 1),
+ value: fields[field],
+ short: prefix[1] === ''short''
+ });
+ }
+ }
+ catch (error) {
+ Zabbix.log(4, ''[ RocketChat Webhook ] Can\\''t parse field "'' + field +
+ ''". The field ignored.'');
+ }
+ }
+ });
+ }
+
+ return data;
+ },
+
+ request: function (method, query, data) {
+ [''url'', ''api_url'', ''user_id'', ''user_token'', ''send_to''].forEach(function (field) {
+ if (typeof RocketChat.params !== ''object'' || typeof RocketChat.params[field] === ''undefined''
+ || RocketChat.params[field] === '''' ) {
+ throw ''Required parameter is not set: "'' + field + ''".'';
+ }
+ });
+
+ var response,
+ url = RocketChat.params.url + query,
+ request = new HttpRequest();
+
+ request.addHeader(''Content-Type: application/json'');
+ request.addHeader(''X-Auth-Token:'' + RocketChat.params.user_token);
+ request.addHeader(''X-User-Id:'' + RocketChat.params.user_id);
+
+ if (typeof RocketChat.HTTPProxy !== ''undefined'' && RocketChat.HTTPProxy !== '''') {
+ request.setProxy(RocketChat.HTTPProxy);
+ }
+
+ if (typeof data !== ''undefined'') {
+ data = JSON.stringify(data);
+ }
+
+ Zabbix.log(4, ''[ RocketChat Webhook ] Sending request: '' + url +
+ ((typeof data === ''string'') ? (''\\n'' + data) : ''''));
+
+ switch (method) {
+ case ''get'':
+ response = request.get(url, data);
+ break;
+
+ case ''post'':
+ response = request.post(url, data);
+ break;
+
+ default:
+ throw ''Unsupported HTTP request method: '' + method;
+ }
+
+ Zabbix.log(4, ''[ RocketChat Webhook ] Received response with status code '' +
+ request.getStatus() + ''\\n'' + response);
+
+ if (response !== null) {
+ try {
+ response = JSON.parse(response);
+ }
+ catch (error) {
+ Zabbix.log(4, ''[ RocketChat Webhook ] Failed to parse response received from RocketChat'');
+ response = null;
+ }
+ }
+
+ if (request.getStatus() < 200 || request.getStatus() >= 300) {
+ var message = ''Request failed with status code '' + request.getStatus();
+
+ if (response !== null && typeof response.message !== ''undefined'') {
+ message += '': '' + JSON.stringify(response.message);
+ }
+ else if (response !== null && typeof response.error !== ''undefined'') {
+ message += '': '' + JSON.stringify(response.error);
+ }
+
+ throw message + ''. Check debug log for more information.'';
+ }
+
+ return {
+ status: request.getStatus(),
+ response: response
+ };
+ },
+
+ postMessage: function(use_default_message, message, fields) {
+ var data = {
+ channel: RocketChat.params.send_to,
+ attachments: [{
+ collapsed: false,
+ color: RocketChat.params.color,
+ title: params.alert_subject
+ }]
+ };
+
+ if (RocketChat.params.title_link) {
+ data.attachments[0].title_link = RocketChat.params.title_link;
+ }
+
+ if (use_default_message) {
+ data.attachments[0].text = message;
+ }
+ else {
+ data.attachments[0].fields = RocketChat.addFields(fields);
+ }
+
+ var result = RocketChat.request(''post'', ''chat.postMessage'', data);
+
+ if (typeof result.response !== ''object'' || typeof result.response.message._id === ''undefined'') {
+ throw ''Cannot send RocketChat message. Check debug log for more information.'';
+ }
+
+ return {
+ id: result.response.message._id,
+ rid: result.response.message.rid,
+ channel: result.response.channel
+ };
+ },
+
+ sendMessage: function(update, fields) {
+
+ var data = {
+ message: {
+ rid: RocketChat.params.room_id,
+ tmid: RocketChat.params.msg_id,
+ tshow: true
+ }
+ };
+
+ if (update.status === ''0'') {
+ data.message.attachments = [{
+ collapsed: false,
+ color: RocketChat.params.color,
+ title: params.alert_subject,
+ title_link: RocketChat.params.title_link,
+ fields: RocketChat.addFields(fields)
+ }];
+ }
+ else {
+ data.message.alias = update.user;
+ data.message.msg = update.action;
+ if (update.message) {
+ data.message.attachments = [{
+ color: RocketChat.params.color,
+ text: update.message
+ }];
+ }
+ }
+
+ RocketChat.request(''post'', ''chat.sendMessage'', data);
+ },
+
+ getMessageLink: function(rid, id) {
+ var room = RocketChat.request(''get'', ''rooms.info?roomId='' + encodeURIComponent(rid)),
+ link = params.rc_url +
+ (params.rc_url.endsWith(''/'') ? '''' : ''/'');
+
+ switch (room.response.room.t) {
+ case ''c'':
+ link += ''channel/'' + room.response.room.name + ''?msg='' + id;
+ break;
+
+ case ''p'':
+ link += ''group/'' + room.response.room.name + ''?msg='' + id;
+ break;
+
+ case ''d'':
+ link += ''direct/'' + rid + ''?msg='' + id;
+ break;
+
+ default:
+ Zabbix.log(4, ''[ RocketChat Webhook ] Can\\''t get room type. Link to message will not be added.'');
+ }
+
+ return link;
+ }
+};
+
+try {
+ var params = JSON.parse(value),
+ response,
+ fields = {},
+ rc = {},
+ update = {},
+ result = {tags: {}},
+ required_params = [''alert_subject'', ''alert_message'', ''event_source'', ''event_value''],
+ severities = [
+ {name: ''not_classified'', color: ''#97AAB3''},
+ {name: ''information'', color: ''#7499FF''},
+ {name: ''warning'', color: ''#FFC859''},
+ {name: ''average'', color: ''#FFA059''},
+ {name: ''high'', color: ''#E97659''},
+ {name: ''disaster'', color: ''#E45959''},
+ {name: ''resolved'', color: ''#009900''},
+ {name: ''default'', color: ''#000000''}
+ ];
+
+ Object.keys(params)
+ .forEach(function (key) {
+ if (key.startsWith(''rc_'')) {
+ rc[key.substring(3)] = params[key];
+ }
+ else if (key.startsWith(''field_'')) {
+ fields[key.substring(6)] = params[key];
+ }
+ else if (key.startsWith(''event_update_'')) {
+ update[key.substring(13)] = params[key];
+ }
+ else if (required_params.indexOf(key) !== -1 && params[key] === '''') {
+ throw ''Parameter "'' + key + ''" can\\''t be empty.'';
+ }
+ });
+
+ if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''\\nMust be 0-3.'';
+ }
+
+ // Forcing parameters for non trigger-based events.
+ if (params.event_source !== ''0'') {
+ params.use_default_message = ''true'';
+ params.event_nseverity = ''0'';
+ params.rc_title_link = false;
+ }
+
+ // 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 ([0, 1, 2, 3, 4, 5].indexOf(parseInt(params.event_nseverity)) === -1) {
+ params.event_nseverity = ''7'';
+ }
+
+ if (params.event_value === ''0'') {
+ params.event_nseverity = ''6'';
+ }
+
+ RocketChat.setParams(rc);
+ RocketChat.setProxy(params.HTTPProxy);
+ RocketChat.params.color = severities[params.event_nseverity].color;
+
+ // Send default message if use_default_message === true.
+ if (params.use_default_message.toLowerCase() === ''true'') {
+ response = RocketChat.postMessage(true, params.alert_message);
+ result.tags.__zbx_rc_id = response.id;
+ result.tags.__zbx_rc_rid = response.rid;
+ result.tags.__zbx_rc_msg_url = RocketChat.getMessageLink(response.rid, response.id);
+ }
+ // Send message for trigger-based events.
+ else if (params.event_value === ''1'' && update.status === ''0'') {
+ response = RocketChat.postMessage(false, params.alert_message, fields);
+ result.tags.__zbx_rc_id = response.id;
+ result.tags.__zbx_rc_rid = response.rid;
+ result.tags.__zbx_rc_msg_url = RocketChat.getMessageLink(response.rid, response.id);
+ }
+ // Send thread message for trigger-based event.
+ else {
+ RocketChat.sendMessage(update, fields);
+ }
+
+ return JSON.stringify(result);
+}
+catch (error) {
+ Zabbix.log(3, ''[ RocketChat Webhook ] ERROR: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','1','{EVENT.TAGS.__zbx_rc_msg_url}','Rocket.Chat','','0'),
+('92','4','ServiceNow','','','','','','','','25','0','0','0','0','1','3','10s','1',E'var ServiceNow = {
+ params: {},
+
+ setParams: function (params) {
+ if (typeof params !== ''object'') {
+ return;
+ }
+
+ ServiceNow.params = params;
+ if (typeof ServiceNow.params.url === ''string'') {
+ if (!ServiceNow.params.url.endsWith(''/'')) {
+ ServiceNow.params.url += ''/'';
+ }
+
+ ServiceNow.params.url += ''api/now/table/incident'';
+ }
+ },
+
+ setProxy: function (HTTPProxy) {
+ ServiceNow.HTTPProxy = HTTPProxy;
+ },
+
+ setFields: function (data, fields) {
+ if (typeof fields === ''object'' && Object.keys(fields).length) {
+ Object.keys(fields)
+ .forEach(function(field) {
+ data[field] = (fields[field].match(/^\\d{4}\\.\\d{2}\\.\\d{2}$/) !== null)
+ ? fields[field].replace(/\\./g, ''-'')
+ : fields[field];
+ });
+ }
+ },
+
+ request: function (method, data) {
+ [''url'', ''user'', ''password''].forEach(function (field) {
+ if (typeof ServiceNow.params !== ''object'' || typeof ServiceNow.params[field] === ''undefined''
+ || ServiceNow.params[field] === '''' ) {
+ throw ''Required ServiceNow param is not set: "'' + field + ''".'';
+ }
+ });
+
+ var response,
+ url = ServiceNow.params.url,
+ request = new HttpRequest();
+
+ request.addHeader(''Content-Type: application/json'');
+ request.addHeader(''Authorization: Basic '' + btoa(ServiceNow.params.user + '':'' + ServiceNow.params.password));
+
+ if (typeof ServiceNow.HTTPProxy !== ''undefined'' && ServiceNow.HTTPProxy !== '''') {
+ request.setProxy(ServiceNow.HTTPProxy);
+ }
+
+ if (typeof data !== ''undefined'') {
+ data = JSON.stringify(data);
+ }
+
+ Zabbix.log(4, ''[ ServiceNow Webhook ] Sending request: '' + url + ((typeof data === ''string'')
+ ? (''\\n'' + data)
+ : ''''));
+
+ switch (method) {
+ case ''get'':
+ response = request.get(url, data);
+ break;
+
+ case ''post'':
+ response = request.post(url, data);
+ break;
+
+ case ''put'':
+ response = request.put(url, data);
+ break;
+
+ default:
+ throw ''Unsupported HTTP request method: '' + method;
+ }
+
+ Zabbix.log(4, ''[ ServiceNow Webhook ] Received response with status code '' +
+ request.getStatus() + ''\\n'' + response);
+
+ if (response !== null) {
+ try {
+ response = JSON.parse(response);
+ }
+ catch (error) {
+ Zabbix.log(4, ''[ ServiceNow Webhook ] Failed to parse response received from ServiceNow'');
+ response = null;
+ }
+ }
+
+ if (request.getStatus() < 200 || request.getStatus() >= 300) {
+ var message = ''Request failed with status code '' + request.getStatus();
+
+ if (response !== null && typeof response.error.message !== ''undefined''
+ && Object.keys(response.error).length > 0) {
+ message += '': '' + JSON.stringify(response.error.message);
+ }
+
+ throw message + '' Check debug log for more information.'';
+ }
+ else if (typeof response.result !== ''object'' || typeof response.result.sys_id === ''undefined'') {
+ throw ''Cannot create ServiceNow incident. Check debug log for more information.'';
+ }
+
+ return response.result;
+ }
+};
+
+try {
+ var params = JSON.parse(value),
+ fields = {},
+ servicenow = {},
+ data = {},
+ result = {tags: {}},
+ required_params = [
+ ''alert_subject'', ''alert_message'', ''event_source'', ''event_value'',
+ ''event_update_status'', ''event_recovery_value'', ''event_nseverity''
+ ],
+ severities = [
+ {name: ''not_classified'', color: ''#97AAB3''},
+ {name: ''information'', color: ''#7499FF''},
+ {name: ''warning'', color: ''#FFC859''},
+ {name: ''average'', color: ''#FFA059''},
+ {name: ''high'', color: ''#E97659''},
+ {name: ''disaster'', color: ''#E45959''},
+ {name: ''resolved'', color: ''#009900''},
+ {name: ''default'', color: ''#000000''}
+ ],
+ method = ''post'',
+ process_tags = true;
+
+ Object.keys(params)
+ .forEach(function (key) {
+ if (key.startsWith(''servicenow_'')) {
+ servicenow[key.substring(11)] = params[key];
+ }
+ else if (key.startsWith(''u_'')) {
+ fields[key] = params[key];
+ }
+ else if (required_params.indexOf(key) !== -1 && params[key] === '''') {
+ throw ''Parameter "'' + key + ''" can\\''t be empty.'';
+ }
+ });
+
+ if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''\\nMust be 0-3.'';
+ }
+
+ if ([0, 1, 2, 3, 4, 5].indexOf(parseInt(params.event_nseverity)) === -1) {
+ params.event_nseverity = ''7'';
+ }
+
+ // 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_source !== ''0'' && params.event_recovery_value === ''0'') {
+ throw ''Recovery operations are supported only for trigger-based actions.'';
+ }
+
+ data.short_description = params.alert_subject;
+ data.description = params.alert_message;
+ data.comments = params.alert_message;
+
+ if (typeof params[''urgency_for_'' + severities[params.event_nseverity].name] !== ''undefined'') {
+ data.urgency = params[''urgency_for_'' + severities[params.event_nseverity].name];
+ }
+
+ ServiceNow.setParams(servicenow);
+ ServiceNow.setProxy(params.HTTPProxy);
+ ServiceNow.setFields(data, fields);
+
+ if (params.event_source === ''0'' && (params.event_value === ''0'' || params.event_update_status === ''1'')) {
+ process_tags = false;
+ method = ''put'';
+ delete data.description;
+ delete data.urgency;
+ ServiceNow.params.url += ''/'' + params.servicenow_sys_id;
+ }
+
+ var response = ServiceNow.request(method, data);
+
+ if (process_tags) {
+ result.tags.__zbx_servicenow_sys_id = response.sys_id;
+ result.tags.__zbx_servicenow_link = params.servicenow_url +
+ (params.servicenow_url.endsWith(''/'') ? '''' : ''/'') + ''incident.do?sys_id='' + response.sys_id;
+ result.tags.__zbx_servicenow_number = response.number;
+ }
+
+ return JSON.stringify(result);
+}
+catch (error) {
+ Zabbix.log(3, ''[ ServiceNow Webhook ] ERROR: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','1','{EVENT.TAGS.__zbx_servicenow_link}','ServiceNow: {EVENT.TAGS.__zbx_servicenow_number}','','0'),
+('93','4','SIGNL4','','','','','','','','25','0','0','0','0','1','3','10s','1',E'// SIGNL4 Webhook
+try {
+ var response,
+ payload,
+ params = JSON.parse(value),
+ endpoint = ''https://connect.signl4.com/webhook/'',
+ request = new HttpRequest();
+
+ if (typeof params.HTTPProxy === ''string'' && params.HTTPProxy.trim() !== '''') {
+ request.setProxy(params.HTTPProxy);
+ }
+
+ if (typeof params.teamsecret === ''string'' && params.teamsecret.trim() !== '''') {
+ endpoint += params.teamsecret;
+ delete params.teamsecret;
+ }
+ else {
+ throw ''The team secret of your SIGNL4 team cannot be empty.'';
+ }
+
+ if (typeof params.Severity === ''string'' && params.Severity === ''{EVENT.SEVERITY}'') {
+ params.Severity = ''Not classified'';
+ }
+
+ if (typeof params.User === ''string'' && params.User === ''{USER.FULLNAME}'') {
+ params.User = '''';
+ }
+
+ if (typeof params.Event_Update_Action === ''string'' && params.Event_Update_Action === ''{EVENT.UPDATE.ACTION}'') {
+ params.Event_Update_Action = '''';
+ }
+
+ // Assemble X-S4-ExternalID for two-way integration
+ // Format: "ZabbixEventID: 222 ZabbixURL: https://your-zabbix-server/zabbix/"
+ params[''X-S4-ExternalID''] = ''ZabbixEventID: '' + params.Event_ID;
+ if (typeof params.Zabbix_URL === ''string'' && params.Zabbix_URL.indexOf(''http'') == 0) {
+ // Make sure the URL ends with ''/''
+ if (params.Zabbix_URL.charAt(params.Zabbix_URL.length - 1) != ''/'') {
+ params.Zabbix_URL = params.Zabbix_URL + ''/'';
+ }
+
+ params[''X-S4-ExternalID''] = params[''X-S4-ExternalID''] + '' ZabbixURL: '' + params.Zabbix_URL;
+
+ // Add Link parameter
+ params[''Link''] = params.Zabbix_URL + "tr_events.php?triggerid="+params.Trigger_ID + "&eventid=" + params.Event_ID;
+ }
+
+ // Check if this is a new problem or a recovery
+ if (params.Trigger_Status == ''OK'') {
+ params[''X-S4-Status''] = ''resolved'';
+ }
+ else {
+ params[''X-S4-Status''] = ''new'';
+ params[''X-S4-SourceSystem''] = ''Zabbix'';
+ }
+
+ payload = JSON.stringify(params);
+ Zabbix.log(4, ''[ SIGNL4 Webhook ] Sending request: '' + payload);
+
+ request.addHeader(''Content-Type: application/json'');
+ response = request.post(endpoint, ''payload='' + payload);
+
+ Zabbix.log(4, ''[ SIGNL4 Webhook ] Received response with status code '' +
+ request.getStatus() + ''\\n'' + response
+ );
+
+ if (request.getStatus() !== 201) {
+ throw ''Request failed with status code '' + request.getStatus() +
+ ''. Check debug log for more information.'';
+ }
+
+ return ''OK'';
+}
+catch (error) {
+ Zabbix.log(4, ''[ SIGNL4 Webhook ] ERROR: '' + error);
+
+ throw ''Sending failed: '' + error;
+}','30s','0','0','','','SIGNL4 is a mobile alert notification app for powerful alerting, alert management and mobile assignment of work items. It offers alerting via app push, SMS and voice calls including escalations, tracking, and duty scheduling.
+
+Get the app at https://www.signl4.com.
+
+Find out more including an integration video here: https://www.signl4.com/blog/portfolio_item/zabbix-mobile-alert-notification-duty-schedule-escalation/','0'),
+('94','4','Slack','','','','','','','','25','0','0','0','0','1','1','10s','1',E'const CLogger = function(serviceName) {
+ this.serviceName = serviceName;
+ this.INFO = 4
+ this.WARN = 3
+ this.ERROR = 2
+ this.log = function(level, msg) {
+ Zabbix.log(level, ''['' + this.serviceName + ''] '' + msg);
+ }
+}
+
+const CWebhook = function(value) {
+ try {
+ params = JSON.parse(value);
+
+ if ([''0'', ''1'', ''2'', ''3'', ''4''].indexOf(params.event_source) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''.\\nMust be 0-4.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1 && [''0'', ''1''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0 or 1.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1) {
+ if (params.event_source === ''1'' && [''0'', ''1'', ''2'', ''3''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0-3.'';
+ }
+
+ if (params.event_source === ''0'' && [''0'', ''1''].indexOf(params.event_update_status) === -1) {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''.\\nMust be 0 or 1.'';
+ }
+
+ if (params.event_source === ''4'') {
+ if ([''0'', ''1'', ''2'', ''3'', ''4'', ''5''].indexOf(params.event_update_nseverity) !== -1 && params.event_update_nseverity != params.event_nseverity) {
+ params.event_nseverity = params.event_update_nseverity;
+ params.event_severity = params.event_update_severity;
+ params.event_update_status = ''1'';
+ }
+ }
+ }
+
+ this.runCallback = function(name, params) {
+ if (typeof this[name] === ''function'') {
+ return this[name].apply(this, [params]);
+ }
+ }
+
+ this.handleEvent = function(source, event) {
+ const alert = { source: source, event: event };
+ return [
+ this.runCallback(''on'' + source + event, alert),
+ this.runCallback(''on'' + event, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.handleEventless = function(source) {
+ const alert = { source: source, event: null };
+ return [
+ this.runCallback(''on'' + source, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.run = function() {
+ var results = [];
+ if (typeof this.httpProxy === ''string'' && this.httpProxy.trim() !== '''') {
+ this.request.setProxy(this.httpProxy);
+ }
+ const types = { ''0'': ''Trigger'', ''1'': ''Discovery'', ''2'': ''Autoreg'', ''3'': ''Internal'', ''4'': ''Service'' };
+
+ if ([''0'', ''3'', ''4''].indexOf(this.params.event_source) !== -1) {
+ var event = (this.params.event_update_status === ''1'')
+ ? ''Update''
+ : ((this.params.event_value === ''1'') ? ''Problem'' : ''Resolve'');
+
+ results = this.handleEvent(types[this.params.event_source], event);
+ }
+ else if (typeof types[this.params.event_source] !== ''undefined'') {
+ results = this.handleEventless(types[this.params.event_source]);
+ }
+ else {
+ throw ''Unexpected "event_source": '' + this.params.event_source;
+ }
+
+ for (idx in results) {
+ if (typeof results[idx] !== ''undefined'') {
+ return JSON.stringify(results[idx]);
+ }
+ }
+ }
+ this.httpProxy = params.http_proxy;
+ this.params = params;
+ this.runCallback(''onCheckParams'', {});
+ } catch (error) {
+ throw ''Webhook processing failed: '' + error;
+ }
+}
+
+const CParamValidator = {
+
+ isType: function(value, type) {
+ if (type === ''array'') {
+ return Array.isArray(value);
+ }
+ if (type === ''integer'') {
+ return CParamValidator.isInteger(value);
+ }
+ if (type === ''float'') {
+ return CParamValidator.isFloat(value);
+ }
+
+ return (typeof value === type);
+ },
+
+ isInteger: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseInt(value));
+ },
+
+ isFloat: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+\\.\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseFloat(value));
+ },
+
+ isDefined: function(value) {
+ return !CParamValidator.isType(value, ''undefined'');
+ },
+
+ isEmpty: function(value) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be checked for emptiness.'';
+ }
+
+ return (value.trim() === '''');
+ },
+
+ isMacroSet: function(value, macro) {
+ if (CParamValidator.isDefined(macro)) {
+ return !(CParamValidator.ifMatch(value, ''^\\{'' + macro + ''\\}$''))
+ }
+
+ return !(CParamValidator.ifMatch(value, ''^\\{[$#]{0,1}[A-Z_\\.]+[\\:]{0,1}["]{0,1}.*["]{0,1}\\}$'') || value === ''*UNKNOWN*'')
+ },
+
+ withinRange: function(value, min, max) {
+ if (!CParamValidator.isType(value, ''number'')) {
+ throw ''Value "'' + value + ''" must be a number to be checked for range.'';
+ }
+ if (value < ((CParamValidator.isDefined(min)) ? min : value)
+ || value > ((CParamValidator.isDefined(max)) ? max : value)) {
+ return false;
+ }
+
+ return true;
+ },
+
+ inArray: function(value, array) {
+ if (!CParamValidator.isType(array, ''array'')) {
+ throw ''The array must be an array to check the value for existing in it.'';
+ }
+
+ return (array.indexOf((typeof value === ''string'') ? value.toLowerCase() : value) !== -1);
+ },
+
+ ifMatch: function(value, regex) {
+ return (new RegExp(regex)).test(value);
+ },
+
+ match: function(value, regex) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be matched with the regular expression.'';
+ }
+
+ return value.match(new RegExp(regex));
+ },
+
+ checkURL: function(value) {
+ if (CParamValidator.isEmpty(value)) {
+ throw ''URL value "'' + value + ''" must be a non-empty string.'';
+ }
+ if (!CParamValidator.ifMatch(value, ''^(http|https):\\/\\/.+'')) {
+ throw ''URL value "'' + value + ''" must contain a schema.'';
+ }
+
+ return value.endsWith(''/'') ? value.slice(0, -1) : value;
+ },
+
+ check: function(key, rule, params) {
+ if (!CParamValidator.isDefined(rule.type)) {
+ throw ''Mandatory attribute "type" has not been defined for parameter "'' + key + ''".'';
+ }
+ if (!CParamValidator.isDefined(params[key])) {
+ throw ''Checked parameter "'' + key + ''" was not found in the list of input parameters.'';
+ }
+ var value = params[key],
+ error_message = null;
+ switch (rule.type) {
+ case ''string'':
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + key + ''" must be a string.'';
+ }
+ if (CParamValidator.isEmpty(value)) {
+ error_message = ''Value "'' + key + ''" must be a non-empty string'';
+ break;
+ }
+ if (CParamValidator.isDefined(rule.len) && value.length < rule.len) {
+ error_message = ''Value "'' + key + ''" must be a string with a length > '' + rule.len;
+ }
+ if (CParamValidator.isDefined(rule.regex) && !CParamValidator.ifMatch(value, rule.regex)) {
+ error_message = ''Value "'' + key + ''" must match the regular expression "'' + rule.regex + ''"'';
+ }
+ if (CParamValidator.isDefined(rule.url) && rule.url === true) {
+ value = CParamValidator.checkURL(value);
+ }
+ break;
+ case ''integer'':
+ if (!CParamValidator.isInteger(value)) {
+ error_message = ''Value "'' + key + ''" must be an integer'';
+ break;
+ }
+ value = parseInt(value);
+ break;
+ case ''float'':
+ if (!CParamValidator.isFloat(value)) {
+ error_message = ''Value "'' + key + ''" must be a floating-point number'';
+ break;
+ }
+ value = parseFloat(value);
+ break;
+ case ''boolean'':
+ if (CParamValidator.inArray(value, [''1'', ''true'', ''yes'', ''on''])) {
+ value = true;
+ }
+ else if (CParamValidator.inArray(value, [''0'', ''false'', ''no'', ''off''])) {
+ value = false;
+ }
+ else {
+ error_message = ''Value "'' + key + ''" must be a boolean-like.'';
+ }
+ break;
+ case ''array'':
+ try {
+ value = JSON.parse(value);
+ } catch (error) {
+ throw ''Value "'' + key + ''" contains invalid JSON.'';
+ }
+ if (!CParamValidator.isType(value, ''array'')) {
+ error_message = ''Value "'' + key + ''" must be an array.'';
+ }
+ if (CParamValidator.isDefined(rule.tags) && rule.tags === true) {
+ value = value.reduce(function(acc, obj) {
+ acc[obj.tag] = obj.value || null;
+ return acc;
+ }, {});
+ }
+ break;
+ case ''object'':
+ value = JSON.parse(value);
+ if (!CParamValidator.isType(value, ''object'')) {
+ error_message = ''Value "'' + key + ''" must be an object.'';
+ }
+ break;
+ default:
+ throw ''Unexpected attribute type "'' + rule.type + ''" for value "'' + key + ''". Available: '' +
+ [''integer'', ''float'', ''string'', ''boolean'', ''array'', ''object''].join('', '');
+ }
+ params[key] = value;
+ if (CParamValidator.inArray(rule.type, [''integer'', ''float'']) && error_message === null && (CParamValidator.isDefined(rule.min)
+ || CParamValidator.isDefined(rule.max)) && !CParamValidator.withinRange(value, rule.min, rule.max)) {
+ error_message = ''Value "'' + key + ''" must be a number '' + ((CParamValidator.isDefined(rule.min) && CParamValidator.isDefined(rule.max))
+ ? (rule.min + ''..'' + rule.max) : ((CParamValidator.isDefined(rule.min)) ? ''>'' + rule.min : ''<'' + rule.max));
+ }
+ else if (CParamValidator.isDefined(rule.array) && !CParamValidator.inArray(value, rule.array)) {
+ error_message = ''Value "'' + key + ''" must be in the array '' + JSON.stringify(rule.array);
+ }
+ else if (CParamValidator.isDefined(rule.macro) && !CParamValidator.isMacroSet(value.toString(), rule.macro)) {
+ error_message = ''The macro '' + ((CParamValidator.isDefined(rule.macro)) ? ''{'' + rule.macro + ''} '' : '' '') + ''is not set'';
+ }
+ if (error_message !== null) {
+ if (CParamValidator.isDefined(rule.default) && CParamValidator.isType(rule.default, rule.type)) {
+ params[key] = rule.default;
+ }
+ else {
+ Zabbix.log(4, ''Default value for "'' + key + ''" must be a '' + rule.type + ''. Skipped.'');
+ throw ''Incorrect value for variable "'' + key + ''". '' + error_message;
+ }
+ }
+
+ return this;
+ },
+
+ validate: function(rules, params) {
+ if (!CParamValidator.isType(params, ''object'') || CParamValidator.isType(params, ''array'')) {
+ throw ''Incorrect parameters value. The value must be an object.'';
+ }
+ for (var key in rules) {
+ CParamValidator.check(key, rules[key], params);
+ }
+ }
+}
+
+const CHttpRequest = function(logger) {
+ this.request = new HttpRequest();
+ if (typeof logger !== ''object'' || logger === null) {
+ this.logger = Zabbix;
+ }
+ else {
+ this.logger = logger;
+ }
+
+ this.clearHeader = function() {
+ this.request.clearHeader();
+ }
+
+ this.addHeaders = function(value) {
+ var headers = [];
+
+ if (typeof value === ''object'' && value !== null) {
+ if (!Array.isArray(value)) {
+ Object.keys(value).forEach(function(key) {
+ headers.push(key + '': '' + value[key]);
+ });
+ }
+ else {
+ headers = value;
+ }
+ }
+ else if (typeof value === ''string'') {
+ value.split(''\\r\\n'').forEach(function(header) {
+ headers.push(header);
+ });
+ }
+
+ for (var idx in headers) {
+ this.request.addHeader(headers[idx]);
+ }
+ }
+
+ this.setProxy = function(proxy) {
+ this.request.setProxy(proxy);
+ }
+
+ this.plainRequest = function(method, url, data) {
+ var resp = null;
+ method = method.toLowerCase();
+ this.logger.log(4, ''Sending '' + method + '' request:'' + JSON.stringify(data));
+ if ([''get'', ''post'', ''put'', ''patch'', ''delete'', ''trace''].indexOf(method) !== -1) {
+ resp = this.request[method](url, data);
+ }
+ else if ([''connect'', ''head'', ''options''].indexOf(method) !== -1) {
+ resp = this.request[method](url);
+ }
+ else {
+ throw ''Unexpected method. Method '' + method + '' is not supported.'';
+ }
+ this.logger.log(4, ''Response has been received: '' + resp);
+
+ return resp;
+ }
+
+ this.jsonRequest = function(method, url, data) {
+ this.addHeaders(''Content-Type: application/json'');
+ var resp = this.plainRequest(method, url, JSON.stringify(data));
+ try {
+ resp = JSON.parse(resp);
+ }
+ catch (error) {
+ throw ''Failed to parse response: not well-formed JSON was received'';
+ }
+
+ return resp;
+ }
+
+ this.getStatus = function() {
+ return this.request.getStatus();
+ }
+}
+
+const CWebhookHelper = {
+
+ createProblemURL: function(event_source, zabbix_url, trigger_id, event_id) {
+ if (event_source === ''0'') {
+ return zabbix_url + ''/tr_events.php?triggerid='' + trigger_id + ''&eventid='' + event_id;
+ } else if (event_source === ''4'') {
+ return zabbix_url + ''/zabbix.php?action=service.list'';
+ }
+
+ return zabbix_url;
+ },
+
+};
+
+var serviceLogName = ''Slack Webhook'',
+ Logger = new CLogger(serviceLogName),
+ Slack = CWebhook;
+
+Slack.prototype.onCheckParams = function () {
+ CParamValidator.validate({
+ alert_subject: { type: ''string'' },
+ alert_message: { type: ''string'' },
+ bot_token: { type: ''string'' },
+ zabbix_url: { type: ''string'', url: true },
+ channel: { type: ''string'', macro: ''ALERT.SENDTO'' },
+ slack_mode: { type: ''string'', array: [''alarm'', ''event''], }
+ }, this.params);
+
+ if (this.params.event_source === ''0'') {
+ CParamValidator.validate({
+ event_id: { type: ''integer'' },
+ trigger_id: { type: ''integer'' }
+ }, this.params);
+ }
+
+ if (CParamValidator.inArray(this.params.event_source, [''0'', ''3'', ''4''])) {
+ CParamValidator.validate({
+ event_tags: { type: ''array'', macro: ''EVENT.TAGSJSON'', tags: true, default: {} }
+ }, this.params);
+ }
+
+ if (this.params.event_value != ''0'' && CParamValidator.isDefined(this.params.event_tags[''__channel_id_'' + this.params.channel])) {
+ this.params.event_update_status = ''1'';
+ }
+
+ this.severity_colors = [
+ ''#97AAB3'',
+ ''#7499FF'',
+ ''#FFC859'',
+ ''#FFA059'',
+ ''#E97659'',
+ ''#E45959''
+ ];
+
+ this.resolve_color = ''#009900'';
+ this.slack_endpoint = ''https://slack.com/api/'';
+
+ this.problem_url = CWebhookHelper.createProblemURL(this.params.event_source, this.params.zabbix_url, this.params.trigger_id, this.params.event_id);
+
+ this.data = {
+ channel: this.params.channel,
+ attachments: [
+ {
+ fallback: this.params.alert_subject,
+ title: this.params.alert_subject,
+ color: this.severity_colors[this.params.event_nseverity],
+ title_link: this.problem_url,
+ text: this.params.alert_message,
+ actions: [
+ {
+ type: ''button'',
+ text: ''Open in Zabbix'',
+ url: this.problem_url
+ }
+ ]
+ }
+ ]
+ };
+
+ this.reply = {
+ channel: this.params.channel,
+ thread_ts: '''',
+ blocks: [
+ {
+ type: ''context'',
+ elements: [
+ {
+ type: ''plain_text'',
+ text: ''Event update message''
+ }
+ ]
+ },
+ {
+ type: ''rich_text'',
+ elements: [
+ {
+ type: ''rich_text_section'',
+ elements: [
+ {
+ type: ''text'',
+ text: '''',
+ style: {
+ italic: true
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ };
+};
+
+Slack.prototype.sendRequest = function (route, data, tags) {
+ this.request.clearHeader();
+ this.request.addHeaders({
+ ''Content-Type'': ''application/json; charset=utf-8;'',
+ ''Authorization'': ''Bearer '' + this.params.bot_token
+ });
+
+ var response = this.request.jsonRequest(''POST'', this.slack_endpoint + route, data);
+
+ if (this.request.getStatus() !== 200 || !CParamValidator.isType(response.ok, ''boolean'') || response.ok !== true) {
+ Logger.log(Logger.INFO, ''HTTP code: '' + this.request.getStatus());
+ if (CParamValidator.isType(response.error, ''string'')) {
+ throw ''Endpoint response:'' + response.error;
+ }
+ else {
+ throw ''Unknown error. Check debug log for more information.'';
+ }
+ }
+
+ if (tags) {
+ return {
+ tags: {
+ [''__message_ts_'' + this.params.channel]: response.ts,
+ [''__channel_id_'' + this.params.channel]: response.channel,
+ [''__message_link_'' + this.params.channel]: this.getPermalink(response.channel, response.ts),
+ }
+ };
+
+ }
+ else {
+ return { tags: {} };
+ }
+};
+
+Slack.prototype.getPermalink = function (channel, message_ts) {
+ var response = this.request.jsonRequest(''GET'', this.slack_endpoint + ''chat.getPermalink'' + ''?channel='' + channel + ''&message_ts='' + message_ts);
+
+ if (this.request.getStatus() !== 200 || !CParamValidator.isType(response.ok, ''boolean'') || response.ok !== true) {
+ Logger.log(Logger.INFO, ''HTTP code: '' + this.request.getStatus());
+ if (CParamValidator.isType(response.error, ''string'')) {
+ throw ''Endpoint response:'' + response.error;
+ }
+ else {
+ throw ''Unknown error. Check debug log for more information.'';
+ }
+ }
+
+ if (!CParamValidator.isDefined(response.permalink)) {
+ throw ''Permalink is missed from the JSON response'';
+ }
+
+ return response.permalink;
+};
+
+Slack.prototype.onProblem = function (properties) {
+ Logger.log(Logger.INFO, ''Source: '' + properties.source + ''; Event: '' + properties.event);
+
+ if (this.params.slack_mode === "alarm") {
+ return this.sendRequest(''chat.postMessage'', this.data, true);
+ } else {
+ return this.sendRequest(''chat.postMessage'', this.data, false);
+ }
+};
+
+Slack.prototype.onUpdate = function (properties) {
+ Logger.log(Logger.INFO, ''Source: '' + properties.source + ''; Event: '' + properties.event);
+
+ if (this.params.slack_mode === "alarm") {
+ this.data.channel = this.params.event_tags[''__channel_id_'' + this.params.channel];
+ this.data.ts = this.params.event_tags[''__message_ts_'' + this.params.channel];
+
+ if (CParamValidator.isMacroSet(this.params.event_update_message, ''EVENT.UPDATE.MESSAGE'') && !CParamValidator.isEmpty(this.params.event_update_message)) {
+ this.reply.thread_ts = this.data.ts;
+ this.reply.blocks[1].elements[0].elements[0].text = this.params.event_update_message;
+ this.sendRequest(''chat.postMessage'', this.reply, false);
+ }
+
+ if (/\\backnowledged/.test(this.params.event_update_action)) {
+ this.sendRequest(''reactions.add'', { channel: this.data.channel, timestamp: this.data.ts, name: ''white_check_mark'' }, false);
+ }
+
+ if (/\\bunacknowledged/.test(this.params.event_update_action)) {
+ this.sendRequest(''reactions.remove'', { channel: this.data.channel, timestamp: this.data.ts, name: ''white_check_mark'' }, false);
+ }
+
+ if (/\\bclosed/.test(this.params.event_update_action)) {
+ return { tags: {} };
+ }
+ else {
+ return this.sendRequest(''chat.update'', this.data, false);
+ }
+ } else {
+ return this.sendRequest(''chat.postMessage'', this.data, false);
+ }
+};
+
+Slack.prototype.onResolve = function (properties) {
+ Logger.log(Logger.INFO, ''Source: '' + properties.source + ''; Event: '' + properties.event);
+ this.data.attachments[0].color = this.resolve_color;
+
+ if (this.params.slack_mode === "alarm") {
+ this.data.channel = this.params.event_tags[''__channel_id_'' + this.params.channel];
+ this.data.ts = this.params.event_tags[''__message_ts_'' + this.params.channel];
+
+ return this.sendRequest(''chat.update'', this.data, false);
+ } else {
+ return this.sendRequest(''chat.postMessage'', this.data, false);
+ }
+};
+
+Slack.prototype.onDiscovery = function (properties) {
+ return this.onProblem(properties);
+};
+
+Slack.prototype.onAutoreg = function (properties) {
+ return this.onProblem(properties);
+};
+
+try {
+ var hook = new Slack(value);
+ hook.request = new CHttpRequest(Logger);
+ return hook.run();
+}
+catch (error) {
+ Logger.log(Logger.WARN, ''Notification failed: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','0','','','Preparing slack for a Zabbix media type:
+1. On the page Your Apps (https://api.slack.com/apps) press ''Create an App'', select ''From scratch'' and specify its name and workspace.
+2. In the ''Add features and functionality'' section, select ''Bots'' and press ''Review Scopes to Add''.
+3. In the ''Scopes'' section, find ''Bot Token Scopes'', press ''Add an OAuth Scope'' and add ''chat:write'', ''im:write'', ''groups:write'' and ''reactions:write'' scopes.
+4. In the ''Settings'' section on the left side of the page press ''Install App'' and then ''Install to Workspace''.
+5. Press ''Allow'' and copy ''Bot User OAuth Access Token'', which will be used to set up webhook.
+
+In Zabbix:
+1. Set global macro {$ZABBIX.URL}
+2. Set user media for slack using channel name or member ID
+3. Set media param ''bot_token'' to the previously created token
+
+For a detailed instructions please read full README file https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/templates/media/slack/README.md','0'),
+('95','4','SolarWinds Service Desk','','','','','','','','25','0','0','0','0','1','3','10s','1',E'var SolarWinds = {
+ params: {},
+
+ setParams: function (params) {
+ if (typeof params !== ''object'') {
+ return;
+ }
+
+ SolarWinds.params = params;
+ SolarWinds.params.endpoint = ''https://api.samanage.com/'';
+ },
+
+ setProxy: function (HTTPProxy) {
+ SolarWinds.HTTPProxy = HTTPProxy;
+ },
+
+ addCustomFields: function (data, fields) {
+ if (typeof data.incident === ''object'' && typeof fields === ''object'' && Object.keys(fields).length) {
+ if (typeof fields.sw_fields === ''object'' && Object.keys(fields.sw_fields).length) {
+ Object.keys(fields.sw_fields)
+ .forEach(function(field) {
+ try {
+ data.incident[field] = JSON.parse(fields.sw_fields[field]);
+ }
+ catch (error) {
+ data.incident[field] = fields.sw_fields[field];
+ }
+ });
+ }
+
+ if (typeof fields.sw_customfields === ''object'' && Object.keys(fields.sw_customfields).length) {
+ data.incident.custom_fields_values = {custom_fields_value: []};
+ Object.keys(fields.sw_customfields)
+ .forEach(function(field) {
+ data.incident.custom_fields_values.custom_fields_value.push({
+ name: field,
+ value: fields.sw_customfields[field]
+ });
+ });
+ }
+ }
+
+ return data;
+ },
+
+ request: function (method, query, data) {
+ [''token''].forEach(function (field) {
+ if (typeof SolarWinds.params !== ''object'' || typeof SolarWinds.params[field] === ''undefined''
+ || SolarWinds.params[field] === '''' ) {
+ throw ''Required SolarWinds param is not set: "'' + field + ''".'';
+ }
+ });
+
+ var response,
+ url = SolarWinds.params.endpoint + query,
+ request = new HttpRequest();
+
+ request.addHeader(''Content-Type: application/json'');
+ request.addHeader(''X-Samanage-Authorization: Bearer '' + SolarWinds.params.token);
+ request.addHeader(''Accept: application/vnd.samanage.v2.1+json'');
+
+ if (typeof SolarWinds.HTTPProxy !== ''undefined'' && SolarWinds.HTTPProxy !== '''') {
+ request.setProxy(SolarWinds.HTTPProxy);
+ }
+
+ if (typeof data !== ''undefined'') {
+ data = JSON.stringify(data);
+ }
+
+ Zabbix.log(4, ''[ SolarWinds SD Webhook ] Sending request: '' + url + ((typeof data === ''string'')
+ ? (''\\n'' + data)
+ : ''''));
+
+ switch (method) {
+ case ''get'':
+ response = request.get(url, data);
+ break;
+
+ case ''post'':
+ response = request.post(url, data);
+ break;
+
+ case ''put'':
+ response = request.put(url, data);
+ break;
+
+ default:
+ throw ''Unsupported HTTP request method: '' + method;
+ }
+
+ Zabbix.log(4, ''[ SolarWinds SD Webhook ] Received response with status code '' + request.getStatus() +
+ ''\\n'' + response);
+
+ if (response !== null) {
+ try {
+ response = JSON.parse(response);
+ }
+ catch (error) {
+ Zabbix.log(4, ''[ SolarWinds SD Webhook ] Failed to parse response received from SolarWinds'');
+ response = null;
+ }
+ }
+
+ if (request.getStatus() < 200 || request.getStatus() >= 300) {
+ var message = ''Request failed with status code '' + request.getStatus();
+
+ if (response !== null && typeof response.error !== ''undefined''
+ && Object.keys(response.error).length > 0) {
+ message += '': '' + JSON.stringify(response.error);
+ }
+ else if (response !== null && typeof response === ''object''
+ && Object.keys(response).length > 0) {
+ Object.keys(response)
+ .forEach(function(field) {
+ message += ''\\n'' + field + '': '' + response[field][0];
+ });
+ }
+
+ throw message + '' Check debug log for more information.'';
+ }
+
+ return {
+ status: request.getStatus(),
+ response: response
+ };
+ },
+
+ createIncident: function(name, description, fields) {
+ var data = {
+ incident: {
+ name: name,
+ description: description,
+ priority: SolarWinds.params.priority
+ }
+ };
+
+ var result = SolarWinds.request(''post'', ''incidents.json'', SolarWinds.addCustomFields(data, fields));
+
+ if (typeof result.response !== ''object'' || typeof result.response.id === ''undefined'') {
+ throw ''Cannot create SolarWinds incident. Check debug log for more information.'';
+ }
+
+ return result.response.id;
+ },
+
+ updateIncident: function(name, fields, message) {
+ var data = {
+ incident: {
+ name: name,
+ priority: SolarWinds.params.priority
+ }
+ };
+
+ SolarWinds.request(
+ ''put'',
+ ''incidents/'' + SolarWinds.params.incident_id + ''.json'',
+ SolarWinds.addCustomFields(data, fields));
+
+ SolarWinds.commenIncident(message);
+ },
+
+ commenIncident: function(message) {
+ var data = {
+ comment: {
+ body: message
+ }
+ };
+
+ SolarWinds.request(''post'', ''incidents/'' + SolarWinds.params.incident_id + ''/comments.json'', data);
+ }
+};
+
+try {
+ var params = JSON.parse(value),
+ fields = {},
+ samanage = {},
+ result = {tags: {}},
+ required_params = [''alert_subject'', ''event_recovery_value'', ''event_source'', ''event_value'', ''priority_default''],
+ severities = [
+ {name: ''not_classified''},
+ {name: ''information''},
+ {name: ''warning''},
+ {name: ''average''},
+ {name: ''high''},
+ {name: ''disaster''},
+ {name: ''resolved''},
+ {name: ''default''}
+ ];
+
+ fields.sw_fields = {};
+ fields.sw_customfields = {};
+
+ Object.keys(params)
+ .forEach(function (key) {
+ if (key.startsWith(''samanage_'')) {
+ samanage[key.substring(9)] = params[key];
+ }
+ else if (key.startsWith(''sw_field_'')) {
+ fields.sw_fields[key.substring(9)] = params[key];
+ }
+ else if (key.startsWith(''sw_customfield_'')) {
+ fields.sw_customfields[key.substring(15)] = params[key];
+ }
+ else if (required_params.indexOf(key) !== -1 && params[key] === '''') {
+ throw ''Parameter "'' + key + ''" can\\''t be empty.'';
+ }
+ });
+
+ if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''\\nMust be 0-3.'';
+ }
+
+ // 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_source !== ''0'' && params.event_recovery_value === ''0'') {
+ throw ''Recovery operations are supported only for trigger-based actions.'';
+ }
+
+ if ([0, 1, 2, 3, 4, 5].indexOf(parseInt(params.event_nseverity)) === -1) {
+ params.event_nseverity = ''7'';
+ }
+
+ if (params.event_value === ''0'') {
+ params.event_nseverity = ''6'';
+ }
+
+ samanage.priority = params[''priority_'' + severities[params.event_nseverity].name] || params.priority_default;
+
+ SolarWinds.setParams(samanage);
+ SolarWinds.setProxy(params.HTTPProxy);
+
+ // Create incident for non trigger-based events.
+ if (params.event_source !== ''0'' && params.event_recovery_value !== ''0'') {
+ SolarWinds.createIncident(params.alert_subject, params.alert_message);
+ }
+ // Create incident for trigger-based events.
+ else if (params.event_value === ''1'' && params.event_update_status === ''0''
+ && (samanage.incident_id === ''{EVENT.TAGS.__zbx_solarwinds_inc_id}'' || samanage.incident_id === ''*UNKNOWN*'')) {
+ var key = SolarWinds.createIncident(params.alert_subject, params.alert_message, fields);
+
+
+ result.tags.__zbx_solarwinds_inc_id = key;
+ result.tags.__zbx_solarwinds_inc_link = params.samanage_url +
+ (params.samanage_url.endsWith(''/'') ? '''' : ''/'') + ''incidents/'' + key;
+ }
+ // Update created incident for trigger-based event.
+ else {
+ if (samanage.incident_id === ''{EVENT.TAGS.__zbx_solarwinds_inc_id}'' || samanage.incident_id === '''' || samanage.incident_id === ''*UNKNOWN*'') {
+ throw ''Incorrect incident key given: '' + samanage.incident_id;
+ }
+ if (!params.alert_message) {
+ throw ''Parameter "alert_message" can\\''t be empty.'';
+ }
+ SolarWinds.updateIncident(params.alert_subject, fields, params.alert_message);
+ }
+
+ if (params.event_source === ''0'') {
+ return JSON.stringify(result);
+ }
+ else {
+ return ''OK'';
+ }
+}
+catch (error) {
+ Zabbix.log(3, ''[ SolarWinds SD Webhook ] ERROR: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','1','{EVENT.TAGS.__zbx_solarwinds_inc_link}','SolarWinds incident ID: {EVENT.TAGS.__zbx_solarwinds_inc_id}','','0'),
+('96','4','SysAid','','','','','','','','25','0','0','0','0','1','3','10s','1',E'var SysAid = {
+ params: {},
+
+ setParams: function (params) {
+ var required = [''url'', ''auth_user'', ''auth_password'', ''category_level_1'', ''category_level_2'',
+ ''category_level_3'', ''incident_id'', ''template_id'', ''urgency_id'', ''incident_state'',
+ ''default_priority_id''
+ ];
+
+ required.forEach(function (field) {
+ if (typeof params !== ''object'' || typeof params[field] === ''undefined'' || params[field] === '''') {
+ throw ''Required param is not set: "'' + field + ''".'';
+ }
+ });
+
+ SysAid.params = params;
+ if (typeof SysAid.params.url === ''string'' && !SysAid.params.url.endsWith(''/'')) {
+ SysAid.params.url += ''/'';
+ }
+ },
+
+ login: function () {
+ var result = SysAid.request(''post'', ''api/v1/login'', {
+ user_name: SysAid.params.auth_user,
+ password: SysAid.params.auth_password
+ });
+
+ return result.response.user.id;
+ },
+
+ request: function (method, query, data) {
+ var response,
+ request = SysAid.req || (SysAid.req = new HttpRequest()),
+ url = SysAid.params.url + query;
+
+ if (typeof SysAid.HTTPProxy !== ''undefined'' && SysAid.HTTPProxy.trim() !== '''') {
+ request.setProxy(SysAid.HTTPProxy);
+ }
+
+ if (typeof data !== ''undefined'') {
+ data = JSON.stringify(data);
+ }
+
+ Zabbix.log(4, ''[ SysAid Webhook ] Sending request: '' +
+ url + ((typeof data === ''string'') ? ('' '' + data) : ''''));
+
+ switch (method) {
+ case ''get'':
+ response = request.get(url, data);
+ break;
+
+ case ''post'':
+ response = request.post(url, data);
+ break;
+
+ case ''put'':
+ response = request.put(url, data);
+ break;
+
+ default:
+ throw ''Unsupported HTTP request method: '' + method;
+ }
+
+ Zabbix.log(4, ''[ SysAid Webhook ] Received response with status code '' + request.getStatus() + '': '' + response);
+
+ if (request.getStatus() !== 200) {
+ var message = ''Request failed with status code '' + request.getStatus();
+
+ message += '': '' + response;
+ throw message + '' Check debug log for more information.'';
+ }
+
+ if (response !== null) {
+ try {
+ response = JSON.parse(response);
+ }
+ catch (error) {
+ Zabbix.log(4, ''[ SysAid Webhook ] Failed to parse response received from SysAid'');
+ response = null;
+ }
+ }
+
+ if (response === null || (typeof response.Error !== ''undefined'' && Object.keys(response.Error).length > 0)) {
+ throw ''Request failed: '' + JSON.stringify(response.Error);
+ }
+
+ return {
+ status: request.getStatus(),
+ response: response
+ };
+ },
+
+ createIncident: function(subject, message, priority) {
+ var result = SysAid.request(''post'', ''api/v1/sr/?template='' + encodeURIComponent(SysAid.params.template_id), {
+ info: [
+ {
+ key: ''problem_type'',
+ value: [
+ SysAid.params.category_level_1,
+ SysAid.params.category_level_2,
+ SysAid.params.category_level_3
+ ].join(''_'')
+ },
+ {
+ key: ''title'',
+ value: subject
+ },
+ {
+ key: ''description'',
+ value: message
+ },
+ {
+ key: ''status'',
+ value: ''1''
+ },
+ {
+ key: ''urgency'',
+ value: SysAid.params.urgency_id
+ },
+ {
+ key: ''priority'',
+ value: priority || SysAid.params.default_priority_id,
+ }
+ ]
+ });
+
+ if (result.response.id === ''undefined'') {
+ throw ''Cannot create SysAid incident. Check debug log for more information.'';
+ }
+
+ return result.response.id;
+ },
+
+ updateTicket: function(note) {
+ var date = new Date().getTime();
+
+ SysAid.request(''put'', ''api/v1/sr/'' + encodeURIComponent(SysAid.params.incident_id), {
+ id: SysAid.params.incident_id,
+ info: [
+ {
+ key: ''update_time'',
+ value: date
+ },
+ {
+ key: ''notes'',
+ value: [
+ {
+ userName: ''Zabbix'',
+ createDate: date,
+ text: note
+ }
+ ]
+ }
+ ]
+ });
+ }
+};
+
+try {
+ var params = JSON.parse(value),
+ params_sysaid = {},
+ params_update = {},
+ result = {tags: {}},
+ required_params = [''alert_subject'', ''event_source'', ''event_value'', ''event_update_status''],
+ severities = [
+ {name: ''not_classified'', color: ''#97AAB3''},
+ {name: ''information'', color: ''#7499FF''},
+ {name: ''warning'', color: ''#FFC859''},
+ {name: ''average'', color: ''#FFA059''},
+ {name: ''high'', color: ''#E97659''},
+ {name: ''disaster'', color: ''#E45959''},
+ {name: ''resolved'', color: ''#009900''},
+ {name: null, color: ''#000000''}
+ ],
+ priority;
+
+ Object.keys(params)
+ .forEach(function (key) {
+ if (key.startsWith(''sysaid_'')) {
+ params_sysaid[key.substring(7)] = params[key];
+ }
+ else if (key.startsWith(''event_update_'')) {
+ params_update[key.substring(13)] = params[key];
+ }
+ else if (required_params.indexOf(key) !== -1 && params[key].trim() === '''') {
+ throw ''Parameter "'' + key + ''" cannot be empty.'';
+ }
+ });
+
+ if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''\\nMust be 0-3.'';
+ }
+
+ // 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_source === ''0'' && params.event_update_status !== ''0'' && params.event_update_status !== ''1'') {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''\\nMust be 0 or 1.'';
+ }
+
+ if (params.event_source !== ''0'' && params.event_value === ''0'') {
+ throw ''Recovery operations are supported only for trigger-based actions.'';
+ }
+
+ if (params.event_source === ''0'' && ((params.event_value === ''1'' && params.event_update_status === ''1'')
+ || (params.event_value === ''0'' && (params.event_update_status === ''0'' || params.event_update_status === ''1'')))
+ && (isNaN(parseInt(params.sysaid_incident_id)) || parseInt(params.sysaid_incident_id) < 1 )) {
+ throw ''Incorrect "sysaid_incident_id" parameter given: '' + params.sysaid_incident_id + ''\\nMust be positive integer.'';
+ }
+
+ if ([0, 1, 2, 3, 4, 5].indexOf(parseInt(params.event_nseverity)) === -1) {
+ params.event_nseverity = ''7'';
+ }
+
+ if (params.event_value === ''0'') {
+ params.event_nseverity = ''6'';
+ }
+
+ priority = params[''severity_'' + severities[params.event_nseverity].name];
+ priority = priority && priority.trim() || severities[7].name;
+
+ SysAid.setParams(params_sysaid);
+ SysAid.HTTPProxy = params.HTTPProxy;
+ SysAid.login();
+
+ if (params.event_source !== ''0'' && params.event_value !== ''0'') {
+ // Create ticket for non trigger-based events.
+ SysAid.createIncident(params.alert_subject, params.alert_message, priority);
+ }
+ else if (params.event_value === ''1'' && params_update.status === ''0'') {
+ // Create ticket for trigger-based events.
+ var incident_id = SysAid.createIncident(params.alert_subject, params.alert_subject + ''\\n'' + params.alert_message +
+ ''\\n'' + params.zabbix_url + (params.zabbix_url.endsWith(''/'') ? '''' : ''/'') + ''tr_events.php?triggerid='' +
+ params.trigger_id + ''&eventid='' + params.event_id + ''\\n'', priority
+ );
+
+ result.tags.__zbx_sysaid_incident_id = incident_id;
+ result.tags.__zbx_sysaid_incidentlink = params.sysaid_url +
+ (params.sysaid_url.endsWith(''/'') ? '''' : ''/'') + ''SREdit.jsp?id='' + incident_id + ''&fromId=IncidentsList'';
+ }
+ else {
+ // Update created ticket for trigger-based event.
+ SysAid.updateTicket(params.alert_subject + ''\\n'' + params.alert_message);
+ }
+
+ return JSON.stringify(result);
+}
+catch (error) {
+ Zabbix.log(3, ''[ SysAid Webhook ] ERROR: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','1','{EVENT.TAGS.__zbx_sysaid_incidentlink}','SysAid: incident #{EVENT.TAGS.__zbx_sysaid_incident_id}','','0'),
+('97','4','Telegram','','','','','','','','25','0','0','0','0','1','3','10s','1',E'const CLogger = function(serviceName) {
+ this.serviceName = serviceName;
+ this.INFO = 4
+ this.WARN = 3
+ this.ERROR = 2
+ this.log = function(level, msg) {
+ Zabbix.log(level, ''['' + this.serviceName + ''] '' + msg);
+ }
+}
+
+const CWebhook = function(value) {
+ try {
+ params = JSON.parse(value);
+
+ if ([''0'', ''1'', ''2'', ''3'', ''4''].indexOf(params.event_source) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''.\\nMust be 0-4.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1 && [''0'', ''1''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0 or 1.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1) {
+ if (params.event_source === ''1'' && [''0'', ''1'', ''2'', ''3''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0-3.'';
+ }
+
+ if (params.event_source === ''0'' && [''0'', ''1''].indexOf(params.event_update_status) === -1) {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''.\\nMust be 0 or 1.'';
+ }
+
+ if (params.event_source === ''4'') {
+ if ([''0'', ''1'', ''2'', ''3'', ''4'', ''5''].indexOf(params.event_update_nseverity) !== -1 && params.event_update_nseverity != params.event_nseverity) {
+ params.event_nseverity = params.event_update_nseverity;
+ params.event_severity = params.event_update_severity;
+ params.event_update_status = ''1'';
+ }
+ }
+ }
+
+ this.runCallback = function(name, params) {
+ if (typeof this[name] === ''function'') {
+ return this[name].apply(this, [params]);
+ }
+ }
+
+ this.handleEvent = function(source, event) {
+ const alert = { source: source, event: event };
+ return [
+ this.runCallback(''on'' + source + event, alert),
+ this.runCallback(''on'' + event, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.handleEventless = function(source) {
+ const alert = { source: source, event: null };
+ return [
+ this.runCallback(''on'' + source, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.run = function() {
+ var results = [];
+ if (typeof this.httpProxy === ''string'' && this.httpProxy.trim() !== '''') {
+ this.request.setProxy(this.httpProxy);
+ }
+ const types = { ''0'': ''Trigger'', ''1'': ''Discovery'', ''2'': ''Autoreg'', ''3'': ''Internal'', ''4'': ''Service'' };
+
+ if ([''0'', ''3'', ''4''].indexOf(this.params.event_source) !== -1) {
+ var event = (this.params.event_update_status === ''1'')
+ ? ''Update''
+ : ((this.params.event_value === ''1'') ? ''Problem'' : ''Resolve'');
+
+ results = this.handleEvent(types[this.params.event_source], event);
+ }
+ else if (typeof types[this.params.event_source] !== ''undefined'') {
+ results = this.handleEventless(types[this.params.event_source]);
+ }
+ else {
+ throw ''Unexpected "event_source": '' + this.params.event_source;
+ }
+
+ for (idx in results) {
+ if (typeof results[idx] !== ''undefined'') {
+ return JSON.stringify(results[idx]);
+ }
+ }
+ }
+ this.httpProxy = params.http_proxy;
+ this.params = params;
+ this.runCallback(''onCheckParams'', {});
+ } catch (error) {
+ throw ''Webhook processing failed: '' + error;
+ }
+}
+
+const CParamValidator = {
+
+ isType: function(value, type) {
+ if (type === ''array'') {
+ return Array.isArray(value);
+ }
+ if (type === ''integer'') {
+ return CParamValidator.isInteger(value);
+ }
+ if (type === ''float'') {
+ return CParamValidator.isFloat(value);
+ }
+
+ return (typeof value === type);
+ },
+
+ isInteger: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseInt(value));
+ },
+
+ isFloat: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+\\.\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseFloat(value));
+ },
+
+ isDefined: function(value) {
+ return !CParamValidator.isType(value, ''undefined'');
+ },
+
+ isEmpty: function(value) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be checked for emptiness.'';
+ }
+
+ return (value.trim() === '''');
+ },
+
+ isMacroSet: function(value, macro) {
+ if (CParamValidator.isDefined(macro)) {
+ return !(CParamValidator.ifMatch(value, ''^\\{'' + macro + ''\\}$''))
+ }
+
+ return !(CParamValidator.ifMatch(value, ''^\\{[$#]{0,1}[A-Z_\\.]+[\\:]{0,1}["]{0,1}.*["]{0,1}\\}$'') || value === ''*UNKNOWN*'')
+ },
+
+ withinRange: function(value, min, max) {
+ if (!CParamValidator.isType(value, ''number'')) {
+ throw ''Value "'' + value + ''" must be a number to be checked for range.'';
+ }
+ if (value < ((CParamValidator.isDefined(min)) ? min : value)
+ || value > ((CParamValidator.isDefined(max)) ? max : value)) {
+ return false;
+ }
+
+ return true;
+ },
+
+ inArray: function(value, array) {
+ if (!CParamValidator.isType(array, ''array'')) {
+ throw ''The array must be an array to check the value for existing in it.'';
+ }
+
+ return (array.indexOf((typeof value === ''string'') ? value.toLowerCase() : value) !== -1);
+ },
+
+ ifMatch: function(value, regex) {
+ return (new RegExp(regex)).test(value);
+ },
+
+ match: function(value, regex) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be matched with the regular expression.'';
+ }
+
+ return value.match(new RegExp(regex));
+ },
+
+ checkURL: function(value) {
+ if (CParamValidator.isEmpty(value)) {
+ throw ''URL value "'' + value + ''" must be a non-empty string.'';
+ }
+ if (!CParamValidator.ifMatch(value, ''^(http|https):\\/\\/.+'')) {
+ throw ''URL value "'' + value + ''" must contain a schema.'';
+ }
+
+ return value.endsWith(''/'') ? value.slice(0, -1) : value;
+ },
+
+ check: function(key, rule, params) {
+ if (!CParamValidator.isDefined(rule.type)) {
+ throw ''Mandatory attribute "type" has not been defined for parameter "'' + key + ''".'';
+ }
+ if (!CParamValidator.isDefined(params[key])) {
+ throw ''Checked parameter "'' + key + ''" was not found in the list of input parameters.'';
+ }
+ var value = params[key],
+ error_message = null;
+ switch (rule.type) {
+ case ''string'':
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + key + ''" must be a string.'';
+ }
+ if (CParamValidator.isEmpty(value)) {
+ error_message = ''Value "'' + key + ''" must be a non-empty string'';
+ break;
+ }
+ if (CParamValidator.isDefined(rule.len) && value.length < rule.len) {
+ error_message = ''Value "'' + key + ''" must be a string with a length > '' + rule.len;
+ }
+ if (CParamValidator.isDefined(rule.regex) && !CParamValidator.ifMatch(value, rule.regex)) {
+ error_message = ''Value "'' + key + ''" must match the regular expression "'' + rule.regex + ''"'';
+ }
+ if (CParamValidator.isDefined(rule.url) && rule.url === true) {
+ value = CParamValidator.checkURL(value);
+ }
+ break;
+ case ''integer'':
+ if (!CParamValidator.isInteger(value)) {
+ error_message = ''Value "'' + key + ''" must be an integer'';
+ break;
+ }
+ value = parseInt(value);
+ break;
+ case ''float'':
+ if (!CParamValidator.isFloat(value)) {
+ error_message = ''Value "'' + key + ''" must be a floating-point number'';
+ break;
+ }
+ value = parseFloat(value);
+ break;
+ case ''boolean'':
+ if (CParamValidator.inArray(value, [''1'', ''true'', ''yes'', ''on''])) {
+ value = true;
+ }
+ else if (CParamValidator.inArray(value, [''0'', ''false'', ''no'', ''off''])) {
+ value = false;
+ }
+ else {
+ error_message = ''Value "'' + key + ''" must be a boolean-like.'';
+ }
+ break;
+ case ''array'':
+ try {
+ value = JSON.parse(value);
+ } catch (error) {
+ throw ''Value "'' + key + ''" contains invalid JSON.'';
+ }
+ if (!CParamValidator.isType(value, ''array'')) {
+ error_message = ''Value "'' + key + ''" must be an array.'';
+ }
+ if (CParamValidator.isDefined(rule.tags) && rule.tags === true) {
+ value = value.reduce(function(acc, obj) {
+ acc[obj.tag] = obj.value || null;
+ return acc;
+ }, {});
+ }
+ break;
+ case ''object'':
+ value = JSON.parse(value);
+ if (!CParamValidator.isType(value, ''object'')) {
+ error_message = ''Value "'' + key + ''" must be an object.'';
+ }
+ break;
+ default:
+ throw ''Unexpected attribute type "'' + rule.type + ''" for value "'' + key + ''". Available: '' +
+ [''integer'', ''float'', ''string'', ''boolean'', ''array'', ''object''].join('', '');
+ }
+ params[key] = value;
+ if (CParamValidator.inArray(rule.type, [''integer'', ''float'']) && error_message === null && (CParamValidator.isDefined(rule.min)
+ || CParamValidator.isDefined(rule.max)) && !CParamValidator.withinRange(value, rule.min, rule.max)) {
+ error_message = ''Value "'' + key + ''" must be a number '' + ((CParamValidator.isDefined(rule.min) && CParamValidator.isDefined(rule.max))
+ ? (rule.min + ''..'' + rule.max) : ((CParamValidator.isDefined(rule.min)) ? ''>'' + rule.min : ''<'' + rule.max));
+ }
+ else if (CParamValidator.isDefined(rule.array) && !CParamValidator.inArray(value, rule.array)) {
+ error_message = ''Value "'' + key + ''" must be in the array '' + JSON.stringify(rule.array);
+ }
+ else if (CParamValidator.isDefined(rule.macro) && !CParamValidator.isMacroSet(value.toString(), rule.macro)) {
+ error_message = ''The macro '' + ((CParamValidator.isDefined(rule.macro)) ? ''{'' + rule.macro + ''} '' : '' '') + ''is not set'';
+ }
+ if (error_message !== null) {
+ if (CParamValidator.isDefined(rule.default) && CParamValidator.isType(rule.default, rule.type)) {
+ params[key] = rule.default;
+ }
+ else {
+ Zabbix.log(4, ''Default value for "'' + key + ''" must be a '' + rule.type + ''. Skipped.'');
+ throw ''Incorrect value for variable "'' + key + ''". '' + error_message;
+ }
+ }
+
+ return this;
+ },
+
+ validate: function(rules, params) {
+ if (!CParamValidator.isType(params, ''object'') || CParamValidator.isType(params, ''array'')) {
+ throw ''Incorrect parameters value. The value must be an object.'';
+ }
+ for (var key in rules) {
+ CParamValidator.check(key, rules[key], params);
+ }
+ }
+}
+
+const CHttpRequest = function(logger) {
+ this.request = new HttpRequest();
+ if (typeof logger !== ''object'' || logger === null) {
+ this.logger = Zabbix;
+ }
+ else {
+ this.logger = logger;
+ }
+
+ this.clearHeader = function() {
+ this.request.clearHeader();
+ }
+
+ this.addHeaders = function(value) {
+ var headers = [];
+
+ if (typeof value === ''object'' && value !== null) {
+ if (!Array.isArray(value)) {
+ Object.keys(value).forEach(function(key) {
+ headers.push(key + '': '' + value[key]);
+ });
+ }
+ else {
+ headers = value;
+ }
+ }
+ else if (typeof value === ''string'') {
+ value.split(''\\r\\n'').forEach(function(header) {
+ headers.push(header);
+ });
+ }
+
+ for (var idx in headers) {
+ this.request.addHeader(headers[idx]);
+ }
+ }
+
+ this.setProxy = function(proxy) {
+ this.request.setProxy(proxy);
+ }
+
+ this.plainRequest = function(method, url, data) {
+ var resp = null;
+ method = method.toLowerCase();
+ this.logger.log(4, ''Sending '' + method + '' request:'' + JSON.stringify(data));
+ if ([''get'', ''post'', ''put'', ''patch'', ''delete'', ''trace''].indexOf(method) !== -1) {
+ resp = this.request[method](url, data);
+ }
+ else if ([''connect'', ''head'', ''options''].indexOf(method) !== -1) {
+ resp = this.request[method](url);
+ }
+ else {
+ throw ''Unexpected method. Method '' + method + '' is not supported.'';
+ }
+ this.logger.log(4, ''Response has been received: '' + resp);
+
+ return resp;
+ }
+
+ this.jsonRequest = function(method, url, data) {
+ this.addHeaders(''Content-Type: application/json'');
+ var resp = this.plainRequest(method, url, JSON.stringify(data));
+ try {
+ resp = JSON.parse(resp);
+ }
+ catch (error) {
+ throw ''Failed to parse response: not well-formed JSON was received'';
+ }
+
+ return resp;
+ }
+
+ this.getStatus = function() {
+ return this.request.getStatus();
+ }
+}
+
+var serviceLogName = ''Telegram Webhook'',
+ Logger = new CLogger(serviceLogName),
+ Telegram = CWebhook;
+
+function escapeMarkup(str, mode) {
+ switch (mode) {
+ case ''markdown'':
+ return str.replace(/([_*\\[`])/g, ''\\\\$&'');
+ case ''markdownv2'':
+ return str.replace(/([_*\\[\\]()~`>#+\\-=|{}.!])/g, ''\\\\$&'');
+ case ''html'':
+ return str.replace(/<(\\s|[^a-z\\/])/g, ''<$1'');
+ default:
+ return str;
+ }
+}
+
+Telegram.prototype.getMessageID = function (chat_id, message_thread_id) {
+ const tag_key = ''__telegram_msg_id_'' + chat_id + (message_thread_id ? ''_'' + message_thread_id : '''');
+ if (CParamValidator.isDefined(this.params.event_tags[tag_key])) {
+ return this.params.event_tags[tag_key];
+ }
+ return null;
+}
+
+Telegram.prototype.onCheckParams = function () {
+ CParamValidator.validate(
+ {
+ api_token: {type: ''string''},
+ api_chat_id: {type: ''string''},
+ alert_message: {type: ''string''}
+ },
+ this.params
+ );
+
+ if (CParamValidator.inArray(this.params.event_source, [''0'', ''3'', ''4''])) {
+ CParamValidator.validate({
+ event_tags: {type: ''array'', macro: ''EVENT.TAGSJSON'', tags: true, default: {}}
+ }, this.params);
+ }
+
+ this.params.url = ''https://api.telegram.org/bot'';
+ this.data = {
+ disable_web_page_preview: true,
+ disable_notification: false
+ };
+ const match = this.params.api_chat_id.match(/^(-?\\d+|@[a-zA-Z0-9_]+)(?::(\\d+))?$/);
+ if (!match) {
+ throw ''Invalid format for api_chat_id: "'' + this.params.api_chat_id + ''". Must be a numeric group ID or @GroupName, optionally followed by :message_thread_id.'';
+ }
+ this.data[''chat_id''] = match[1];
+ if (CParamValidator.isDefined(match[2])) {
+ this.data[''message_thread_id''] = match[2];
+ }
+ this.data[''text''] = ((this.params.alert_subject !== '''') ? this.params.alert_subject + ''\\n'' : '''') + this.params.alert_message;
+ if ([''markdown'', ''html'', ''markdownv2''].indexOf(this.params.api_parse_mode.toLowerCase()) !== -1) {
+ this.data[''parse_mode''] = this.params.api_parse_mode.toLowerCase();
+ this.data[''text''] = escapeMarkup(this.data[''text''], this.data[''parse_mode'']);
+ }
+ const reply_to_message_id = this.getMessageID(this.data[''chat_id''], this.data[''message_thread_id'']);
+ if (reply_to_message_id !== null) {
+ this.data[''reply_to_message_id''] = reply_to_message_id;
+ }
+ this.result = {tags: {}};
+};
+
+Telegram.prototype.onEvent = function (alert) {
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+ Logger.log(Logger.INFO, ''URL: '' + this.params.url.replace(this.params.api_token, ''''));
+ var response = this.request.jsonRequest(''POST'', this.params.url + this.params.api_token + ''/sendMessage'', this.data);
+
+ if (this.request.getStatus() !== 200 || !CParamValidator.isType(response.ok, ''boolean'') || response.ok !== true) {
+ Logger.log(Logger.INFO, ''HTTP code: '' + this.request.getStatus());
+ if (CParamValidator.isType(response.description, ''string'')) {
+ throw response.description;
+ }
+ else {
+ throw ''Unknown error. Check debug log for more information.'';
+ }
+ }
+
+ if (CParamValidator.isDefined(response.result.message_id) && this.getMessageID(this.data[''chat_id''], this.data[''message_thread_id'']) === null) {
+ this.result.tags[''__telegram_msg_id_'' + this.data[''chat_id''] + (this.data[''message_thread_id''] ? ''_'' + this.data[''message_thread_id''] : '''')] = response.result.message_id;
+ }
+
+ return this.result;
+};
+
+try {
+ var hook = new Telegram(value);
+ hook.request = new CHttpRequest(Logger);
+ return hook.run();
+}
+catch (error) {
+ Logger.log(Logger.WARN, ''notification failed: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','0','','','This media type integrates your Zabbix installation with Telegram using the Zabbix webhook feature.
+
+Telegram configuration:
+
+1. Register a new Telegram bot: send "/newbot" to "@BotFather" and follow the instructions. The token provided by "@BotFather" in the final step will be needed for configuring the Zabbix webhook.
+
+2. Set up personal or group notifications:
+
+2.1 Personal notifications:
+
+2.1.1 Retrieve the chat ID of the user the bot should send messages to. The user should send "/getid" to "@myidbot" in the Telegram messenger.
+
+2.1.2 The user should also send "/start" to the bot created in step 1. If you skip this step, the Telegram bot won''t be able to send messages to the user (bots cannot initiate conversations with users).
+
+2.2 Group notifications:
+
+2.2.1 Retrieve the group ID of the group that the bot should send messages to. Add "@myidbot" and the bot created in step 1 to your group.
+
+2.2.2 In the group chat, send: "/getgroupid@myidbot".
+
+2.2.3 If the bot is added to a supergroup and you want the bot to send messages to a specific topic instead of the default "General" channel, right-click any message in that topic and click "Copy Message Link". The copied link will have the following format: "https://t.me/c///", for example: "https://t.me/c/1234567890/2/1". In this example, the topic ID is "2".
+
+Note:
+- The group ID is a negative number, for example: "-1234567890".
+- The supergroup ID is a negative number prefixed with "-100", for example: "-1001234567890"
+- The public group or supergroup ID can also be specified in media type properties as a name prefixed by "@", for example: "@MyGroupName".
+
+3. Depending on where you want to send notifications, copy and save the bot token, personal chat ID or group ID, and topic ID (if you want to send messages to a specific supergroup topic), as you will need these later to set up the media type in Zabbix.
+
+Zabbix configuration:
+
+1. Set the following webhook parameters:
+- "api_parse_mode" - the formatting mode applied for messages (possible values: "markdown", "html", "markdownv2")
+- "api_token" - the token of the bot used to send messages
+
+Learn more about message formatting options in Telegram Bot API documentation:
+- Markdown: https://core.telegram.org/bots/api#markdown-style
+- HTML: https://core.telegram.org/bots/api#html-style
+- MarkdownV2: https://core.telegram.org/bots/api#markdownv2-style
+
+Note: Your Telegram-related actions should be separated from other notification types (e.g., SMS); otherwise, if you use Markdown or HTML in the alert subject or body, you may receive plain-text alerts with raw tags.
+
+2. Click the "Enabled" checkbox to enable the media type and click the "Update" button to save the webhook settings.
+
+3. Create a Zabbix user and add media:
+- To create a new user, go to the "Users" → "Users" section, click the "Create user" button in the top right corner. In the "User" tab, fill in all required fields (marked with red asterisks).
+- Make sure this user has access to all hosts for which you would like problem notifications to be sent to Telegram.
+- In the "Media" tab, click "Add" and select the type "Telegram" from the drop-down list.
+- In the "Send to" field, specify the Telegram user chat ID or group ID that you retrieved during Telegram setup. To send notifications to a specific topic within a supergroup, specify the topic ID after the semicolon delimiter in the format ":", for example: "-1001234567890:2", "@MyGroupName:2".
+
+4. Done! You can now start using this media type in actions and create tickets.
+
+You can find the latest version of this media and additional information in the official Zabbix repository:
+https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/templates/media/telegram','0'),
+('98','4','TOPdesk','','','','','','','','25','0','0','0','0','1','3','10s','1',E'var Media = {
+ params: {},
+ name: '''',
+ labels: [],
+ HTTPProxy: '''',
+
+ setParams: function (params) {
+ if (typeof params !== ''object'') {
+ return;
+ }
+
+ Media.params = params;
+ Media.params.api += Media.params.api.endsWith(''/'') ? '''' : ''/'';
+ },
+
+ setProxy: function (HTTPProxy) {
+ if (typeof HTTPProxy !== ''undefined'' && HTTPProxy.trim() !== '''') {
+ Media.HTTPProxy = HTTPProxy;
+ }
+ },
+
+ request: function (method, query, data) {
+ [''api'', ''token''].forEach(function (field) {
+ if (typeof Media.params !== ''object'' || typeof Media.params[field] === ''undefined''
+ || Media.params[field] === '''') {
+ throw ''Required '' + Media.name + '' param is not set: "'' + field + ''".'';
+ }
+ });
+
+ var response,
+ url = Media.params.api + query,
+ request = new HttpRequest();
+
+ request.addHeader(''Content-Type: application/json'');
+ request.addHeader(''Accept: application/json'');
+ request.addHeader(''Authorization: '' + Media.params.token);
+ request.setProxy(Media.HTTPProxy);
+
+ if (typeof data !== ''undefined'') {
+ data = JSON.stringify(data);
+ }
+
+ Zabbix.log(4, ''[ '' + Media.name + '' Webhook ] Sending request: '' +
+ url + ((typeof data === ''string'') ? (''\\n'' + data) : ''''));
+
+ switch (method) {
+ case ''get'':
+ response = request.get(url, data);
+ break;
+
+ case ''post'':
+ response = request.post(url, data);
+ break;
+
+ case ''put'':
+ response = request.put(url, data);
+ break;
+
+ default:
+ throw ''Unsupported HTTP request method: '' + method;
+ }
+
+ Zabbix.log(4, ''[ '' + Media.name + '' Webhook ] Received response with status code '' +
+ request.getStatus() + ''\\n'' + response);
+
+ if (response !== null) {
+ try {
+ response = JSON.parse(response);
+ }
+ catch (error) {
+ Zabbix.log(4, ''[ '' + Media.name + '' Webhook ] Failed to parse response.'');
+ response = null;
+ }
+ }
+
+ if (request.getStatus() < 200 || request.getStatus() >= 300) {
+ var message = ''Request failed with status code '' + request.getStatus();
+
+ if (response !== null) {
+ if (typeof response.errors === ''object'' && Object.keys(response.errors).length > 0) {
+ message += '': '' + JSON.stringify(response.errors);
+ }
+ else if (typeof response.errorMessages === ''object'' && Object.keys(response.errorMessages).length > 0) {
+ message += '': '' + JSON.stringify(response.errorMessages);
+ }
+ else if (typeof response.message === ''string'') {
+ message += '': '' + response.message;
+ }
+ }
+
+ throw message + '' Check debug log for more information.'';
+ }
+
+ return {
+ status: request.getStatus(),
+ response: response
+ };
+ }
+};
+
+try {
+ var result = {tags: {}},
+ params = JSON.parse(value),
+ media = {},
+ fields = {},
+ resp = {},
+ required_params = [
+ ''alert_subject'',
+ ''alert_message'',
+ ''event_id'',
+ ''event_source'',
+ ''event_value'',
+ ''event_update_status'',
+ ''topdesk_api'',
+ ''topdesk_user'',
+ ''topdesk_password''
+ ],
+ severities = [
+ ''not_classified'',
+ ''information'',
+ ''warning'',
+ ''average'',
+ ''high'',
+ ''disaster'',
+ ''resolved'',
+ ''default''
+ ],
+ priority;
+
+ Object.keys(params)
+ .forEach(function (key) {
+ if (required_params.indexOf(key) !== -1 && params[key].trim() === '''') {
+ throw ''Parameter "'' + key + ''" cannot be empty.'';
+ }
+ if (key.startsWith(''topdesk_'')) {
+ media[key.substring(8)] = params[key];
+ }
+ });
+
+ // Possible values of event_source:
+ // 0 - Trigger, 1 - Discovery, 2 - Autoregistration, 3 - Internal.
+ if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
+ throw ''Incorrect "event_source" parameter given: "'' + params.event_source + ''".\\nMust be 0-3.'';
+ }
+
+ // Check event_value for trigger-based and internal events.
+ // Possible values: 1 for problem, 0 for recovering
+ 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.
+ // Possible values: 0 - Webhook was called because of problem/recovery event, 1 - Update operation.
+ if (params.event_source === ''0'' && params.event_update_status !== ''0'' && params.event_update_status !== ''1'') {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''\\nMust be 0 or 1.'';
+ }
+
+ // Check event_id for a numeric value.
+ if (isNaN(parseInt(params.event_id)) || params.event_id < 1) {
+ throw ''Incorrect "event_id" parameter given: '' + params.event_id + ''\\nMust be a positive number.'';
+ }
+
+ if ((params.event_source === ''1'' || params.event_source === ''2'') && params.event_value === ''0'') {
+ throw ''Recovery operations are supported only for Trigger and Internal actions.'';
+ }
+
+ if ([0, 1, 2, 3, 4, 5].indexOf(parseInt(params.event_nseverity)) === -1) {
+ params.event_nseverity = ''7'';
+ }
+
+ if (params.event_value === ''0'') {
+ params.event_nseverity = ''6'';
+ }
+
+ priority = params[''severity_'' + severities[params.event_nseverity]];
+ params.zbxurl = params.zbxurl + (params.zbxurl.endsWith(''/'') ? '''' : ''/'');
+
+ Media.name = ''TOPdesk'';
+ Media.setParams(media);
+ Media.params.token = ''Basic '' + btoa(Media.params.user + '':'' + Media.params.password);
+ Media.setProxy(params.HTTPProxy);
+
+ // Create an issue.
+ // Numeric value of the event that triggered an action (1 for problem, 0 for recovering).
+ // Numeric value of the problem update status. Possible values:
+ // 0 - Webhook was called because of problem/recovery event, 1 - Update operation.
+ if ((params.event_source == 0 && params.event_value == 1 && params.event_update_status == 0)
+ || (params.event_source == 3 && params.event_value == 1)
+ || params.event_source == 1 || params.event_source == 2) {
+ Zabbix.log(4, ''[ '' + Media.name + '' Webhook ] Request of the ticket creating.'');
+ fields.caller = {dynamicName: ''Zabbix''};
+ fields.briefDescription = params.alert_subject;
+ fields.request = params.alert_message.replace(/\\n/g, ''
'');
+ fields.priority = {name: priority};
+ fields.processingStatus = {name: Media.params.status};
+ fields.externalNumber = params.event_id;
+ fields.request += ''
'' + params.zbxurl;
+
+ if (params.event_source === ''0'') {
+ fields.request += ''tr_events.php?triggerid='' + params.trigger_id + ''&eventid='' + params.event_id;
+ }
+
+ resp = Media.request(''post'', ''tas/api/incidents'', fields);
+ if (typeof resp.response !== ''object'' || typeof resp.response.id === ''undefined'') {
+ throw ''Cannot create '' + Media.name + '' issue. Check debug log for more information.'';
+ }
+
+ if (params.event_source == 0 && params.event_value == 1 && params.event_update_status == 0) {
+ result.tags.__zbx_tpd_issuekey = resp.response.number;
+ result.tags.__zbx_tpd_issuelink = Media.params.api +
+ ''tas/secure/incident?action=show&unid='' + resp.response.id;
+ }
+ }
+ // Update a created issue.
+ else {
+ if (params.event_source == 3 && params.event_value == 0) {
+ throw ''Internal event recovery actions are not supported.'';
+ }
+
+ Zabbix.log(4, ''[ '' + Media.name + '' Webhook ] Request of the ticket updating.'');
+ fields.action = params.alert_message.replace(/\\n/g, ''
'');
+
+ resp = Media.request(''put'', ''tas/api/incidents/number/'' + Media.params.issue_key, fields);
+ if (typeof resp.response !== ''object'' || typeof resp.response.id === ''undefined''
+ || resp.response.number !== Media.params.issue_key) {
+ throw ''Cannot update '' + Media.name + '' issue. Check debug log for more information.'';
+ }
+ }
+
+ return JSON.stringify(result);
+}
+catch (error) {
+ Zabbix.log(3, ''[ '' + Media.name + '' Webhook ] ERROR: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','1','{EVENT.TAGS.__zbx_tpd_issuelink}','TOPdesk: {EVENT.TAGS.__zbx_tpd_issuekey}','Please refer to https://developers.topdesk.com/documentation/index.html and https://www.zabbix.com/documentation/8.0/manual/config/notifications/media/webhook#example_scripts.
+
+Set global macro {$ZABBIX.URL} with your Zabbix server URL.
+Add a dedicated user with the media type "TOPdesk".
+Change the values of the variables topdesk_api (URL), topdesk_password, topdesk_user. The topdesk_status is the default status for creating a new TOPdesk ticket.','0'),
+('99','4','VictorOps','','','','','','','','25','0','0','0','0','1','3','10s','1',E'var VictorOps = {
+ params: {},
+
+ setParams: function (params) {
+ if (typeof params !== ''object'') {
+ return;
+ }
+
+ VictorOps.params = params;
+ if (VictorOps.params.endpoint) {
+ if (!VictorOps.params.endpoint.endsWith(''/'')) {
+ VictorOps.params.endpoint += ''/'';
+ }
+
+ if (typeof VictorOps.params.routing_key !== ''undefined''
+ && VictorOps.params.routing_key !== ''{ALERT.SENDTO}''
+ && VictorOps.params.routing_key !== ''Default'') {
+ VictorOps.params.endpoint += VictorOps.params.routing_key;
+ }
+ }
+ },
+
+ setProxy: function (HTTPProxy) {
+ VictorOps.HTTPProxy = HTTPProxy;
+ },
+
+ addFields: function (fields) {
+ var data = {};
+
+ if (typeof fields === ''object'') {
+ Object.keys(fields)
+ .forEach(function(field) {
+ if (fields[field] === '''') {
+ Zabbix.log(4, ''[ VictorOps Webhook ] Field "'' + field +
+ ''" can\\''t be empty. The field ignored.'');
+ }
+ else {
+ try {
+ var parts = field.split('':''),
+ prefix = parts[0].split(''_'');
+
+ if (typeof prefix[1] === ''undefined''
+ || (prefix[1] === ''p'' && params.event_value === ''1''
+ && (params.event_update_status === ''0''
+ || params.event_update_status === ''{EVENT.UPDATE.STATUS}''))
+ || (prefix[1] === ''r'' && params.event_value === ''0''
+ && (params.event_update_status === ''0''
+ || params.event_update_status === ''{EVENT.UPDATE.STATUS}''))
+ || (prefix[1] === ''u'' && params.event_update_status === ''1'')) {
+ data[field.substring(field.indexOf('':'') + 1)] = fields[field];
+ }
+ }
+ catch (error) {
+ Zabbix.log(4, ''[ VictorOps Webhook ] Can\\''t parse field "'' + field +
+ ''". The field ignored.'');
+ }
+ }
+ });
+ }
+
+ return data;
+ },
+
+ request: function (data) {
+ if (typeof VictorOps.params !== ''object'' || typeof VictorOps.params.endpoint === ''undefined''
+ || VictorOps.params.endpoint === '''' ) {
+ throw ''Required parameter is not set: "vops_endpoint".'';
+ }
+
+ var response,
+ url = VictorOps.params.endpoint,
+ request = new HttpRequest();
+
+ request.addHeader(''Content-Type: application/json'');
+
+ if (typeof VictorOps.HTTPProxy !== ''undefined'' && VictorOps.HTTPProxy !== '''') {
+ request.setProxy(VictorOps.HTTPProxy);
+ }
+
+ if (typeof data !== ''undefined'') {
+ data = JSON.stringify(data);
+ }
+
+ Zabbix.log(4, ''[ VictorOps Webhook ] Sending request: '' + url +
+ ((typeof data === ''string'') ? (''\\n'' + data) : ''''));
+
+ response = request.post(url, data);
+
+ Zabbix.log(4, ''[ VictorOps Webhook ] Received response with status code '' +
+ request.getStatus() + ''\\n'' + response);
+
+ if (response !== null) {
+ try {
+ response = JSON.parse(response);
+ }
+ catch (error) {
+ Zabbix.log(4, ''[ VictorOps Webhook ] Failed to parse response received from VictorOps'');
+ response = null;
+ }
+ }
+
+ if (request.getStatus() < 200 || request.getStatus() >= 300) {
+ var message = ''Request failed with status code '' + request.getStatus();
+
+ if (response !== null && typeof response.messages !== ''undefined'') {
+ message += '': '' + JSON.stringify(response.messages);
+ }
+
+ throw message + ''. Check debug log for more information.'';
+ }
+
+ return response;
+ }
+};
+
+try {
+ var params = JSON.parse(value),
+ fields = {},
+ vops = {},
+ required_params = [''event_source'', ''event_value'', ''priority_update''],
+ severities = [
+ {name: ''not_classified'', color: ''#97AAB3''},
+ {name: ''information'', color: ''#7499FF''},
+ {name: ''warning'', color: ''#FFC859''},
+ {name: ''average'', color: ''#FFA059''},
+ {name: ''high'', color: ''#E97659''},
+ {name: ''disaster'', color: ''#E45959''},
+ {name: ''resolved'', color: ''#009900''},
+ {name: ''default'', color: ''#000000''}
+ ];
+
+ Object.keys(params)
+ .forEach(function (key) {
+ if (key.startsWith(''vops_'')) {
+ vops[key.substring(5)] = params[key];
+ }
+ else if (key.startsWith(''field'')) {
+ fields[key.substring(5)] = params[key];
+ }
+ else if (required_params.indexOf(key) !== -1 && params[key] === '''') {
+ throw ''Parameter "'' + key + ''" can\\''t be empty.'';
+ }
+ });
+
+ if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''\\nMust be 0-3.'';
+ }
+
+ // 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 ([0, 1, 2, 3, 4, 5].indexOf(parseInt(params.event_nseverity)) === -1) {
+ params.event_nseverity = ''7'';
+ }
+
+ if (params.event_value === ''0'') {
+ params.event_nseverity = ''6'';
+ }
+
+ if (params.event_update_status === ''1'') {
+ fields['':message_type''] = params.priority_update;
+ }
+ else {
+ fields['':message_type''] = params[''priority_'' + severities[params.event_nseverity].name]
+ || ''INFO'';
+ }
+
+ if (params.event_info && params.event_source === ''0'') {
+ fields['':event_info''] = params.event_info;
+ }
+
+ VictorOps.setParams(vops);
+ VictorOps.setProxy(params.HTTPProxy);
+ VictorOps.request(VictorOps.addFields(fields));
+
+ return ''OK'';
+}
+catch (error) {
+ Zabbix.log(3, ''[ VictorOps Webhook ] ERROR: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','0','0','','','','0'),
+('100','4','Zammad','','','','','','','','25','0','0','0','0','1','3','10s','1',E'const CLogger = function(serviceName) {
+ this.serviceName = serviceName;
+ this.INFO = 4
+ this.WARN = 3
+ this.ERROR = 2
+ this.log = function(level, msg) {
+ Zabbix.log(level, ''['' + this.serviceName + ''] '' + msg);
+ }
+}
+
+const CWebhook = function(value) {
+ try {
+ params = JSON.parse(value);
+
+ if ([''0'', ''1'', ''2'', ''3'', ''4''].indexOf(params.event_source) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''.\\nMust be 0-4.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1 && [''0'', ''1''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0 or 1.'';
+ }
+
+ if ([''0'', ''3'', ''4''].indexOf(params.event_source) !== -1) {
+ if (params.event_source === ''1'' && [''0'', ''1'', ''2'', ''3''].indexOf(params.event_value) === -1) {
+ throw ''Incorrect "event_value" parameter given: '' + params.event_value + ''.\\nMust be 0-3.'';
+ }
+
+ if (params.event_source === ''0'' && [''0'', ''1''].indexOf(params.event_update_status) === -1) {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''.\\nMust be 0 or 1.'';
+ }
+
+ if (params.event_source === ''4'') {
+ if ([''0'', ''1'', ''2'', ''3'', ''4'', ''5''].indexOf(params.event_update_nseverity) !== -1 && params.event_update_nseverity != params.event_nseverity) {
+ params.event_nseverity = params.event_update_nseverity;
+ params.event_severity = params.event_update_severity;
+ params.event_update_status = ''1'';
+ }
+ }
+ }
+
+ this.runCallback = function(name, params) {
+ if (typeof this[name] === ''function'') {
+ return this[name].apply(this, [params]);
+ }
+ }
+
+ this.handleEvent = function(source, event) {
+ const alert = { source: source, event: event };
+ return [
+ this.runCallback(''on'' + source + event, alert),
+ this.runCallback(''on'' + event, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.handleEventless = function(source) {
+ const alert = { source: source, event: null };
+ return [
+ this.runCallback(''on'' + source, alert),
+ this.runCallback(''onEvent'', alert)
+ ];
+ }
+
+ this.run = function() {
+ var results = [];
+ if (typeof this.httpProxy === ''string'' && this.httpProxy.trim() !== '''') {
+ this.request.setProxy(this.httpProxy);
+ }
+ const types = { ''0'': ''Trigger'', ''1'': ''Discovery'', ''2'': ''Autoreg'', ''3'': ''Internal'', ''4'': ''Service'' };
+
+ if ([''0'', ''3'', ''4''].indexOf(this.params.event_source) !== -1) {
+ var event = (this.params.event_update_status === ''1'')
+ ? ''Update''
+ : ((this.params.event_value === ''1'') ? ''Problem'' : ''Resolve'');
+
+ results = this.handleEvent(types[this.params.event_source], event);
+ }
+ else if (typeof types[this.params.event_source] !== ''undefined'') {
+ results = this.handleEventless(types[this.params.event_source]);
+ }
+ else {
+ throw ''Unexpected "event_source": '' + this.params.event_source;
+ }
+
+ for (idx in results) {
+ if (typeof results[idx] !== ''undefined'') {
+ return JSON.stringify(results[idx]);
+ }
+ }
+ }
+ this.httpProxy = params.http_proxy;
+ this.params = params;
+ this.runCallback(''onCheckParams'', {});
+ } catch (error) {
+ throw ''Webhook processing failed: '' + error;
+ }
+}
+
+const CParamValidator = {
+
+ isType: function(value, type) {
+ if (type === ''array'') {
+ return Array.isArray(value);
+ }
+ if (type === ''integer'') {
+ return CParamValidator.isInteger(value);
+ }
+ if (type === ''float'') {
+ return CParamValidator.isFloat(value);
+ }
+
+ return (typeof value === type);
+ },
+
+ isInteger: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseInt(value));
+ },
+
+ isFloat: function(value) {
+ if (!CParamValidator.ifMatch(value, /^-?\\d+\\.\\d+$/)) {
+ return false;
+ }
+
+ return !isNaN(parseFloat(value));
+ },
+
+ isDefined: function(value) {
+ return !CParamValidator.isType(value, ''undefined'');
+ },
+
+ isEmpty: function(value) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be checked for emptiness.'';
+ }
+
+ return (value.trim() === '''');
+ },
+
+ isMacroSet: function(value, macro) {
+ if (CParamValidator.isDefined(macro)) {
+ return !(CParamValidator.ifMatch(value, ''^\\{'' + macro + ''\\}$''))
+ }
+
+ return !(CParamValidator.ifMatch(value, ''^\\{[$#]{0,1}[A-Z_\\.]+[\\:]{0,1}["]{0,1}.*["]{0,1}\\}$'') || value === ''*UNKNOWN*'')
+ },
+
+ withinRange: function(value, min, max) {
+ if (!CParamValidator.isType(value, ''number'')) {
+ throw ''Value "'' + value + ''" must be a number to be checked for range.'';
+ }
+ if (value < ((CParamValidator.isDefined(min)) ? min : value)
+ || value > ((CParamValidator.isDefined(max)) ? max : value)) {
+ return false;
+ }
+
+ return true;
+ },
+
+ inArray: function(value, array) {
+ if (!CParamValidator.isType(array, ''array'')) {
+ throw ''The array must be an array to check the value for existing in it.'';
+ }
+
+ return (array.indexOf((typeof value === ''string'') ? value.toLowerCase() : value) !== -1);
+ },
+
+ ifMatch: function(value, regex) {
+ return (new RegExp(regex)).test(value);
+ },
+
+ match: function(value, regex) {
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + value + ''" must be a string to be matched with the regular expression.'';
+ }
+
+ return value.match(new RegExp(regex));
+ },
+
+ checkURL: function(value) {
+ if (CParamValidator.isEmpty(value)) {
+ throw ''URL value "'' + value + ''" must be a non-empty string.'';
+ }
+ if (!CParamValidator.ifMatch(value, ''^(http|https):\\/\\/.+'')) {
+ throw ''URL value "'' + value + ''" must contain a schema.'';
+ }
+
+ return value.endsWith(''/'') ? value.slice(0, -1) : value;
+ },
+
+ check: function(key, rule, params) {
+ if (!CParamValidator.isDefined(rule.type)) {
+ throw ''Mandatory attribute "type" has not been defined for parameter "'' + key + ''".'';
+ }
+ if (!CParamValidator.isDefined(params[key])) {
+ throw ''Checked parameter "'' + key + ''" was not found in the list of input parameters.'';
+ }
+ var value = params[key],
+ error_message = null;
+ switch (rule.type) {
+ case ''string'':
+ if (!CParamValidator.isType(value, ''string'')) {
+ throw ''Value "'' + key + ''" must be a string.'';
+ }
+ if (CParamValidator.isEmpty(value)) {
+ error_message = ''Value "'' + key + ''" must be a non-empty string'';
+ break;
+ }
+ if (CParamValidator.isDefined(rule.len) && value.length < rule.len) {
+ error_message = ''Value "'' + key + ''" must be a string with a length > '' + rule.len;
+ }
+ if (CParamValidator.isDefined(rule.regex) && !CParamValidator.ifMatch(value, rule.regex)) {
+ error_message = ''Value "'' + key + ''" must match the regular expression "'' + rule.regex + ''"'';
+ }
+ if (CParamValidator.isDefined(rule.url) && rule.url === true) {
+ value = CParamValidator.checkURL(value);
+ }
+ break;
+ case ''integer'':
+ if (!CParamValidator.isInteger(value)) {
+ error_message = ''Value "'' + key + ''" must be an integer'';
+ break;
+ }
+ value = parseInt(value);
+ break;
+ case ''float'':
+ if (!CParamValidator.isFloat(value)) {
+ error_message = ''Value "'' + key + ''" must be a floating-point number'';
+ break;
+ }
+ value = parseFloat(value);
+ break;
+ case ''boolean'':
+ if (CParamValidator.inArray(value, [''1'', ''true'', ''yes'', ''on''])) {
+ value = true;
+ }
+ else if (CParamValidator.inArray(value, [''0'', ''false'', ''no'', ''off''])) {
+ value = false;
+ }
+ else {
+ error_message = ''Value "'' + key + ''" must be a boolean-like.'';
+ }
+ break;
+ case ''array'':
+ try {
+ value = JSON.parse(value);
+ } catch (error) {
+ throw ''Value "'' + key + ''" contains invalid JSON.'';
+ }
+ if (!CParamValidator.isType(value, ''array'')) {
+ error_message = ''Value "'' + key + ''" must be an array.'';
+ }
+ if (CParamValidator.isDefined(rule.tags) && rule.tags === true) {
+ value = value.reduce(function(acc, obj) {
+ acc[obj.tag] = obj.value || null;
+ return acc;
+ }, {});
+ }
+ break;
+ case ''object'':
+ value = JSON.parse(value);
+ if (!CParamValidator.isType(value, ''object'')) {
+ error_message = ''Value "'' + key + ''" must be an object.'';
+ }
+ break;
+ default:
+ throw ''Unexpected attribute type "'' + rule.type + ''" for value "'' + key + ''". Available: '' +
+ [''integer'', ''float'', ''string'', ''boolean'', ''array'', ''object''].join('', '');
+ }
+ params[key] = value;
+ if (CParamValidator.inArray(rule.type, [''integer'', ''float'']) && error_message === null && (CParamValidator.isDefined(rule.min)
+ || CParamValidator.isDefined(rule.max)) && !CParamValidator.withinRange(value, rule.min, rule.max)) {
+ error_message = ''Value "'' + key + ''" must be a number '' + ((CParamValidator.isDefined(rule.min) && CParamValidator.isDefined(rule.max))
+ ? (rule.min + ''..'' + rule.max) : ((CParamValidator.isDefined(rule.min)) ? ''>'' + rule.min : ''<'' + rule.max));
+ }
+ else if (CParamValidator.isDefined(rule.array) && !CParamValidator.inArray(value, rule.array)) {
+ error_message = ''Value "'' + key + ''" must be in the array '' + JSON.stringify(rule.array);
+ }
+ else if (CParamValidator.isDefined(rule.macro) && !CParamValidator.isMacroSet(value.toString(), rule.macro)) {
+ error_message = ''The macro '' + ((CParamValidator.isDefined(rule.macro)) ? ''{'' + rule.macro + ''} '' : '' '') + ''is not set'';
+ }
+ if (error_message !== null) {
+ if (CParamValidator.isDefined(rule.default) && CParamValidator.isType(rule.default, rule.type)) {
+ params[key] = rule.default;
+ }
+ else {
+ Zabbix.log(4, ''Default value for "'' + key + ''" must be a '' + rule.type + ''. Skipped.'');
+ throw ''Incorrect value for variable "'' + key + ''". '' + error_message;
+ }
+ }
+
+ return this;
+ },
+
+ validate: function(rules, params) {
+ if (!CParamValidator.isType(params, ''object'') || CParamValidator.isType(params, ''array'')) {
+ throw ''Incorrect parameters value. The value must be an object.'';
+ }
+ for (var key in rules) {
+ CParamValidator.check(key, rules[key], params);
+ }
+ }
+}
+
+const CHttpRequest = function(logger) {
+ this.request = new HttpRequest();
+ if (typeof logger !== ''object'' || logger === null) {
+ this.logger = Zabbix;
+ }
+ else {
+ this.logger = logger;
+ }
+
+ this.clearHeader = function() {
+ this.request.clearHeader();
+ }
+
+ this.addHeaders = function(value) {
+ var headers = [];
+
+ if (typeof value === ''object'' && value !== null) {
+ if (!Array.isArray(value)) {
+ Object.keys(value).forEach(function(key) {
+ headers.push(key + '': '' + value[key]);
+ });
+ }
+ else {
+ headers = value;
+ }
+ }
+ else if (typeof value === ''string'') {
+ value.split(''\\r\\n'').forEach(function(header) {
+ headers.push(header);
+ });
+ }
+
+ for (var idx in headers) {
+ this.request.addHeader(headers[idx]);
+ }
+ }
+
+ this.setProxy = function(proxy) {
+ this.request.setProxy(proxy);
+ }
+
+ this.plainRequest = function(method, url, data) {
+ var resp = null;
+ method = method.toLowerCase();
+ this.logger.log(4, ''Sending '' + method + '' request:'' + JSON.stringify(data));
+ if ([''get'', ''post'', ''put'', ''patch'', ''delete'', ''trace''].indexOf(method) !== -1) {
+ resp = this.request[method](url, data);
+ }
+ else if ([''connect'', ''head'', ''options''].indexOf(method) !== -1) {
+ resp = this.request[method](url);
+ }
+ else {
+ throw ''Unexpected method. Method '' + method + '' is not supported.'';
+ }
+ this.logger.log(4, ''Response has been received: '' + resp);
+
+ return resp;
+ }
+
+ this.jsonRequest = function(method, url, data) {
+ this.addHeaders(''Content-Type: application/json'');
+ var resp = this.plainRequest(method, url, JSON.stringify(data));
+ try {
+ resp = JSON.parse(resp);
+ }
+ catch (error) {
+ throw ''Failed to parse response: not well-formed JSON was received'';
+ }
+
+ return resp;
+ }
+
+ this.getStatus = function() {
+ return this.request.getStatus();
+ }
+}
+
+const CWebhookHelper = {
+
+ createProblemURL: function(event_source, zabbix_url, trigger_id, event_id) {
+ if (event_source === ''0'') {
+ return zabbix_url + ''/tr_events.php?triggerid='' + trigger_id + ''&eventid='' + event_id;
+ } else if (event_source === ''4'') {
+ return zabbix_url + ''/zabbix.php?action=service.list'';
+ }
+
+ return zabbix_url;
+ },
+
+};
+
+var ZABBIX_SEVERITY_MAP = ["not_classified", "information", "warning", "average", "high", "disaster"],
+ serviceLogName = ''Zammad Webhook'',
+ Logger = new CLogger(serviceLogName),
+ Zammad = CWebhook;
+
+Zammad.prototype.onCheckParams = function () {
+ CParamValidator.validate({
+ alert_message: {type: ''string''},
+ alert_subject: {type: ''string''},
+ zammad_url: {type: ''string'', url: true},
+ zammad_customer: {type: ''string''},
+ zammad_access_token: {type: ''string''},
+ zammad_group: {type: ''string''},
+ zammad_enable_tags: {type: ''boolean'', default: false},
+ event_nseverity: {type: ''integer'', default: -1},
+ zabbix_url: {type: ''string'', url: true}
+ }, this.params);
+
+ if (CParamValidator.inArray(this.params.event_source, [''0'', ''3'', ''4''])) {
+ CParamValidator.validate({
+ event_tags: {type: ''array'', macro: ''EVENT.TAGSJSON'', tags: true, default: {}}
+ }, this.params);
+ }
+
+ var priority;
+
+ if (this.params.event_nseverity >= 0 && this.params.event_nseverity < ZABBIX_SEVERITY_MAP.length) {
+ priority = this.params[''severity_'' + ZABBIX_SEVERITY_MAP[this.params.event_nseverity]];
+ }
+ this.priority = (CParamValidator.isDefined(priority)) ? priority.trim() : null;
+
+ this.result = {tags: {}};
+};
+
+Zammad.prototype.onProblem = function (alert) {
+ if (CParamValidator.isDefined(this.params.event_tags[''__zbx_zammad_ticket_id''])) {
+ return this.onUpdate(alert);
+ }
+
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+
+ this.request.addHeaders(''Authorization: Token token='' + this.params.zammad_access_token);
+
+ var payload_data = {
+ title: this.params.alert_subject,
+ group: this.params.zammad_group,
+ article: {
+ subject: this.params.alert_subject,
+ body: this.params.alert_message + ''\\n'' + CWebhookHelper.createProblemURL(this.params.event_source, this.params.zabbix_url, this.params.trigger_id, this.params.event_id),
+ type: ''note'',
+ internal: false
+ },
+ customer: this.params.zammad_customer
+ };
+
+ if (this.priority) {
+ payload_data.priority_id = this.priority;
+ }
+
+ const response = this.request.jsonRequest(''POST'', this.params.zammad_url + ''/api/v1/tickets'', payload_data);
+
+ if (this.request.getStatus() != 201 || !CParamValidator.isDefined(response.id)) {
+ var message = ''Cannot create Zammad ticket. Request failed with status code '' + this.request.getStatus();
+
+ if (CParamValidator.isDefined(response.error) && Object.keys(response.error).length > 0) {
+ message += '': '' + response.error;
+ }
+
+ throw message + '' Check debug log for more information.'';
+ }
+
+ this.result.tags = {
+ __zbx_zammad_ticket_id: response.id,
+ __zbx_zammad_ticketlink: this.params.zammad_url + ''/#ticket/zoom/'' + response.id
+ };
+
+ if (this.params.zammad_enable_tags && Object.keys(this.params.event_tags).length > 0 && CParamValidator.inArray(this.params.event_source, [''0'', ''3'', ''4''])) {
+ this.request.clearHeader();
+ this.request.addHeaders({
+ "Content-Type": "application/json",
+ "Authorization": "Token token=" + this.params.zammad_access_token
+ });
+
+ payload_data = {
+ item: '''',
+ object: ''Ticket'',
+ o_id: response.id
+ };
+
+ try {
+ for (var tag in this.params.event_tags) {
+ payload_data.item = tag;
+
+ if (this.params.event_tags[tag]) {
+ payload_data.item += ": " + this.params.event_tags[tag];
+ }
+
+ this.request.plainRequest(''POST'', this.params.zammad_url + ''/api/v1/tags/add'', JSON.stringify(payload_data));
+
+ if (this.request.getStatus() != 201) {
+ Logger.log(Logger.INFO, ''Failed to set tag: '' + tag);
+ }
+ }
+ }
+ catch (error) {
+ Logger.log(Logger.INFO, ''Failed to add ticket tags: '' + error);
+ }
+ }
+
+ return this.result;
+}
+
+Zammad.prototype.onUpdate = function (alert) {
+ Logger.log(Logger.INFO, ''Source: '' + alert.source + ''; Event: '' + alert.event);
+
+ if (!CParamValidator.isDefined(this.params.event_tags[''__zbx_zammad_ticket_id''])) {
+ throw "Failed to update the existing ticket: no ticket ID was received."
+ }
+
+
+ this.request.addHeaders(''Authorization: Token token='' + this.params.zammad_access_token);
+
+ const payload_data = {
+ ticket_id: this.params.event_tags[''__zbx_zammad_ticket_id''],
+ subject: this.params.alert_subject,
+ body: this.params.alert_message,
+ type: ''note'',
+ internal: false
+ };
+
+ const response = this.request.jsonRequest(''POST'', this.params.zammad_url + ''/api/v1/ticket_articles'', payload_data);
+
+ if (this.request.getStatus() != 201 || !CParamValidator.isDefined(response.id)) {
+ var message = ''Cannot update Zammad ticket. Request failed with status code '' + this.request.getStatus();
+
+ if (CParamValidator.isDefined(response.error) && Object.keys(response.error).length > 0) {
+ message += '': '' + response.error;
+ }
+
+ throw message + '' Check debug log for more information.'';
+ }
+
+ return this.result;
+}
+
+Zammad.prototype.onResolve = function (alert) {
+ return this.onUpdate(alert);
+}
+
+Zammad.prototype.onDiscovery = function (alert) {
+ return this.onProblem(alert);
+}
+
+Zammad.prototype.onAutoreg = function (alert) {
+ return this.onProblem(alert);
+}
+
+try {
+ var hook = new Zammad(value);
+ hook.request = new CHttpRequest(Logger);
+ return hook.run();
+}
+catch (error) {
+ Logger.log(Logger.WARN, ''notification failed: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','1','{EVENT.TAGS.__zbx_zammad_ticketlink}','Zammad: Ticket #{EVENT.TAGS.__zbx_zammad_ticket_id}','This media type integrates your Zabbix installation with your Zammad installation using the Zabbix webhook feature.
+
+Zammad configuration:
+
+1. Check that API Token Access is enabled in "Settings" → "System" → "API".
+2. Open the profile settings of the customer user and create a new Personal User Token.
+3. Set the "ticket.agent" permission for the token and press Create.
+4. Copy and save the created token somewhere, as it will be shown only once for security reasons.
+
+Zabbix configuration:
+
+1. Before you can start using Zammad webhook, set up the global macro "{$ZABBIX.URL}":
+- In the Zabbix web interface, go to "Administration" → "Macros" section in the dropdown menu in the top left corner.
+- Set up the global macro "{$ZABBIX.URL}" which will contain the URL to the Zabbix frontend. The URL should be either an IP address, a fully qualified domain name, or localhost.
+- Specifying a protocol is mandatory, whereas the port is optional. Depending on the web server configuration you might also need to append "/zabbix" to the end of URL. Good examples:
+ - http://zabbix.com
+ - https://zabbix.lan/zabbix
+ - http://server.zabbix.lan/
+ - http://localhost
+ - http://127.0.0.1:8080
+- Bad examples:
+ - zabbix.com
+ - http://zabbix/
+
+2. Set the following webhook parameters:
+- zammad_access_token - the access token that you created during Zammad configuration
+- zammad_url - the frontend URL of your Zammad installation
+- zammad_customer - the Zammad user email
+- zammad_enable_tags - if you want to add the Zabbix event tags to the Zammad tickets that are created, you can set it to one of the following values: "1", "true", "yes", "on" (note, that if the tag support is enabled, each tag is sent via separate HTTP request and created tags will also remain in the Zammad when tickets are closed/deleted)
+- zammad_group - if needed, you can change the Zammad user group
+
+3. If you want to prioritize issues according to the severity values in Zabbix, you can define mapping parameters (create them as additional webhook parameters):
+- severity_ - the Zammad priority ID ( in the parameter name can be one of the following values: "not_classified", "information", "warning", "average", "high", "disaster")
+
+4. Create a Zabbix user and add media:
+- If you want to create a new user, go to the "Users" → "Users" section, click the "Create user" button in the top right corner. In the "User" tab, fill in all required fields (marked with red asterisks).
+- In the "Media" tab, add a new media and select "Zammad" type from the drop-down list. Add any value to the "Send to" field: it is required to be filled, but it is not used.
+- Make sure this user has access to all hosts for which you would like problem notifications to be sent to Zammad.
+
+5. Great! You can now start using this media type in actions and create tickets!
+
+You can find the latest version of this media and additional information in the official Zabbix repository:
+https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/templates/media/zammad','0'),
+('101','4','Zendesk','','','','','','','','25','0','0','0','0','1','3','10s','1',E'var Zendesk = {
+ params: {},
+
+ setParams: function (params) {
+ if (typeof params !== ''object'') {
+ return;
+ }
+
+ Zendesk.params = params;
+ if (typeof Zendesk.params.url === ''string'') {
+ if (!Zendesk.params.url.endsWith(''/'')) {
+ Zendesk.params.url += ''/'';
+ }
+ Zendesk.params.url += ''api/v2/'';
+ }
+ },
+
+ addCustomFields: function (data, fields) {
+ if (typeof fields === ''object'' && Object.keys(fields).length) {
+ var schema = Zendesk.getSchema(),
+ arr = [],
+ i,
+ n;
+
+ if (schema) {
+ Object.keys(fields)
+ .forEach(function(field) {
+ for (i = 0, n = schema.ticket_fields.length; i < n; i++) {
+ if (schema.ticket_fields[i].id == field
+ && [''text'', ''integer'', ''date''].indexOf(schema.ticket_fields[i].type) !== -1){
+
+ switch (schema.ticket_fields[i].type) {
+ case ''integer'':
+ fields[field] = parseInt(fields[field]);
+ break;
+ case ''date'':
+ if (fields[field].match(/^\\d{4}[.-]\\d{2}[.-]\\d{2}$/) !== null) {
+ fields[field] = fields[field].replace(/\\./g, ''-'');
+ }
+ else {
+ fields[field] = '''';
+ }
+ break;
+ }
+
+ arr.push({id: field, value: fields[field]});
+ break;
+ }
+ }
+ });
+
+ if (arr.length) {
+ data.ticket[''custom_fields''] = arr;
+ }
+ }
+ else {
+ Zabbix.log(4, ''[Zendesk Webhook] Failed to retrieve field schema.'');
+ }
+ }
+
+ return data;
+ },
+
+ request: function (method, query, data) {
+ [''url'', ''token'', ''type''].forEach(function (field) {
+ if (typeof Zendesk.params !== ''object'' || typeof Zendesk.params[field] === ''undefined'') {
+ throw ''Required Zendesk param is not set: '' + field + ''\\n'' + Zendesk.params[field];
+ }
+ });
+
+ var response,
+ url = Zendesk.params.url + query,
+ request = new HttpRequest();
+
+ if (typeof Zendesk.HTTPProxy === ''string'' && Zendesk.HTTPProxy.trim() !== '''') {
+ request.setProxy(Zendesk.HTTPProxy);
+ }
+
+ request.addHeader(''Content-Type: application/json'');
+ request.addHeader(''Authorization: Basic '' + btoa(Zendesk.params.token));
+
+ if (typeof data !== ''undefined'') {
+ data = JSON.stringify(data);
+ }
+
+ Zabbix.log(4, ''[Zendesk Webhook] Sending request: '' + url + ((typeof data === ''string'') ? ('' '' + data) : ''''));
+
+ switch (method) {
+ case ''get'':
+ response = request.get(url, data);
+ break;
+
+ case ''post'':
+ response = request.post(url, data);
+ break;
+
+ case ''put'':
+ response = request.put(url, data);
+ break;
+
+ default:
+ throw ''Unsupported HTTP request method: '' + method;
+ }
+
+ Zabbix.log(4, ''[Zendesk Webhook] Received response with status code '' + request.getStatus() + ''. '' + response);
+
+ if (response !== null) {
+ try {
+ response = JSON.parse(response);
+ }
+ catch (error) {
+ Zabbix.log(4, ''[Zendesk Webhook] Failed to parse response received from Zendesk.'');
+ }
+ }
+
+ if (request.getStatus() < 200 || request.getStatus() >= 300) {
+ var message = ''Request failed with status code '' + request.getStatus();
+
+ if (response !== null && typeof response.error !== ''undefined''
+ && Object.keys(response.error).length > 0) {
+ message += '': '' + JSON.stringify(response.error);
+ }
+ else if (response !== null && typeof response.description !== ''undefined''
+ && Object.keys(response.description).length > 0) {
+ message += '': '' + JSON.stringify(response.description);
+ }
+ else {
+ message += ''. '' + response;
+ }
+ throw message + ''. Check debug log for more information.'';
+ }
+
+ return {
+ status: request.getStatus(),
+ response: response
+ };
+ },
+
+ getSchema: function() {
+ var result = Zendesk.request(''get'', ''ticket_fields.json'');
+
+ return result.response;
+ },
+
+ createIssue: function(data, fields) {
+ var result = Zendesk.request(''post'', ''tickets.json'', Zendesk.addCustomFields(data, fields));
+
+ if (typeof result.response !== ''object'' || typeof result.response.ticket.id === ''undefined''
+ || result.status != 201) {
+ throw ''Cannot create Zendesk issue. Check debug log for more information.'';
+ }
+
+ return result.response.ticket.id;
+ },
+
+ updateIssue: function(data, fields) {
+ Zendesk.request(''put'', ''tickets/'' + Zendesk.params.issue_key + ''.json'', Zendesk.addCustomFields(data, fields));
+ }
+};
+
+try {
+ var params = JSON.parse(value),
+ fields = {},
+ zendesk = {},
+ update = {},
+ data = {},
+ result = {tags: {}},
+ required_params = [
+ ''alert_subject'',
+ ''alert_message'',
+ ''event_id'',
+ ''event_source'',
+ ''event_value'',
+ ''event_update_status''
+ ],
+ severities = [
+ {name: ''not_classified'', color: ''#97AAB3''},
+ {name: ''information'', color: ''#7499FF''},
+ {name: ''warning'', color: ''#FFC859''},
+ {name: ''average'', color: ''#FFA059''},
+ {name: ''high'', color: ''#E97659''},
+ {name: ''disaster'', color: ''#E45959''},
+ {name: ''resolved'', color: ''#009900''},
+ {name: ''default'', color: ''#000000''}
+ ],
+ priority;
+
+ Object.keys(params)
+ .forEach(function (key) {
+ if (key.startsWith(''zendesk_'')) {
+ zendesk[key.substring(8)] = params[key];
+ }
+ else if (key.startsWith(''customfield_'')) {
+ fields[key.substring(12)] = params[key];
+ }
+ else if (key.startsWith(''event_update_'')) {
+ update[key.substring(13)] = params[key];
+ }
+ else if (required_params.indexOf(key) !== -1 && params[key].trim() === '''') {
+ throw ''Parameter '' + key + '' cannot be empty.'';
+ }
+ });
+
+ // Possible values: question, incident, problems, task
+ if ([''question'', ''incident'', ''problem'', ''task''].indexOf(params.zendesk_type) === -1) {
+ throw ''Incorrect "zendesk_type" parameter given: '' + params.zendesk_type +
+ ''\\nMust be one of question, incident, problem, task.'';
+ }
+
+ // Possible values: 0 - Trigger, 1 - Discovery, 2 - Autoregistration, 3 - Internal.
+ if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
+ throw ''Incorrect "event_source" parameter given: '' + params.event_source + ''\\nMust be 0-3.'';
+ }
+
+ // Check {EVENT.VALUE} for trigger-based and internal events.
+ // Possible values: 1 for problem, 0 for recovering
+ 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.
+ // Possible values: 0 - Webhook was called because of problem/recovery event, 1 - Update operation.
+ if (params.event_source === ''0'' && params.event_update_status !== ''0'' && params.event_update_status !== ''1'') {
+ throw ''Incorrect "event_update_status" parameter given: '' + params.event_update_status + ''\\nMust be 0 or 1.'';
+ }
+
+ if (params.event_source !== ''0'' && params.event_value === ''0'') {
+ throw ''Recovery operations are supported only for trigger-based actions.'';
+ }
+
+ // Zendesk_issue_key must be a positive integer if an update action is being performed.
+ if (params.event_source === ''0'' && ((params.event_value === ''1'' && params.event_update_status === ''1'')
+ || (params.event_value === ''0'' && (params.event_update_status === ''0'' || params.event_update_status === ''1'')))
+ && (isNaN(parseInt(params.zendesk_issue_key)) || parseInt(params.zendesk_issue_key) < 1 )) {
+ throw ''Incorrect "zendesk_issue_key" parameter given: '' + params.zendesk_issue_key +
+ ''\\nMust be positive integer.'';
+ }
+
+ if ([0, 1, 2, 3, 4, 5].indexOf(parseInt(params.event_nseverity)) === -1) {
+ params.event_nseverity = ''7'';
+ }
+
+ if (params.event_value === ''0'') {
+ params.event_nseverity = ''6'';
+ }
+
+ priority = params[''severity_'' + severities[params.event_nseverity].name] || severities[7].name;
+
+ Zendesk.setParams(zendesk);
+ Zendesk.HTTPProxy = params.HTTPProxy;
+
+ // Create issue for non trigger-based events.
+ if (params.event_source !== ''0'' && params.event_value !== ''0'') {
+ data = {
+ ticket: {
+ external_id: params.event_id,
+ type: Zendesk.params.type,
+ status: ''new'',
+ subject: params.alert_subject,
+ comment: {
+ body: params.alert_message,
+ public: ''false''
+ },
+ priority: priority,
+ tags: params.event_tags
+ }
+ };
+
+ Zendesk.createIssue(data, fields);
+ }
+ // Create issue for trigger-based events.
+ else if (params.event_value === ''1'' && update.status === ''0'') {
+ data = {
+ ticket: {
+ external_id: params.event_id,
+ type: Zendesk.params.type,
+ status: ''new'',
+ subject: params.alert_subject,
+ comment: {
+ body: params.zbxurl + (params.zbxurl.endsWith(''/'') ? '''' : ''/'') + ''tr_events.php?triggerid='' +
+ params.trigger_id + ''&eventid='' + params.event_id + ''\\n'' + params.alert_message,
+ public: ''false''
+ },
+ priority: priority,
+ tags: params.event_tags
+ }
+ };
+ var key = Zendesk.createIssue(data, fields);
+
+ result.tags.__zbx_zdk_issuekey = key;
+ result.tags.__zbx_zdk_issuelink = params.zendesk_url +
+ (params.zendesk_url.endsWith(''/'') ? '''' : ''/'') + ''agent/tickets/'' + key;
+ }
+ // Update created issue for trigger-based event.
+ else {
+ data = {
+ ticket: {
+ type: Zendesk.params.type,
+ subject: params.alert_subject,
+ comment: {
+ body: params.alert_message,
+ public: ''false''
+ }
+ }
+ };
+
+ Zendesk.updateIssue(data, fields);
+ }
+
+ return JSON.stringify(result);
+}
+catch (error) {
+ Zabbix.log(3, ''[Zendesk Webhook] ERROR: '' + error);
+ throw ''Sending failed: '' + error;
+}','30s','1','1','{EVENT.TAGS.__zbx_zdk_issuelink}','Zendesk: {EVENT.TAGS.__zbx_zdk_issuekey}','','0');
+INSERT INTO media_type_param (mediatype_paramid,mediatypeid,name,value,sortorder) VALUES ('646','70','endpoint','','0'),
+('647','70','flash','false','0'),
+('648','70','password','','0'),
+('649','70','ring','false','0'),
+('650','70','send_to','{ALERT.SENDTO}','0'),
+('651','70','telauto','true','0'),
+('652','70','text','{ALERT.MESSAGE}','0'),
+('653','70','username','','0'),
+('654','71','alert_message','{ALERT.MESSAGE}','0'),
+('655','71','alert_subject','{ALERT.SUBJECT}','0'),
+('656','71','discord_endpoint','{ALERT.SENDTO}','0'),
+('657','71','event_id','{EVENT.ID}','0'),
+('658','71','event_nseverity','{EVENT.NSEVERITY}','0'),
+('659','71','event_severity','{EVENT.SEVERITY}','0'),
+('660','71','event_source','{EVENT.SOURCE}','0'),
+('661','71','event_update_nseverity','{EVENT.UPDATE.NSEVERITY}','0'),
+('662','71','event_update_severity','{EVENT.UPDATE.SEVERITY}','0'),
+('663','71','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('664','71','event_value','{EVENT.VALUE}','0'),
+('665','71','trigger_id','{TRIGGER.ID}','0'),
+('666','71','user_agent','ZabbixServer (zabbix.com, 8.0)','0'),
+('667','71','zabbix_url','{$ZABBIX.URL}','0'),
+('668','72','acknowledged','{EVENT.ACK.STATUS}','0'),
+('669','72','endpoint','/endpoint','0'),
+('670','72','event_date','{EVENT.DATE}','0'),
+('671','72','event_id','{EVENT.ID}','0'),
+('672','72','event_name','{EVENT.NAME}','0'),
+('673','72','event_nseverity','{EVENT.NSEVERITY}','0'),
+('674','72','event_object','{EVENT.OBJECT}','0'),
+('675','72','event_severity','{EVENT.SEVERITY}','0'),
+('676','72','event_source','{EVENT.SOURCE}','0'),
+('677','72','event_tags','{EVENT.TAGSJSON}','0'),
+('678','72','event_time','{EVENT.TIME}','0'),
+('679','72','event_value','{EVENT.VALUE}','0'),
+('680','72','host_groups','{TRIGGER.HOSTGROUP.NAME}','0'),
+('681','72','host_host','{HOST.HOST}','0'),
+('682','72','host_id','{HOST.ID}','0'),
+('683','72','host_ip','{HOST.IP}','0'),
+('684','72','host_port','{HOST.PORT}','0'),
+('685','72','HTTPProxy','','0'),
+('686','72','monitoring_source','Zabbix sever','0'),
+('687','72','operation_data','{EVENT.OPDATA}','0'),
+('688','72','send_to','{ALERT.SENDTO}','0'),
+('689','72','subject','{ALERT.SUBJECT}','0'),
+('690','72','trigger_description','{TRIGGER.DESCRIPTION}','0'),
+('691','72','trigger_id','{TRIGGER.ID}','0'),
+('692','72','trigger_name','{TRIGGER.NAME}','0'),
+('693','73','event_source','{EVENT.SOURCE}','0'),
+('694','73','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('695','73','event_value','{EVENT.VALUE}','0'),
+('696','73','express_message','{ALERT.MESSAGE}','0'),
+('697','73','express_send_to','{ALERT.SENDTO}','0'),
+('698','73','express_tags','{EVENT.TAGSJSON}','0'),
+('699','73','express_token','','0'),
+('700','73','express_url','','0'),
+('701','74','alert_message','{ALERT.MESSAGE}','0'),
+('702','74','alert_subject','{ALERT.SUBJECT}','0'),
+('703','74','event_id','{EVENT.ID}','0'),
+('704','74','event_nseverity','{EVENT.NSEVERITY}','0'),
+('705','74','event_severity','{EVENT.SEVERITY}','0'),
+('706','74','event_source','{EVENT.SOURCE}','0'),
+('707','74','event_update_nseverity','{EVENT.UPDATE.NSEVERITY}','0'),
+('708','74','event_update_severity','{EVENT.UPDATE.SEVERITY}','0'),
+('709','74','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('710','74','event_value','{EVENT.VALUE}','0'),
+('711','74','github_api_version','2022-11-28','0'),
+('712','74','github_issue_number','{EVENT.TAGS.__zbx_github_issue_number}','0'),
+('713','74','github_repo','{ALERT.SENDTO}','0'),
+('714','74','github_token','','0'),
+('715','74','github_url','https://api.github.com','0'),
+('716','74','github_user_agent','Zabbix/8.0','0'),
+('717','74','github_zabbix_event_priority_label_prefix','Zabbix Event Priority:','0'),
+('718','74','github_zabbix_event_source_label_prefix','Zabbix Event Source:','0'),
+('719','74','github_zabbix_event_status_label_prefix','Zabbix Event Status:','0'),
+('720','74','github_zabbix_generic_label','Zabbix GitHub Webhook','0'),
+('721','74','trigger_id','{TRIGGER.ID}','0'),
+('722','74','zabbix_url','{$ZABBIX.URL}','0'),
+('723','75','alert_message','{ALERT.MESSAGE}','0'),
+('724','75','alert_subject','{ALERT.SUBJECT}','0'),
+('725','75','event_id','{EVENT.ID}','0'),
+('726','75','event_nseverity','{EVENT.NSEVERITY}','0'),
+('727','75','event_severity','{EVENT.SEVERITY}','0'),
+('728','75','event_source','{EVENT.SOURCE}','0'),
+('729','75','event_update_nseverity','{EVENT.UPDATE.NSEVERITY}','0'),
+('730','75','event_update_severity','{EVENT.UPDATE.SEVERITY}','0'),
+('731','75','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('732','75','event_value','{EVENT.VALUE}','0'),
+('733','75','glpi_problem_id','{EVENT.TAGS.__zbx_glpi_problem_id}','0'),
+('735','75','glpi_url','','0'),
+('736','75','trigger_id','{TRIGGER.ID}','0'),
+('737','75','zabbix_url','{$ZABBIX.URL}','0'),
+('738','76','.ILERT.ALERT.SOURCE.KEY','{ALERT.SENDTO}','0'),
+('739','76','.ILERT.INCIDENT.SUMMARY','','0'),
+('740','76','ALERT.MESSAGE','{ALERT.MESSAGE}','0'),
+('741','76','ALERT.SUBJECT','{ALERT.SUBJECT}','0'),
+('742','76','EVENT.ACK.STATUS','{EVENT.ACK.STATUS}','0'),
+('743','76','EVENT.DATE','{EVENT.DATE}','0'),
+('744','76','EVENT.ID','{EVENT.ID}','0'),
+('745','76','EVENT.NAME','{EVENT.NAME}','0'),
+('746','76','EVENT.NSEVERITY','{EVENT.NSEVERITY}','0'),
+('747','76','EVENT.OPDATA','{EVENT.OPDATA}','0'),
+('748','76','EVENT.RECOVERY.DATE','{EVENT.RECOVERY.DATE}','0'),
+('749','76','EVENT.RECOVERY.TIME','{EVENT.RECOVERY.TIME}','0'),
+('750','76','EVENT.RECOVERY.VALUE','{EVENT.RECOVERY.VALUE}','0'),
+('751','76','EVENT.SEVERITY','{EVENT.SEVERITY}','0'),
+('752','76','EVENT.TAGS','{EVENT.TAGS}','0'),
+('753','76','EVENT.TIME','{EVENT.TIME}','0'),
+('754','76','EVENT.UPDATE.ACTION','{EVENT.UPDATE.ACTION}','0'),
+('755','76','EVENT.UPDATE.DATE','{EVENT.UPDATE.DATE}','0'),
+('756','76','EVENT.UPDATE.MESSAGE','{EVENT.UPDATE.MESSAGE}','0'),
+('757','76','EVENT.UPDATE.STATUS','{EVENT.UPDATE.STATUS}','0'),
+('758','76','EVENT.UPDATE.TIME','{EVENT.UPDATE.TIME}','0'),
+('759','76','EVENT.VALUE','{EVENT.VALUE}','0'),
+('760','76','HOST.HOST','{HOST.HOST}','0'),
+('761','76','HOST.IP','{HOST.IP}','0'),
+('762','76','HOST.NAME','{HOST.NAME}','0'),
+('763','76','ITEM.ID1','{ITEM.ID1}','0'),
+('764','76','ITEM.ID2','{ITEM.ID2}','0'),
+('765','76','ITEM.ID3','{ITEM.ID3}','0'),
+('766','76','ITEM.ID4','{ITEM.ID4}','0'),
+('767','76','ITEM.ID5','{ITEM.ID5}','0'),
+('768','76','ITEM.NAME1','{ITEM.NAME1}','0'),
+('769','76','ITEM.NAME2','{ITEM.NAME2}','0'),
+('770','76','ITEM.NAME3','{ITEM.NAME3}','0'),
+('771','76','ITEM.NAME4','{ITEM.NAME4}','0'),
+('772','76','ITEM.NAME5','{ITEM.NAME5}','0'),
+('773','76','TRIGGER.DESCRIPTION','{TRIGGER.DESCRIPTION}','0'),
+('774','76','TRIGGER.ID','{TRIGGER.ID}','0'),
+('775','76','TRIGGER.NAME','{TRIGGER.NAME}','0'),
+('776','76','TRIGGER.SEVERITY','{TRIGGER.SEVERITY}','0'),
+('777','76','TRIGGER.STATUS','{TRIGGER.STATUS}','0'),
+('778','76','TRIGGER.URL','{TRIGGER.URL}','0'),
+('779','76','TRIGGER.VALUE','{TRIGGER.VALUE}','0'),
+('780','76','USER.FULLNAME','{USER.FULLNAME}','0'),
+('781','76','ZABBIX.URL','{$ZABBIX.URL}','0'),
+('782','77','alert_message','{ALERT.MESSAGE}','0'),
+('783','77','alert_subject','{ALERT.SUBJECT}','0'),
+('784','77','event_recovery_value','{EVENT.RECOVERY.VALUE}','0'),
+('785','77','event_source','{EVENT.SOURCE}','0'),
+('786','77','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('787','77','event_value','{EVENT.VALUE}','0'),
+('788','77','itop_api_version','1.3','0'),
+('789','77','itop_class','UserRequest','0'),
+('790','77','itop_comment','Created by Zabbix action {ACTION.NAME}','0'),
+('791','77','itop_id','{EVENT.TAGS.__zbx_itop_id}','0'),
+('792','77','itop_log','private_log','0'),
+('793','77','itop_organization_id','','0'),
+('794','77','itop_password','','0'),
+('795','77','itop_url','','0'),
+('796','77','itop_user','','0'),
+('797','78','alert_message','{ALERT.MESSAGE}','0'),
+('798','78','alert_subject','{ALERT.SUBJECT}','0'),
+('799','78','event_id','{EVENT.ID}','0'),
+('800','78','event_nseverity','{EVENT.NSEVERITY}','0'),
+('801','78','event_recovery_value','{EVENT.RECOVERY.VALUE}','0'),
+('802','78','event_severity','{EVENT.SEVERITY}','0'),
+('803','78','event_source','{EVENT.SOURCE}','0'),
+('804','78','event_tags_json','{EVENT.TAGSJSON}','0'),
+('805','78','event_update_action','{EVENT.UPDATE.ACTION}','0'),
+('806','78','event_update_message','{EVENT.UPDATE.MESSAGE}','0'),
+('807','78','event_update_nseverity','{EVENT.UPDATE.NSEVERITY}','0'),
+('808','78','event_update_severity','{EVENT.UPDATE.SEVERITY}','0'),
+('809','78','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('810','78','event_update_user','{USER.FULLNAME}','0'),
+('811','78','event_value','{EVENT.VALUE}','0'),
+('812','78','jira_issue_type','','0'),
+('813','78','jira_password','','0'),
+('814','78','jira_priority_autoregistration','Low','0'),
+('815','78','jira_priority_discovery','Low','0'),
+('816','78','jira_priority_internal','Low','0'),
+('817','78','jira_project_key','','0'),
+('818','78','jira_url','','0'),
+('819','78','jira_user','','0'),
+('820','78','severity_average','Medium','0'),
+('821','78','severity_disaster','Highest','0'),
+('822','78','severity_high','High','0'),
+('823','78','severity_information','Lowest','0'),
+('824','78','severity_not_classified','Lowest','0'),
+('825','78','severity_warning','Low','0'),
+('826','78','trigger_description','{TRIGGER.DESCRIPTION}','0'),
+('827','78','trigger_id','{TRIGGER.ID}','0'),
+('828','78','zabbix_url','{$ZABBIX.URL}','0'),
+('829','79','alert_message','{ALERT.MESSAGE}','0'),
+('830','79','alert_subject','{ALERT.SUBJECT}','0'),
+('831','79','event_id','{EVENT.ID}','0'),
+('832','79','event_nseverity','{EVENT.NSEVERITY}','0'),
+('833','79','event_recovery_value','{EVENT.RECOVERY.VALUE}','0'),
+('834','79','event_severity','{EVENT.SEVERITY}','0'),
+('835','79','event_source','{EVENT.SOURCE}','0'),
+('836','79','event_tags_json','{EVENT.TAGSJSON}','0'),
+('837','79','event_update_nseverity','{EVENT.UPDATE.NSEVERITY}','0'),
+('838','79','event_update_severity','{EVENT.UPDATE.SEVERITY}','0'),
+('839','79','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('840','79','event_value','{EVENT.VALUE}','0'),
+('841','79','issue_comments_public','false','0'),
+('842','79','jira_password','','0'),
+('843','79','jira_priority_autoregistration','Low','0'),
+('844','79','jira_priority_discovery','Low','0'),
+('845','79','jira_priority_internal','Low','0'),
+('846','79','jira_request_type_id','','0'),
+('847','79','jira_servicedesk_id','','0'),
+('848','79','jira_url','','0'),
+('849','79','jira_user','','0'),
+('850','79','severity_average','Medium','0'),
+('851','79','severity_disaster','Highest','0'),
+('852','79','severity_high','High','0'),
+('853','79','severity_information','Lowest','0'),
+('854','79','severity_not_classified','Lowest','0'),
+('855','79','severity_warning','Low','0'),
+('856','79','trigger_id','{TRIGGER.ID}','0'),
+('857','79','zabbix_url','{$ZABBIX.URL}','0'),
+('858','80','alert_message','{ALERT.MESSAGE}','0'),
+('859','80','alert_subject','{ALERT.SUBJECT}','0'),
+('860','80','bot_token','','0'),
+('861','80','event_id','{EVENT.ID}','0'),
+('862','80','event_nseverity','{EVENT.NSEVERITY}','0'),
+('863','80','event_source','{EVENT.SOURCE}','0'),
+('864','80','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('865','80','event_value','{EVENT.VALUE}','0'),
+('866','80','send_to','{ALERT.SENDTO}','0'),
+('867','80','trigger_description','{TRIGGER.DESCRIPTION}','0'),
+('868','80','trigger_id','{TRIGGER.ID}','0'),
+('869','80','zabbix_url','{$ZABBIX.URL}','0'),
+('870','81','event_nseverity','{EVENT.NSEVERITY}','0'),
+('871','81','event_recovery_value','{EVENT.RECOVERY.VALUE}','0'),
+('872','81','event_source','{EVENT.SOURCE}','0'),
+('873','81','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('874','81','event_value','{EVENT.VALUE}','0'),
+('875','81','field_ref:requester','','0'),
+('876','81','field_string:description','{ALERT.MESSAGE}','0'),
+('877','81','field_string:subject','{ALERT.SUBJECT}','0'),
+('878','81','priority_average','Normal','0'),
+('879','81','priority_default','Normal','0'),
+('880','81','priority_disaster','High','0'),
+('881','81','priority_high','High','0'),
+('882','81','priority_information','Low','0'),
+('883','81','priority_not_classified','Low','0'),
+('884','81','priority_warning','Medium','0'),
+('885','81','sd_on_demand_client_id','','0'),
+('886','81','sd_on_demand_client_secret','','0'),
+('887','81','sd_on_demand_refresh_token','','0'),
+('888','81','sd_on_demand_url_auth','','0'),
+('889','81','sd_on_premise','true','0'),
+('890','81','sd_on_premise_auth_token','','0'),
+('891','81','sd_request_id','{EVENT.TAGS.__zbx_sd_request_id}','0'),
+('892','81','sd_url','','0'),
+('893','81','trigger_description','{TRIGGER.DESCRIPTION}','0'),
+('894','82','alert_message','{ALERT.MESSAGE}','0'),
+('895','82','alert_sendto','{ALERT.SENDTO}','0'),
+('896','82','alert_subject','{ALERT.SUBJECT}','0'),
+('897','82','event_id','{EVENT.ID}','0'),
+('898','82','event_nseverity','{EVENT.NSEVERITY}','0'),
+('899','82','event_recovery_value','{EVENT.RECOVERY.VALUE}','0'),
+('900','82','event_source','{EVENT.SOURCE}','0'),
+('901','82','event_tagsjson','{EVENT.TAGSJSON}','0'),
+('902','82','event_update_action','{EVENT.UPDATE.ACTION}','0'),
+('903','82','event_update_message','{EVENT.UPDATE.MESSAGE}','0'),
+('904','82','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('905','82','event_value','{EVENT.VALUE}','0'),
+('906','82','mantisbt_category','[All Projects] General','0'),
+('907','82','mantisbt_issue_number','{EVENT.TAGS.__zbx_mantisbt_issue_number}','0'),
+('908','82','mantisbt_token','','0'),
+('909','82','mantisbt_url','','0'),
+('910','82','mantisbt_use_zabbix_tags','true','0'),
+('911','82','trigger_id','{TRIGGER.ID}','0'),
+('912','82','zabbix_url','{$ZABBIX.URL}','0'),
+('913','83','alert_message','{ALERT.MESSAGE}','0'),
+('914','83','alert_subject','{ALERT.SUBJECT}','0'),
+('915','83','bot_token','','0'),
+('916','83','discovery_host_dns','{DISCOVERY.DEVICE.DNS}','0'),
+('917','83','discovery_host_ip','{DISCOVERY.DEVICE.IPADDRESS}','0'),
+('918','83','event_date','{EVENT.DATE}','0'),
+('919','83','event_id','{EVENT.ID}','0'),
+('920','83','event_nseverity','{EVENT.NSEVERITY}','0'),
+('921','83','event_opdata','{EVENT.OPDATA}','0'),
+('922','83','event_recovery_date','{EVENT.RECOVERY.DATE}','0'),
+('923','83','event_recovery_time','{EVENT.RECOVERY.TIME}','0'),
+('924','83','event_severity','{EVENT.SEVERITY}','0'),
+('925','83','event_source','{EVENT.SOURCE}','0'),
+('926','83','event_tags','{EVENT.TAGS}','0'),
+('927','83','event_time','{EVENT.TIME}','0'),
+('928','83','event_update_date','{EVENT.UPDATE.DATE}','0'),
+('929','83','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('930','83','event_update_time','{EVENT.UPDATE.TIME}','0'),
+('931','83','event_value','{EVENT.VALUE}','0'),
+('932','83','host_ip','{HOST.IP}','0'),
+('933','83','host_name','{HOST.HOST}','0'),
+('934','83','mattermost_url','','0'),
+('935','83','send_mode','alarm','0'),
+('936','83','send_to','{ALERT.SENDTO}','0'),
+('937','83','trigger_description','{TRIGGER.DESCRIPTION}','0'),
+('938','83','trigger_id','{TRIGGER.ID}','0'),
+('939','83','zabbix_url','{$ZABBIX.URL}','0'),
+('940','84','alert_message','{ALERT.MESSAGE}','0'),
+('941','84','alert_subject','{ALERT.SUBJECT}','0'),
+('942','84','event_date','{EVENT.DATE}','0'),
+('943','84','event_id','{EVENT.ID}','0'),
+('944','84','event_nseverity','{EVENT.NSEVERITY}','0'),
+('945','84','event_opdata','{EVENT.OPDATA}','0'),
+('946','84','event_recovery_date','{EVENT.RECOVERY.DATE}','0'),
+('947','84','event_recovery_time','{EVENT.RECOVERY.TIME}','0'),
+('948','84','event_severity','{EVENT.SEVERITY}','0'),
+('949','84','event_source','{EVENT.SOURCE}','0'),
+('950','84','event_status','{EVENT.STATUS}','0'),
+('951','84','event_tags','{EVENT.TAGS}','0'),
+('952','84','event_time','{EVENT.TIME}','0'),
+('953','84','event_update_action','{EVENT.UPDATE.ACTION}','0'),
+('954','84','event_update_date','{EVENT.UPDATE.DATE}','0'),
+('955','84','event_update_message','{EVENT.UPDATE.MESSAGE}','0'),
+('956','84','event_update_nseverity','{EVENT.UPDATE.NSEVERITY}','0'),
+('957','84','event_update_severity','{EVENT.UPDATE.SEVERITY}','0'),
+('958','84','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('959','84','event_update_time','{EVENT.UPDATE.TIME}','0'),
+('960','84','event_update_user','{USER.FULLNAME}','0'),
+('961','84','event_value','{EVENT.VALUE}','0'),
+('962','84','host_ip','{HOST.IP}','0'),
+('963','84','host_name','{HOST.NAME}','0'),
+('964','84','teams_endpoint','','0'),
+('965','84','trigger_description','{TRIGGER.DESCRIPTION}','0'),
+('966','84','trigger_id','{TRIGGER.ID}','0'),
+('967','84','use_default_message','false','0'),
+('968','84','zabbix_url','{$ZABBIX.URL}','0'),
+('969','85','alert_message','{ALERT.MESSAGE}','0'),
+('970','85','alert_subject','{ALERT.SUBJECT}','0'),
+('971','85','event_id','{EVENT.ID}','0'),
+('972','85','event_nseverity','{EVENT.NSEVERITY}','0'),
+('973','85','event_severity','{EVENT.SEVERITY}','0'),
+('974','85','event_source','{EVENT.SOURCE}','0'),
+('975','85','event_update_nseverity','{EVENT.UPDATE.NSEVERITY}','0'),
+('976','85','event_update_severity','{EVENT.UPDATE.SEVERITY}','0'),
+('977','85','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('978','85','event_value','{EVENT.VALUE}','0'),
+('979','85','teams_endpoint','','0'),
+('980','85','trigger_id','{TRIGGER.ID}','0'),
+('981','85','zabbix_url','{$ZABBIX.URL}','0'),
+('982','86','alert_message','{ALERT.MESSAGE}','0'),
+('983','86','alert_subject','{ALERT.SUBJECT}','0'),
+('984','86','event_id','{EVENT.ID}','0'),
+('985','86','event_nseverity','{EVENT.NSEVERITY}','0'),
+('986','86','event_source','{EVENT.SOURCE}','0'),
+('987','86','event_tags_json','{EVENT.TAGSJSON}','0'),
+('988','86','event_update_action','{EVENT.UPDATE.ACTION}','0'),
+('989','86','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('990','86','event_value','{EVENT.VALUE}','0'),
+('991','86','opsgenie_api','','0'),
+('992','86','opsgenie_tags','','0'),
+('993','86','opsgenie_teams','','0'),
+('994','86','opsgenie_token','','0'),
+('995','86','opsgenie_web','','0'),
+('996','86','severity_average','P3','0'),
+('997','86','severity_default','P5','0'),
+('998','86','severity_disaster','P1','0'),
+('999','86','severity_high','P2','0'),
+('1000','86','severity_information','P5','0'),
+('1001','86','severity_not_classified','P5','0'),
+('1002','86','severity_warning','P4','0'),
+('1003','86','status_counter','25','0'),
+('1004','86','trigger_id','{TRIGGER.ID}','0'),
+('1005','86','zbxurl','{$ZABBIX.URL}','0'),
+('1006','86','zbxuser','{USER.FULLNAME}','0'),
+('1007','87','alert_message','{ALERT.MESSAGE}','0'),
+('1008','87','alert_subject','{ALERT.SUBJECT}','0'),
+('1009','87','event_id','{EVENT.ID}','0'),
+('1010','87','event_nseverity','{EVENT.NSEVERITY}','0'),
+('1011','87','event_severity','{EVENT.SEVERITY}','0'),
+('1012','87','event_source','{EVENT.SOURCE}','0'),
+('1013','87','event_update_nseverity','{EVENT.UPDATE.NSEVERITY}','0'),
+('1014','87','event_update_severity','{EVENT.UPDATE.SEVERITY}','0'),
+('1015','87','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('1016','87','event_value','{EVENT.VALUE}','0'),
+('1017','87','otrs_auth_password','','0'),
+('1018','87','otrs_auth_user','','0'),
+('1019','87','otrs_closed_state_id','0','0'),
+('1020','87','otrs_customer','','0'),
+('1021','87','otrs_default_priority_id','3','0'),
+('1022','87','otrs_queue','','0'),
+('1023','87','otrs_ticket_id','{EVENT.TAGS.__zbx_otrs_ticket_id}','0'),
+('1024','87','otrs_ticket_state','new','0'),
+('1025','87','otrs_time_unit','0','0'),
+('1026','87','otrs_url','','0'),
+('1027','87','trigger_id','{TRIGGER.ID}','0'),
+('1028','87','zabbix_url','{$ZABBIX.URL}','0'),
+('1029','88','alert_message','{ALERT.MESSAGE}','0'),
+('1030','88','alert_subject','{ALERT.SUBJECT}','0'),
+('1031','88','api_token','{ALERT.SENDTO}','0'),
+('1032','88','event_ack','{EVENT.ACK.STATUS}','0'),
+('1033','88','event_id','{EVENT.ID}','0'),
+('1034','88','event_nseverity','{EVENT.NSEVERITY}','0'),
+('1035','88','event_severity','{EVENT.SEVERITY}','0'),
+('1036','88','event_source','{EVENT.SOURCE}','0'),
+('1037','88','event_update_nseverity','{EVENT.UPDATE.NSEVERITY}','0'),
+('1038','88','event_update_severity','{EVENT.UPDATE.SEVERITY}','0'),
+('1039','88','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('1040','88','event_value','{EVENT.VALUE}','0'),
+('1041','88','host_ip','{HOST.IP}','0'),
+('1042','88','host_name','{HOST.NAME}','0'),
+('1043','88','trigger_id','{TRIGGER.ID}','0'),
+('1044','88','zabbix_url','{$ZABBIX.URL}','0'),
+('1045','89','endpoint','https://api.pushover.net/1/messages.json','0'),
+('1046','89','eventid','{EVENT.ID}','0'),
+('1047','89','event_nseverity','{EVENT.NSEVERITY}','0'),
+('1048','89','event_source','{EVENT.SOURCE}','0'),
+('1049','89','event_value','{EVENT.VALUE}','0'),
+('1050','89','expire','1200','0'),
+('1051','89','message','{ALERT.MESSAGE}','0'),
+('1052','89','priority_average','0','0'),
+('1053','89','priority_default','0','0'),
+('1054','89','priority_disaster','0','0'),
+('1055','89','priority_high','0','0'),
+('1056','89','priority_information','0','0'),
+('1057','89','priority_not_classified','0','0'),
+('1058','89','priority_warning','0','0'),
+('1059','89','retry','60','0'),
+('1060','89','title','{ALERT.SUBJECT}','0'),
+('1061','89','token','','0'),
+('1062','89','triggerid','{TRIGGER.ID}','0'),
+('1063','89','url','{$ZABBIX.URL}','0'),
+('1064','89','url_title','Zabbix','0'),
+('1065','89','user','{ALERT.SENDTO}','0'),
+('1066','90','alert_message','{ALERT.MESSAGE}','0'),
+('1067','90','alert_subject','{ALERT.SUBJECT}','0'),
+('1068','90','event_id','{EVENT.ID}','0'),
+('1069','90','event_nseverity','{EVENT.NSEVERITY}','0'),
+('1070','90','event_source','{EVENT.SOURCE}','0'),
+('1071','90','event_update_message','{EVENT.UPDATE.MESSAGE}','0'),
+('1072','90','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('1073','90','event_value','{EVENT.VALUE}','0'),
+('1074','90','redmine_access_key','','0'),
+('1075','90','redmine_issue_key','{EVENT.TAGS.__zbx_redmine_issue_id}','0'),
+('1076','90','redmine_project','','0'),
+('1077','90','redmine_tracker_id','','0'),
+('1078','90','redmine_url','','0'),
+('1079','90','trigger_id','{TRIGGER.ID}','0'),
+('1080','90','zabbix_url','{$ZABBIX.URL}','0'),
+('1081','91','alert_message','{ALERT.MESSAGE}','0'),
+('1082','91','alert_subject','{ALERT.SUBJECT}','0'),
+('1083','91','event_nseverity','{EVENT.NSEVERITY}','0'),
+('1084','91','event_source','{EVENT.SOURCE}','0'),
+('1085','91','event_update_action','{EVENT.UPDATE.ACTION}','0'),
+('1086','91','event_update_message','{EVENT.UPDATE.MESSAGE}','0'),
+('1087','91','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('1088','91','event_update_user','{USER.FULLNAME}','0'),
+('1089','91','event_value','{EVENT.VALUE}','0'),
+('1090','91','field_1_full:Host','{HOST.NAME} [{HOST.IP}]','0'),
+('1091','91','field_2_short:Severity','{EVENT.SEVERITY}','0'),
+('1092','91','field_3_short:Event time','{EVENT.DATE} {EVENT.TIME}','0'),
+('1093','91','field_3_short_r:Recovery time','{EVENT.RECOVERY.DATE} {EVENT.RECOVERY.TIME}','0'),
+('1094','91','field_4_short_r:Event duration','{EVENT.DURATION}','0'),
+('1095','91','field_5_short:Operational data','{EVENT.OPDATA}','0'),
+('1096','91','field_999_full_p:Trigger description','{TRIGGER.DESCRIPTION}','0'),
+('1097','91','rc_api_url','api/v1/','0'),
+('1098','91','rc_msg_id','{EVENT.TAGS.__zbx_rc_id}','0'),
+('1099','91','rc_room_id','{EVENT.TAGS.__zbx_rc_rid}','0'),
+('1100','91','rc_send_to','{ALERT.SENDTO}','0'),
+('1101','91','rc_title_link','{$ZABBIX.URL}/tr_events.php?triggerid={TRIGGER.ID}&eventid={EVENT.ID}','0'),
+('1102','91','rc_url','','0'),
+('1103','91','rc_user_id','','0'),
+('1104','91','rc_user_token','','0'),
+('1105','91','use_default_message','false','0'),
+('1106','92','alert_message','{ALERT.MESSAGE}','0'),
+('1107','92','alert_subject','{ALERT.SUBJECT}','0'),
+('1108','92','event_nseverity','{EVENT.NSEVERITY}','0'),
+('1109','92','event_recovery_value','{EVENT.RECOVERY.VALUE}','0'),
+('1110','92','event_source','{EVENT.SOURCE}','0'),
+('1111','92','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('1112','92','event_value','{EVENT.VALUE}','0'),
+('1113','92','servicenow_password','','0'),
+('1114','92','servicenow_sys_id','{EVENT.TAGS.__zbx_servicenow_sys_id}','0'),
+('1115','92','servicenow_url','{ALERT.SENDTO}','0'),
+('1116','92','servicenow_user','','0'),
+('1117','92','urgency_for_average','2','0'),
+('1118','92','urgency_for_disaster','1','0'),
+('1119','92','urgency_for_high','2','0'),
+('1120','92','urgency_for_information','3','0'),
+('1121','92','urgency_for_not_classified','3','0'),
+('1122','92','urgency_for_warning','3','0'),
+('1123','93','Event_Ack_Status','{EVENT.ACK.STATUS}','0'),
+('1124','93','Event_Date_Time','{EVENT.DATE} {EVENT.TIME}','0'),
+('1125','93','Event_ID','{EVENT.ID}','0'),
+('1126','93','Event_Update_Action','{EVENT.UPDATE.ACTION}','0'),
+('1127','93','Event_Update_Status','{EVENT.UPDATE.STATUS}','0'),
+('1128','93','Hostname','{HOST.NAME}','0'),
+('1129','93','Host_IP','{HOST.IP}','0'),
+('1130','93','Message','{ALERT.MESSAGE}','0'),
+('1131','93','Severity','{EVENT.SEVERITY}','0'),
+('1132','93','Subject','{ALERT.SUBJECT}','0'),
+('1133','93','teamsecret','{ALERT.SENDTO}','0'),
+('1134','93','Trigger_ID','{TRIGGER.ID}','0'),
+('1135','93','Trigger_Status','{TRIGGER.STATUS}','0'),
+('1136','93','User','{USER.FULLNAME}','0'),
+('1137','93','Zabbix_URL','{$ZABBIX.URL}','0'),
+('1138','94','alert_message','{ALERT.MESSAGE}','0'),
+('1139','94','alert_subject','{ALERT.SUBJECT}','0'),
+('1140','94','bot_token','','0'),
+('1141','94','channel','{ALERT.SENDTO}','0'),
+('1142','94','event_id','{EVENT.ID}','0'),
+('1143','94','event_nseverity','{EVENT.NSEVERITY}','0'),
+('1144','94','event_severity','{EVENT.SEVERITY}','0'),
+('1145','94','event_source','{EVENT.SOURCE}','0'),
+('1146','94','event_tags','{EVENT.TAGSJSON}','0'),
+('1147','94','event_update_action','{EVENT.UPDATE.ACTION}','0'),
+('1148','94','event_update_message','{EVENT.UPDATE.MESSAGE}','0'),
+('1149','94','event_update_nseverity','{EVENT.UPDATE.NSEVERITY}','0'),
+('1150','94','event_update_severity','{EVENT.UPDATE.SEVERITY}','0'),
+('1151','94','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('1152','94','event_value','{EVENT.VALUE}','0'),
+('1153','94','slack_mode','alarm','0'),
+('1154','94','trigger_id','{TRIGGER.ID}','0'),
+('1155','94','zabbix_url','{$ZABBIX.URL}','0'),
+('1156','95','alert_message','{ALERT.MESSAGE}','0'),
+('1157','95','alert_subject','{ALERT.SUBJECT}','0'),
+('1158','95','event_nseverity','{EVENT.NSEVERITY}','0'),
+('1159','95','event_recovery_value','{EVENT.RECOVERY.VALUE}','0'),
+('1160','95','event_source','{EVENT.SOURCE}','0'),
+('1161','95','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('1162','95','event_value','{EVENT.VALUE}','0'),
+('1163','95','priority_average','Medium','0'),
+('1164','95','priority_default','Low','0'),
+('1165','95','priority_disaster','Critical','0'),
+('1166','95','priority_high','High','0'),
+('1167','95','samanage_incident_id','{EVENT.TAGS.__zbx_solarwinds_inc_id}','0'),
+('1168','95','samanage_token','','0'),
+('1169','95','samanage_url','','0'),
+('1170','96','alert_message','{ALERT.MESSAGE}','0'),
+('1171','96','alert_subject','{ALERT.SUBJECT}','0'),
+('1172','96','event_id','{EVENT.ID}','0'),
+('1173','96','event_nseverity','{EVENT.NSEVERITY}','0'),
+('1174','96','event_source','{EVENT.SOURCE}','0'),
+('1175','96','event_update_message','{EVENT.UPDATE.MESSAGE}','0'),
+('1176','96','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('1177','96','event_value','{EVENT.VALUE}','0'),
+('1178','96','sysaid_auth_password','','0'),
+('1179','96','sysaid_auth_user','','0'),
+('1180','96','sysaid_category_level_1','','0'),
+('1181','96','sysaid_category_level_2','','0'),
+('1182','96','sysaid_category_level_3','','0'),
+('1183','96','sysaid_default_priority_id','1','0'),
+('1184','96','sysaid_incident_id','{EVENT.TAGS.__zbx_sysaid_incident_id}','0'),
+('1185','96','sysaid_incident_state','1','0'),
+('1186','96','sysaid_template_id','','0'),
+('1187','96','sysaid_urgency_id','','0'),
+('1188','96','sysaid_url','','0'),
+('1189','96','trigger_id','{TRIGGER.ID}','0'),
+('1190','96','zabbix_url','{$ZABBIX.URL}','0'),
+('1191','97','alert_message','{ALERT.MESSAGE}','0'),
+('1192','97','alert_subject','{ALERT.SUBJECT}','0'),
+('1193','97','api_chat_id','{ALERT.SENDTO}','0'),
+('1194','97','api_parse_mode','','0'),
+('1195','97','api_token','','0'),
+('1196','97','event_nseverity','{EVENT.NSEVERITY}','0'),
+('1197','97','event_severity','{EVENT.SEVERITY}','0'),
+('1198','97','event_source','{EVENT.SOURCE}','0'),
+('1199','97','event_tags','{EVENT.TAGSJSON}','0'),
+('1200','97','event_update_nseverity','{EVENT.UPDATE.NSEVERITY}','0'),
+('1201','97','event_update_severity','{EVENT.UPDATE.SEVERITY}','0'),
+('1202','97','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('1203','97','event_value','{EVENT.VALUE}','0'),
+('1204','98','alert_message','{ALERT.MESSAGE}','0'),
+('1205','98','alert_subject','{ALERT.SUBJECT}','0'),
+('1206','98','event_id','{EVENT.ID}','0'),
+('1207','98','event_nseverity','{EVENT.NSEVERITY}','0'),
+('1208','98','event_source','{EVENT.SOURCE}','0'),
+('1209','98','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('1210','98','event_value','{EVENT.VALUE}','0'),
+('1211','98','severity_average','P3','0'),
+('1212','98','severity_default','P5','0'),
+('1213','98','severity_disaster','P1','0'),
+('1214','98','severity_high','P2','0'),
+('1215','98','severity_information','P5','0'),
+('1216','98','severity_not_classified','P5','0'),
+('1217','98','severity_warning','P4','0'),
+('1218','98','topdesk_api','','0'),
+('1219','98','topdesk_issue_key','{EVENT.TAGS.__zbx_tpd_issuekey}','0'),
+('1220','98','topdesk_password','','0'),
+('1221','98','topdesk_status','','0'),
+('1222','98','topdesk_user','','0'),
+('1223','98','trigger_id','{TRIGGER.ID}','0'),
+('1224','98','zbxurl','{$ZABBIX.URL}','0'),
+('1225','99','event_info','{$ZABBIX.URL}/tr_events.php?triggerid={TRIGGER.ID}&eventid={EVENT.ID}','0'),
+('1226','99','event_nseverity','{EVENT.NSEVERITY}','0'),
+('1227','99','event_recovery_value','{EVENT.RECOVERY.VALUE}','0'),
+('1228','99','event_source','{EVENT.SOURCE}','0'),
+('1229','99','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('1230','99','event_value','{EVENT.VALUE}','0'),
+('1231','99','field:entity_display_name','{ALERT.SUBJECT}','0'),
+('1232','99','field:entity_id','{EVENT.ID}','0'),
+('1233','99','field:hostname','{HOST.NAME}','0'),
+('1234','99','field:monitoring_tool','Zabbix','0'),
+('1235','99','field:operational_data','{EVENT.OPDATA}','0'),
+('1236','99','field:severity','{EVENT.SEVERITY}','0'),
+('1237','99','field:state_message','{ALERT.MESSAGE}','0'),
+('1238','99','field_p:trigger_description','{TRIGGER.DESCRIPTION}','0'),
+('1239','99','field_r:event_duration','{EVENT.DURATION}','0'),
+('1240','99','field_r:recovery time','{EVENT.RECOVERY.DATE} {EVENT.RECOVERY.TIME}','0'),
+('1241','99','priority_average','WARNING','0'),
+('1242','99','priority_default','INFO','0'),
+('1243','99','priority_disaster','CRITICAL','0'),
+('1244','99','priority_high','WARNING','0'),
+('1245','99','priority_information','INFO','0'),
+('1246','99','priority_not_classified','INFO','0'),
+('1247','99','priority_resolved','OK','0'),
+('1248','99','priority_update','INFO','0'),
+('1249','99','priority_warning','INFO','0'),
+('1250','99','vops_endpoint','','0'),
+('1251','99','vops_routing_key','{ALERT.SENDTO}','0'),
+('1252','100','alert_message','{ALERT.MESSAGE}','0'),
+('1253','100','alert_subject','{ALERT.SUBJECT}','0'),
+('1254','100','event_id','{EVENT.ID}','0'),
+('1255','100','event_nseverity','{EVENT.NSEVERITY}','0'),
+('1256','100','event_severity','{EVENT.SEVERITY}','0'),
+('1257','100','event_source','{EVENT.SOURCE}','0'),
+('1258','100','event_tags','{EVENT.TAGSJSON}','0'),
+('1259','100','event_update_nseverity','{EVENT.UPDATE.NSEVERITY}','0'),
+('1260','100','event_update_severity','{EVENT.UPDATE.SEVERITY}','0'),
+('1261','100','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('1262','100','event_value','{EVENT.VALUE}','0'),
+('1263','100','trigger_id','{TRIGGER.ID}','0'),
+('1264','100','zabbix_url','{$ZABBIX.URL}','0'),
+('1265','100','zammad_access_token','','0'),
+('1266','100','zammad_customer','','0'),
+('1267','100','zammad_enable_tags','false','0'),
+('1268','100','zammad_group','Users','0'),
+('1269','100','zammad_url','','0'),
+('1270','101','alert_message','{ALERT.MESSAGE}','0'),
+('1271','101','alert_subject','{ALERT.SUBJECT}','0'),
+('1272','101','event_id','{EVENT.ID}','0'),
+('1273','101','event_nseverity','{EVENT.NSEVERITY}','0'),
+('1274','101','event_source','{EVENT.SOURCE}','0'),
+('1275','101','event_tags','{EVENT.TAGS}','0'),
+('1276','101','event_update_status','{EVENT.UPDATE.STATUS}','0'),
+('1277','101','event_value','{EVENT.VALUE}','0'),
+('1278','101','severity_average','normal','0'),
+('1279','101','severity_default','-','0'),
+('1280','101','severity_disaster','urgent','0'),
+('1281','101','severity_high','high','0'),
+('1282','101','severity_information','low','0'),
+('1283','101','severity_not_classified','low','0'),
+('1284','101','severity_warning','normal','0'),
+('1285','101','trigger_id','{TRIGGER.ID}','0'),
+('1286','101','zbxurl','{$ZABBIX.URL}','0'),
+('1287','101','zendesk_issue_key','{EVENT.TAGS.__zbx_zdk_issuekey}','0'),
+('1288','101','zendesk_token','','0'),
+('1289','101','zendesk_type','incident','0'),
+('1290','101','zendesk_url','','0'),
+('1291','87','otrs_ticket_type','Unclassified','0'),
+('1292','75','glpi_app_token','','0'),
+('1293','75','glpi_user_token','','0');
+INSERT INTO media_type_message (mediatype_messageid,mediatypeid,eventsource,recovery,subject,message) VALUES ('1','1','0','0','Problem: {EVENT.NAME}','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}'),
+('2','1','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','Problem has been resolved at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Problem duration: {EVENT.DURATION}
+Host: {HOST.NAME}
+Severity: {EVENT.SEVERITY}
+Original problem ID: {EVENT.ID}
+{TRIGGER.URL}'),
+('3','1','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
+{EVENT.UPDATE.MESSAGE}
+
+Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.'),
+('4','1','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('5','1','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('6','3','0','0','','{EVENT.SEVERITY}: {EVENT.NAME}
+Host: {HOST.NAME}
+{EVENT.DATE} {EVENT.TIME}'),
+('7','3','0','1','','Resolved in {EVENT.DURATION}: {EVENT.NAME}
+Host: {HOST.NAME}
+{EVENT.DATE} {EVENT.TIME}'),
+('8','3','0','2','','{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem in {EVENT.AGE} at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}'),
+('9','3','1','0','','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}'),
+('10','3','2','0','','Autoregistration: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('11','4','0','0','Problem: {EVENT.NAME}','Problem started at {{EVENT.TIME}.htmlencode()} on {{EVENT.DATE}.htmlencode()}
Problem name: {{EVENT.NAME}.htmlencode()}
Host: {{HOST.NAME}.htmlencode()}
Severity: {{EVENT.SEVERITY}.htmlencode()}
Operational data: {{EVENT.OPDATA}.htmlencode()}
Original problem ID: {{EVENT.ID}.htmlencode()}
{{TRIGGER.URL}.htmlencode()}'),
+('12','4','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','Problem has been resolved at {{EVENT.RECOVERY.TIME}.htmlencode()} on {{EVENT.RECOVERY.DATE}.htmlencode()}
Problem name: {{EVENT.NAME}.htmlencode()}
Problem duration: {{EVENT.DURATION}.htmlencode()}
Host: {{HOST.NAME}.htmlencode()}
Severity: {{EVENT.SEVERITY}.htmlencode()}
Original problem ID: {{EVENT.ID}.htmlencode()}
{{TRIGGER.URL}.htmlencode()}'),
+('13','4','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{{USER.FULLNAME}.htmlencode()} {{EVENT.UPDATE.ACTION}.htmlencode()} problem at {{EVENT.UPDATE.DATE}.htmlencode()} {{EVENT.UPDATE.TIME}.htmlencode()}.
{{EVENT.UPDATE.MESSAGE}.htmlencode()}
Current problem status: {{EVENT.STATUS}.htmlencode()}
Age: {{EVENT.AGE}.htmlencode()}
Acknowledged: {{EVENT.ACK.STATUS}.htmlencode()}.'),
+('14','4','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','Discovery rule: {{DISCOVERY.RULE.NAME}.htmlencode()}
Device IP: {{DISCOVERY.DEVICE.IPADDRESS}.htmlencode()}
Device DNS: {{DISCOVERY.DEVICE.DNS}.htmlencode()}
Device status: {{DISCOVERY.DEVICE.STATUS}.htmlencode()}
Device uptime: {{DISCOVERY.DEVICE.UPTIME}.htmlencode()}
Device service name: {{DISCOVERY.SERVICE.NAME}.htmlencode()}
Device service port: {{DISCOVERY.SERVICE.PORT}.htmlencode()}
Device service status: {{DISCOVERY.SERVICE.STATUS}.htmlencode()}
Device service uptime: {{DISCOVERY.SERVICE.UPTIME}.htmlencode()}'),
+('15','4','2','0','Autoregistration: {HOST.HOST}','Host name: {{HOST.HOST}.htmlencode()}
Host IP: {{HOST.IP}.htmlencode()}
Agent port: {{HOST.PORT}.htmlencode()}'),
+('160','34','0','0','Problem: {EVENT.NAME}','Problem started at {{EVENT.TIME}.htmlencode()} on {{EVENT.DATE}.htmlencode()}
Problem name: {{EVENT.NAME}.htmlencode()}
Host: {{HOST.NAME}.htmlencode()}
Severity: {{EVENT.SEVERITY}.htmlencode()}
Operational data: {{EVENT.OPDATA}.htmlencode()}
Original problem ID: {{EVENT.ID}.htmlencode()}
{{TRIGGER.URL}.htmlencode()}'),
+('161','34','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','Problem has been resolved at {{EVENT.RECOVERY.TIME}.htmlencode()} on {{EVENT.RECOVERY.DATE}.htmlencode()}
Problem name: {{EVENT.NAME}.htmlencode()}
Problem duration: {{EVENT.DURATION}.htmlencode()}
Host: {{HOST.NAME}.htmlencode()}
Severity: {{EVENT.SEVERITY}.htmlencode()}
Original problem ID: {{EVENT.ID}.htmlencode()}
{{TRIGGER.URL}.htmlencode()}'),
+('162','34','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{{USER.FULLNAME}.htmlencode()} {{EVENT.UPDATE.ACTION}.htmlencode()} problem at {{EVENT.UPDATE.DATE}.htmlencode()} {{EVENT.UPDATE.TIME}.htmlencode()}.
{{EVENT.UPDATE.MESSAGE}.htmlencode()}
Current problem status: {{EVENT.STATUS}.htmlencode()}
Age: {{EVENT.AGE}.htmlencode()}
Acknowledged: {{EVENT.ACK.STATUS}.htmlencode()}.'),
+('163','34','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','Discovery rule: {{DISCOVERY.RULE.NAME}.htmlencode()}
Device IP: {{DISCOVERY.DEVICE.IPADDRESS}.htmlencode()}
Device DNS: {{DISCOVERY.DEVICE.DNS}.htmlencode()}
Device status: {{DISCOVERY.DEVICE.STATUS}.htmlencode()}
Device uptime: {{DISCOVERY.DEVICE.UPTIME}.htmlencode()}
Device service name: {{DISCOVERY.SERVICE.NAME}.htmlencode()}
Device service port: {{DISCOVERY.SERVICE.PORT}.htmlencode()}
Device service status: {{DISCOVERY.SERVICE.STATUS}.htmlencode()}
Device service uptime: {{DISCOVERY.SERVICE.UPTIME}.htmlencode()}'),
+('164','34','2','0','Autoregistration: {HOST.HOST}','Host name: {{HOST.HOST}.htmlencode()}
Host IP: {{HOST.IP}.htmlencode()}
Agent port: {{HOST.PORT}.htmlencode()}'),
+('165','35','0','0','Problem: {EVENT.NAME}','Problem started at {{EVENT.TIME}.htmlencode()} on {{EVENT.DATE}.htmlencode()}
Problem name: {{EVENT.NAME}.htmlencode()}
Host: {{HOST.NAME}.htmlencode()}
Severity: {{EVENT.SEVERITY}.htmlencode()}
Operational data: {{EVENT.OPDATA}.htmlencode()}
Original problem ID: {{EVENT.ID}.htmlencode()}
{{TRIGGER.URL}.htmlencode()}'),
+('166','35','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','Problem has been resolved at {{EVENT.RECOVERY.TIME}.htmlencode()} on {{EVENT.RECOVERY.DATE}.htmlencode()}
Problem name: {{EVENT.NAME}.htmlencode()}
Problem duration: {{EVENT.DURATION}.htmlencode()}
Host: {{HOST.NAME}.htmlencode()}
Severity: {{EVENT.SEVERITY}.htmlencode()}
Original problem ID: {{EVENT.ID}.htmlencode()}
{{TRIGGER.URL}.htmlencode()}'),
+('167','35','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{{USER.FULLNAME}.htmlencode()} {{EVENT.UPDATE.ACTION}.htmlencode()} problem at {{EVENT.UPDATE.DATE}.htmlencode()} {{EVENT.UPDATE.TIME}.htmlencode()}.
{{EVENT.UPDATE.MESSAGE}.htmlencode()}
Current problem status: {{EVENT.STATUS}.htmlencode()}
Age: {{EVENT.AGE}.htmlencode()}
Acknowledged: {{EVENT.ACK.STATUS}.htmlencode()}.'),
+('168','35','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','Discovery rule: {{DISCOVERY.RULE.NAME}.htmlencode()}
Device IP: {{DISCOVERY.DEVICE.IPADDRESS}.htmlencode()}
Device DNS: {{DISCOVERY.DEVICE.DNS}.htmlencode()}
Device status: {{DISCOVERY.DEVICE.STATUS}.htmlencode()}
Device uptime: {{DISCOVERY.DEVICE.UPTIME}.htmlencode()}
Device service name: {{DISCOVERY.SERVICE.NAME}.htmlencode()}
Device service port: {{DISCOVERY.SERVICE.PORT}.htmlencode()}
Device service status: {{DISCOVERY.SERVICE.STATUS}.htmlencode()}
Device service uptime: {{DISCOVERY.SERVICE.UPTIME}.htmlencode()}'),
+('169','35','2','0','Autoregistration: {HOST.HOST}','Host name: {{HOST.HOST}.htmlencode()}
Host IP: {{HOST.IP}.htmlencode()}
Agent port: {{HOST.PORT}.htmlencode()}'),
+('170','36','0','0','Problem: {EVENT.NAME}','Problem started at {{EVENT.TIME}.htmlencode()} on {{EVENT.DATE}.htmlencode()}
Problem name: {{EVENT.NAME}.htmlencode()}
Host: {{HOST.NAME}.htmlencode()}
Severity: {{EVENT.SEVERITY}.htmlencode()}
Operational data: {{EVENT.OPDATA}.htmlencode()}
Original problem ID: {{EVENT.ID}.htmlencode()}
{{TRIGGER.URL}.htmlencode()}'),
+('171','36','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','Problem has been resolved at {{EVENT.RECOVERY.TIME}.htmlencode()} on {{EVENT.RECOVERY.DATE}.htmlencode()}
Problem name: {{EVENT.NAME}.htmlencode()}
Problem duration: {{EVENT.DURATION}.htmlencode()}
Host: {{HOST.NAME}.htmlencode()}
Severity: {{EVENT.SEVERITY}.htmlencode()}
Original problem ID: {{EVENT.ID}.htmlencode()}
{{TRIGGER.URL}.htmlencode()}'),
+('172','36','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{{USER.FULLNAME}.htmlencode()} {{EVENT.UPDATE.ACTION}.htmlencode()} problem at {{EVENT.UPDATE.DATE}.htmlencode()} {{EVENT.UPDATE.TIME}.htmlencode()}.
{{EVENT.UPDATE.MESSAGE}.htmlencode()}
Current problem status: {{EVENT.STATUS}.htmlencode()}
Age: {{EVENT.AGE}.htmlencode()}
Acknowledged: {{EVENT.ACK.STATUS}.htmlencode()}.'),
+('173','36','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','Discovery rule: {{DISCOVERY.RULE.NAME}.htmlencode()}
Device IP: {{DISCOVERY.DEVICE.IPADDRESS}.htmlencode()}
Device DNS: {{DISCOVERY.DEVICE.DNS}.htmlencode()}
Device status: {{DISCOVERY.DEVICE.STATUS}.htmlencode()}
Device uptime: {{DISCOVERY.DEVICE.UPTIME}.htmlencode()}
Device service name: {{DISCOVERY.SERVICE.NAME}.htmlencode()}
Device service port: {{DISCOVERY.SERVICE.PORT}.htmlencode()}
Device service status: {{DISCOVERY.SERVICE.STATUS}.htmlencode()}
Device service uptime: {{DISCOVERY.SERVICE.UPTIME}.htmlencode()}'),
+('174','36','2','0','Autoregistration: {HOST.HOST}','Host name: {{HOST.HOST}.htmlencode()}
Host IP: {{HOST.IP}.htmlencode()}
Agent port: {{HOST.PORT}.htmlencode()}'),
+('175','37','0','0','Problem: {EVENT.NAME}','Problem started at {{EVENT.TIME}.htmlencode()} on {{EVENT.DATE}.htmlencode()}
Problem name: {{EVENT.NAME}.htmlencode()}
Host: {{HOST.NAME}.htmlencode()}
Severity: {{EVENT.SEVERITY}.htmlencode()}
Operational data: {{EVENT.OPDATA}.htmlencode()}
Original problem ID: {{EVENT.ID}.htmlencode()}
{{TRIGGER.URL}.htmlencode()}'),
+('176','37','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','Problem has been resolved at {{EVENT.RECOVERY.TIME}.htmlencode()} on {{EVENT.RECOVERY.DATE}.htmlencode()}
Problem name: {{EVENT.NAME}.htmlencode()}
Problem duration: {{EVENT.DURATION}.htmlencode()}
Host: {{HOST.NAME}.htmlencode()}
Severity: {{EVENT.SEVERITY}.htmlencode()}
Original problem ID: {{EVENT.ID}.htmlencode()}
{{TRIGGER.URL}.htmlencode()}'),
+('177','37','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{{USER.FULLNAME}.htmlencode()} {{EVENT.UPDATE.ACTION}.htmlencode()} problem at {{EVENT.UPDATE.DATE}.htmlencode()} {{EVENT.UPDATE.TIME}.htmlencode()}.
{{EVENT.UPDATE.MESSAGE}.htmlencode()}
Current problem status: {{EVENT.STATUS}.htmlencode()}
Age: {{EVENT.AGE}.htmlencode()}
Acknowledged: {{EVENT.ACK.STATUS}.htmlencode()}.'),
+('178','37','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','Discovery rule: {{DISCOVERY.RULE.NAME}.htmlencode()}
Device IP: {{DISCOVERY.DEVICE.IPADDRESS}.htmlencode()}
Device DNS: {{DISCOVERY.DEVICE.DNS}.htmlencode()}
Device status: {{DISCOVERY.DEVICE.STATUS}.htmlencode()}
Device uptime: {{DISCOVERY.DEVICE.UPTIME}.htmlencode()}
Device service name: {{DISCOVERY.SERVICE.NAME}.htmlencode()}
Device service port: {{DISCOVERY.SERVICE.PORT}.htmlencode()}
Device service status: {{DISCOVERY.SERVICE.STATUS}.htmlencode()}
Device service uptime: {{DISCOVERY.SERVICE.UPTIME}.htmlencode()}'),
+('179','37','2','0','Autoregistration: {HOST.HOST}','Host name: {{HOST.HOST}.htmlencode()}
Host IP: {{HOST.IP}.htmlencode()}
Agent port: {{HOST.PORT}.htmlencode()}'),
+('397','70','0','0','[{EVENT.STATUS}] {EVENT.NAME}','[{EVENT.STATUS}] {EVENT.NAME}
+Started at {EVENT.TIME} on {EVENT.DATE}
+Host: {HOST.NAME}
+Severity: {EVENT.SEVERITY}
+Operational data: {EVENT.OPDATA}
+Event info: {$ZABBIX.URL}/tr_events.php?triggerid={TRIGGER.ID}&eventid={EVENT.ID}'),
+('398','70','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','[{EVENT.STATUS}] {EVENT.NAME}
+Resolved in {EVENT.DURATION} at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Host: {HOST.NAME}
+Severity: {EVENT.SEVERITY}
+Event info: {$ZABBIX.URL}/tr_events.php?triggerid={TRIGGER.ID}&eventid={EVENT.ID}'),
+('399','70','0','2','[{EVENT.STATUS}] {EVENT.NAME}','[{EVENT.STATUS}] {EVENT.NAME}
+
+{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
+{EVENT.UPDATE.MESSAGE}'),
+('400','70','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}
+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}'),
+('401','70','2','0','Autoregistration: {HOST.HOST}','Autoregistration: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('402','71','0','0','Problem: {EVENT.NAME}','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}'),
+('403','71','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','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}'),
+('404','71','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
+{EVENT.UPDATE.MESSAGE}
+
+Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.'),
+('405','71','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('406','71','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('407','71','3','0','[{EVENT.STATUS}] {EVENT.NAME}','Problem started at {EVENT.TIME} on {EVENT.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('408','71','3','1','[{EVENT.STATUS}] {EVENT.NAME}','Problem has been resolved in {EVENT.DURATION} at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('409','71','4','0','Service "{SERVICE.NAME}" problem: {EVENT.NAME}','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}'),
+('410','71','4','1','Service "{SERVICE.NAME}" resolved in {EVENT.DURATION}: {EVENT.NAME}','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}'),
+('411','71','4','2','Changed "{SERVICE.NAME}" service status to {EVENT.UPDATE.SEVERITY} in {EVENT.AGE}','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}'),
+('412','72','0','0','Event ID: {EVENT.ID}, Host: {HOST.HOST}, Problem: {EVENT.NAME}',''),
+('413','73','0','0','[{EVENT.STATUS}] {EVENT.NAME}','[{EVENT.STATUS}] {EVENT.NAME}
+Started at {EVENT.TIME} on {EVENT.DATE}
+Host: {HOST.NAME}
+Severity: {EVENT.SEVERITY}
+Operational data: {EVENT.OPDATA}
+Event info: {$ZABBIX.URL}/tr_events.php?triggerid={TRIGGER.ID}&eventid={EVENT.ID}'),
+('414','73','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','[{EVENT.STATUS}] {EVENT.NAME}
+Resolved in {EVENT.DURATION} at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Host: {HOST.NAME}
+Severity: {EVENT.SEVERITY}
+Event info: {$ZABBIX.URL}/tr_events.php?triggerid={TRIGGER.ID}&eventid={EVENT.ID}'),
+('415','73','0','2','[{EVENT.STATUS}] {EVENT.NAME}','[{EVENT.STATUS}] {EVENT.NAME}
+
+{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
+{EVENT.UPDATE.MESSAGE}'),
+('416','73','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}
+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}'),
+('417','73','2','0','Autoregistration: {HOST.HOST}','Autoregistration: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('418','74','0','0','Problem: {EVENT.NAME}','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}'),
+('419','74','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','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}'),
+('420','74','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
+{EVENT.UPDATE.MESSAGE}
+
+Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.'),
+('421','74','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('422','74','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('423','74','3','0','[{EVENT.STATUS}] {EVENT.NAME}','Problem started at {EVENT.TIME} on {EVENT.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('424','74','3','1','[{EVENT.STATUS}] {EVENT.NAME}','Problem has been resolved in {EVENT.DURATION} at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('425','74','4','0','Service "{SERVICE.NAME}" problem: {EVENT.NAME}','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}'),
+('426','74','4','1','Service "{SERVICE.NAME}" resolved in {EVENT.DURATION}: {EVENT.NAME}','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}'),
+('427','74','4','2','Changed "{SERVICE.NAME}" service status to {EVENT.UPDATE.SEVERITY} in {EVENT.AGE}','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}'),
+('428','75','0','0','Problem: {EVENT.NAME}','- 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}'),
+('429','75','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','- 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}
- Operational data: {EVENT.OPDATA}
- Original problem ID: {EVENT.ID}
{TRIGGER.URL}'),
+('430','75','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.TIME} on {EVENT.UPDATE.DATE}.
{EVENT.UPDATE.MESSAGE}
Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.
'),
+('431','75','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','- 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}
'),
+('432','75','2','0','Autoregistration: {HOST.HOST}','- Host name: {HOST.HOST}
- Host IP: {HOST.IP}
- Agent port: {HOST.PORT}
'),
+('433','75','3','0','[{EVENT.STATUS}] {EVENT.NAME}','- Problem started at {EVENT.TIME} on {EVENT.DATE}
- Problem name: {EVENT.NAME}
- Host: {HOST.NAME}
- Original problem ID: {EVENT.ID}
'),
+('434','75','3','1','[{EVENT.STATUS}] {EVENT.NAME}','- Problem has been resolved in {EVENT.DURATION} at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
- Problem name: {EVENT.NAME}
- Host: {HOST.NAME}
- Original problem ID: {EVENT.ID}
'),
+('435','75','4','0','Service "{SERVICE.NAME}" problem: {EVENT.NAME}','- 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}
'),
+('436','75','4','1','Service "{SERVICE.NAME}" resolved in {EVENT.DURATION}: {EVENT.NAME}','- 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:
'),
+('437','75','4','2','Changed "{SERVICE.NAME}" service status to {EVENT.UPDATE.SEVERITY} in {EVENT.AGE}','- 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}
'),
+('438','76','0','0','Problem: {EVENT.NAME}','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}'),
+('439','76','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','Problem has been resolved at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Problem duration: {EVENT.DURATION}
+Host: {HOST.NAME}
+Severity: {EVENT.SEVERITY}
+Original problem ID: {EVENT.ID}
+{TRIGGER.URL}'),
+('440','76','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
+{EVENT.UPDATE.MESSAGE}
+
+Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.'),
+('441','77','0','0','[{EVENT.STATUS}] {EVENT.NAME}','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}'),
+('442','77','0','1','[{EVENT.STATUS}] {EVENT.NAME}','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}'),
+('443','77','0','2','[{EVENT.STATUS}] {EVENT.NAME}','{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}.'),
+('444','77','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('445','77','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('446','78','0','0','[{EVENT.STATUS}] {EVENT.NAME}','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}'),
+('447','78','0','1','[{EVENT.STATUS}] {EVENT.NAME}','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}'),
+('448','78','0','2','[{EVENT.STATUS}] {EVENT.NAME}','{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}.'),
+('449','78','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('450','78','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('451','78','3','0','[{EVENT.STATUS}] {EVENT.NAME}','Problem started at {EVENT.TIME} on {EVENT.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('452','78','3','1','[{EVENT.STATUS}] {EVENT.NAME}','Problem has been resolved in {EVENT.DURATION} at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('453','78','4','0','[{EVENT.STATUS}] Service "{SERVICE.NAME}" problem: {EVENT.NAME}','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}'),
+('454','78','4','1','[{EVENT.STATUS}] Service "{SERVICE.NAME}" problem: {EVENT.NAME}','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}'),
+('455','78','4','2','[{EVENT.STATUS}] Service "{SERVICE.NAME}" problem: {EVENT.NAME}','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}'),
+('456','79','0','0','[{EVENT.STATUS}] {EVENT.NAME}','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}'),
+('457','79','0','1','[{EVENT.STATUS}] {EVENT.NAME}','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}'),
+('458','79','0','2','[{EVENT.STATUS}] {EVENT.NAME}','{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}.'),
+('459','79','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('460','79','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('461','79','3','0','[{EVENT.STATUS}] {EVENT.NAME}','Problem started at {EVENT.TIME} on {EVENT.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('462','79','3','1','[{EVENT.STATUS}] {EVENT.NAME}','Problem has been resolved in {EVENT.DURATION} at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('463','79','4','0','[{EVENT.STATUS}] Service "{SERVICE.NAME}" problem: {EVENT.NAME}','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}'),
+('464','79','4','1','[{EVENT.STATUS}] Service "{SERVICE.NAME}" problem: {EVENT.NAME}','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}'),
+('465','79','4','2','[{EVENT.STATUS}] Service "{SERVICE.NAME}" problem: {EVENT.NAME}','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}'),
+('466','80','0','0','Problem: {EVENT.NAME}','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}'),
+('467','80','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','Problem has been resolved at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Problem duration: {EVENT.DURATION}
+Host: {HOST.NAME}
+Severity: {EVENT.SEVERITY}
+Original problem ID: {EVENT.ID}'),
+('468','80','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
+{EVENT.UPDATE.MESSAGE}
+
+Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.'),
+('469','80','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('470','80','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('471','81','0','0','[{EVENT.STATUS}] {EVENT.NAME}','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}'),
+('472','81','0','1','[{EVENT.STATUS}] {EVENT.NAME}','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}'),
+('473','81','0','2','[{EVENT.STATUS}] {EVENT.NAME}','{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}.'),
+('474','81','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('475','81','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('476','82','0','0','[{EVENT.STATUS}] {EVENT.NAME}','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}'),
+('477','82','0','1','[{EVENT.STATUS}] {EVENT.NAME}','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}'),
+('478','82','0','2','[{EVENT.STATUS}] {EVENT.NAME}','{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}.'),
+('479','82','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('480','82','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('481','82','3','0','[{EVENT.STATUS}] {EVENT.NAME}','Problem started at {EVENT.TIME} on {EVENT.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('482','82','3','1','[{EVENT.STATUS}] {EVENT.NAME}','Problem has been resolved in {EVENT.DURATION}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('483','83','0','0','Problem: {EVENT.NAME}','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}'),
+('484','83','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','Problem has been resolved at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Problem duration: {EVENT.DURATION}
+Host: {HOST.NAME}
+Severity: {EVENT.SEVERITY}
+Original problem ID: {EVENT.ID}
+{TRIGGER.URL}'),
+('485','83','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
+{EVENT.UPDATE.MESSAGE}
+
+Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.'),
+('486','83','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('487','83','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('488','84','0','0','Problem: {EVENT.NAME}','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}'),
+('489','84','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','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}'),
+('490','84','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
+{EVENT.UPDATE.MESSAGE}
+
+Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.'),
+('491','84','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('492','84','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('493','84','3','0','[{EVENT.STATUS}] {EVENT.NAME}','Problem started at {EVENT.TIME} on {EVENT.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('494','84','3','1','[{EVENT.STATUS}] {EVENT.NAME}','Problem has been resolved in {EVENT.DURATION} at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('495','84','4','0','Service "{SERVICE.NAME}" problem: {EVENT.NAME}','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}'),
+('496','84','4','1','Service "{SERVICE.NAME}" resolved in {EVENT.DURATION}: {EVENT.NAME}','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}'),
+('497','84','4','2','Changed "{SERVICE.NAME}" service status to {EVENT.UPDATE.SEVERITY} in {EVENT.AGE}','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}'),
+('498','85','0','0','Problem: {EVENT.NAME}','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}'),
+('499','85','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','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}'),
+('500','85','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
+{EVENT.UPDATE.MESSAGE}
+
+Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.'),
+('501','85','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('502','85','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('503','85','3','0','[{EVENT.STATUS}] {EVENT.NAME}','Problem started at {EVENT.TIME} on {EVENT.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('504','85','3','1','[{EVENT.STATUS}] {EVENT.NAME}','Problem has been resolved in {EVENT.DURATION} at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('505','85','4','0','Service "{SERVICE.NAME}" problem: {EVENT.NAME}','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}'),
+('506','85','4','1','Service "{SERVICE.NAME}" resolved in {EVENT.DURATION}: {EVENT.NAME}','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}'),
+('507','85','4','2','Changed "{SERVICE.NAME}" service status to {EVENT.UPDATE.SEVERITY} in {EVENT.AGE}','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}'),
+('508','86','0','0','Problem: {EVENT.NAME}','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}'),
+('509','86','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','Problem has been resolved at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Problem duration: {EVENT.DURATION}
+Host: {HOST.NAME}
+Severity: {EVENT.SEVERITY}
+Original problem ID: {EVENT.ID}
+{TRIGGER.URL}'),
+('510','86','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
+{EVENT.UPDATE.MESSAGE}
+
+Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.'),
+('511','86','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('512','86','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('513','87','0','0','Problem: {EVENT.NAME}','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}'),
+('514','87','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','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}'),
+('515','87','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
+{EVENT.UPDATE.MESSAGE}
+
+Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.'),
+('516','87','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('517','87','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('518','87','3','0','[{EVENT.STATUS}] {EVENT.NAME}','Problem started at {EVENT.TIME} on {EVENT.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('519','87','3','1','[{EVENT.STATUS}] {EVENT.NAME}','Problem has been resolved in {EVENT.DURATION} at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('520','87','4','0','Service "{SERVICE.NAME}" problem: {EVENT.NAME}','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}'),
+('521','87','4','1','Service "{SERVICE.NAME}" resolved in {EVENT.DURATION}: {EVENT.NAME}','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}'),
+('522','87','4','2','Changed "{SERVICE.NAME}" service status to {EVENT.UPDATE.SEVERITY} in {EVENT.AGE}','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}'),
+('523','88','0','0','Problem: {EVENT.NAME}','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}'),
+('524','88','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','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}'),
+('525','88','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
+{EVENT.UPDATE.MESSAGE}
+
+Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.'),
+('526','88','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('527','88','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('528','88','3','0','[{EVENT.STATUS}] {EVENT.NAME}','Problem started at {EVENT.TIME} on {EVENT.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('529','88','3','1','[{EVENT.STATUS}] {EVENT.NAME}','Problem has been resolved in {EVENT.DURATION} at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('530','88','4','0','Service "{SERVICE.NAME}" problem: {EVENT.NAME}','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}'),
+('531','88','4','1','Service "{SERVICE.NAME}" resolved in {EVENT.DURATION}: {EVENT.NAME}','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}'),
+('532','88','4','2','Changed "{SERVICE.NAME}" service status to {EVENT.UPDATE.SEVERITY} in {EVENT.AGE}','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}'),
+('533','89','0','0','Problem: {EVENT.NAME}','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}'),
+('534','89','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','Problem has been resolved at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Problem duration: {EVENT.DURATION}
+Host: {HOST.NAME}
+Severity: {EVENT.SEVERITY}
+Original problem ID: {EVENT.ID}
+{TRIGGER.URL}'),
+('535','89','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
+{EVENT.UPDATE.MESSAGE}
+
+Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.'),
+('536','89','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('537','89','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('538','90','0','0','Problem: {EVENT.NAME}','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}'),
+('539','90','0','1','Resolved: {EVENT.NAME}','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}'),
+('540','90','0','2','Updated problem: {EVENT.NAME}','{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}.'),
+('541','90','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('542','90','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('543','91','0','0','[{EVENT.STATUS}] {EVENT.NAME}','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}'),
+('544','91','0','1','[{EVENT.STATUS}] {EVENT.NAME}','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}'),
+('545','91','0','2','[{EVENT.STATUS}] {EVENT.NAME}','{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}.'),
+('546','91','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('547','91','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('548','92','0','0','[{EVENT.STATUS}] {EVENT.NAME}','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}'),
+('549','92','0','1','[{EVENT.STATUS}] {EVENT.NAME}','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}'),
+('550','92','0','2','[{EVENT.STATUS}] {EVENT.NAME}','{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}.'),
+('551','92','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('552','92','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('553','93','0','0','Problem: {EVENT.NAME}','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}'),
+('554','93','0','1','Resolved: {EVENT.NAME}','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}'),
+('555','93','0','2','Updated problem: {EVENT.NAME}','{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}.'),
+('556','93','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('557','93','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('558','94','0','0','Problem: {EVENT.NAME}','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}'),
+('559','94','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','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}'),
+('560','94','0','2','Updated: {EVENT.NAME}','Problem updated at {EVENT.TIME} on {EVENT.DATE}
+{USER.FULLNAME} {EVENT.UPDATE.ACTION}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Operational data: {EVENT.OPDATA}
+Original problem ID: {EVENT.ID}
+{TRIGGER.URL}'),
+('561','94','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('562','94','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('563','94','3','0','[{EVENT.STATUS}] {EVENT.NAME}','Problem started at {EVENT.TIME} on {EVENT.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('564','94','3','1','[{EVENT.STATUS}] {EVENT.NAME}','Problem has been resolved in {EVENT.DURATION} at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('565','94','4','0','Service "{SERVICE.NAME}" problem: {EVENT.NAME}','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}'),
+('566','94','4','1','Service "{SERVICE.NAME}" resolved in {EVENT.DURATION}: {EVENT.NAME}','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}'),
+('567','94','4','2','Changed "{SERVICE.NAME}" service status to {EVENT.UPDATE.SEVERITY} in {EVENT.AGE}','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}'),
+('568','95','0','0','[{EVENT.STATUS}] {EVENT.NAME}','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 description: {TRIGGER.DESCRIPTION}'),
+('569','95','0','1','[{EVENT.STATUS}] {EVENT.NAME}','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}'),
+('570','95','0','2','[{EVENT.STATUS}] {EVENT.NAME}','{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}.'),
+('571','95','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('572','95','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('573','96','0','0','Problem: {EVENT.NAME}','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}'),
+('574','96','0','1','Resolved: {EVENT.NAME}','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}'),
+('575','96','0','2','Updated problem: {EVENT.NAME}','{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}.'),
+('576','96','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('577','96','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('578','97','0','0','Problem: {EVENT.NAME}','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}'),
+('579','97','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','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}'),
+('580','97','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
+{EVENT.UPDATE.MESSAGE}
+
+Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.'),
+('581','97','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('582','97','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('583','97','3','0','[{EVENT.STATUS}] {EVENT.NAME}','Problem started at {EVENT.TIME} on {EVENT.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('584','97','3','1','[{EVENT.STATUS}] {EVENT.NAME}','Problem has been resolved in {EVENT.DURATION} at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('585','97','4','0','Service "{SERVICE.NAME}" problem: {EVENT.NAME}','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}'),
+('586','97','4','1','Service "{SERVICE.NAME}" resolved in {EVENT.DURATION}: {EVENT.NAME}','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}'),
+('587','97','4','2','Changed "{SERVICE.NAME}" service status to {EVENT.UPDATE.SEVERITY} in {EVENT.AGE}','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}'),
+('588','98','0','0','Problem: {EVENT.NAME}','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}'),
+('589','98','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','Problem has been resolved at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Problem duration: {EVENT.DURATION}
+Host: {HOST.NAME}
+Severity: {EVENT.SEVERITY}
+Original problem ID: {EVENT.ID}
+{TRIGGER.URL}'),
+('590','98','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
+{EVENT.UPDATE.MESSAGE}
+
+Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.'),
+('591','98','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('592','98','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('593','99','0','0','Problem: {EVENT.NAME}','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}'),
+('594','99','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','Problem has been resolved at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Problem duration: {EVENT.DURATION}
+Host: {HOST.NAME}
+Severity: {EVENT.SEVERITY}
+Original problem ID: {EVENT.ID}
+{TRIGGER.URL}'),
+('595','99','0','2','[{EVENT.STATUS}] {EVENT.NAME}','{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}.'),
+('596','99','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('597','99','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('598','100','0','0','Problem: {EVENT.NAME}','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}'),
+('599','100','0','1','Resolved in {EVENT.DURATION}: {EVENT.NAME}','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}'),
+('600','100','0','2','Updated problem in {EVENT.AGE}: {EVENT.NAME}','{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
+{EVENT.UPDATE.MESSAGE}
+
+Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.'),
+('601','100','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('602','100','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('603','100','3','0','[{EVENT.STATUS}] {EVENT.NAME}','Problem started at {EVENT.TIME} on {EVENT.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('604','100','3','1','[{EVENT.STATUS}] {EVENT.NAME}','Problem has been resolved in {EVENT.DURATION} at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Original problem ID: {EVENT.ID}'),
+('605','100','4','0','Service "{SERVICE.NAME}" problem: {EVENT.NAME}','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}'),
+('606','100','4','1','Service "{SERVICE.NAME}" resolved in {EVENT.DURATION}: {EVENT.NAME}','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}'),
+('607','100','4','2','Changed "{SERVICE.NAME}" service status to {EVENT.UPDATE.SEVERITY} in {EVENT.AGE}','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}'),
+('608','101','0','0','{EVENT.NAME}','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}'),
+('609','101','0','1','{EVENT.NAME}','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}
+Operational data: {EVENT.OPDATA}
+Original problem ID: {EVENT.ID}
+{TRIGGER.URL}'),
+('610','101','0','2','{EVENT.NAME}','{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}.'),
+('611','101','1','0','Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}','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}'),
+('612','101','2','0','Autoregistration: {HOST.HOST}','Host name: {HOST.HOST}
+Host IP: {HOST.IP}
+Agent port: {HOST.PORT}'),
+('613','101','3','0','Internal problem: {EVENT.NAME}','Internal problem started at {EVENT.TIME} on {EVENT.DATE}
+Problem name: {EVENT.NAME}
+Host: {HOST.NAME}
+Operational data: {EVENT.OPDATA}
+Original problem ID: {EVENT.ID}');
+INSERT INTO usrgrp (usrgrpid,name,gui_access,users_status,debug_mode,userdirectoryid,mfa_status,mfaid) VALUES ('7','Zabbix administrators','0','0','0',NULL,'0',NULL),
+('8','Guests','0','0','0',NULL,'0',NULL),
+('9','Disabled','0','1','0',NULL,'0',NULL),
+('11','Enabled debug mode','0','0','1',NULL,'0',NULL),
+('12','No access to the frontend','3','0','0',NULL,'0',NULL),
+('13','Internal','1','0','0',NULL,'0',NULL);
+INSERT INTO users_groups (id,usrgrpid,userid) VALUES ('2','8','2'),
+('3','9','2'),
+('4','7','1'),
+('5','13','1'),
+('6','13','2');
+INSERT INTO ugset_group (ugsetid,usrgrpid) VALUES ('1','13'),
+('1','8'),
+('1','9');
+INSERT INTO user_ugset (userid,ugsetid) VALUES ('2','1');
+INSERT INTO scripts (scriptid,name,command,host_access,usrgrpid,groupid,description,confirmation,type,execute_on,timeout,scope,port,authtype,username,password,publickey,privatekey,menu_path,url,new_window,manualinput,manualinput_prompt,manualinput_validator,manualinput_validator_type,manualinput_default_value) VALUES ('1','Ping','ping -c 3 {HOST.CONN}; case $? in [01]) true;; *) false;; esac','2',NULL,NULL,'','','0','2','30s','2','','0','','','','','','','1','0','','','0',''),
+('2','Traceroute','/usr/bin/traceroute {HOST.CONN}','2',NULL,NULL,'','','0','2','30s','2','','0','','','','','','','1','0','','','0',''),
+('3','Detect operating system','sudo /usr/bin/nmap -O {HOST.CONN}','2','7',NULL,'','','0','2','30s','2','','0','','','','','','','1','0','','','0','');
+INSERT INTO actions (actionid,name,eventsource,evaltype,status,esc_period,formula,pause_suppressed,notify_if_canceled,pause_symptoms) VALUES ('2','Auto discovery. Linux servers.','1','0','1','0','','1','1','1'),
+('3','Report problems to Zabbix administrators','0','0','1','1h','','1','1','1'),
+('4','Report not supported items','3','0','1','1h','','1','1','1'),
+('5','Report not supported low level discovery rules','3','0','1','1h','','1','1','1'),
+('6','Report unknown triggers','3','0','1','1h','','1','1','1');
+INSERT INTO operations (operationid,actionid,operationtype,esc_period,esc_step_from,esc_step_to,evaltype,recovery) VALUES ('1','2','6','0','1','1','0','0'),
+('2','2','4','0','1','1','0','0'),
+('3','3','0','0','1','1','0','0'),
+('4','4','0','0','1','1','0','0'),
+('5','5','0','0','1','1','0','0'),
+('6','6','0','0','1','1','0','0'),
+('7','3','11','0','1','1','0','1'),
+('8','4','11','0','1','1','0','1'),
+('9','5','11','0','1','1','0','1'),
+('10','6','11','0','1','1','0','1');
+INSERT INTO opmessage (operationid,default_msg,subject,message,mediatypeid) VALUES ('3','1','','',NULL),
+('4','1','','',NULL),
+('5','1','','',NULL),
+('6','1','','',NULL),
+('7','1','','',NULL),
+('8','1','','',NULL),
+('9','1','','',NULL),
+('10','1','','',NULL);
+INSERT INTO opmessage_grp (opmessage_grpid,operationid,usrgrpid) VALUES ('1','3','7'),
+('2','4','7'),
+('3','5','7'),
+('4','6','7');
+INSERT INTO opgroup (opgroupid,operationid,groupid) VALUES ('1','2','2');
+INSERT INTO conditions (conditionid,actionid,conditiontype,operator,value,value2) VALUES ('2','2','10','0','0',''),
+('3','2','8','0','9',''),
+('4','2','12','2','Linux',''),
+('6','4','23','0','0',''),
+('7','5','23','0','2',''),
+('8','6','23','0','4','');
+INSERT INTO graph_theme (graphthemeid,theme,backgroundcolor,graphcolor,gridcolor,maingridcolor,gridbordercolor,textcolor,highlightcolor,leftpercentilecolor,rightpercentilecolor,nonworktimecolor,colorpalette) VALUES ('1','blue-theme','FFFFFF','FFFFFF','CCD5D9','ACBBC2','ACBBC2','1F2C33','E33734','429E47','E33734','EBEBEB','1A7C11,F63100,2774A4,A54F10,FC6EA3,6C59DC,AC8C14,611F27,F230E0,5CCD18,BB2A02,5A2B57,89ABF8,7EC25C,274482,2B5429,8048B4,FD5434,790E1F,87AC4D,E89DF4'),
+('2','dark-theme','2B2B2B','2B2B2B','454545','4F4F4F','4F4F4F','F2F2F2','E45959','59DB8F','E45959','333333','199C0D,F63100,2774A4,F7941D,FC6EA3,6C59DC,C7A72D,BA2A5D,F230E0,5CCD18,BB2A02,AC41A5,89ABF8,7EC25C,3165D5,79A277,AA73DE,FD5434,F21C3E,87AC4D,E89DF4'),
+('3','hc-light','FFFFFF','FFFFFF','555555','000000','333333','000000','333333','000000','000000','EBEBEB','1A7C11,F63100,2774A4,A54F10,FC6EA3,6C59DC,AC8C14,611F27,F230E0,5CCD18,BB2A02,5A2B57,89ABF8,7EC25C,274482,2B5429,8048B4,FD5434,790E1F,87AC4D,E89DF4'),
+('4','hc-dark','000000','000000','666666','888888','4F4F4F','FFFFFF','FFFFFF','FFFFFF','FFFFFF','333333','199C0D,F63100,2774A4,F7941D,FC6EA3,6C59DC,C7A72D,BA2A5D,F230E0,5CCD18,BB2A02,AC41A5,89ABF8,7EC25C,3165D5,79A277,AA73DE,FD5434,F21C3E,87AC4D,E89DF4');
+INSERT INTO globalmacro (globalmacroid,macro,value,description,type) VALUES ('2','{$SNMP_COMMUNITY}','public','','0');
+INSERT INTO regexps (regexpid,name,test_string) VALUES ('1','File systems for discovery','ext3'),
+('2','Network interfaces for discovery','eth0'),
+('3','Storage devices for SNMP discovery','/boot'),
+('4','Windows service names for discovery','SysmonLog'),
+('5','Windows service startup states for discovery','automatic');
+INSERT INTO expressions (expressionid,regexpid,expression,expression_type,exp_delimiter,case_sensitive) VALUES ('1','1','^(btrfs|ext2|ext3|ext4|reiser|xfs|ffs|ufs|jfs|jfs2|vxfs|hfs|apfs|refs|ntfs|fat32|zfs)$','3',',','0'),
+('3','3','^(Physical memory|Virtual memory|Memory buffers|Cached memory|Swap space)$','4',',','1'),
+('5','4','^(MMCSS|gupdate|SysmonLog|clr_optimization_v2.0.50727_32|clr_optimization_v4.0.30319_32)$','4',',','1'),
+('6','5','^(automatic|automatic delayed)$','3',',','1'),
+('7','2','^Software Loopback Interface','4',',','1'),
+('8','2','^(In)?[Ll]oop[Bb]ack[0-9._]*$','4',',','1'),
+('9','2','^NULL[0-9.]*$','4',',','1'),
+('10','2','^[Ll]o[0-9.]*$','4',',','1'),
+('11','2','^[Ss]ystem$','4',',','1'),
+('12','2','^Nu[0-9.]*$','4',',','1');
+INSERT INTO config_autoreg_tls (autoreg_tlsid,tls_psk_identity,tls_psk) VALUES ('1','','');
+INSERT INTO module (moduleid,id,relative_path,status,config) VALUES ('1','actionlog','widgets/actionlog','1','[]'),
+('2','clock','widgets/clock','1','[]'),
+('3','topitems','widgets/topitems','1','[]'),
+('4','discovery','widgets/discovery','1','[]'),
+('5','favgraphs','widgets/favgraphs','1','[]'),
+('6','favmaps','widgets/favmaps','1','[]'),
+('7','geomap','widgets/geomap','1','[]'),
+('8','graph','widgets/graph','1','[]'),
+('9','graphprototype','widgets/graphprototype','1','[]'),
+('10','hostavail','widgets/hostavail','1','[]'),
+('11','item','widgets/item','1','[]'),
+('12','map','widgets/map','1','[]'),
+('13','navtree','widgets/navtree','1','[]'),
+('14','itemhistory','widgets/itemhistory','1','[]'),
+('15','problemhosts','widgets/problemhosts','1','[]'),
+('16','problems','widgets/problems','1','[]'),
+('17','problemsbysv','widgets/problemsbysv','1','[]'),
+('18','slareport','widgets/slareport','1','[]'),
+('19','svggraph','widgets/svggraph','1','[]'),
+('20','systeminfo','widgets/systeminfo','1','[]'),
+('21','tophosts','widgets/tophosts','1','[]'),
+('22','trigover','widgets/trigover','1','[]'),
+('23','url','widgets/url','1','[]'),
+('24','web','widgets/web','1','[]'),
+('25','gauge','widgets/gauge','1','[]'),
+('26','toptriggers','widgets/toptriggers','1','[]'),
+('27','piechart','widgets/piechart','1','[]'),
+('28','honeycomb','widgets/honeycomb','1','[]'),
+('29','hostnavigator','widgets/hostnavigator','1','[]'),
+('30','itemnavigator','widgets/itemnavigator','1','[]'),
+('31','hostcard','widgets/hostcard','1','[]'),
+('32','itemcard','widgets/itemcard','1','[]'),
+('33','scatterplot','widgets/scatterplot','1','[]');
+INSERT INTO role_rule (role_ruleid,roleid,type,name,value_int,value_str,value_moduleid,value_serviceid) VALUES ('1','1','0','ui.default_access','1','',NULL,NULL),
+('2','1','0','services.read','1','',NULL,NULL),
+('3','1','0','services.write','0','',NULL,NULL),
+('4','1','0','modules.default_access','1','',NULL,NULL),
+('5','1','0','api.access','1','',NULL,NULL),
+('6','1','0','api.mode','0','',NULL,NULL),
+('7','1','0','actions.default_access','1','',NULL,NULL),
+('8','2','0','ui.default_access','1','',NULL,NULL),
+('9','2','0','services.read','1','',NULL,NULL),
+('10','2','0','services.write','1','',NULL,NULL),
+('11','2','0','modules.default_access','1','',NULL,NULL),
+('12','2','0','api.access','1','',NULL,NULL),
+('13','2','0','api.mode','0','',NULL,NULL),
+('14','2','0','actions.default_access','1','',NULL,NULL),
+('15','3','0','ui.default_access','1','',NULL,NULL),
+('16','3','0','services.read','1','',NULL,NULL),
+('17','3','0','services.write','1','',NULL,NULL),
+('18','3','0','modules.default_access','1','',NULL,NULL),
+('19','3','0','api.access','1','',NULL,NULL),
+('20','3','0','api.mode','0','',NULL,NULL),
+('21','3','0','actions.default_access','1','',NULL,NULL),
+('22','4','0','ui.default_access','1','',NULL,NULL),
+('23','4','0','services.read','1','',NULL,NULL),
+('24','4','0','services.write','0','',NULL,NULL),
+('25','4','0','modules.default_access','1','',NULL,NULL),
+('26','4','0','api.access','0','',NULL,NULL),
+('27','4','0','actions.default_access','0','',NULL,NULL);
+INSERT INTO settings (name,type,value_str,value_int,value_usrgrpid,value_hostgroupid,value_userdirectoryid,value_mfaid) VALUES ('alert_usrgrpid','3','','0','7',NULL,NULL,NULL),
+('auditlog_enabled','2','','1',NULL,NULL,NULL,NULL),
+('auditlog_mode','2','','1',NULL,NULL,NULL,NULL),
+('authentication_type','2','','0',NULL,NULL,NULL,NULL),
+('autoreg_tls_accept','2','','1',NULL,NULL,NULL,NULL),
+('blink_period','1','2m','0',NULL,NULL,NULL,NULL),
+('compress_older','1','7d','0',NULL,NULL,NULL,NULL),
+('compression_status','2','','0',NULL,NULL,NULL,NULL),
+('connect_timeout','1','3s','0',NULL,NULL,NULL,NULL),
+('custom_color','2','','0',NULL,NULL,NULL,NULL),
+('db_extension','1','','0',NULL,NULL,NULL,NULL),
+('dbversion_status','1','','0',NULL,NULL,NULL,NULL),
+('default_inventory_mode','2','','-1',NULL,NULL,NULL,NULL),
+('default_lang','1','en_US','0',NULL,NULL,NULL,NULL),
+('default_theme','1','blue-theme','0',NULL,NULL,NULL,NULL),
+('default_timezone','1','system','0',NULL,NULL,NULL,NULL),
+('disabled_usrgrpid','3','','0',NULL,NULL,NULL,NULL),
+('discovery_groupid','4','','0',NULL,'5',NULL,NULL),
+('geomaps_attribution','1','','0',NULL,NULL,NULL,NULL),
+('geomaps_max_zoom','2','','0',NULL,NULL,NULL,NULL),
+('geomaps_tile_provider','1','OpenStreetMap.Mapnik','0',NULL,NULL,NULL,NULL),
+('geomaps_tile_url','1','','0',NULL,NULL,NULL,NULL),
+('ha_failover_delay','1','1m','0',NULL,NULL,NULL,NULL),
+('history_period','1','24h','0',NULL,NULL,NULL,NULL),
+('hk_audit','1','31d','0',NULL,NULL,NULL,NULL),
+('hk_audit_mode','2','','1',NULL,NULL,NULL,NULL),
+('hk_events_autoreg','1','1d','0',NULL,NULL,NULL,NULL),
+('hk_events_discovery','1','1d','0',NULL,NULL,NULL,NULL),
+('hk_events_internal','1','1d','0',NULL,NULL,NULL,NULL),
+('hk_events_mode','2','','1',NULL,NULL,NULL,NULL),
+('hk_events_service','1','1d','0',NULL,NULL,NULL,NULL),
+('hk_events_trigger','1','365d','0',NULL,NULL,NULL,NULL),
+('hk_history','1','31d','0',NULL,NULL,NULL,NULL),
+('hk_history_global','2','','0',NULL,NULL,NULL,NULL),
+('hk_history_mode','2','','1',NULL,NULL,NULL,NULL),
+('hk_services','1','365d','0',NULL,NULL,NULL,NULL),
+('hk_services_mode','2','','1',NULL,NULL,NULL,NULL),
+('hk_sessions','1','31d','0',NULL,NULL,NULL,NULL),
+('hk_sessions_mode','2','','1',NULL,NULL,NULL,NULL),
+('hk_trends','1','365d','0',NULL,NULL,NULL,NULL),
+('hk_trends_global','2','','0',NULL,NULL,NULL,NULL),
+('hk_trends_mode','2','','1',NULL,NULL,NULL,NULL),
+('http_auth_enabled','2','','0',NULL,NULL,NULL,NULL),
+('http_case_sensitive','2','','1',NULL,NULL,NULL,NULL),
+('http_login_form','2','','0',NULL,NULL,NULL,NULL),
+('http_strip_domains','1','','0',NULL,NULL,NULL,NULL),
+('iframe_sandboxing_enabled','2','','1',NULL,NULL,NULL,NULL),
+('iframe_sandboxing_exceptions','1','','0',NULL,NULL,NULL,NULL),
+('instanceid','1','','0',NULL,NULL,NULL,NULL),
+('item_test_timeout','1','60s','0',NULL,NULL,NULL,NULL),
+('jit_provision_interval','1','1h','0',NULL,NULL,NULL,NULL),
+('ldap_auth_enabled','2','','0',NULL,NULL,NULL,NULL),
+('ldap_case_sensitive','2','','1',NULL,NULL,NULL,NULL),
+('ldap_jit_status','2','','0',NULL,NULL,NULL,NULL),
+('ldap_userdirectoryid','5','','0',NULL,NULL,NULL,NULL),
+('login_attempts','2','','5',NULL,NULL,NULL,NULL),
+('login_block','1','30s','0',NULL,NULL,NULL,NULL),
+('max_in_table','2','','50',NULL,NULL,NULL,NULL),
+('max_overview_table_size','2','','50',NULL,NULL,NULL,NULL),
+('max_period','1','2y','0',NULL,NULL,NULL,NULL),
+('media_type_test_timeout','1','65s','0',NULL,NULL,NULL,NULL),
+('mfa_status','2','','0',NULL,NULL,NULL,NULL),
+('mfaid','6','','0',NULL,NULL,NULL,NULL),
+('ok_ack_color','1','009900','0',NULL,NULL,NULL,NULL),
+('ok_ack_style','2','','1',NULL,NULL,NULL,NULL),
+('ok_period','1','5m','0',NULL,NULL,NULL,NULL),
+('ok_unack_color','1','009900','0',NULL,NULL,NULL,NULL),
+('ok_unack_style','2','','1',NULL,NULL,NULL,NULL),
+('passwd_check_rules','2','','8',NULL,NULL,NULL,NULL),
+('passwd_min_length','2','','8',NULL,NULL,NULL,NULL),
+('period_default','1','1h','0',NULL,NULL,NULL,NULL),
+('problem_ack_color','1','CC0000','0',NULL,NULL,NULL,NULL),
+('problem_ack_style','2','','1',NULL,NULL,NULL,NULL),
+('problem_unack_color','1','CC0000','0',NULL,NULL,NULL,NULL),
+('problem_unack_style','2','','1',NULL,NULL,NULL,NULL),
+('proxy_secrets_provider','2','','0',NULL,NULL,NULL,NULL),
+('report_test_timeout','1','60s','0',NULL,NULL,NULL,NULL),
+('saml_auth_enabled','2','','0',NULL,NULL,NULL,NULL),
+('saml_case_sensitive','2','','0',NULL,NULL,NULL,NULL),
+('saml_jit_status','2','','0',NULL,NULL,NULL,NULL),
+('script_timeout','1','60s','0',NULL,NULL,NULL,NULL),
+('search_limit','2','','1000',NULL,NULL,NULL,NULL),
+('server_check_interval','2','','10',NULL,NULL,NULL,NULL),
+('server_status','1','','0',NULL,NULL,NULL,NULL),
+('session_key','1','0e1e3fb9846cbe4e079a22d38b2db33e','0',NULL,NULL,NULL,NULL),
+('severity_color_0','1','97AAB3','0',NULL,NULL,NULL,NULL),
+('severity_color_1','1','7499FF','0',NULL,NULL,NULL,NULL),
+('severity_color_2','1','FFC859','0',NULL,NULL,NULL,NULL),
+('severity_color_3','1','FFA059','0',NULL,NULL,NULL,NULL),
+('severity_color_4','1','E97659','0',NULL,NULL,NULL,NULL),
+('severity_color_5','1','E45959','0',NULL,NULL,NULL,NULL),
+('severity_name_0','1','Not classified','0',NULL,NULL,NULL,NULL),
+('severity_name_1','1','Information','0',NULL,NULL,NULL,NULL),
+('severity_name_2','1','Warning','0',NULL,NULL,NULL,NULL),
+('severity_name_3','1','Average','0',NULL,NULL,NULL,NULL),
+('severity_name_4','1','High','0',NULL,NULL,NULL,NULL),
+('severity_name_5','1','Disaster','0',NULL,NULL,NULL,NULL),
+('show_technical_errors','2','','0',NULL,NULL,NULL,NULL),
+('snmptrap_logging','2','','1',NULL,NULL,NULL,NULL),
+('socket_timeout','1','3s','0',NULL,NULL,NULL,NULL),
+('software_update_check_data','1','','0',NULL,NULL,NULL,NULL),
+('software_update_checkid','1','','0',NULL,NULL,NULL,NULL),
+('timeout_browser','1','60s','0',NULL,NULL,NULL,NULL),
+('timeout_db_monitor','1','3s','0',NULL,NULL,NULL,NULL),
+('timeout_external_check','1','3s','0',NULL,NULL,NULL,NULL),
+('timeout_http_agent','1','3s','0',NULL,NULL,NULL,NULL),
+('timeout_script','1','3s','0',NULL,NULL,NULL,NULL),
+('timeout_simple_check','1','3s','0',NULL,NULL,NULL,NULL),
+('timeout_snmp_agent','1','3s','0',NULL,NULL,NULL,NULL),
+('timeout_ssh_agent','1','3s','0',NULL,NULL,NULL,NULL),
+('timeout_telnet_agent','1','3s','0',NULL,NULL,NULL,NULL),
+('timeout_zabbix_agent','1','3s','0',NULL,NULL,NULL,NULL),
+('uri_valid_schemes','1','http,https,ftp,file,mailto,tel,ssh','0',NULL,NULL,NULL,NULL),
+('url','1','','0',NULL,NULL,NULL,NULL),
+('validate_uri_schemes','2','','1',NULL,NULL,NULL,NULL),
+('vault_provider','2','','0',NULL,NULL,NULL,NULL),
+('work_period','1','1-5,09:00-18:00','0',NULL,NULL,NULL,NULL),
+('x_frame_options','1','SAMEORIGIN','0',NULL,NULL,NULL,NULL);
+INSERT INTO hgset (hgsetid,hash) VALUES ('1','e629fa6598d732768f7c726b4b621285f9c3b85303900aa912017db7617d8bdb'),
+('2','4ec9599fc203d176a301536c2e091a19bc852759b255bd6818810a42c5fed14a'),
+('3','4523540f1504cd17100c4835e85b7eefd49911580f8efff0599a8f283be6b9e3'),
+('4','ef8704ac79657fbf2818c74a70a571c131283abd8914eca173cd032929702789'),
+('5','6f4b6612125fb3a0daecd2799dfd6c9c299424fd920f9b308110a2c1fbd8f443'),
+('6','4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a'),
+('7','19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7'),
+('8','6b51d431df5d7f141cbececcf79edf3dd861c3b4069f0b11661a3eefacbba918'),
+('9','b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9'),
+('10','4fc82b26aecb47d2868c4efbe3581732a3e7cbcc6c2efb32062c08170a05eeb8'),
+('11','4a44dc15364204a80fe80e9039455cc1608281820fe2b24f1e5233ade6af1dd5'),
+('12','3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278'),
+('13','18825963bca486408507a3ec26cb578a35efbf77182c0f1738502102c18890fa');
+INSERT INTO hosts (hostid,proxyid,host,status,ipmi_authtype,ipmi_privilege,ipmi_username,ipmi_password,name,flags,templateid,description,tls_connect,tls_accept,tls_issuer,tls_subject,tls_psk_identity,tls_psk,discover,custom_interfaces,uuid,name_upper,vendor_name,vendor_version,proxy_groupid,monitored_by,wizard_ready,readme) VALUES ('10001',NULL,'Linux by Zabbix agent','3','-1','2','','','Linux by Zabbix agent','0',NULL,'This is an official Linux template. It requires Zabbix agent 8.0 or newer.
+
+Notes on filesystem (FS) discovery:
+- The ext4/3/2 filesystem reserves space for privileged usage, typically set at 5% by default.
+- BTRFS allocates a default of 10% of the volume for its own needs.
+- To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: ''pused = 100 - 100 * (available / total - free + available)''
+- The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/387225-discussion-thread-for-official-zabbix-template-for-linux
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','f8f7908280354f2abeed07dc788c3747','LINUX BY ZABBIX AGENT','Zabbix','8.0-0',NULL,'0','1','## Overview
+
+This is an official Linux template. It requires Zabbix agent 8.0 or newer.
+
+#### Notes on filesystem (FS) discovery:
+- The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+- BTRFS allocates a default of 10% of the volume for its own needs.
+- To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: `pused = 100 - 100 * (available / total - free + available)`
+- The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.'),
+('10047',NULL,'Zabbix server health','3','-1','2','','','Zabbix server health','0',NULL,'This template is designed to monitor internal Zabbix metrics on the local Zabbix server.
+
+Link this template to the local Zabbix server host.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e2d2b4e4ac28483996cc11fe42823d57','ZABBIX SERVER HEALTH','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed to monitor internal Zabbix metrics on the local Zabbix server.
+
+## Setup
+
+Link this template to the local Zabbix server host.'),
+('10048',NULL,'Zabbix proxy health','3','-1','2','','','Zabbix proxy health','0',NULL,'This template is designed to monitor internal Zabbix metrics on the local Zabbix proxy.
+
+Link this template to the local Zabbix proxy host.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','dd114bf0fb2f46bc84840f1bb24e2b23','ZABBIX PROXY HEALTH','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed to monitor internal Zabbix metrics on the local Zabbix proxy.
+
+## Setup
+
+Link this template to the local Zabbix proxy host.'),
+('10074',NULL,'OpenBSD by Zabbix agent','3','-1','2','','','OpenBSD by Zabbix agent','0',NULL,'This is an Official OpenBSD template. It requires Zabbix agent 8.0 or newer.
+
+Notes on filesystem (FS) discovery:
+ - The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+ - BTRFS allocates a default of 10% of the volume for its own needs.
+ - To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: ''pused = 100 - 100 * (available / total - free + available)''
+ - The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','760be6e1c2194a5bb7c0df47cc5f71ca','OPENBSD BY ZABBIX AGENT','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This is an Official OpenBSD template. It requires Zabbix agent 8.0 or newer.
+
+#### Notes on filesystem (FS) discovery:
+- The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+- BTRFS allocates a default of 10% of the volume for its own needs.
+- To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: `pused = 100 - 100 * (available / total - free + available)`
+- The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.
+
+
+## Setup
+
+Install Zabbix agent on OpenBSD according to Zabbix documentation.'),
+('10075',NULL,'FreeBSD by Zabbix agent','3','-1','2','','','FreeBSD by Zabbix agent','0',NULL,'This is an official FreeBSD template. It requires Zabbix agent 8.0 or newer.
+
+Notes on filesystem (FS) discovery:
+ - The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+ - BTRFS allocates a default of 10% of the volume for its own needs.
+ - To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: ''pused = 100 - 100 * (available / total - free + available)''
+ - The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','a3dc630729e443139f4e608954fa6e19','FREEBSD BY ZABBIX AGENT','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This is an official FreeBSD template. It requires Zabbix agent 8.0 or newer.
+
+#### Notes on filesystem (FS) discovery:
+- The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+- BTRFS allocates a default of 10% of the volume for its own needs.
+- To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: `pused = 100 - 100 * (available / total - free + available)`
+- The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.
+
+
+## Setup
+
+Install Zabbix agent on FreeBSD according to Zabbix documentation.'),
+('10076',NULL,'AIX by Zabbix agent','3','-1','2','','','AIX by Zabbix agent','0',NULL,'This is an official AIX template. It requires Zabbix agent 8.0 or newer.
+
+Notes on filesystem (FS) discovery:
+ - The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+ - BTRFS allocates a default of 10% of the volume for its own needs.
+ - To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: ''pused = 100 - 100 * (available / total - free + available)''
+ - The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','7e6bb0931a72459db9514aa924b420bc','AIX BY ZABBIX AGENT','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This is an official AIX template. It requires Zabbix agent 8.0 or newer.
+
+#### Notes on filesystem (FS) discovery:
+- The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+- BTRFS allocates a default of 10% of the volume for its own needs.
+- To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: `pused = 100 - 100 * (available / total - free + available)`
+- The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.
+
+
+## Setup
+
+Install Zabbix agent on the AIX OS according to Zabbix documentation.'),
+('10077',NULL,'HP-UX by Zabbix agent','3','-1','2','','','HP-UX by Zabbix agent','0',NULL,'This is an official HP-UX template. It requires Zabbix agent 8.0 or newer.
+
+Notes on filesystem (FS) discovery:
+ - The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+ - BTRFS allocates a default of 10% of the volume for its own needs.
+ - To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: ''pused = 100 - 100 * (available / total - free + available)''
+ - The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','b1fd823d262042e08291313f72be9452','HP-UX BY ZABBIX AGENT','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This is an official HP-UX template. It requires Zabbix agent 8.0 or newer.
+
+#### Notes on filesystem (FS) discovery:
+- The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+- BTRFS allocates a default of 10% of the volume for its own needs.
+- To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: `pused = 100 - 100 * (available / total - free + available)`
+- The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.
+
+
+## Setup
+
+Install Zabbix agent on the HP-UX OS according to Zabbix documentation.'),
+('10078',NULL,'Solaris by Zabbix agent','3','-1','2','','','Solaris by Zabbix agent','0',NULL,'This is an official Solaris OS template. It requires Zabbix agent 8.0 or newer.
+
+Notes on filesystem (FS) discovery:
+ - The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+ - BTRFS allocates a default of 10% of the volume for its own needs.
+ - To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: ''pused = 100 - 100 * (available / total - free + available)''
+ - The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','eaf36c98b91843b7b79bd5184a23d377','SOLARIS BY ZABBIX AGENT','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This is an official Solaris OS template. It requires Zabbix agent 8.0 or newer.
+
+#### Notes on filesystem (FS) discovery:
+- The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+- BTRFS allocates a default of 10% of the volume for its own needs.
+- To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: `pused = 100 - 100 * (available / total - free + available)`
+- The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.
+
+
+## Setup
+
+Install Zabbix agent on Solaris OS according to Zabbix documentation.'),
+('10079',NULL,'macOS by Zabbix agent','3','-1','2','','','macOS by Zabbix agent','0',NULL,'This is an official macOS template. It requires Zabbix agent 8.0 or newer.
+
+Notes on filesystem (FS) discovery:
+ - The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+ - BTRFS allocates a default of 10% of the volume for its own needs.
+ - To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: ''pused = 100 - 100 * (available / total - free + available)''
+ - The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','f895df5b37494f668cde1a2388d7af8b','MACOS BY ZABBIX AGENT','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This is an official MacOS template. It requires Zabbix agent 8.0 or newer.
+
+#### Notes on filesystem (FS) discovery:
+- The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+- BTRFS allocates a default of 10% of the volume for its own needs.
+- To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: `pused = 100 - 100 * (available / total - free + available)`
+- The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.
+
+## Setup
+
+Install Zabbix agent on macOS according to Zabbix documentation.'),
+('10081',NULL,'Windows by Zabbix agent','3','-1','2','','','Windows by Zabbix agent','0',NULL,'This is an official Windows template. It requires Zabbix agent 8.0 or newer.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/387224-discussion-thread-for-official-zabbix-template-for-windows
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','13b06904a6bf41cbb795e3193d896340','WINDOWS BY ZABBIX AGENT','Zabbix','8.0-0',NULL,'0','1','## Overview
+
+This is an official Windows template. It requires Zabbix agent 8.0 or newer.'),
+('10084',NULL,'Zabbix server','0','-1','2','','','Zabbix server','0',NULL,'','1','1','','','','','0','0','','ZABBIX SERVER','','',NULL,'0','0',''),
+('10169',NULL,'Generic Java JMX','3','-1','2','','','Generic Java JMX','0',NULL,'Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','72aab08f7f27406a8f2c291648e5ba95','GENERIC JAVA JMX','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+Official JMX Template from Zabbix distribution. Could be useful for many Java Applications (JMX).'),
+('10171',NULL,'Intel SR1530 IPMI','3','-1','2','','','Intel SR1530 IPMI','0',NULL,'Template for monitoring Intel SR1530 server system.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','f01bd64eef4049fabe087cccae590226','INTEL SR1530 IPMI','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+Template for monitoring Intel SR1530 server system.'),
+('10172',NULL,'Intel SR1630 IPMI','3','-1','2','','','Intel SR1630 IPMI','0',NULL,'Template for monitoring Intel SR1630 server system.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','2327c665b46e4aa781d41240168c3867','INTEL SR1630 IPMI','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+Template for monitoring Intel SR1630 server system.'),
+('10173',NULL,'VMware','3','-1','2','','','VMware','0',NULL,'You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/.
+
+Note: To enable discovery of hardware sensors of VMware Hypervisors, set the macro ''{$VMWARE.HV.SENSOR.DISCOVERY}'' to the value ''true'' on the discovered host level.
+
+Note: To create custom performance counter see documentation: https://www.zabbix.com/documentation/8.0/manual/vm_monitoring/vmware_keys#footnotes.
+
+Note: To get all supported counters and generate path for custom performance counter see documentation: https://www.zabbix.com/documentation/8.0/manual/appendix/items/perf_counters.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','56079badd056419383cc26e6a4fcc7e0','VMWARE','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template set is designed for the effortless deployment of VMware vCenter and ESX hypervisor monitoring and doesn''t require any external scripts.
+
+- The template "VMware Guest" is used in discovery and normally should not be manually linked to a host.
+- The template "VMware Hypervisor" can be used in discovery as well as manually linked to a host.
+
+For additional information, please see [Zabbix documentation on VM monitoring](https://www.zabbix.com/documentation/8.0/manual/vm_monitoring).
+
+## Setup
+
+1. Compile Zabbix server with the required options (`--with-libxml2` and `--with-libcurl`).
+2. Set the `StartVMwareCollectors` option in the Zabbix server configuration file to "1" or more.
+3. Create a new host.
+4. If you want to use a separate user for monitoring, make sure that the user is a member of the `SystemConfiguration.ReadOnly` and `vStatsGroup` groups.
+Set the host wizard configuration fields required for VMware authentication: `VMware URL`, `VMware username` and `VMware password`.
+5. Link the template to the host created earlier.
+
+Note: To enable discovery of hardware sensors of VMware hypervisors, set the host wizard configuration field `Monitoring of hardware sensors` to the selected state.
+
+Additional resources:
+- How to [create a custom performance counter](https://www.zabbix.com/documentation/8.0/manual/vm_monitoring/vmware_keys#footnotes).
+- How to get all supported counters and [generate a path for the custom performance counter](https://www.zabbix.com/documentation/8.0/manual/appendix/items/perf_counters).'),
+('10174',NULL,'VMware Guest','3','-1','2','','','VMware Guest','0',NULL,'Note: To enable trigger for free space for guest VM, set macro ''{$VMWARE.VM.FS.TRIGGER.USED}'' to the value ''1'' on the discovered host level.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','7942fb93ae3b47cf9ca0ea4beb0675ce','VMWARE GUEST','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+This template is used in low-level discovery and will be auto-assigned to host prototypes. Additional configuration is not required.'),
+('10175',NULL,'VMware Hypervisor','3','-1','2','','','VMware Hypervisor','0',NULL,'You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/.
+
+This template can be used in discovery as well as manually linked to a host. To use this template as manually linked to a host, attach it to the host and set manually the value of ''{$VMWARE.HV.UUID}'' macro.
+
+Note: To create custom performance counter see documentation: https://www.zabbix.com/documentation/8.0/manual/vm_monitoring/vmware_keys#footnotes.
+
+Note: To get all supported counters and generate path for custom performance counter see documentation: https://www.zabbix.com/documentation/8.0/manual/appendix/items/perf_counters.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','5899b2f0aced4085b5ac25d0461b3425','VMWARE HYPERVISOR','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is designed for the effortless deployment of VMware ESX hypervisor monitoring and doesn''t require any external scripts.
+
+This template can be used in discovery as well as manually linked to a host.
+
+For additional information, please see [Zabbix documentation on VM monitoring](https://www.zabbix.com/documentation/8.0/manual/vm_monitoring).
+
+To use this template as manually linked to a host, attach it to the host and manually set the `Hypervisor UUID` host wizard configuration field.
+
+## Setup
+
+To use this template as manually linked to a host:
+ 1. Compile Zabbix server with the required options (`--with-libxml2` and `--with-libcurl`).
+ 2. Set the `StartVMwareCollectors` option in the Zabbix server configuration file to "1" or more.
+ 3. Set the host wizard configuration fields required for VMware authentication: `VMware URL`, `VMware username` and `VMware password`.
+ 4. To get the hypervisor UUID, enable access to the hypervisor via SSH and log in via SSH using a valid login and password.
+ 5. Run the following command and specify the UUID in the `Hypervisor UUID` host wizard configuration field:
+ ```text
+ vim-cmd hostsvc/hostsummary | grep uuid
+ ```
+
+Note: To enable discovery of hardware sensors of VMware hypervisors, set the host wizard configuration field `Monitoring of hardware sensors` to the selected state.'),
+('10207',NULL,'Alcatel Timetra TiMOS by SNMP','3','-1','2','','','Alcatel Timetra TiMOS by SNMP','0',NULL,'Template Net Alcatel Timetra TiMOS
+
+MIBs used:
+EtherLike-MIB
+TIMETRA-SYSTEM-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+TIMETRA-CHASSIS-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','53044571fb864d87af32473e08c76d0b','ALCATEL TIMETRA TIMOS BY SNMP','Zabbix','8.0-2',NULL,'0','1','Template Net Alcatel Timetra TiMOS
+
+ MIBs used:
+ EtherLike-MIB
+ TIMETRA-SYSTEM-MIB
+ HOST-RESOURCES-MIB
+ SNMPv2-MIB
+ TIMETRA-CHASSIS-MIB
+ IF-MIB'),
+('10208',NULL,'Brocade FC by SNMP','3','-1','2','','','Brocade FC by SNMP','0',NULL,'Template Net Brocade FC
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+SW-MIB
+IF-MIB
+
+Known Issues:
+
+ Description: no IF-MIB::ifAlias is available
+ Version: v6.3.1c, v7.0.0c, v7.4.1c
+ Device: all
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','de96d02bd5f242bfa31308ae2131d03f','BROCADE FC BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+https://community.brocade.com/dtscp75322/attachments/dtscp75322/fibre/25235/1/FOS_MIB_Reference_v740.pdf
+
+### Known Issues
+- Description: no IF-MIB::ifAlias is available
+ - version: v6.3.1c, v7.0.0c, v7.4.1c'),
+('10210',NULL,'Brocade_Foundry Nonstackable by SNMP','3','-1','2','','','Brocade_Foundry Nonstackable by SNMP','0',NULL,'Template Net Brocade Foundry Nonstackable
+
+MIBs used:
+FOUNDRY-SN-AGENT-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','6ecfb7083ddf45f183ab4be50cfba37a','BROCADE_FOUNDRY NONSTACKABLE BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+For devices(old Foundry devices, MLXe and so on) that doesn''t support Stackable SNMP Tables: snChasFan2Table, snChasPwrSupply2Table,snAgentTemp2Table -
+FOUNDRY-SN-AGENT-MIB::snChasFanTable, snChasPwrSupplyTable,snAgentTempTable are used instead.
+For example:
+The objects in table snChasPwrSupply2Table is not supported on the NetIron and the FastIron SX devices.
+snChasFan2Table is not supported on the NetIron devices.
+snAgentTemp2Table is not supported on old versions of MLXe.'),
+('10211',NULL,'Brocade_Foundry Stackable by SNMP','3','-1','2','','','Brocade_Foundry Stackable by SNMP','0',NULL,'Template Brocade Foundry Stackable
+
+MIBs used:
+FOUNDRY-SN-AGENT-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+FOUNDRY-SN-STACKING-MIB
+IF-MIB
+
+Known Issues:
+
+ Description: Correct fan(returns fan status as ''other(1)'' and temperature (returns 0) for the non-master Switches are not available in SNMP
+ Version: Version 08.0.40b and above
+ Device: ICX 7750 in stack
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','f64ad01567914165a493815e492fb315','BROCADE_FOUNDRY STACKABLE BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+For devices(most of the IronWare Brocade devices) that support Stackable SNMP Tables in FOUNDRY-SN-AGENT-MIB: snChasFan2Table, snChasPwrSupply2Table,snAgentTemp2Table - so objects from all Stack members are provided.'),
+('10218',NULL,'Cisco IOS by SNMP','3','-1','2','','','Cisco IOS by SNMP','0',NULL,'Template Cisco IOS Software releases 12.2(3.5) or later
+
+MIBs used:
+CISCO-MEMORY-POOL-MIB
+IF-MIB
+EtherLike-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+CISCO-ENVMON-MIB
+CISCO-PROCESS-MIB
+ENTITY-MIB
+
+Known Issues:
+
+ Description: no if(in|out)(Errors|Discards) are available for vlan ifType
+ Version: IOS for example: 12.1(22)EA11, 15.4(3)M2
+ Device: C2911, C7600
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','aa3ce9bd8c1d40a2b0f83f9e642e88ee','CISCO IOS BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+### Known Issues
+
+- Description: no if(in|out)(Errors|Discards) are available for vlan ifType
+ - Version: IOS for example: 12.1(22)EA11, 15.4(3)M2
+ - Device: C2911, C7600'),
+('10220',NULL,'Cisco IOS prior to 12.0_3_T by SNMP','3','-1','2','','','Cisco IOS prior to 12.0_3_T by SNMP','0',NULL,'Cisco IOS Software releases prior to 12.0(3)T
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+OLD-CISCO-CPU-MIB
+CISCO-ENVMON-MIB
+CISCO-MEMORY-POOL-MIB
+ENTITY-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','1bb42fbdb9054645a62ff81f14ba3b99','CISCO IOS PRIOR TO 12.0_3_T BY SNMP','Zabbix','8.0-2',NULL,'0','1',''),
+('10221',NULL,'Dell Force S-Series by SNMP','3','-1','2','','','Dell Force S-Series by SNMP','0',NULL,'Template Dell Force S-Series
+
+MIBs used:
+F10-S-SERIES-CHASSIS-MIB
+EtherLike-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e5ec7acc7efc4ac491b6fa552ab077ae','DELL FORCE S-SERIES BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+These high performance and low latency Gigabit Ethernet switches deliver the critical functionality that advanced data center network edges demand.'),
+('10222',NULL,'D-Link DES 7200 by SNMP','3','-1','2','','','D-Link DES 7200 by SNMP','0',NULL,'Template D-Link DES 7200
+
+MIBs used:
+ENTITY-MIBdescription has changed
+IF-MIB
+MY-PROCESS-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MY-MEMORY-MIB
+ENTITY-MIB
+MY-SYSTEM-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','395184b5d5b048a68e06c91154c56847','D-LINK DES 7200 BY SNMP','Zabbix','8.0-2',NULL,'0','1',''),
+('10223',NULL,'D-Link DES_DGS Switch by SNMP','3','-1','2','','','D-Link DES_DGS Switch by SNMP','0',NULL,'Template D-Link DES_DGS Switch
+
+MIBs used:
+EQUIPMENT-MIB
+IF-MIB
+DLINK-AGENT-MIB
+EtherLike-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+ENTITY-MIB
+
+Known Issues:
+
+ Description: D-Link reports missing PSU as fail(4)
+ Version: Firmware: 1.73R008,hardware revision: B1
+ Device: DGS-3420-26SC Gigabit Ethernet Switch
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','d3176749a5274264938f487cd89d17eb','D-LINK DES_DGS SWITCH BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is designed for the effortless deployment of D-Link DES_DGS Switch monitoring by Zabbix via SNMP and doesn''t require any external scripts.
+
+### Known Issues:
+
+Description: D-Link reports missing PSU as fail(4)
+ - version: Firmware: 1.73R008,hardware revision: B1
+ - device: DGS-3420-26SC Gigabit Ethernet Switch'),
+('10224',NULL,'Extreme EXOS by SNMP','3','-1','2','','','Extreme EXOS by SNMP','0',NULL,'Template Extreme EXOS
+
+MIBs used:
+EXTREME-SYSTEM-MIB
+IF-MIB
+EtherLike-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+EXTREME-SOFTWARE-MONITOR-MIB
+ENTITY-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','861dbdece18f4b8f85214a319995eb3e','EXTREME EXOS BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+ExtremeXOS is the software or the network operating system used in newer Extreme Networks network switches. It is Extreme Networks second generation operating system after the VxWorks based ExtremeWare operating system. ExtremeXOS is based on the Linux kernel and BusyBox.'),
+('10226',NULL,'Network Generic Device by SNMP','3','-1','2','','','Network Generic Device by SNMP','0',NULL,'Template Net Network Generic Device
+
+MIBs used:
+EtherLike-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','67332e679035423f85090aa985947c36','NETWORK GENERIC DEVICE BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+Use this template if you can''t find the template for specific vendor or device family.'),
+('10227',NULL,'HP Comware HH3C by SNMP','3','-1','2','','','HP Comware HH3C by SNMP','0',NULL,'Template Net HP Comware (HH3C)
+
+MIBs used:
+EtherLike-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+ENTITY-MIB
+HH3C-ENTITY-EXT-MIB
+IF-MIB
+
+Known Issues:
+
+ Description: No temperature sensors. All entities of them return 0 for HH3C-ENTITY-EXT-MIB::hh3cEntityExtTemperature
+ Version: 1910-48 Switch Software Version 5.20.99, Release 1116 Copyright(c)2010-2016 Hewlett Packard Enterprise Development LP
+ Device: HP 1910-48
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','57aeccd43b744942b9555269b79a96ad','HP COMWARE HH3C BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+http://certifiedgeek.weebly.com/blog/hp-comware-snmp-mib-for-cpu-memory-and-temperature
+http://www.h3c.com.hk/products___solutions/technology/system_management/configuration_example/200912/656451_57_0.htm
+
+### Known Issues
+
+Description: No temperature sensors. All entities of them return 0 for HH3C-ENTITY-EXT-MIB::hh3cEntityExtTemperature
+- Version: 1910-48 Switch Software Version 5.20.99, Release 1116 Copyright(c)2010-2016 Hewlett Packard Enterprise Development LP
+- Device: HP 1910-48'),
+('10229',NULL,'Huawei VRP by SNMP','3','-1','2','','','Huawei VRP by SNMP','0',NULL,'Template Net Huawei VRP
+
+MIBs used:
+EtherLike-MIB
+HUAWEI-ENTITY-EXTENT-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+ENTITY-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','ad4c3dad4b7b492685d1fd3bd3a664f9','HUAWEI VRP BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+Reference: https://www.slideshare.net/Huanetwork/huawei-s5700-naming-conventions-and-port-numbering-conventions
+Reference: http://support.huawei.com/enterprise/KnowledgebaseReadAction.action?contentId=KB1000090234'),
+('10230',NULL,'Intel_Qlogic Infiniband by SNMP','3','-1','2','','','Intel_Qlogic Infiniband by SNMP','0',NULL,'Template Net Intel_Qlogic Infiniband
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+ICS-CHASSIS-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','6f7f2c44e13a46a4b219fbb5db92f3f7','INTEL_QLOGIC INFINIBAND BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+The Intel® 12200 is a 36-port, 40Gbps switch based on InfiniBand* architecture that cost-effectively supports a cluster of up to 36 servers, or provides an edge switch option for a larger fabric. This fixed-configuration switch is a member of the 12000 series, which delivers an exceptional set of high-speed networking features and functions.'),
+('10231',NULL,'Juniper by SNMP','3','-1','2','','','Juniper by SNMP','0',NULL,'Template Net Juniper
+
+MIBs used:
+EtherLike-MIB
+JUNIPER-ALARM-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+JUNIPER-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','a326034825984bbd8a3a5885f3939bb3','JUNIPER BY SNMP','Zabbix','8.0-2',NULL,'0','1','Template Net Juniper
+
+ MIBs used:
+ EtherLike-MIB
+ JUNIPER-ALARM-MIB
+ HOST-RESOURCES-MIB
+ SNMPv2-MIB
+ JUNIPER-MIB
+ IF-MIB'),
+('10233',NULL,'Mikrotik by SNMP','3','-1','2','','','Mikrotik by SNMP','0',NULL,'Template Net Mikrotik
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Known Issues:
+
+ Description: Doesn''t have ifHighSpeed filled. Fixed in more recent versions
+ Version: RouterOS 6.28 or lower
+
+ Description: Doesn''t have any temperature sensors
+ Version: RouterOS 6.38.5
+ Device: Mikrotik 941-2nD, Mikrotik 951G-2HnD
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','815b5a81b29a477695fddbd533ad9c84','MIKROTIK BY SNMP','Zabbix','8.0-3',NULL,'0','1','## Overview
+
+At the core of all MikroTik hardware is RouterOS, a powerful and versatile operating system. It offers a vast array of networking features.
+
+### Known Issues
+
+- Description: Doesn''t have ifHighSpeed filled. Fixed in more recent versions
+ - Version: RouterOS 6.28 or lower
+
+- Description: Doesn''t have any temperature sensors
+ - Version: RouterOS 6.38.5
+ - Device: Mikrotik 941-2nD, Mikrotik 951G-2HnD'),
+('10234',NULL,'Netgear Fastpath by SNMP','3','-1','2','','','Netgear Fastpath by SNMP','0',NULL,'Template Net Netgear Fastpath
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+FASTPATH-SWITCHING-MIB
+FASTPATH-BOXSERVICES-PRIVATE-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','5920713da492452889adabc25e259caa','NETGEAR FASTPATH BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+https://kb.netgear.com/24352/MIBs-for-Smart-switches'),
+('10235',NULL,'QTech QSW by SNMP','3','-1','2','','','QTech QSW by SNMP','0',NULL,'Template Net QTech QSW
+
+MIBs used:
+QTECH-MIB
+EtherLike-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+ENTITY-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','21f3e79e1d2e4f5e868d1ef81c94bbfd','QTECH QSW BY SNMP','Zabbix','8.0-2',NULL,'0','1','Template Net QTech QSW
+
+ MIBs used:
+ QTECH-MIB
+ EtherLike-MIB
+ HOST-RESOURCES-MIB
+ SNMPv2-MIB
+ ENTITY-MIB
+ IF-MIB'),
+('10236',NULL,'TP-LINK by SNMP','3','-1','2','','','TP-LINK by SNMP','0',NULL,'Template Net TP-LINK
+
+MIBs used:
+TPLINK-SYSINFO-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+TPLINK-SYSMONITOR-MIB
+IF-MIB
+
+Known Issues:
+
+ Description: Default sysLocation, sysName and sysContact is not filled with proper data. Real hostname and location can be found only in private branch (TPLINK-SYSINFO-MIB). Please check whether this problem exists in the latest firmware: https://www.tp-link.com/en/support/download/t2600g-28ts/#Firmware
+ Version: 2.0.0 Build 20170628 Rel.55184 (Beta)
+ Device: T2600G-28TS 2.0
+
+ Description: The Serial number of the product (tpSysInfoSerialNum) is missing in HW versions prior to V2_170323
+ Version: Prior to version V2_170323
+ Device: T2600G-28TS 2.0
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','2b9039885edf45b8bdd39f16dd069133','TP-LINK BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+Link to MIBs: https://www.tp-link.com/en/support/download/t2600g-28ts/#MIBs_Files
+Sample device overview page: https://www.tp-link.com/en/business-networking/managed-switch/t2600g-28ts/#overview
+Emulation page (web): https://emulator.tp-link.com/T2600G-28TS(UN)_1.0/Index.htm
+
+### Known issues
+
+- Description: ''Default sysLocation, sysName and sysContact is not filled with proper data. Real hostname and location can be found only in private branch (TPLINK-SYSINFO-MIB). Please check whether this problem exists in the latest firmware: https://www.tp-link.com/en/support/download/t2600g-28ts/#Firmware''
+ version: 2.0.0 Build 20170628 Rel.55184 (Beta)
+ device: T2600G-28TS 2.0
+
+- Description: The Serial number of the product (tpSysInfoSerialNum) is missing in HW versions prior to V2_170323
+ version: Prior to version V2_170323
+ device: T2600G-28TS 2.0'),
+('10237',NULL,'Ubiquiti AirOS by SNMP','3','-1','2','','','Ubiquiti AirOS by SNMP','0',NULL,'Template Net Ubiquiti AirOS
+
+MIBs used:
+FROGFOOT-RESOURCES-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+IEEE802dot11-MIB
+IF-MIB
+
+Known Issues:
+
+ Description: UBNT unifi reports speed: like IF-MIB::ifSpeed.1 = Gauge32: 4294967295 for all interfaces
+ Version: Firmware: BZ.ar7240.v3.7.51.6230.170322.1513
+ Device: UBNT UAP-LR
+
+ Description: UBNT AirMax(NanoStation, NanoBridge etc) reports ifSpeed: as 0 for VLAN and wireless(ath0) interfaces
+ Version: Firmware: XW.ar934x.v5.6-beta4.22359.140521.1836
+ Device: NanoStation M5
+
+ Description: UBNT AirMax(NanoStation, NanoBridge etc) reports always return ifType: as ethernet(6) even for wifi,vlans and other types
+ Version: Firmware: XW.ar934x.v5.6-beta4.22359.140521.1836
+ Device: NanoStation M5
+
+ Description: ifXTable is not provided in IF-MIB. So Interfaces Simple Template is used instead
+ Version: all above
+ Device: NanoStation, UAP-LR
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','6c235d126c1f4895acfe2156b140a886','UBIQUITI AIROS BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is designed for the effortless deployment of Ubiquiti AirOS monitoring by Zabbix via SNMP and doesn''t require any external scripts.
+
+### Known issues
+
+- Description: ''UBNT unifi reports speed: like IF-MIB::ifSpeed.1 = Gauge32: 4294967295 for all interfaces''
+ - version: ''Firmware: BZ.ar7240.v3.7.51.6230.170322.1513''
+ - device: UBNT UAP-LR
+- Description: ''UBNT AirMax(NanoStation, NanoBridge etc) reports ifSpeed: as 0 for VLAN and wireless(ath0) interfaces''
+ - version: ''Firmware: XW.ar934x.v5.6-beta4.22359.140521.1836''
+ - device: NanoStation M5
+- Description: ''UBNT AirMax(NanoStation, NanoBridge etc) reports always return ifType: as ethernet(6) even for wifi,vlans and other types''
+ - version: ''Firmware: XW.ar934x.v5.6-beta4.22359.140521.1836''
+ - device: NanoStation M5
+- Description: ifXTable is not provided in IF-MIB. So Interfaces Simple Template is used instead
+ - version: all above
+ - device: NanoStation, UAP-LR'),
+('10248',NULL,'Linux by SNMP','3','-1','2','','','Linux by SNMP','0',NULL,'This is an official Linux template. It requires an SNMP client.
+
+MIBs used:
+EtherLike-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+UCD-DISKIO-MIB
+UCD-SNMP-MIB
+IF-MIB
+
+Notes on filesystem (FS) discovery:
+ - The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+ - BTRFS allocates a default of 10% of the volume for its own needs.
+ - To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: ''pused = 100 * (used / used + available)''
+ - The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/387225-discussion-thread-for-official-zabbix-template-for-linux
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','4d3a7adbb6964bd08f2b9d28e0da6496','LINUX BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This is an official Linux template. It requires an SNMP client.
+
+#### Notes on filesystem (FS) discovery:
+- The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+- BTRFS allocates a default of 10% of the volume for its own needs.
+- To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: `pused = 100 * (used / used + available)`
+- The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.
+
+## Setup
+
+Install snmpd agent on Linux OS, enable SNMPv2.
+
+Make sure access to UCD-SNMP-MIB is allowed from Zabbix server/proxy host, since,
+by default, snmpd (for example, in Ubuntu) limits access to basic system information only:
+
+```text
+rocommunity public default -V systemonly
+```
+
+Ensure snmpd is monitoring disks, using `includeALLDisks` or `disk` options. Example:
+```
+includeALLDisks 0% # monitors all disks starting with 0% fill rate
+# disk / 0% # monitor only / root volume starting with 0% fill rate
+```
+Make sure you change that in order to read metrics of UCD-SNMP-MIB and UCD-DISKIO-MIB.
+Please refer to the documentation: http://www.net-snmp.org/wiki/index.php/Vacm.
+
+You can also try to use `snmpconf`: http://www.net-snmp.org/wiki/index.php/TUT:snmpd_configuration.'),
+('10249',NULL,'Windows by SNMP','3','-1','2','','','Windows by SNMP','0',NULL,'This is an official Windows template. It requires an SNMP client.
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+IF-MIB
+
+Known Issues:
+
+ Description:
+ 64-bit I/O is not supported even though `IfxTable` is present.
+ Currently, Windows gets its interface status from MIB-2. Since these 64-bit SNMP counters (`ifHCInOctets`, `ifHCOutOctets`, etc.) are defined as an extension to IF-MIB, Microsoft has not implemented it.
+ Version: Win2008, Win2012R2.
+
+ Description: MIB is not supported
+ Version: WindowsXP
+
+ Description: EtherLike MIB is not supported
+ Version: any
+
+ Description:
+ HOST-RESOURCES-MIB::hrStorageSize is limited to number 2147483647.
+ Storage size is calculated using: `hrStorageSize` and `hrStorageAllocationUnits`.
+ Allocation size of 512 bytes, sets the limit of monitored device to 1TB.
+ Version: any
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','f9a59315c8944853bb91c0a9ec3056d7','WINDOWS BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This is an official Windows template. It requires an SNMP client.
+
+MIBs used:
+- HOST-RESOURCES-MIB
+- SNMPv2-MIB
+- IF-MIB
+
+### Known Issues
+
+- 64-bit I/O is not supported even though `IfxTable` is present.
+ Currently, Windows gets its interface status from MIB-2. Since these 64-bit SNMP counters (`ifHCInOctets`, `ifHCOutOctets`, etc.) are defined as an extension to IF-MIB, Microsoft has not implemented it.
+ - Version: Win2008, Win2012R2.
+- `ifXTable` is not supported.
+ - Version: WindowsXP
+- EtherLike MIB is not supported
+ - Version: any
+- HOST-RESOURCES-MIB::hrStorageSize is limited to number 2147483647.
+ Storage size is calculated using: `hrStorageSize` and `hrStorageAllocationUnits`.
+ An allocation size of 512 bytes, sets the limit of monitored device to 1TB.
+
+ | **hrStorageAllocationUnits** | **Max size (TB)** |
+ |:-----------------------------|-------------------:|
+ | 512 bytes | 1 |
+ | 1024 bytes | 2 |
+ | 2048 bytes | 4 |
+ | 64 KB | 128 |
+ - Version: any'),
+('10250',NULL,'HP Enterprise Switch by SNMP','3','-1','2','','','HP Enterprise Switch by SNMP','0',NULL,'Template Net HP Enterprise Switch
+
+MIBs used:
+NETSWITCH-MIB
+HP-ICF-CHASSIS
+ENTITY-SENSORS-MIB
+IF-MIB
+EtherLike-MIB
+SEMI-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+ENTITY-MIB
+STATISTICS-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','cce20a5d149a48b7ac7f5383c3510883','HP ENTERPRISE SWITCH BY SNMP','Zabbix','8.0-2',NULL,'0','1',''),
+('10251',NULL,'Mellanox by SNMP','3','-1','2','','','Mellanox by SNMP','0',NULL,'The updated template for monitoring the Mellanox network switches over SNMP agent. All items collected in one template without any linked templates.
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+ENTITY-SENSORS-MIB
+ENTITY-STATE-MIB
+ENTITY-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','a60798c651604d93a062bec0f8a89751','MELLANOX BY SNMP','Zabbix','8.0-2',NULL,'0','1',''),
+('10253',NULL,'Cisco IOS versions 12.0_3_T-12.2_3.5 by SNMP','3','-1','2','','','Cisco IOS versions 12.0_3_T-12.2_3.5 by SNMP','0',NULL,'Cisco IOS Software releases later to 12.0(3)T and prior to 12.2(3.5)
+
+MIBs used:
+CISCO-MEMORY-POOL-MIB
+IF-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+CISCO-ENVMON-MIB
+CISCO-PROCESS-MIB
+ENTITY-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','40c233aaa3424fd29dc378022ff3461d','CISCO IOS VERSIONS 12.0_3_T-12.2_3.5 BY SNMP','Zabbix','8.0-2',NULL,'0','1',''),
+('10254',NULL,'Arista by SNMP','3','-1','2','','','Arista by SNMP','0',NULL,'Template Net Arista
+
+MIBs used:
+ENTITY-SENSORS-MIB
+ENTITY-STATE-MIB
+IF-MIB
+EtherLike-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+ENTITY-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','26674f62500e4e79b9f470bbf962130d','ARISTA BY SNMP','Zabbix','8.0-2',NULL,'0','1',''),
+('10255',NULL,'Dell iDRAC by SNMP','3','-1','2','','','Dell iDRAC by SNMP','0',NULL,'Template for Dell servers with iDRAC version 7 and later.
+
+MIBs used:
+HOST-RESOURCES-MIB
+IDRAC-MIB-SMIv2
+SNMPv2-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/426752-discussion-thread-for-official-zabbix-dell-templates
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','43dc5c8a9a0e4786b64e44422c7f32b4','DELL IDRAC BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This is a template for monitoring Dell iDRAC servers with iDRAC version 7 (and later) via Zabbix SNMP agent that works without any external scripts.'),
+('10256',NULL,'HP iLO by SNMP','3','-1','2','','','HP iLO by SNMP','0',NULL,'Template Server HP iLO
+MIBs used:
+HOST-RESOURCES-MIB
+CPQHLTH-MIB
+SNMPv2-MIB
+CPQSINFO-MIB
+CPQIDA-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','c2a7ddca051d4b4a9553f339c57e47a9','HP ILO BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+for HP iLO adapters that support SNMP get. Or via operating system, using SNMP HP subagent'),
+('10258',NULL,'IBM IMM by SNMP','3','-1','2','','','IBM IMM by SNMP','0',NULL,'Template Server IBM IMM
+
+MIBs used:
+IMM-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+
+Known Issues:
+
+ Description: Some IMMs (IMM1) do not return disks
+ Version: IMM1
+ Device: IBM x3250M3
+
+ Description: Some IMMs (IMM1) do not return fan status: fanHealthStatus
+ Version: IMM1
+ Device: IBM x3250M3
+
+ Description: IMM1 servers (M2, M3 generations) sysObjectID is NET-SNMP-MIB::netSnmpAgentOIDs.10
+ Version: IMM1
+ Device: IMM1 servers (M2,M3 generations)
+
+ Description: IMM1 servers (M2, M3 generations) only Ambient temperature sensor available
+ Version: IMM1
+ Device: IMM1 servers (M2,M3 generations)
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','c9e1acd3ae4a427ab39724b6bcaf839e','IBM IMM BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+for IMM2 and IMM1 IBM serverX hardware
+
+### Known Issues:
+
+Description: Some IMMs (IMM1) do not return disks
+ - version: IMM1
+ - device: IBM x3250M3
+
+Description: Some IMMs (IMM1) do not return fan status: fanHealthStatus
+ - version: IMM1
+ - device: IBM x3250M3
+
+Description: IMM1 servers (M2, M3 generations) sysObjectID is NET-SNMP-MIB::netSnmpAgentOIDs.10
+ - version: IMM1
+ - device: IMM1 servers (M2,M3 generations)
+
+Description: IMM1 servers (M2, M3 generations) only Ambient temperature sensor available
+ - version: IMM1
+ - device: IMM1 servers (M2,M3 generations)'),
+('10259',NULL,'Supermicro Aten by SNMP','3','-1','2','','','Supermicro Aten by SNMP','0',NULL,'Template Server Supermicro Aten
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+ATEN-IPMI-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','cf0947cc05d3450b9a6d66b2eb180482','SUPERMICRO ATEN BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+for BMC ATEN IPMI controllers of Supermicro servers
+https://www.supermicro.com/solutions/IPMI.cfm'),
+('10260',NULL,'Apache Tomcat by JMX','3','-1','2','','','Apache Tomcat by JMX','0',NULL,'The template to monitor Apache Tomcat by Zabbix that work without any external scripts.
+The metrics are collected by JMX.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/411862-discussion-thread-for-official-zabbix-template-tomcat
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','3cc8c9ae7055458c9a803597007f70bd','APACHE TOMCAT BY JMX','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+Metrics are collected by JMX.
+
+1. Enable and configure JMX access to Apache Tomcat.
+ See documentation for [instructions](https://tomcat.apache.org/tomcat-10.0-doc/monitoring.html#Enabling_JMX_Remote) (chose your version).
+2. If your Tomcat installation require authentication for JMX, set values in host wizard configuration fields `Username` and `Password`.
+3. You can set custom macro values and add macros with context for specific metrics following macro description.'),
+('10261',NULL,'Remote Zabbix server health','3','-1','2','','','Remote Zabbix server health','0',NULL,'This template is designed to monitor internal Zabbix metrics on the remote Zabbix server.
+
+Specify the address of the remote Zabbix server by changing the {$ZABBIX.SERVER.ADDRESS} and {$ZABBIX.SERVER.PORT} macros. Don''t forget to adjust the "StatsAllowedIP" parameter in the remote server''s configuration file to allow the collection of statistics.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','79b16cbbe593444eae3de66de0cb566b','REMOTE ZABBIX SERVER HEALTH','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is designed to monitor internal Zabbix metrics on the remote Zabbix server.
+
+## Setup
+
+Specify the address of the remote Zabbix server as the values for the `Zabbix server Address` and `Zabbix server Port` configuration fields. Don''t forget to adjust the `StatsAllowedIP` parameter in the remote server''s configuration file to allow the collection of statistics.'),
+('10262',NULL,'Remote Zabbix proxy health','3','-1','2','','','Remote Zabbix proxy health','0',NULL,'This template is designed to monitor internal Zabbix metrics on the remote Zabbix proxy.
+
+Specify the address of the remote Zabbix proxy by updating the {$ZABBIX.PROXY.ADDRESS} and {$ZABBIX.PROXY.PORT} macros. Don''t forget to adjust the "StatsAllowedIP" parameter in the remote proxy''s configuration file to allow the collection of statistics.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','970c2342146549768e6b91a26089bcdf','REMOTE ZABBIX PROXY HEALTH','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is designed to monitor internal Zabbix metrics on the remote Zabbix proxy.
+
+## Setup
+
+Specify the address of the remote Zabbix proxy as the values for the `Zabbix proxy Address` and `Zabbix proxy Port` configuration fields. Don''t forget to adjust the `StatsAllowedIP` parameter in the remote proxy''s configuration file to allow the collection of statistics.'),
+('10264',NULL,'Apache by Zabbix agent','3','-1','2','','','Apache by Zabbix agent','0',NULL,'Get metrics from mod_status module using HTTP agent.
+https://httpd.apache.org/docs/current/mod/mod_status.html
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/384764-discussion-thread-for-official-zabbix-template-apache
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','a8d91e4f36794e32b73090d5edf3d7ae','APACHE BY ZABBIX AGENT','Zabbix','8.0-0',NULL,'0','1','## Overview
+
+This template is designed for the effortless deployment of Apache monitoring by Zabbix via Zabbix agent and doesn''t require any external scripts.
+The template `Apache by Zabbix agent` - collects metrics by polling [mod_status](https://httpd.apache.org/docs/current/mod/mod_status.html) locally with Zabbix agent:
+
+```text
+127.0.0.1
+ServerVersion: Apache/2.4.41 (Unix)
+ServerMPM: event
+Server Built: Aug 14 2019 00:35:10
+CurrentTime: Friday, 16-Aug-2019 12:38:40 UTC
+RestartTime: Wednesday, 14-Aug-2019 07:58:26 UTC
+ParentServerConfigGeneration: 1
+ParentServerMPMGeneration: 0
+ServerUptimeSeconds: 189613
+ServerUptime: 2 days 4 hours 40 minutes 13 seconds
+Load1: 4.60
+Load5: 1.20
+Load15: 0.47
+Total Accesses: 27860
+Total kBytes: 33011
+Total Duration: 54118
+CPUUser: 18.02
+CPUSystem: 31.76
+CPUChildrenUser: 0
+CPUChildrenSystem: 0
+CPULoad: .0262535
+Uptime: 189613
+ReqPerSec: .146931
+BytesPerSec: 178.275
+BytesPerReq: 1213.33
+DurationPerReq: 1.9425
+BusyWorkers: 7
+IdleWorkers: 93
+Processes: 4
+Stopping: 0
+BusyWorkers: 7
+IdleWorkers: 93
+ConnsTotal: 13
+ConnsAsyncWriting: 0
+ConnsAsyncKeepAlive: 5
+ConnsAsyncClosing: 0
+Scoreboard: ...
+
+```
+
+It also uses Zabbix agent to collect `Apache` Linux process statistics such as CPU usage, memory usage, and whether the process is running or not.
+
+## Setup
+
+See the setup instructions for [mod_status](https://httpd.apache.org/docs/current/mod/mod_status.html).
+
+Check the availability of the module with this command line: `httpd -M 2>/dev/null | grep status_module`
+
+This is an example configuration of the Apache web server:
+
+```text
+
+ SetHandler server-status
+ Require host example.com
+
+```
+
+If you use another path, then do not forget to change the `Apache status page path` host wizard configuration field.'),
+('10265',NULL,'Apache by HTTP','3','-1','2','','','Apache by HTTP','0',NULL,'This template is designed for the effortless deployment of Apache monitoring by Zabbix via HTTP and doesn''t require any external scripts.
+
+The template collects metrics by polling ''mod_status'' with HTTP agent remotely.
+
+Setup:
+
+1. See the setup instructions for mod_status:
+https://httpd.apache.org/docs/current/mod/mod_status.html
+
+Check the availability of the module with this command line:
+httpd -M 2>/dev/null | grep status_module
+
+This is an example configuration of the Apache web server:
+
+
+ SetHandler server-status
+ Require host example.com
+
+
+2. Set the hostname or IP address of the Apache status page host in the ''{$APACHE.STATUS.HOST}'' macro. You can also change the status page port in the ''{$APACHE.STATUS.PORT}'' macro and status page path in the ''{$APACHE.STATUS.PATH}'' macro if necessary.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/384764-discussion-thread-for-official-zabbix-template-apache
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','86702e8bc514434e8c914d50c206cb94','APACHE BY HTTP','Zabbix','8.0-0',NULL,'0','1','## Overview
+
+This template is designed for the effortless deployment of Apache monitoring by Zabbix via HTTP and doesn''t require any external scripts.
+
+The template collects metrics by polling [`mod_status`](https://httpd.apache.org/docs/current/mod/mod_status.html) with HTTP agent remotely:
+
+```text
+127.0.0.1
+ServerVersion: Apache/2.4.41 (Unix)
+ServerMPM: event
+Server Built: Aug 14 2019 00:35:10
+CurrentTime: Friday, 16-Aug-2019 12:38:40 UTC
+RestartTime: Wednesday, 14-Aug-2019 07:58:26 UTC
+ParentServerConfigGeneration: 1
+ParentServerMPMGeneration: 0
+ServerUptimeSeconds: 189613
+ServerUptime: 2 days 4 hours 40 minutes 13 seconds
+Load1: 4.60
+Load5: 1.20
+Load15: 0.47
+Total Accesses: 27860
+Total kBytes: 33011
+Total Duration: 54118
+CPUUser: 18.02
+CPUSystem: 31.76
+CPUChildrenUser: 0
+CPUChildrenSystem: 0
+CPULoad: .0262535
+Uptime: 189613
+ReqPerSec: .146931
+BytesPerSec: 178.275
+BytesPerReq: 1213.33
+DurationPerReq: 1.9425
+BusyWorkers: 7
+IdleWorkers: 93
+Processes: 4
+Stopping: 0
+BusyWorkers: 7
+IdleWorkers: 93
+ConnsTotal: 13
+ConnsAsyncWriting: 0
+ConnsAsyncKeepAlive: 5
+ConnsAsyncClosing: 0
+Scoreboard: ...
+```
+
+## Setup
+
+1. See the setup instructions for [`mod_status`](https://httpd.apache.org/docs/current/mod/mod_status.html).
+
+Check the availability of the module with this command line:
+`httpd -M 2>/dev/null | grep status_module`
+
+This is an example configuration of the Apache web server:
+
+```text
+
+ SetHandler server-status
+ Require host example.com
+
+```
+
+2. Set the hostname or IP address of the Apache status page host in the `Apache status host` host wizard configuration field. You can also change the status page port in the `Apache status page port` field and status page path in the `Apache status page path` field if necessary.'),
+('10266',NULL,'Nginx by Zabbix agent','3','-1','2','','','Nginx by Zabbix agent','0',NULL,'Get metrics from stub status module using Zabbix agent running on Linux
+https://nginx.ru/en/docs/http/ngx_http_stub_status_module.html
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/384765-discussion-thread-for-official-zabbix-template-nginx
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','27f6424905884dbb96ab9210d987a56c','NGINX BY ZABBIX AGENT','Zabbix','8.0-0',NULL,'0','1','## Overview
+
+This template is developed to monitor Nginx by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template `Nginx by Zabbix agent` - collects metrics by polling the [Module ngx_http_stub_status_module](https://nginx.ru/en/docs/http/ngx_http_stub_status_module.html) locally with Zabbix agent:
+
+```text
+Active connections: 291
+server accepts handled requests
+16630948 16630948 31070465
+Reading: 6 Writing: 179 Waiting: 106
+```
+
+Note that this template doesn''t support HTTPS and redirects (limitations of `web.page.get`).
+
+It also uses Zabbix agent to collect `Nginx` Linux process statistics, such as CPU usage, memory usage and whether the process is running or not.
+
+
+## Setup
+
+See the setup instructions for [ngx_http_stub_status_module](https://nginx.ru/en/docs/http/ngx_http_stub_status_module.html).
+Test the availability of the `http_stub_status_module` `nginx -V 2>&1 | grep -o with-http_stub_status_module`.
+
+Example configuration of Nginx:
+```text
+location = /basic_status {
+ stub_status;
+ allow 127.0.0.1;
+ allow ::1;
+ deny all;
+}
+```
+
+If you use another location, then don''t forget to change the `Nginx status page path` host wizard configuration field.
+
+Example answer from Nginx:
+```text
+Active connections: 291
+server accepts handled requests
+16630948 16630948 31070465
+Reading: 6 Writing: 179 Waiting: 106
+```
+
+Note that this template doesn''t support https and redirects (limitations of web.page.get).'),
+('10267',NULL,'Nginx by HTTP','3','-1','2','','','Nginx by HTTP','0',NULL,'This template is developed to monitor Nginx by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template collects metrics by polling the module ''ngx_http_stub_status_module'' with HTTP agent remotely:
+https://nginx.ru/en/docs/http/ngx_http_stub_status_module.html
+
+Active connections: 291
+server accepts handled requests
+16630948 16630948 31070465
+Reading: 6 Writing: 179 Waiting: 106
+
+Setup:
+
+1. See the setup instructions for ''ngx_http_stub_status_module'':
+https://nginx.ru/en/docs/http/ngx_http_stub_status_module.html
+
+Test the availability of the ''http_stub_status_module'' with ''nginx -V 2>&1 | grep -o with-http_stub_status_module''.
+
+Example configuration of Nginx:
+
+location = /basic_status {
+ stub_status;
+ allow ;
+ deny all;
+}
+
+2. Set the hostname or IP address of the Nginx host or Nginx container in the ''{$NGINX.STUB_STATUS.HOST}'' macro. You can also change the status page port in the ''{$NGINX.STUB_STATUS.PORT}'' macro, the status page scheme in the ''{$NGINX.STUB_STATUS.SCHEME}'' macro and the status page path in the ''{$NGINX.STUB_STATUS.PATH}'' macro if necessary.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/384765-discussion-thread-for-official-zabbix-template-nginx
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','13d5bb0a4ae84228bff408aab5be338e','NGINX BY HTTP','Zabbix','8.0-0',NULL,'0','1','## Overview
+
+This template is developed to monitor Nginx by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template collects metrics by polling the module [`ngx_http_stub_status_module`](https://nginx.ru/en/docs/http/ngx_http_stub_status_module.html) with HTTP agent remotely:
+
+```text
+Active connections: 291
+server accepts handled requests
+16630948 16630948 31070465
+Reading: 6 Writing: 179 Waiting: 106
+```
+
+## Setup
+
+1. See the setup instructions for [`ngx_http_stub_status_module`](https://nginx.ru/en/docs/http/ngx_http_stub_status_module.html).
+
+Test the availability of the `http_stub_status_module` with `nginx -V 2>&1 | grep -o with-http_stub_status_module`.
+
+Example configuration of Nginx:
+
+```text
+location = /basic_status {
+ stub_status;
+ allow ;
+ deny all;
+}
+```
+
+2. Set the hostname or IP address of the Nginx host or Nginx container in the `Nginx status host` host wizard configuration field. You can also change the status page port in the `Nginx status page path` field, select the status page scheme in the `Request scheme` field and change the status page path in the `Nginx status page path` field if necessary.
+
+Example answer from Nginx:
+
+```text
+Active connections: 291
+server accepts handled requests
+16630948 16630948 31070465
+Reading: 6 Writing: 179 Waiting: 106
+```'),
+('10285',NULL,'Linux by Prom','3','-1','2','','','Linux by Prom','0',NULL,'This template collects Linux metrics from node_exporter 0.18 and above. Support for older node_exporter versions is provided as ''best effort''.
+
+Setup:
+
+1. Set up the node_exporter according to the official documentation:
+https://prometheus.io/docs/guides/node-exporter/
+
+Use node_exporter v0.18.0 or above.
+
+2. Set the hostname or IP address of the node_exporter host in the ''{$NODE_EXPORTER_HOST}'' macro. You can also change the Prometheus endpoint port in the ''{$NODE_EXPORTER_PORT}'' macro if necessary.
+
+Known Issues:
+
+ - Node Exporter 0.16.0 renamed many metrics. CPU utilization for "guest" and "guest_nice" metrics are not supported in this template with Node Exporter < 0.16. Disk IO metrics are not supported. Other metrics provided as best effort. See https://github.com/prometheus/node_exporter/releases/tag/v0.16.0 for details.
+ - Version: below 0.16.0
+ - Metric node_network_info with label ''device'' cannot be found, so network discovery is not possible.
+ - Version: below 0.18
+
+Notes on filesystem (FS) discovery:
+ - The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+ - BTRFS allocates a default of 10% of the volume for its own needs.
+ - To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: ''pused = 100 - 100 * (available / total - free + available)''
+ - The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/387225-discussion-thread-for-official-zabbix-template-for-linux
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','2506b0ca01884903b547b1e19b76ce6d','LINUX BY PROM','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template collects Linux metrics from Node Exporter 0.18 and above. Support for older Node Exporter versions is provided as best effort.
+
+### Known Issues
+
+ - Node Exporter 0.16.0 renamed many metrics. CPU utilization for "guest" and "guest_nice" metrics are not supported in this template with Node Exporter < 0.16. Disk IO metrics are not supported. Other metrics provided as best effort. See https://github.com/prometheus/node_exporter/releases/tag/v0.16.0 for details.
+ - Version: below 0.16.0
+ - Metric node_network_info with label ''device'' cannot be found, so network discovery is not possible.
+ - Version: below 0.18
+
+#### Notes on filesystem (FS) discovery:
+ - The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+ - BTRFS allocates a default of 10% of the volume for its own needs.
+ - To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: `pused = 100 - 100 * (available / total - free + available)`
+ - The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.
+
+## Setup
+
+1. Set up the node_exporter according to the [`official documentation`](https://prometheus.io/docs/guides/node-exporter/). Use node_exporter v0.18.0 or above.
+
+2. Set the hostname or IP address of the node_exporter host in the `The node_exporter host` parameter. You can also change the Prometheus endpoint port in the `TCP Port node_exporter` parameter if necessary.'),
+('10300',NULL,'RabbitMQ cluster by Zabbix agent','3','-1','2','','','RabbitMQ cluster by Zabbix agent','0',NULL,'Get cluster metrics from RabbitMQ management plugin provided an HTTP-based API using Zabbix agent.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/387226-discussion-thread-for-official-zabbix-template-rabbitmq
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','5fa761bc51e4432a90c6c9eece930c4a','RABBITMQ CLUSTER BY ZABBIX AGENT','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is developed to monitor the messaging broker RabbitMQ by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template `RabbitMQ Cluster` — collects metrics by polling [RabbitMQ management plugin](https://www.rabbitmq.com/management.html) with Zabbix agent.
+
+
+## Setup
+
+Enable the RabbitMQ management plugin. See [RabbitMQ documentation](https://www.rabbitmq.com/management.html) for the instructions.
+
+Create a user to monitor the service:
+
+```bash
+rabbitmqctl add_user zbx_monitor
+rabbitmqctl set_permissions -p / zbx_monitor "" "" ".*"
+rabbitmqctl set_user_tags zbx_monitor monitoring
+```
+
+A login name and password are also supported in macros functions:
+
+- {$RABBITMQ.API.USER}
+- {$RABBITMQ.API.PASSWORD}
+
+If your cluster consists of several nodes, it is recommended to assign the `cluster` template to a separate balancing host.
+In the case of a single-node installation, you can assign the `cluster` template to one host with a `node` template.
+
+If you use another API endpoint, then don''t forget to change `Address` host wizard configuration field.
+
+Install and setup [Zabbix agent](https://www.zabbix.com/documentation/8.0/manual/installation/install_from_packages).'),
+('10301',NULL,'RabbitMQ node by Zabbix agent','3','-1','2','','','RabbitMQ node by Zabbix agent','0',NULL,'Get node metrics from RabbitMQ management plugin provided an HTTP-based API using Zabbix agent.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/387226-discussion-thread-for-official-zabbix-template-rabbitmq
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','d5dc11ae9ab143a89c4be534bbb35188','RABBITMQ NODE BY ZABBIX AGENT','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is developed to monitor RabbitMQ by Zabbix that works without any external scripts.
+
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+ The template `RabbitMQ Node` — (Zabbix version >= 4.2) collects metrics by polling [RabbitMQ management plugin](https://www.rabbitmq.com/management.html) with Zabbix agent.
+
+ It also uses Zabbix agent to collect RabbitMQ Linux process statistics, such as CPU usage, memory usage, and whether the process is running or not.
+
+
+## Setup
+
+Enable the RabbitMQ management plugin. See [RabbitMQ documentation](https://www.rabbitmq.com/management.html) for the instructions.
+
+Create a user to monitor the service:
+
+```bash
+rabbitmqctl add_user zbx_monitor
+rabbitmqctl set_permissions -p / zbx_monitor "" "" ".*"
+rabbitmqctl set_user_tags zbx_monitor monitoring
+```
+
+A login name and password are also supported in macros functions:
+
+- {$RABBITMQ.API.USER}
+- {$RABBITMQ.API.PASSWORD}
+
+If you use another API endpoint, then don''t forget to change `Address` host wizard configuration field.
+Install and setup [Zabbix agent](https://www.zabbix.com/documentation/8.0/manual/installation/install_from_packages).'),
+('10302',NULL,'RabbitMQ cluster by HTTP','3','-1','2','','','RabbitMQ cluster by HTTP','0',NULL,'This template is developed to monitor the messaging broker RabbitMQ cluster by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template collects metrics by polling RabbitMQ management plugin with HTTP agent remotely.
+
+Setup:
+
+1. Enable the RabbitMQ management plugin. See the RabbitMQ documentation for the instructions:
+https://www.rabbitmq.com/management.html
+
+2. Create a user to monitor the service:
+
+rabbitmqctl add_user zbx_monitor
+rabbitmqctl set_permissions -p / zbx_monitor "" "" ".*"
+rabbitmqctl set_user_tags zbx_monitor monitoring
+
+3. Set the hostname or IP address of the RabbitMQ cluster host in the ''{$RABBITMQ.API.CLUSTER_HOST}'' macro. You can also change the port in the ''{$RABBITMQ.API.PORT}'' macro and the scheme in the ''{$RABBITMQ.API.SCHEME}'' macro if necessary.
+
+4. Set the user name and password in the macros ''{$RABBITMQ.API.USER}'' and ''{$RABBITMQ.API.PASSWORD}''.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/387226-discussion-thread-for-official-zabbix-template-rabbitmq
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','8c8474148c2a4eaeabe5a9331ea99d77','RABBITMQ CLUSTER BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is developed to monitor the messaging broker RabbitMQ cluster by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template collects metrics by polling RabbitMQ management plugin with HTTP agent remotely.
+
+## Setup
+
+1. Enable the RabbitMQ management plugin. See the [`RabbitMQ documentation`](https://www.rabbitmq.com/management.html) for the instructions.
+
+2. Create a user to monitor the service:
+
+```bash
+rabbitmqctl add_user zbx_monitor
+rabbitmqctl set_permissions -p / zbx_monitor "" "" ".*"
+rabbitmqctl set_user_tags zbx_monitor monitoring
+```
+
+3. Set the hostname or IP address of the RabbitMQ cluster host in the `Address` host wizard configuration field. You can also change the port in the `Port` and the scheme in the `Scheme` if necessary.
+
+4. Set the user name and password in the host wizard configuration fields `Username` and `Password`.'),
+('10303',NULL,'RabbitMQ node by HTTP','3','-1','2','','','RabbitMQ node by HTTP','0',NULL,'This template is developed to monitor the messaging broker RabbitMQ node by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template collects metrics by polling RabbitMQ management plugin with HTTP agent remotely.
+
+Setup:
+
+1. Enable the RabbitMQ management plugin. See the RabbitMQ documentation for the instructions:
+https://www.rabbitmq.com/management.html
+
+2. Create a user to monitor the service:
+
+rabbitmqctl add_user zbx_monitor
+rabbitmqctl set_permissions -p / zbx_monitor "" "" ".*"
+rabbitmqctl set_user_tags zbx_monitor monitoring
+
+3. Set the hostname or IP address of the RabbitMQ node host in the ''{$RABBITMQ.API.HOST}'' macro. You can also change the port in the ''{$RABBITMQ.API.PORT}'' macro and the scheme in the ''{$RABBITMQ.API.SCHEME}'' macro if necessary.
+
+4. Set the user name and password in the macros ''{$RABBITMQ.API.USER}'' and ''{$RABBITMQ.API.PASSWORD}''.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/387226-discussion-thread-for-official-zabbix-template-rabbitmq
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','b9514029d03b44de9adf24251778dbf3','RABBITMQ NODE BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is developed to monitor the messaging broker RabbitMQ node by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template collects metrics by polling RabbitMQ management plugin with HTTP agent remotely.
+
+## Setup
+
+1. Enable the RabbitMQ management plugin. See the [`RabbitMQ documentation`](https://www.rabbitmq.com/management.html) for the instructions.
+
+2. Create a user to monitor the service:
+
+```bash
+rabbitmqctl add_user zbx_monitor
+rabbitmqctl set_permissions -p / zbx_monitor "" "" ".*"
+rabbitmqctl set_user_tags zbx_monitor monitoring
+```
+
+3. Set the hostname or IP address of the RabbitMQ cluster host in the `Address` host wizard configuration field. You can also change the port in the `Port` and the scheme in the `Scheme` if necessary.
+
+4. Set the user name and password in the host wizard configuration fields `Username` and `Password`.'),
+('10304',NULL,'Cisco UCS by SNMP','3','-1','2','','','Cisco UCS by SNMP','0',NULL,'Template Server Cisco UCS
+
+MIBs used:
+CISCO-UNIFIED-COMPUTING-COMPUTE-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+CISCO-UNIFIED-COMPUTING-PROCESSOR-MIB
+CISCO-UNIFIED-COMPUTING-EQUIPMENT-MIB
+CISCO-UNIFIED-COMPUTING-STORAGE-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','cb66d34564e44b3893442fc74cf6e951','CISCO UCS BY SNMP','Zabbix','8.0-2',NULL,'0','1',''),
+('10308',NULL,'HAProxy by Zabbix agent','3','-1','2','','','HAProxy by Zabbix agent','0',NULL,'The template to monitor HAProxy by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template collects metrics by polling the HAProxy stats page with Zabbix agent.
+
+Note, that this template doesn''t support authentication and redirects (limitations of ''web.page.get'').
+
+Setup:
+
+1. Set up the HAProxy stats page:
+https://www.haproxy.com/blog/exploring-the-haproxy-stats-page/
+
+The example configuration of HAProxy:
+
+frontend stats
+ bind *:8404
+ stats enable
+ stats uri /stats
+ stats refresh 10s
+
+2. Set the hostname or IP address of the HAProxy stats host or container in the ''{$HAPROXY.STATS.HOST}'' macro. You can also change the status page port in the ''{$HAPROXY.STATS.PORT}'' macro, the status page scheme in the ''{$HAPROXY.STATS.SCHEME}'' macro and the status page path in the ''{$HAPROXY.STATS.PATH}'' macro if necessary.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/393527-discussion-thread-for-official-zabbix-template-haproxy
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','812073bf8df143bcae2a84b32c3965e5','HAPROXY BY ZABBIX AGENT','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor HAProxy by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template collects metrics by polling the HAProxy stats page with Zabbix agent.
+
+Note, that this template doesn''t support authentication and redirects (limitations of `web.page.get`).
+
+## Setup
+
+1. Set up the [`HAProxy stats page`](https://www.haproxy.com/blog/exploring-the-haproxy-stats-page/).
+
+The example configuration of HAProxy:
+
+```text
+frontend stats
+ bind *:8404
+ stats enable
+ stats uri /stats
+ stats refresh 10s
+```
+2. Set the hostname or IP address of the HAProxy stats host or container in the `Address` host wizard configuration field. You can also change the status page port in the `Port`, the status page scheme in the `Scheme` and the status page path in the `Stats page path` host wizard configuration fields if necessary.'),
+('10309',NULL,'HAProxy by HTTP','3','-1','2','','','HAProxy by HTTP','0',NULL,'The template to monitor HAProxy by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template collects metrics by polling the HAProxy stats page with HTTP agent.
+
+Setup:
+
+1. Set up the HAProxy stats page:
+https://www.haproxy.com/blog/exploring-the-haproxy-stats-page/
+
+If you want to use authentication, set the username and password in the ''stats auth'' option of the configuration file.
+
+The example configuration of HAProxy:
+
+frontend stats
+ bind *:8404
+ stats enable
+ stats uri /stats
+ stats refresh 10s
+ #stats auth Username:Password # Authentication credentials
+
+2. Set the hostname or IP address of the HAProxy stats host or container in the ''{$HAPROXY.STATS.HOST}'' macro. You can also change the status page port in the ''{$HAPROXY.STATS.PORT}'' macro, the status page scheme in the ''{$HAPROXY.STATS.SCHEME}'' macro and the status page path in the ''{$HAPROXY.STATS.PATH}'' macro if necessary.
+
+3. If you have enabled authentication in the HAProxy configuration file in step 1, set the username and password in the `{$HAPROXY.USERNAME}` and `{$HAPROXY.PASSWORD}` macros.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/393527-discussion-thread-for-official-zabbix-template-haproxy
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','948d046cb2894e5c8d07767a518cc1a9','HAPROXY BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor HAProxy by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template collects metrics by polling the HAProxy stats page with HTTP agent.
+
+## Setup
+
+1. Set up the [`HAProxy stats page`](https://www.haproxy.com/blog/exploring-the-haproxy-stats-page/).
+
+If you want to use authentication, set the username and password in the `stats auth` option of the configuration file.
+
+The example configuration of HAProxy:
+
+```text
+frontend stats
+ bind *:8404
+ stats enable
+ stats uri /stats
+ stats refresh 10s
+ #stats auth Username:Password # Authentication credentials
+```
+
+2. Set the hostname or IP address of the HAProxy stats host or container in the `Address` host wizard configuration field. You can also change the status page port in the `Port`, the status page scheme in the `Scheme` and the status page path in the `Stats page path` host wizard configuration fields if necessary.
+
+3. If you have enabled authentication in the HAProxy configuration file in step 1, set the username and password in the `Stats username` and `Stats password` host wizard configuration fields.'),
+('10310',NULL,'Redis by Zabbix agent 2','3','-1','2','','','Redis by Zabbix agent 2','0',NULL,'Get Redis metrics from plugin for the New Zabbix Agent (zabbix-agent2).
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/389050-discussion-thread-for-official-zabbix-template-redis
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e111446745a1425b862f8727ae63bce4','REDIS BY ZABBIX AGENT 2','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+Setup and configure zabbix-agent2 compiled with the Redis monitoring plugin.
+
+Redis'' default user should have permissions to run CONFIG, INFO, PING, CLIENT and SLOWLOG commands.
+
+Or default user ACL should have @admin, @slow, @dangerous, @fast and @connection categories.
+
+Test availability: `zabbix_get -s 127.0.0.1 -k redis.ping[tcp://127.0.0.1:6379]`'),
+('10316',NULL,'MySQL by Zabbix agent','3','-1','2','','','MySQL by Zabbix agent','0',NULL,E'Requirements for template operation:
+
+1. Install Zabbix agent and MySQL client. If necessary, add the path to the ''mysql'' and ''mysqladmin'' utilities to the global environment variable PATH.
+
+2. Copy the ''template_db_mysql.conf'' file with user parameters into folder with Zabbix agent configuration (/etc/zabbix/zabbix_agentd.d/ by default). Don''t forget to restart Zabbix agent.
+
+3. Create the MySQL user that will be used for monitoring ('''' at your discretion). For example:
+
+CREATE USER ''zbx_monitor''@''%'' IDENTIFIED BY '''';
+GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW ON *.* TO ''zbx_monitor''@''%'';
+
+For more information, please see MySQL documentation (https://dev.mysql.com/doc/refman/8.0/en/grant.html).
+
+NOTE: In order to collect replication metrics, MariaDB Enterprise Server 10.5.8-5 and above and MariaDB Community Server 10.5.9 and above require the SLAVE MONITOR privilege to be set for the monitoring user:
+
+GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW,SLAVE MONITOR ON *.* TO ''zbx_monitor''@''%'';
+
+For more information, please read the MariaDB documentation (https://mariadb.com/docs/server/ref/mdb/privileges/SLAVE_MONITOR/).
+
+4. Create ''.my.cnf'' configuration file in the home directory of Zabbix agent for Linux distributions (/var/lib/zabbix by default) or ''my.cnf'' in c:\\ for Windows. For example:
+
+[client]
+protocol=tcp
+user=''zbx_monitor''
+password=''''
+
+For more information, please see MySQL documentation (https://dev.mysql.com/doc/refman/8.0/en/option-files.html).
+
+NOTE: Linux distributions that use SELinux may require additional steps for access configuration.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/384189-discussion-thread-for-official-zabbix-template-db-mysql
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','f255e3fc32124b55b2a17ef3c961e5f5','MYSQL BY ZABBIX AGENT','Zabbix','8.0-3',NULL,'0','1',E'## Setup
+
+1. Install MySQL client. If necessary, add the path to the `mysql` and `mysqladmin` utilities to the global environment variable PATH.
+2. Copy the `template_db_mysql.conf` file with user parameters into folder with Zabbix agent configuration (/etc/zabbix/zabbix_agentd.d/ by default). Don''t forget to restart Zabbix agent.
+3. Create the MySQL user that will be used for monitoring (`` at your discretion). For example:
+
+```text
+CREATE USER ''zbx_monitor''@''%'' IDENTIFIED BY '''';
+GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW ON *.* TO ''zbx_monitor''@''%'';
+```
+
+For more information, please see [`MySQL documentation`](https://dev.mysql.com/doc/refman/8.0/en/grant.html).
+
+4. Create `.my.cnf` configuration file in the home directory of Zabbix agent for Linux distributions (/var/lib/zabbix by default) or `my.cnf` in c:\\ for Windows. For example:
+
+```text
+[client]
+protocol=tcp
+user=''zbx_monitor''
+password=''''
+```
+
+For more information, please see [`MySQL documentation`](https://dev.mysql.com/doc/refman/8.0/en/option-files.html).
+
+**NOTE:** In order to collect replication metrics, MariaDB Enterprise Server 10.5.8-5 and above and MariaDB Community Server 10.5.9 and above require the `SLAVE MONITOR` privilege to be set for the monitoring user:
+
+```text
+GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW,SLAVE MONITOR ON *.* TO ''zbx_monitor''@''%'';
+```
+
+For more information, please read the [`MariaDB documentation`](https://mariadb.com/docs/server/ref/mdb/privileges/SLAVE_MONITOR/).
+
+NOTE: Linux distributions that use SELinux may require additional steps for access configuration.
+
+For example, the following rule could be added to the SELinux policy:
+
+```text
+# cat < zabbix_home.te
+module zabbix_home 1.0;
+
+require {
+ type zabbix_agent_t;
+ type zabbix_var_lib_t;
+ type mysqld_etc_t;
+ type mysqld_port_t;
+ type mysqld_var_run_t;
+ class file { open read };
+ class tcp_socket name_connect;
+ class sock_file write;
+}
+
+#============= zabbix_agent_t ==============
+
+allow zabbix_agent_t zabbix_var_lib_t:file read;
+allow zabbix_agent_t zabbix_var_lib_t:file open;
+allow zabbix_agent_t mysqld_etc_t:file read;
+allow zabbix_agent_t mysqld_port_t:tcp_socket name_connect;
+allow zabbix_agent_t mysqld_var_run_t:sock_file write;
+EOF
+# checkmodule -M -m -o zabbix_home.mod zabbix_home.te
+# semodule_package -o zabbix_home.pp -m zabbix_home.mod
+# semodule -i zabbix_home.pp
+# restorecon -R /var/lib/zabbix
+```'),
+('10317',NULL,'MySQL by ODBC','3','-1','2','','','MySQL by ODBC','0',NULL,'Requirements for template operation:
+1. Create a MySQL user for monitoring. For example:
+
+CREATE USER ''zbx_monitor''@''%'' IDENTIFIED BY '''';
+GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW ON *.* TO ''zbx_monitor''@''%'';
+
+For more information please read the MySQL documentation: https://dev.mysql.com/doc/refman/8.0/en/grant.html.
+
+2. Set the user name and password in the host macros ({$MYSQL.USER} and {$MYSQL.PASSWORD}) if they are not already specified in the `odbc.ini` configuration file for ODBC monitoring.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/384189-discussion-thread-for-official-zabbix-template-db-mysql.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e19c120027e04da69b130e0f6cea29fc','MYSQL BY ODBC','Zabbix','8.0-4',NULL,'0','1','## Setup
+
+1. Create a MySQL user for monitoring (`` at your discretion):
+
+```text
+CREATE USER ''zbx_monitor''@''%'' IDENTIFIED BY '''';
+GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW ON *.* TO ''zbx_monitor''@''%'';
+```
+
+For more information, please see MySQL documentation: https://dev.mysql.com/doc/refman/8.0/en/grant.html.
+
+2. Set the username and password in the `MySQL user` and `MySQL password` fields in the host wizard,
+if they are not already specified in the `odbc.ini` configuration file for ODBC monitoring.
+
+Optionally, it is possible to customize the template:
+- The discovery of tables is disabled by default. To enable table discovery, change the value of the macro `{$MYSQL.TABLE.NAMES.MATCHES}` to the name of a single table, or use a regex string to include multiple tables.
+- You can also add an additional context macro `{$MYSQL.TABLE.NAMES.MATCHES:}` for specific databases to precisely control which tables should be discovered.
+- To exclude certain tables from discovery, change the value of the macro `{$MYSQL.TABLE.NAMES.NOT_MATCHES}` to the name of a single table, or use a regex string to exclude multiple tables.
+- You can also add an additional context macro `{$MYSQL.TABLE.NAMES.NOT_MATCHES:}` for specific databases to precisely control which tables should be excluded.'),
+('10318',NULL,'Docker by Zabbix agent 2','3','-1','2','','','Docker by Zabbix agent 2','0',NULL,'Get Docker engine metrics from plugin for the New Zabbix Agent (zabbix-agent2).
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/435429-discussion-thread-for-official-zabbix-template-docker
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','c5fd214cdd0d4b3b8272e73b022ba5c2','DOCKER BY ZABBIX AGENT 2','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor Docker engine by Zabbix that work without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+Template `Docker by Zabbix agent 2` — collects metrics by polling zabbix-agent2.
+
+## Setup
+
+Setup and configure Zabbix agent 2 compiled with the Docker monitoring plugin. The user by which the Zabbix agent 2 is running should have access permissions to the Docker socket.
+
+Test availability: `zabbix_get -s docker-host -k docker.info`'),
+('10319',NULL,'Memcached by Zabbix agent 2','3','-1','2','','','Memcached by Zabbix agent 2','0',NULL,'Get Memcached metrics from plugin for the New Zabbix Agent (zabbix-agent2).
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/398623-discussion-thread-for-official-zabbix-template-memcached
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','05894ba2c9184d33992bf1bd21c347f6','MEMCACHED BY ZABBIX AGENT 2','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+Setup and configure zabbix-agent2 compiled with the Memcached monitoring [plugin](/go/plugins/memcached).
+
+Test availability: `zabbix_get -s memcached-host -k memcached.ping`'),
+('10320',NULL,'MySQL by Zabbix agent 2','3','-1','2','','','MySQL by Zabbix agent 2','0',NULL,'Requirements for template operation:
+
+1. Create a MySQL user for monitoring. For example:
+
+CREATE USER ''zbx_monitor''@''%'' IDENTIFIED BY '''';
+GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW ON *.* TO ''zbx_monitor''@''%'';
+
+For more information please read the MySQL documentation https://dev.mysql.com/doc/refman/8.0/en/grant.html.
+
+NOTE: In order to collect replication metrics, MariaDB Enterprise Server 10.5.8-5 and above and MariaDB Community Server 10.5.9 and above require the SLAVE MONITOR privilege to be set for the monitoring user:
+
+GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW,SLAVE MONITOR ON *.* TO ''zbx_monitor''@''%'';
+
+For more information please read the MariaDB documentation https://mariadb.com/docs/server/ref/mdb/privileges/SLAVE_MONITOR/.
+
+2. Set in the {$MYSQL.DSN} macro the data source name of the MySQL instance either session name from Zabbix agent 2 configuration file or URI.
+Examples: MySQL1, tcp://localhost:3306, tcp://172.16.0.10, unix:/var/run/mysql.sock
+For more information about MySQL Unix socket file please read the MySQL documentation https://dev.mysql.com/doc/refman/8.0/en/problems-with-mysql-sock.html.
+
+3. If you had set URI in the {$MYSQL.DSN}, please define the user name and password in host macros ({$MYSQL.USER} and {$MYSQL.PASSWORD}).
+Leave macros {$MYSQL.USER} and {$MYSQL.PASSWORD} empty if you use a session name. Set the user name and password in the Plugins.Mysql.<...> section of your Zabbix agent 2 configuration file.
+For more information about configuring the Zabbix MySQL plugin please read the documentation https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/src/go/plugins/mysql/README.md.
+
+NOTE: In order to use this template for monitoring MySQL version 8.4 and later, Zabbix agent 2 version 8.0.0 and later should be used.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/384189-discussion-thread-for-official-zabbix-template-db-mysql.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','4904f84303c74c5e955b7849730c3155','MYSQL BY ZABBIX AGENT 2','Zabbix','8.0-4',NULL,'0','1','## Setup
+
+**NOTE:** In order to use this template for monitoring MySQL version 8.4 and later, Zabbix agent 2 version 8.0.0 and later should be used.
+
+1. Create a MySQL user for monitoring (`` at your discretion):
+
+```text
+CREATE USER ''zbx_monitor''@''%'' IDENTIFIED BY '''';
+GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW ON *.* TO ''zbx_monitor''@''%'';
+```
+
+For more information, please see MySQL documentation https://dev.mysql.com/doc/refman/8.0/en/grant.html
+
+**NOTE:** In order to collect replication metrics, MariaDB Enterprise Server 10.5.8-5 and above and MariaDB Community Server 10.5.9 and above require the `SLAVE MONITOR` privilege to be set for the monitoring user:
+
+```text
+GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW,SLAVE MONITOR ON *.* TO ''zbx_monitor''@''%'';
+```
+
+For more information please read the MariaDB documentation https://mariadb.com/docs/server/ref/mdb/privileges/SLAVE_MONITOR/
+
+2. Set in the `MySQL DSN` host wizard configuration field the data source name of the MySQL instance either session name from Zabbix agent 2 configuration file or URI.
+**Examples:** MySQL1, tcp://localhost:3306, tcp://172.16.0.10, unix:/var/run/mysql.sock
+For more information about MySQL Unix socket file, see the MySQL documentation https://dev.mysql.com/doc/refman/8.0/en/problems-with-mysql-sock.html.
+
+3. If you had set URI in the `MySQL DSN` field, define the user name and password in `MySQL user` and `MySQL password` host wizard configuration fields.
+Leave fields `MySQL user` and `MySQL password` empty if you use a session name. Set the user name and password in the Plugins.Mysql.<...> section of your Zabbix agent 2 configuration file.
+For more information about configuring the Zabbix MySQL plugin, see the documentation https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/src/go/plugins/mysql/README.md.'),
+('10321',NULL,'Chassis by IPMI','3','-1','2','','','Chassis by IPMI','0',NULL,'Template for monitoring servers with BMC over IPMI that work without any external scripts.
+All metrics are collected at once, thanks to Zabbix''s bulk data collection. The template is available starting from Zabbix version 5.0.
+It collects metrics by polling BMC remotely using an IPMI agent.
+
+
+Known Issues:
+
+ Description: If the BMC has a sensor with an empty threshold value, we get the LLD error "Cannot create trigger...".
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/398023-discussion-thread-for-official-zabbix-template-ipmi
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','02f35169a5a54a5aad8b3f06e798ab1f','CHASSIS BY IPMI','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+Template for monitoring servers with BMC over IPMI that work without any external scripts.
+All metrics are collected at once, thanks to Zabbix''s bulk data collection.
+It collects metrics by polling BMC remotely using an IPMI agent.
+
+###Known Issues
+
+- Description: If the BMC has a sensor with an empty threshold value, we get the LLD error "Cannot create trigger...".'),
+('10322',NULL,'Elasticsearch Cluster by HTTP','3','-1','2','','','Elasticsearch Cluster by HTTP','0',NULL,'The template to monitor Elasticsearch by Zabbix that work without any external scripts.
+It works with both standalone and cluster instances.
+The metrics are collected in one pass remotely using an HTTP agent.
+They are getting values from REST API ''_cluster/health'', ''_cluster/stats'', ''_nodes/stats'' requests.
+
+Setup:
+
+1. Set the hostname or IP address of the Elasticsearch host in the ''{$ELASTICSEARCH.HOST}'' macro.
+
+2. Set the login and password in the ''{$ELASTICSEARCH.USERNAME}'' and ''{$ELASTICSEARCH.PASSWORD}'' macros.
+
+3. If you use an atypical location of ES API, don''t forget to change the macros ''{$ELASTICSEARCH.SCHEME}'',''{$ELASTICSEARCH.PORT}''.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/399473-discussion-thread-for-official-zabbix-template-for-elasticsearch
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','52b2664578884d9eba62e47375c99f8e','ELASTICSEARCH CLUSTER BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+The template to monitor Elasticsearch by Zabbix that work without any external scripts.
+It works with both standalone and cluster instances.
+The metrics are collected in one pass remotely using an HTTP agent.
+They are getting values from REST API `_cluster/health`, `_cluster/stats`, `_nodes/stats` requests.
+
+## Setup
+
+1. Set the hostname or IP address of the Elasticsearch host in the `Elasticsearch host` host wizard configuration field.
+
+2. Set the login and password in the `Elasticsearch username` and `Elasticsearch password` host wizard configuration fields.
+
+3. If you use an atypical location of ES API, don''t forget to change the host wizard configuration fields `Elasticsearch scheme`,`Elasticsearch port`.'),
+('10323',NULL,'ClickHouse by HTTP','3','-1','2','','','ClickHouse by HTTP','0',NULL,'This template is designed for the effortless deployment of ClickHouse monitoring by Zabbix via HTTP and doesn''t require any external scripts.
+
+Setup:
+
+1. Create a user to monitor the service. For example, you could create a file ''/etc/clickhouse-server/users.d/zabbix.xml'' with the following content:
+
+
+
+
+ zabbix_pass
+
+ web
+ default
+
+ test
+
+
+
+
+
+2. Set the hostname or IP address of the ClickHouse HTTP endpoint in the ''{$CLICKHOUSE.HOST}'' macro. You can also change the port in the ''{$CLICKHOUSE.PORT}'' macro and scheme in the ''{$CLICKHOUSE.SCHEME}'' macro if necessary.
+
+3. Set the login and password in the macros ''{$CLICKHOUSE.USER}'' and ''{$CLICKHOUSE.PASSWORD}''. If you don''t need an authentication - remove headers from HTTP-Agent type items.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','95f2053c21094ad4968440b562cc7ea2','CLICKHOUSE BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed for the effortless deployment of ClickHouse monitoring by Zabbix via HTTP and doesn''t require any external scripts.
+
+## Setup
+
+1. Create a user to monitor the service. For example, you could create a file `/etc/clickhouse-server/users.d/zabbix.xml` with the following content:
+
+```
+
+
+
+ zabbix_pass
+
+ web
+ default
+
+ test
+
+
+
+
+```
+
+2. Set the hostname or IP address of the ClickHouse HTTP endpoint in the `ClickHouse host` host wizard configuration field. You can also change the port in the `ClickHouse port` and scheme in the `ClickHouse scheme` if necessary.
+
+3. Set the login and password in the host wizard configuration fields `Username` and `Password`. If you don''t need an authentication - remove headers from HTTP-Agent type items.'),
+('10324',NULL,'Etcd by HTTP','3','-1','2','','','Etcd by HTTP','0',NULL,'This template is designed to monitor ''etcd'' by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template ''Etcd by HTTP'' — collects metrics by help of the HTTP agent from ''/metrics'' endpoint.
+
+Refer to the vendor documentation:
+https://etcd.io/docs/v3.5/op-guide/monitoring/#metrics-endpoint
+
+For the users of ''etcd version <= 3.4'':
+
+In ''etcd v3.5'' some metrics have been deprecated. See more details on ''Upgrade etcd from 3.4 to 3.5'':
+https://etcd.io/docs/v3.4/upgrades/upgrade_3_5/
+Please upgrade your ''etcd'' instance, or use older ''Etcd by HTTP'' template version.
+
+Setup:
+
+1. Make sure that ''etcd'' allows the collection of metrics. You can test it by running:
+curl -L http://localhost:2379/metrics
+
+2. Check if ''etcd'' is accessible from Zabbix proxy or Zabbix server depending on where you are planning to do the monitoring. To verify it, run:
+curl -L http://:2379/metrics
+
+3. Add the template to the ''etcd'' node. Set the hostname or IP address of the ''etcd'' host in the ''{$ETCD.HOST}'' macro. By default, the template uses a client''s port.
+You can configure metrics endpoint location by adding ''--listen-metrics-urls'' flag.
+
+For more details, see the etcd documentation:
+https://etcd.io/docs/v3.5/op-guide/configuration/#profiling-and-monitoring
+
+Additional points to consider:
+
+- If you have specified a non-standard port for ''etcd'', don''t forget to change macros: ''{$ETCD.SCHEME}'' and ''{$ETCD.PORT}''.
+- You can set ''{$ETCD.USERNAME}'' and ''{$ETCD.PASSWORD}'' macros in the template to use on a host level if necessary.
+- To test availability, run : ''zabbix_get -s etcd-host -k etcd.health''.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','b25b8b517a4743c48037bfa10af3dc3c','ETCD BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed to monitor `etcd` by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template `Etcd by HTTP` — collects metrics by help of the HTTP agent from `/metrics` endpoint.
+
+> Refer to the [`vendor documentation`](https://etcd.io/docs/v3.5/op-guide/monitoring/#metrics-endpoint).
+
+**For the users of `etcd version <= 3.4` !**
+
+> In `etcd v3.5` some metrics have been deprecated. See more details on [`Upgrade etcd from 3.4 to 3.5`](https://etcd.io/docs/v3.4/upgrades/upgrade_3_5/).
+Please upgrade your `etcd` instance, or use older `Etcd by HTTP` template version.
+
+## Setup
+
+1. Make sure that `etcd` allows the collection of metrics. You can test it by running: `curl -L http://localhost:2379/metrics`.
+
+2. Check if `etcd` is accessible from Zabbix proxy or Zabbix server depending on where you are planning to do the monitoring. To verify it, run `curl -L http://:2379/metrics`.
+
+3. Add the template to the `etcd` node. Set the hostname or IP address of the `etcd` host in the `Etcd API host` host wizard configuration field. By default, the template uses a client''s port.
+You can configure metrics endpoint location by adding `--listen-metrics-urls` flag.
+
+For more details, see the [`etcd documentation`](https://etcd.io/docs/v3.5/op-guide/configuration/#profiling-and-monitoring).
+
+Additional points to consider:
+
+- If you have specified a non-standard port for `etcd`, don''t forget to change host wizard configuration fields: `Etcd request scheme` and `Etcd API port`.
+- To test availability, run: `zabbix_get -s etcd-host -k etcd.health`.
+- See the host wizard configuration fields section, as it will set the trigger values.'),
+('10325',NULL,'IIS by Zabbix agent','3','-1','2','','','IIS by Zabbix agent','0',NULL,'Get metrics from IIS using Zabbix agent running on Windows.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/401862-discussion-thread-for-official-zabbix-template-internet-information-services
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','c7c7e5dc319b4801982e719beb1c5191','IIS BY ZABBIX AGENT','Zabbix','8.0-1',NULL,'0','1',E'## Overview
+
+The template to monitor IIS (Internet Information Services) by Zabbix that works without any external scripts.
+
+## Setup
+
+You have to enable the following Windows Features (Control Panel > Programs and Features > Turn Windows features on or off) on your server
+```text
+Web Server (IIS)
+Web Server (IIS)\\Management Tools\\IIS Management Scripts and Tools
+```
+
+Optionally, it is possible to customize the template:
+- Set value for the host wizard configuration field `Max app pool request queue length (trigger)`, if you want to receive alerts when a number of requests in the application pool queue exceeds the threshold.
+- If you use a non-standard port for the IIS, don''t forget to update the host wizard configuration fields `Service type` and `Listening port`.
+- Change the value of host wizard configuration field `Monitoring status for discovered app pools` to "0", if you want to disable all notifications about application pools state.
+You can also add additional context macro `{$IIS.APPPOOL.MONITORED:}` for excluding specific application pools from monitoring.
+- Change regexp in the host wizard configuration fields `Application pools filter (include)` and `Application pools filter (exclude)` used for filtering application pools discovery results.'),
+('10326',NULL,'IIS by Zabbix agent active','3','-1','2','','','IIS by Zabbix agent active','0',NULL,'Get metrics from IIS using Zabbix agent running on Windows.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/401862-discussion-thread-for-official-zabbix-template-internet-information-services
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','4677be3e07bf4f3285496f2f4230b928','IIS BY ZABBIX AGENT ACTIVE','Zabbix','8.0-1',NULL,'0','1',E'## Overview
+
+The template to monitor IIS (Internet Information Services) by Zabbix that works without any external scripts.
+
+## Setup
+
+You have to enable the following Windows Features (Control Panel > Programs and Features > Turn Windows features on or off) on your server
+```text
+Web Server (IIS)
+Web Server (IIS)\\Management Tools\\IIS Management Scripts and Tools
+```
+
+Optionally, it is possible to customize the template:
+- Set value for the host wizard configuration field `Max app pool request queue length (trigger)`, if you want to receive alerts when a number of requests in the application pool queue exceeds the threshold.
+- If you use a non-standard port for the IIS, don''t forget to update the host wizard configuration fields `Service type` and `Listening port`.
+- Change the value of host wizard configuration field `Monitoring status for discovered app pools` to "0", if you want to disable all notifications about application pools state.
+You can also add additional context macro `{$IIS.APPPOOL.MONITORED:}` for excluding specific application pools from monitoring.
+- Change regexp in the host wizard configuration fields `Application pools filter (include)` and `Application pools filter (exclude)` used for filtering application pools discovery results.'),
+('10327',NULL,'MSSQL by ODBC','3','-1','2','','','MSSQL by ODBC','0',NULL,'This template is designed for the effortless deployment of MSSQL monitoring by Zabbix via ODBC and doesn''t require any external scripts.
+
+Setup:
+
+1. Create an MSSQL user for monitoring.
+
+ View Server State and View Any Definition permissions should be granted to the user.
+ Grant this user read permissions to the sysjobschedules, sysjobhistory, and sysjobs tables.
+
+ For more information, see MSSQL documentation:
+
+ - Create a database user: https://docs.microsoft.com/en-us/sql/relational-databases/security/authentication-access/create-a-database-user?view=sql-server-ver16
+
+ - GRANT Server Permissions: https://docs.microsoft.com/en-us/sql/t-sql/statements/grant-server-permissions-transact-sql?view=sql-server-ver16
+
+ - Configure a User to Create and Manage SQL Server Agent Jobs: https://docs.microsoft.com/en-us/sql/ssms/agent/configure-a-user-to-create-and-manage-sql-server-agent-jobs?view=sql-server-ver16
+
+2. Set the user name and password in the host macros ({$MSSQL.USER} and {$MSSQL.PASSWORD}).
+
+3. Do not forget to install Microsoft ODBC driver on Zabbix server or Zabbix proxy and specify data source name in macro {$MSSQL.DSN}.
+
+ See Microsoft documentation for instructions: https://docs.microsoft.com/en-us/sql/connect/odbc/linux-mac/installing-the-microsoft-odbc-driver-for-sql-server?view=sql-server-ver16.
+
+ Note! Credentials in the odbc.ini do not work for MSSQL.
+
+The "Service''s TCP port state" item uses the {$MSSQL.HOST} and {$MSSQL.PORT} macros to check the availability of the MSSQL instance, change these if necessary. Keep in mind that if dynamic ports are used on the MSSQL server side, this check will not work correctly.
+
+If your instance uses a non-default TCP port, set the port in your section of odbc.ini in the line Server = IP or FQDN name, port.
+
+Note: You can use the context macros {$MSSQL.BACKUP_FULL.USED}, {$MSSQL.BACKUP_LOG.USED}, and {$MSSQL.BACKUP_DIFF.USED} to disable backup age triggers for a certain database. If set to a value other than "1", the trigger expression for the backup age will not fire.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','001a1677f6a949b6bddfdb2926023300','MSSQL BY ODBC','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+1. Create a monitoring user on MSSQL for Zabbix to connect to:
+ - for MSSQL Server 2022
+ ```sql
+ CREATE LOGIN zabbix WITH PASSWORD = ''password''
+ GRANT VIEW SERVER PERFORMANCE STATE TO zabbix
+ GRANT VIEW ANY DEFINITION TO zabbix
+ USE msdb
+ CREATE USER zabbix FOR LOGIN zabbix
+ GRANT EXECUTE ON msdb.dbo.agent_datetime TO zabbix
+ GRANT SELECT ON msdb.dbo.sysjobactivity TO zabbix
+ GRANT SELECT ON msdb.dbo.sysjobservers TO zabbix
+ GRANT SELECT ON msdb.dbo.sysjobs TO zabbix
+ GO
+ ```
+ - for MSSQL versions 2017 and 2019
+ ```sql
+ CREATE LOGIN zabbix WITH PASSWORD = ''password''
+ GRANT VIEW SERVER STATE TO zabbix
+ GRANT VIEW ANY DEFINITION TO zabbix
+ USE msdb
+ CREATE USER zabbix FOR LOGIN zabbix
+ GRANT EXECUTE ON msdb.dbo.agent_datetime TO zabbix
+ GRANT SELECT ON msdb.dbo.sysjobactivity TO zabbix
+ GRANT SELECT ON msdb.dbo.sysjobservers TO zabbix
+ GRANT SELECT ON msdb.dbo.sysjobs TO zabbix
+ GO
+ ```
+
+ To allow Zabbix to query SQL Server Agent job information, a dedicated login must be created and granted the required permissions through T-SQL:
+ - **VIEW SERVER STATE** is required for Microsoft SQL Server 2017 and 2019
+ - **VIEW SERVER PERFORMANCE STATE** is required for Microsoft SQL Server 2022
+ - **VIEW ANY DEFINITION** allows access to object definitions and metadata
+ - **SELECT** allows the user to read data from the sysjobschedules, sysjobhistory, and sysjobs tables in the msdb database
+
+
+ For more information, see MSSQL documentation:
+ - [Create a database user](https://docs.microsoft.com/en-us/sql/relational-databases/security/authentication-access/create-a-database-user?view=sql-server-ver16)
+ - [GRANT Server Permissions](https://docs.microsoft.com/en-us/sql/t-sql/statements/grant-server-permissions-transact-sql?view=sql-server-ver16)
+ - [Configure a User to Create and Manage SQL Server Agent Jobs](https://docs.microsoft.com/en-us/sql/ssms/agent/configure-a-user-to-create-and-manage-sql-server-agent-jobs?view=sql-server-ver16)
+
+2. Set the username and password in the `MSSQL user` and `MSSQL password` host wizard configuration fields.
+3. Set the connection string for the MSSQL instance in the `MSSQL URI` host wizard configuration field as a URI, such as ``, or specify the named session - ``.
+
+ The `Service''s TCP port state` item uses the `MSSQL address` and `MSSQL TCP port` host wizard configuration fields to check the availability of the MSSQL instance, change these if necessary. Keep in mind that if dynamic ports are used on the MSSQL server side, this check will not work correctly.
+
+ Additional notes:
+ - You can use the `Monitoring of full backup`, `Monitoring of log backup`, and `Monitoring of differential backup` host wizard configuration fields to disable backup age triggers. If set to unselected state, the trigger expression for the backup age will not fire.
+ - Since version 7.2.0, you can also connect to the MSSQL instance using its name. To do this, set the connection string in the `MSSQL URI` host wizard configuration field as ``.'),
+('10328',NULL,'Oracle by ODBC','3','-1','2','','','Oracle by ODBC','0',NULL,'1. Create an Oracle user for monitoring.
+
+2. Set the hostname or IP address of the Oracle DB instance, user name and password in host macros ({$ORACLE.HOST}, {$ORACLE.USER} and {$ORACLE.PASSWORD}).
+ Do not forget to install the Microsoft ODBC driver on the Zabbix server or the Zabbix proxy.
+ See Oracle documentation for instructions: https://www.oracle.com/database/technologies/releasenote-odbc-ic.html.
+
+ Note! Credentials in the odbc.ini do not work for Oracle.
+ Note! Be sure that ODBC connects to Oracle with session parameter NLS_NUMERIC_CHARACTERS= ''.,'' It is important for correct display float numbers in Zabbix.
+The "Service''s TCP port state" item uses {$ORACLE.HOST} and {$ORACLE.PORT} macros to check the availability of the listener.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','00ade9277d7c41e8b57d638b22d54372','ORACLE BY ODBC','Zabbix','8.0-0',NULL,'0','1','## Overview
+
+The template is developed to monitor a single DBMS Oracle Database instance with ODBC and can monitor CDB or non-CDB installations.
+
+## Supported versions
+
+Oracle Database 12c2 and newer.
+
+**Important! This integration queries the `V$ACTIVE_SESSION_HISTORY` dynamic performance view which is part of the Oracle Diagnostics Pack. Please make sure that you have the licence required for using this management pack.**
+
+## Setup
+
+1. Create an Oracle Database user for monitoring:
+
+ In CDB installations, it is possible to monitor tablespaces from the CDB (container database) and all PDBs (pluggable databases). To do so, a common user is needed with the correct rights:
+
+ ```
+ CREATE USER c##zabbix_mon IDENTIFIED BY ;
+ -- Grant access to the c##zabbix_mon user.
+ ALTER USER c##zabbix_mon SET CONTAINER_DATA=ALL CONTAINER=CURRENT;
+ GRANT CONNECT, CREATE SESSION TO c##zabbix_mon;
+ GRANT SELECT_CATALOG_ROLE to c##zabbix_mon;
+ GRANT SELECT ON v_$instance TO c##zabbix_mon;
+ GRANT SELECT ON v_$database TO c##zabbix_mon;
+ GRANT SELECT ON v_$sysmetric TO c##zabbix_mon;
+ GRANT SELECT ON v_$system_parameter TO c##zabbix_mon;
+ GRANT SELECT ON v_$session TO c##zabbix_mon;
+ GRANT SELECT ON v_$recovery_file_dest TO c##zabbix_mon;
+ GRANT SELECT ON v_$active_session_history TO c##zabbix_mon;
+ GRANT SELECT ON v_$osstat TO c##zabbix_mon;
+ GRANT SELECT ON v_$process TO c##zabbix_mon;
+ GRANT SELECT ON v_$datafile TO c##zabbix_mon;
+ GRANT SELECT ON v_$pgastat TO c##zabbix_mon;
+ GRANT SELECT ON v_$sgastat TO c##zabbix_mon;
+ GRANT SELECT ON v_$log TO c##zabbix_mon;
+ GRANT SELECT ON v_$archive_dest TO c##zabbix_mon;
+ GRANT SELECT ON v_$asm_diskgroup TO c##zabbix_mon;
+ GRANT SELECT ON v_$asm_diskgroup_stat TO c##zabbix_mon;
+ GRANT SELECT ON DBA_USERS TO c##zabbix_mon;
+ ```
+ This is needed because the template uses `CDB_*` views to monitor tablespaces from the CDB and different PDBs - the monitoring user therefore needs access to the container data objects on all PDBs.
+
+ However, if you wish to monitor only a single PDB or a non-CDB instance, a local user is sufficient:
+
+ ```
+ CREATE USER zabbix_mon IDENTIFIED BY ;
+ -- Grant access to the zabbix_mon user.
+ GRANT CONNECT, CREATE SESSION TO zabbix_mon;
+ GRANT SELECT_CATALOG_ROLE to zabbix_mon;
+ GRANT SELECT ON v_$instance TO zabbix_mon;
+ GRANT SELECT ON v_$database TO zabbix_mon;
+ GRANT SELECT ON v_$sysmetric TO zabbix_mon;
+ GRANT SELECT ON v_$system_parameter TO zabbix_mon;
+ GRANT SELECT ON v_$session TO zabbix_mon;
+ GRANT SELECT ON v_$recovery_file_dest TO zabbix_mon;
+ GRANT SELECT ON v_$active_session_history TO zabbix_mon;
+ GRANT SELECT ON v_$osstat TO zabbix_mon;
+ GRANT SELECT ON v_$process TO zabbix_mon;
+ GRANT SELECT ON v_$datafile TO zabbix_mon;
+ GRANT SELECT ON v_$pgastat TO zabbix_mon;
+ GRANT SELECT ON v_$sgastat TO zabbix_mon;
+ GRANT SELECT ON v_$log TO zabbix_mon;
+ GRANT SELECT ON v_$archive_dest TO zabbix_mon;
+ GRANT SELECT ON v_$asm_diskgroup TO zabbix_mon;
+ GRANT SELECT ON v_$asm_diskgroup_stat TO zabbix_mon;
+ GRANT SELECT ON DBA_USERS TO zabbix_mon;
+ ```
+ **Important! Ensure that the ODBC connection to Oracle includes the session parameter `NLS_NUMERIC_CHARACTERS= ''.,''`. It is important for displaying the float numbers in Zabbix correctly.**
+
+ **Important! These privileges grant the monitoring user `SELECT_CATALOG_ROLE`, which, in turn, gives access to thousands of tables in the database.**
+ This role is required to access the `V$RESTORE_POINT` dynamic performance view.
+ However, there are ways to go around this, if the `SELECT_CATALOG_ROLE` assigned to a monitoring user raises any security issues.
+ One way to do this is using **pipelined table functions**:
+
+ 1. Log into your database as the `SYS` user or make sure that your administration user has the required privileges to execute the steps below;
+
+ 2. Create types for the table function:
+
+ ```sql
+ CREATE OR REPLACE TYPE zbx_mon_restore_point_row AS OBJECT (
+ SCN NUMBER,
+ DATABASE_INCARNATION# NUMBER,
+ GUARANTEE_FLASHBACK_DATABASE VARCHAR2(3),
+ STORAGE_SIZE NUMBER,
+ TIME TIMESTAMP(9),
+ RESTORE_POINT_TIME TIMESTAMP(9),
+ PRESERVED VARCHAR2(3),
+ NAME VARCHAR2(128),
+ PDB_RESTORE_POINT VARCHAR2(3),
+ CLEAN_PDB_RESTORE_POINT VARCHAR2(3),
+ PDB_INCARNATION# NUMBER,
+ REPLICATED VARCHAR2(3),
+ CON_ID NUMBER
+ );
+ CREATE OR REPLACE TYPE zbx_mon_restore_point_tab IS TABLE OF zbx_mon_restore_point_row;
+ ```
+
+ 3. Create the pipelined table function:
+
+ ```sql
+ CREATE OR REPLACE FUNCTION zbx_mon_restore_point RETURN zbx_mon_restore_point_tab PIPELINED AS
+ BEGIN
+ FOR i IN (SELECT * FROM V$RESTORE_POINT) LOOP
+ PIPE ROW (zbx_mon_restore_point_row(i.SCN, i.DATABASE_INCARNATION#, i.GUARANTEE_FLASHBACK_DATABASE, i.STORAGE_SIZE, i.TIME, i.RESTORE_POINT_TIME, i.PRESERVED, i.NAME, i.PDB_RESTORE_POINT, i.CLEAN_PDB_RESTORE_POINT, i.PDB_INCARNATION#, i.REPLICATED, i.CON_ID));
+ END LOOP;
+ RETURN;
+ END;
+ ```
+
+ 4. Grant the Zabbix monitoring user the Execute privilege on the created pipelined table function and replace the monitoring user `V$RESTORE_POINT` view with the `SYS` user function (in this example, the `SYS` user is used to create DB types and function):
+
+ ```sql
+ GRANT EXECUTE ON zbx_mon_restore_point TO c##zabbix_mon;
+ CREATE OR REPLACE VIEW c##zabbix_mon.V$RESTORE_POINT AS SELECT * FROM TABLE(SYS.zbx_mon_restore_point);
+ ```
+
+ 5. Finally, revoke the `SELECT_CATALOG_ROLE` and grant additional permissions that were previously covered by the `SELECT_CATALOG_ROLE`.
+
+ ```sql
+ REVOKE SELECT_CATALOG_ROLE FROM c##zabbix_mon;
+ GRANT SELECT ON v_$pdbs TO c##zabbix_mon;
+ GRANT SELECT ON v_$sort_segment TO c##zabbix_mon;
+ GRANT SELECT ON v_$parameter TO c##zabbix_mon;
+ GRANT SELECT ON CDB_TABLESPACES TO c##zabbix_mon;
+ GRANT SELECT ON CDB_DATA_FILES TO c##zabbix_mon;
+ GRANT SELECT ON CDB_FREE_SPACE TO c##zabbix_mon;
+ GRANT SELECT ON CDB_TEMP_FILES TO c##zabbix_mon;
+ ```
+
+ > Note that in these examples, the monitoring user is named `c##zabbix_mon` and the system user - `SYS`. Change these example usernames to ones that are appropriate for your environment.
+
+ If this workaround does not work for you, there are more options available, such as __materialized views__, but look out for data refresh as `V$RESTORE_POINT` is a dynamic performance view.
+
+2. Install the ODBC driver on Zabbix server or Zabbix proxy.
+ See the [Oracle documentation](https://www.oracle.com/database/technologies/releasenote-odbc-ic.html) for instructions.
+
+3. Configure Zabbix server or Zabbix proxy for using the Oracle environment:
+
+ This step is required only when:
+
+ * installing Oracle Instant Client with .rpm packages with a version < 19.3 (if Instant Client is the only Oracle software installed on Zabbix server or Zabbix proxy);
+
+ * installing Oracle Instant Client manually with .zip files.
+
+ There are multiple configuration options:
+
+ 1. Using the `LDCONFIG` utility **(recommended option)**:
+
+ To update the runtime link path, it is recommended to use the ```LDCONFIG``` utility, for example:
+
+ ```
+ # sh -c "echo /opt/oracle/instantclient_19_18 > /etc/ld.so.conf.d/oracle-instantclient.conf"
+ # ldconfig
+ ```
+
+ 2. Using the application configuration file:
+
+ An alternative solution is to export the required variables by editing or adding a new application configuration file:
+
+ * ```/etc/sysconfig/zabbix-server # for server```
+
+ * ```/etc/sysconfig/zabbix-proxy # for proxy```
+
+ And then, adding:
+
+ ```
+ # Oracle Instant Client library
+ LD_LIBRARY_PATH=/opt/oracle/instantclient_19_18:$LD_LIBRARY_PATH
+ export LD_LIBRARY_PATH
+ ```
+
+ Keep in mind that the library paths will vary depending on your installation.
+
+ This is a minimal configuration example. Depending on the Oracle Instant Client version, required functionality and host operating system, a different set of additional packages might need to be installed.
+ For more detailed configuration instructions, see the [official Oracle Instant Client installation instructions for Linux](https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html).
+
+4. Restart Zabbix server or Zabbix proxy.
+
+5. Set the username and password in host wizard configuration fields `Username` and `Password`.
+
+6. Set the `Oracle URL`, `Oracle driver path` and `Oracle Service Name` in host wizard configuration fields.
+
+ * `Oracle URL` is a hostname or IP address of the Oracle DB instance.
+
+ * `Oracle driver path` is a path to the driver location in the OS. The ODBC driver file should be found in the Instant Client directory and named `libsqora.so.XX.Y`.
+
+ * `Oracle Service Name` is a service name to which the host will connect to. It is important as it determines if the connection is established to a non-CDB, CDB, or PDB. If you wish to monitor tablespaces of all PDBs, you will need to set a service name that points to the CDB.
+ Active service names can be seen from the instance running Oracle Database with `lsnrctl status`.
+
+ **Important! Make sure that the user created in step #1 is present on the specified service.**
+
+ The "Service''s TCP port state" item uses `{$ORACLE.HOST}` and `{$ORACLE.PORT}` macros to check the availability of the listener.'),
+('10329',NULL,'PostgreSQL by Zabbix agent 2','3','-1','2','','','PostgreSQL by Zabbix agent 2','0',NULL,'This template is designed for the deployment of PostgreSQL monitoring by Zabbix via Zabbix agent 2 and uses a loadable plugin to run SQL queries.
+
+Setup:
+
+1. Deploy Zabbix agent 2 with the PostgreSQL plugin. Starting with Zabbix versions 6.0.10 / 6.2.4 / 6.4 PostgreSQL metrics are moved to a loadable plugin and require installation of a separate package or compilation of the plugin from sources (https://www.zabbix.com/documentation/8.0/manual/extensions/plugins/build).
+
+2. Create the PostgreSQL user for monitoring (`` at your discretion) and inherit permissions from the default role `pg_monitor`:
+CREATE USER zbx_monitor WITH PASSWORD '''' INHERIT;
+GRANT pg_monitor TO zbx_monitor;
+
+3. Edit the `pg_hba.conf` configuration file to allow connections for the user `zbx_monitor`. You can check the PostgreSQL documentation for examples (https://www.postgresql.org/docs/current/auth-pg-hba-conf.html).
+
+4. Set the connection string for the PostgreSQL instance in the `{$PG.CONNSTRING.AGENT2}` macro as URI, such as ``, or specify the named session - ``.
+
+Note: if you want to use SSL/TLS encryption to protect communications with the remote PostgreSQL instance, a named session must be used. In that case, the instance URI should be specified in the `Plugins.PostgreSQL.Sessions.*.Uri` parameter in the PostgreSQL plugin configuration files alongside all the encryption parameters (type, certificate/key filepaths if needed etc.).
+
+You can check the PostgreSQL plugin documentation (https://git.zabbix.com/projects/AP/repos/postgresql/browse?at=refs%2Fheads%2Frelease%2F8.0) for details about agent plugin parameters and named sessions.
+
+Also, it is assumed that you set up the PostgreSQL instance to work in the desired encryption mode. Check the PostgreSQL documentation (https://www.postgresql.org/docs/current/ssl-tcp.html) for details.
+
+Note that plugin TLS certificate validation relies on checking the Subject Alternative Names (SAN) instead of the Common Name (CN), check the cryptography package documentation (https://pkg.go.dev/crypto/x509) for details.
+
+For example, to enable required encryption in transport mode without identity checks you could create the file `/etc/zabbix/zabbix_agent2.d/postgresql_myconn.conf` with the following configuration for the named session `myconn` (replace `` with the address of the PostgreSQL instance):
+Plugins.PostgreSQL.Sessions.myconn.Uri=tcp://:5432
+Plugins.PostgreSQL.Sessions.myconn.TLSConnect=required
+
+Then set the `{$PG.CONNSTRING.AGENT2}` macro to `myconn` to use this named session.
+
+5. Set the password that you specified in step 2 in the macro `{$PG.PASSWORD}`.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/384190-%C2%A0discussion-thread-for-official-zabbix-template-db-postgresql
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','d0ef7d659a8f4beaaabfc4b6134e737a','POSTGRESQL BY ZABBIX AGENT 2','Zabbix','8.0-0',NULL,'0','1','## Overview
+
+This template is designed for the deployment of PostgreSQL monitoring by Zabbix via Zabbix agent 2 and uses a loadable plugin to run SQL queries.
+
+## Setup
+
+1. Create the PostgreSQL user for monitoring (`` at your discretion) and inherit permissions from the default role `pg_monitor`:
+
+```sql
+CREATE USER zbx_monitor WITH PASSWORD '''' INHERIT;
+GRANT pg_monitor TO zbx_monitor;
+```
+
+3. Edit the `pg_hba.conf` configuration file to allow connections for the user `zbx_monitor`. For example, you could add one of the following rows to allow local TCP connections from the same host:
+
+```bash
+# TYPE DATABASE USER ADDRESS METHOD
+ host all zbx_monitor localhost trust
+ host all zbx_monitor 127.0.0.1/32 md5
+ host all zbx_monitor ::1/128 scram-sha-256
+```
+
+For more information please read the PostgreSQL documentation `https://www.postgresql.org/docs/current/auth-pg-hba-conf.html`.
+
+4. Set the connection string for the PostgreSQL instance in the `PostgreSQL connection string` host wizard configuration field as URI, such as ``, or specify the named session - ``.
+
+**Note:** if you want to use SSL/TLS encryption to protect communications with the remote PostgreSQL instance, a named session must be used. In that case, the instance URI should be specified in the `Plugins.PostgreSQL.Sessions.*.Uri` parameter in the PostgreSQL plugin configuration files alongside all the encryption parameters (type, certificate/key filepaths if needed etc.).
+
+You can check the [`PostgreSQL plugin documentation`](https://git.zabbix.com/projects/AP/repos/postgresql/browse?at=refs%2Fheads%2Frelease%2F8.0) for details about agent plugin parameters and named sessions.
+
+Also, it is assumed that you set up the PostgreSQL instance to work in the desired encryption mode. Check the [`PostgreSQL documentation`](https://www.postgresql.org/docs/current/ssl-tcp.html) for details.
+
+**Note:** plugin TLS certificate validation relies on checking the Subject Alternative Names (SAN) instead of the Common Name (CN), check the cryptography package [`documentation`](https://pkg.go.dev/crypto/x509) for details.
+
+For example, to enable required encryption in transport mode without identity checks you could create the file `/etc/zabbix/zabbix_agent2.d/postgresql_myconn.conf` with the following configuration for the named session `myconn` (replace `` with the address of the PostgreSQL instance):
+
+```bash
+Plugins.PostgreSQL.Sessions.myconn.Uri=tcp://:5432
+Plugins.PostgreSQL.Sessions.myconn.TLSConnect=required
+```
+
+Then set the `PostgreSQL connection string` field to `myconn` to use this named session.
+
+5. Set the password that you specified in step 2 in the `PostgreSQL user password` field.'),
+('10330',NULL,'PHP-FPM by Zabbix agent','3','-1','2','','','PHP-FPM by Zabbix agent','0',NULL,'Get PHP-FPM metrics using Zabbix agent running on Linux.
+
+Note that depending on your OS distribution, the PHP-FPM process name may vary. Please, check the actual name in the line "Name" from /proc//status file (https://www.zabbix.com/documentation/8.0/manual/appendix/items/proc_mem_num_notes) and change {$PHP_FPM.PROCESS.NAME.PARAMETER} macro if needed.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','1cbda0970410435684135884d0cb7090','PHP-FPM BY ZABBIX AGENT','Zabbix','8.0-1',NULL,'0','1',E'## Overview
+
+This template is developed to monitor the FastCGI Process Manager (PHP-FPM) by Zabbix agent that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template `PHP-FPM by Zabbix agent` - collects metrics by polling the PHP-FPM status-page locally with Zabbix agent.
+
+Note that this template doesn''t support HTTPS and redirects (limitations of `web.page.get`).
+
+It also uses Zabbix agent to collect `php-fpm` Linux process statistics, such as CPU usage, memory usage, and whether the process is running or not.
+
+## Setup
+
+Note that depending on your OS distribution, the PHP-FPM executable/service name can vary. RHEL-like distributions usually name both process and service as `php-fpm`, while for Debian/Ubuntu based distributions it may include the version, for example: executable name - `php-fpm8.2`, systemd service name - `php8.2-fpm`. Adjust the following instructions accordingly if needed.
+
+1. Open the PHP-FPM configuration file and enable the status page as shown.
+ ```
+ pm.status_path = /status
+ ping.path = /ping
+ ```
+
+2. Validate the syntax to ensure it is correct before you reload the service. Replace the `` in the command if needed.
+ ```
+ $ php-fpm -t
+ ```
+ or
+ ```
+ $ php-fpm -t
+ ```
+
+3. Reload the `php-fpm` service to make the change active. Replace the `` in the command if needed.
+ ```
+ $ systemctl reload php-fpm
+ ```
+ or
+ ```
+ $ systemctl reload php-fpm
+ ```
+
+4. Next, edit the configuration of your web server.
+
+If you use Nginx, edit the configuration file of your Nginx server block (virtual host) and add the location block below it.
+ ```
+ # Enable php-fpm status page
+ location ~ ^/(status|ping)$ {
+ ## disable access logging for request if you prefer
+ access_log off;
+
+ ## Only allow trusted IPs for security, deny everyone else
+ # allow 127.0.0.1;
+ # allow 1.2.3.4; # your IP here
+ # deny all;
+
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ fastcgi_index index.php;
+ include fastcgi_params;
+ ## Now the port or socket of the php-fpm pool we want the status of
+ fastcgi_pass 127.0.0.1:9000;
+ # fastcgi_pass unix:/run/php-fpm/your_socket.sock;
+ }
+ ```
+If you use Apache, edit the configuration file of the virtual host and add the following location blocks.
+ ```
+
+ Require ip 127.0.0.1
+ # Require ip 1.2.3.4 # Your IP here
+ # Adjust the path to the socket if needed
+ ProxyPass "unix:/run/php-fpm/www.sock|fcgi://localhost/status"
+
+
+
+ Require ip 127.0.0.1
+ # Require ip 1.2.3.4 # Your IP here
+ # Adjust the path to the socket if needed
+ ProxyPass "unix:/run/php-fpm/www.sock|fcgi://localhost/ping"
+
+ ```
+5. Check the web server configuration syntax. The command may vary depending on the OS distribution and web server.
+ ```
+ $ nginx -t
+ ```
+ or
+ ```
+ $ httpd -t
+ ```
+ or
+ ```
+ $ apachectl configtest
+ ```
+
+6. Reload the web server configuration. The command may vary depending on the OS distribution and web server.
+ ```
+ $ systemctl reload nginx
+ ```
+ or
+ ```
+ $ systemctl reload httpd
+ ```
+ or
+ ```
+ $ systemctl reload apache2
+ ```
+
+7. Verify that the pages are available with these commands.
+ ```
+ curl -L 127.0.0.1/status
+ curl -L 127.0.0.1/ping
+ ```
+
+Depending on your OS distribution, the PHP-FPM process name may vary as well. Please check the actual name in the line "Name" from /proc/\\/status file (https://www.zabbix.com/documentation/8.0/manual/appendix/items/proc_mem_num_notes) and change the `Process name` host wizard configuration field if needed.
+
+If you use another location of the status/ping pages, don''t forget to change the `Status page path/Ping page path` host wizard configuration field.
+
+If you use another web server port or scheme for the location of the PHP-FPM status/ping pages, don''t forget to change the host wizard configuration fields `Scheme` and `PHP-FPM port`.'),
+('10331',NULL,'PHP-FPM by HTTP','3','-1','2','','','PHP-FPM by HTTP','0',NULL,'Get PHP-FPM metrics using the Zabbix HTTP agent.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','49c77ce207f8478da53e761526d6eca5','PHP-FPM BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is developed to monitor the FastCGI Process Manager (PHP-FPM) by Zabbix that work without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template `PHP-FPM by Zabbix agent` - collects metrics by polling PHP-FPM status-page with HTTP agent remotely.
+
+Note that this solution supports HTTPS and redirects.
+
+## Setup
+
+Note that depending on your OS distribution, the PHP-FPM executable/service name can vary. RHEL-like distributions usually name both process and service as `php-fpm`, while for Debian/Ubuntu based distributions it may include the version, for example: executable name - `php-fpm8.2`, systemd service name - `php8.2-fpm`. Adjust the following instructions accordingly if needed.
+
+1. Open the PHP-FPM configuration file and enable the status page as shown.
+ ```
+ pm.status_path = /status
+ ping.path = /ping
+ ```
+
+2. Validate the syntax to ensure it is correct before you reload the service. Replace the `` in the command if needed.
+ ```
+ $ php-fpm -t
+ ```
+ or
+ ```
+ $ php-fpm -t
+ ```
+
+3. Reload the `php-fpm` service to make the change active. Replace the `` in the command if needed.
+ ```
+ $ systemctl reload php-fpm
+ ```
+ or
+ ```
+ $ systemctl reload php-fpm
+ ```
+
+4. Next, edit the configuration of your web server.
+
+If you use Nginx, edit the configuration file of your Nginx server block (virtual host) and add the location block below it.
+ ```
+ # Enable php-fpm status page
+ location ~ ^/(status|ping)$ {
+ ## disable access logging for request if you prefer
+ access_log off;
+
+ ## Only allow trusted IPs for security, deny everyone else
+ # allow 127.0.0.1;
+ # allow 1.2.3.4; # your IP here
+ # deny all;
+
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ fastcgi_index index.php;
+ include fastcgi_params;
+ ## Now the port or socket of the php-fpm pool we want the status of
+ fastcgi_pass 127.0.0.1:9000;
+ # fastcgi_pass unix:/run/php-fpm/your_socket.sock;
+ }
+ ```
+If you use Apache, edit the configuration file of the virtual host and add the following location blocks.
+ ```
+
+ Require ip 127.0.0.1
+ # Require ip 1.2.3.4 # Your IP here
+ # Adjust the path to the socket if needed
+ ProxyPass "unix:/run/php-fpm/www.sock|fcgi://localhost/status"
+
+
+
+ Require ip 127.0.0.1
+ # Require ip 1.2.3.4 # Your IP here
+ # Adjust the path to the socket if needed
+ ProxyPass "unix:/run/php-fpm/www.sock|fcgi://localhost/ping"
+
+ ```
+5. Check the web server configuration syntax. The command may vary depending on the OS distribution and web server.
+ ```
+ $ nginx -t
+ ```
+ or
+ ```
+ $ httpd -t
+ ```
+ or
+ ```
+ $ apachectl configtest
+ ```
+
+6. Reload the web server configuration. The command may vary depending on the OS distribution and web server.
+ ```
+ $ systemctl reload nginx
+ ```
+ or
+ ```
+ $ systemctl reload httpd
+ ```
+ or
+ ```
+ $ systemctl reload apache2
+ ```
+
+7. Verify that the pages are available with these commands.
+ ```
+ curl -L 127.0.0.1/status
+ curl -L 127.0.0.1/ping
+ ```
+
+If you use another location of the status/ping pages, don''t forget to change the `Status page path/Ping page path` host wizard configuration field.
+
+If you use another web server port or scheme for the location of the PHP-FPM status/ping pages, don''t forget to change the host wizard configuration fields `Scheme` and `PHP-FPM port`.'),
+('10335',NULL,'Oracle by Zabbix agent 2','3','-1','2','','','Oracle by Zabbix agent 2','0',NULL,'Get metrics from Oracle Database using Zabbix agent 2.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','d670c32f007d438c9dcd32db57d2b691','ORACLE BY ZABBIX AGENT 2','Zabbix','8.0-0',NULL,'0','1','## Overview
+
+The template is developed to monitor a single DBMS Oracle Database instance with Zabbix agent 2.
+
+## Supported versions
+
+Oracle Database 12c2 and newer.
+
+**Important! This integration queries the `V$ACTIVE_SESSION_HISTORY` dynamic performance view which is part of the Oracle Diagnostics Pack. Please make sure that you have the licence required for using this management pack.**
+
+## Setup
+
+1. Set the ''URI or session name'' value using either or named session.
+2. If you want to override parameters from Zabbix agent configuration file, set the user name, password and service name in host wizard configuration fields(Username, Password, and Service Name).
+
+ User can contain sysdba, sysoper, sysasm privileges. It must be used with `as` as a separator e.g `user as sysdba`, privilege can be upper or lowercase, and must be at the end of username string.
+
+Test availability:
+ ```zabbix_get -s oracle-host -k oracle.ping["{$ORACLE.CONNSTRING}","{$ORACLE.USER}","{$ORACLE.PASSWORD}","{$ORACLE.SERVICE}"]```'),
+('10336',NULL,'Asterisk by HTTP','3','-1','2','','','Asterisk by HTTP','0',NULL,'The template gets Asterisk metrics from AMI by HTTP agent.
+You should enable the mini-HTTP Server, add the option webenabled=yes in the general section of the manager.conf file and create Asterisk Manager user with system and command write permissions within your Asterisk instance.
+Disable the PJSIP driver if you do not use PJSIP or do not have PJSIP endpoints.
+Please, define AMI address in the {$AMI.URL} macro. Also, set the hostname or IP address of the AMI host in the {$AMI.HOST} macro for Zabbix to check Asterisk service status.
+Then you can define {$AMI.USERNAME} and {$AMI.SECRET} macros in the template for using on the host level.
+If there are errors, increase the logging to debug level and see the Zabbix server log.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/410060-discussion-thread-for-official-zabbix-template-asterisk
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','30cc187a4e994c39b07f53d86b5cc6bc','ASTERISK BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template for monitoring Asterisk over HTTP that works without any external scripts.
+It collects metrics by polling the Asterisk Manager API remotely using an HTTP agent and JS preprocessing.
+All metrics are collected at once, thanks to Zabbix''s bulk data collection.
+
+## Setup
+
+You should enable the mini-HTTP Server, add the option webenabled=yes in the general section of the manager.conf file and create Asterisk Manager user with system and command write permissions within your Asterisk instance.
+Disable the PJSIP driver if you do not use PJSIP or do not have PJSIP endpoints.
+Please, define AMI address in the `AMI API URL` host wizard configuration field. Also, set the hostname or IP address of the AMI host in the `AMI host` host wizard configuration field for Zabbix to check Asterisk service status.
+Then you can define `AMI manager name` and `AMI manager secret` host wizard configuration fields in the template for using on the host level.
+If there are errors, increase the logging to debug level and see the Zabbix server log.'),
+('10343',NULL,'Linux by Zabbix agent active','3','-1','2','','','Linux by Zabbix agent active','0',NULL,'This is an official Linux template. It requires Zabbix agent 8.0 or newer.
+
+Notes on filesystem (FS) discovery:
+ - The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+ - BTRFS allocates a default of 10% of the volume for its own needs.
+ - To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: ''pused = 100 - 100 * (available / total - free + available)''
+ - The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/387225-discussion-thread-for-official-zabbix-template-for-linux
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e2307c94f1744af7a8f1f458a67af424','LINUX BY ZABBIX AGENT ACTIVE','Zabbix','8.0-0',NULL,'0','1','## Overview
+
+This is an official Linux template. It requires Zabbix agent 8.0 or newer.
+
+#### Notes on filesystem (FS) discovery:
+- The ext4/3/2 FS reserves space for privileged usage, typically set at 5% by default.
+- BTRFS allocates a default of 10% of the volume for its own needs.
+- To mitigate potential disasters, FS usage triggers are based on the maximum available space.
+ - Utilization formula: `pused = 100 - 100 * (available / total - free + available)`
+- The FS utilization chart, derived from graph prototypes, reflects FS reserved space as the difference between used and available space from the total volume.'),
+('10351',NULL,'Windows by Zabbix agent active','3','-1','2','','','Windows by Zabbix agent active','0',NULL,'This is an official Windows template. It requires Zabbix agent 8.0 or newer.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/387224-discussion-thread-for-official-zabbix-template-for-windows
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','5fdd2ca8b8f84962aaea5a218b46ea7d','WINDOWS BY ZABBIX AGENT ACTIVE','Zabbix','8.0-0',NULL,'0','1','## Overview
+
+This is an official Windows template. It requires Zabbix agent 8.0 or newer.'),
+('10353',NULL,'Ceph by Zabbix agent 2','3','-1','2','','','Ceph by Zabbix agent 2','0',NULL,'You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/410059-discussion-thread-for-official-zabbix-template-ceph
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','09fb25d089f7467f860895f6e71d3fa2','CEPH BY ZABBIX AGENT 2','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor Ceph cluster by Zabbix that work without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+Template `Ceph by Zabbix agent 2` — collects metrics by polling zabbix-agent2.
+
+
+## Setup
+
+1. Setup and configure zabbix-agent2 compiled with the Ceph monitoring plugin.
+2. Set the `Connection string` such as or named session.
+3. Set the user name and password in host wizard configuration field (`Username`, `API key`) if you want to override parameters from the Zabbix agent configuration file.
+
+Test availability: `zabbix_get -s ceph-host -k ceph.ping["{$CEPH.CONNSTRING}","{$CEPH.USER}","{$CEPH.API.KEY}"]`'),
+('10355',NULL,'Squid by SNMP','3','-1','2','','','Squid by SNMP','0',NULL,'Template for monitoring Squid caching proxy via SNMP
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/409339-discussion-thread-for-official-zabbix-template-squid
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','8e5236f799b347a8ae90a979198be85e','SQUID BY SNMP','Zabbix','8.0-2',NULL,'0','1',E'## Setup
+
+### Setup Squid
+Enable SNMP support following [official documentation](https://wiki.squid-cache.org/Features/Snmp).
+Required parameters in squid.conf:
+```
+snmp_port
+acl snmp_community
+snmp_access allow
+```
+
+### Setup Zabbix
+1\\. [Import](https://www.zabbix.com/documentation/8.0/manual/xml_export_import/templates) the template [template_app_squid_snmp.yaml](template_app_squid_snmp.yaml) into Zabbix.
+
+2\\. Set values for {$SQUID.SNMP.COMMUNITY}, {$SQUID.SNMP.PORT} and {$SQUID.HTTP.PORT} as configured in squid.conf.
+
+3\\. [Link](https://www.zabbix.com/documentation/8.0/manual/config/templates/linking) the imported template to a host with Squid.
+
+4\\. Add SNMPv2 interface to Squid host. Set **Port** as {$SQUID.SNMP.PORT} and **SNMP community** as {$SQUID.SNMP.COMMUNITY}.'),
+('10357',NULL,'PostgreSQL by Zabbix agent','3','-1','2','','','PostgreSQL by Zabbix agent','0',NULL,'This template is designed for the deployment of PostgreSQL monitoring by Zabbix via Zabbix agent and uses user parameters to run SQL queries with the `psql` command-line tool.
+
+Note:
+- The template requires `pg_isready` and `psql` utilities to be installed on the same host with Zabbix agent.
+- The template requires files with SQL queries and user parameters that can be found in the Zabbix official repository:
+https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/templates/db/postgresql?at=refs%2Fheads%2Frelease%2F6.0
+
+Setup:
+
+1. Deploy Zabbix agent and create the PostgreSQL user for monitoring (`` at your discretion) with proper access rights to your PostgreSQL instance.
+
+For PostgreSQL version 10 and above:
+CREATE USER zbx_monitor WITH PASSWORD '''' INHERIT;
+GRANT pg_monitor TO zbx_monitor;
+
+For PostgreSQL version 9.6 and below:
+CREATE USER zbx_monitor WITH PASSWORD '''';
+GRANT SELECT ON pg_stat_database TO zbx_monitor;
+ALTER USER zbx_monitor WITH SUPERUSER;
+
+2. Copy the `postgresql/` directory to the `zabbix` user home directory - `/var/lib/zabbix/`. The `postgresql/` directory contains the files with SQL queries needed to obtain metrics from PostgreSQL instance.
+
+If the home directory of the `zabbix` user doesn''t exist, create it first:
+mkdir -m u=rwx,g=rwx,o= -p /var/lib/zabbix
+chown zabbix:zabbix /var/lib/zabbix
+
+3. Copy the `template_db_postgresql.conf` file, containing user parameters, to the Zabbix agent configuration directory `/etc/zabbix/zabbix_agentd.d/` and restart Zabbix agent service.
+
+If you want to use SSL/TLS encryption to protect communications with the remote PostgreSQL instance, you can modify the connection string in user parameters. For example, to enable required encryption in transport mode without identity checks you could append `?sslmode=required` to the end of the connection string for all keys that use `psql`:
+UserParameter=pgsql.bgwriter[*], psql -qtAX postgresql://"$3":"$4"@"$1":"$2"/"$5"?sslmode=required -f "/var/lib/zabbix/postgresql/pgsql.bgwriter.sql"
+
+Consult the PostgreSQL documentation about protection modes (https://www.postgresql.org/docs/current/libpq-ssl.html#LIBPQ-SSL-PROTECTION) and client connection parameters (https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNECT-SSLMODE).
+
+Also, it is assumed that you set up the PostgreSQL instance to work in the desired encryption mode. Check the PostgreSQL documentation (https://www.postgresql.org/docs/current/ssl-tcp.html) for details.
+
+4. Edit the `pg_hba.conf` configuration file to allow connections for the user `zbx_monitor`. You can check the PostgreSQL documentation for examples (https://www.postgresql.org/docs/current/auth-pg-hba-conf.html).
+
+5. Specify the host name or IP address in the `{$PG.HOST}` macro. Adjust the port number with `{$PG.PORT}` macro if needed.
+
+6. Set the password that you specified in step 1 in the macro `{$PG.PASSWORD}`.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/384190-%C2%A0discussion-thread-for-official-zabbix-template-db-postgresql
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','399bd1ee587245ecac6f39beaa99886f','POSTGRESQL BY ZABBIX AGENT','Zabbix','8.0-0',NULL,'0','1','## Overview
+
+This template is designed for the deployment of PostgreSQL monitoring by Zabbix via Zabbix agent and uses user parameters to run SQL queries with the `psql` command-line tool.
+
+## Setup
+
+**Note:**
+- The template requires `pg_isready` and `psql` utilities to be installed on the same host with Zabbix agent.
+
+1. Create the PostgreSQL user for monitoring (`` at your discretion) with proper access rights to your PostgreSQL instance.
+
+For PostgreSQL version 10 and above:
+
+```sql
+CREATE USER zbx_monitor WITH PASSWORD '''' INHERIT;
+GRANT pg_monitor TO zbx_monitor;
+```
+
+For PostgreSQL version 9.6 and below:
+
+```sql
+CREATE USER zbx_monitor WITH PASSWORD '''';
+GRANT SELECT ON pg_stat_database TO zbx_monitor;
+
+-- To collect WAL metrics, the user must have a `superuser` role.
+ALTER USER zbx_monitor WITH SUPERUSER;
+```
+
+2. Copy the `postgresql/` directory to the `zabbix` user home directory - `/var/lib/zabbix/`. The `postgresql/` directory contains the files with SQL queries needed to obtain metrics from PostgreSQL instance.
+
+If the home directory of the `zabbix` user doesn''t exist, create it first:
+
+```bash
+mkdir -m u=rwx,g=rwx,o= -p /var/lib/zabbix
+chown zabbix:zabbix /var/lib/zabbix
+```
+
+3. Copy the `template_db_postgresql.conf` file, containing user parameters, to the Zabbix agent configuration directory `/etc/zabbix/zabbix_agentd.d/` and restart Zabbix agent service.
+
+**Note:** if you want to use SSL/TLS encryption to protect communications with the remote PostgreSQL instance, you can modify the connection string in user parameters. For example, to enable required encryption in transport mode without identity checks you could append `?sslmode=required` to the end of the connection string for all keys that use `psql`:
+
+```bash
+UserParameter=pgsql.bgwriter[*], psql -qtAX postgresql://"$3":"$4"@"$1":"$2"/"$5"?sslmode=required -f "/var/lib/zabbix/postgresql/pgsql.bgwriter.sql"
+```
+
+Consult the PostgreSQL documentation about [`protection modes`](https://www.postgresql.org/docs/current/libpq-ssl.html#LIBPQ-SSL-PROTECTION) and [`client connection parameters`](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNECT-SSLMODE).
+
+Also, it is assumed that you set up the PostgreSQL instance to work in the desired encryption mode. Check the [`PostgreSQL documentation`](https://www.postgresql.org/docs/current/ssl-tcp.html) for details.
+
+4. Edit the `pg_hba.conf` configuration file to allow connections for the user `zbx_monitor`. For example, you could add one of the following rows to allow local TCP connections from the same host:
+
+```bash
+# TYPE DATABASE USER ADDRESS METHOD
+ host all zbx_monitor localhost trust
+ host all zbx_monitor 127.0.0.1/32 md5
+ host all zbx_monitor ::1/128 scram-sha-256
+```
+
+For more information please read the PostgreSQL documentation `https://www.postgresql.org/docs/current/auth-pg-hba-conf.html`.
+
+5. Specify the host name or IP address in the `PostgreSQL host` host wizard configuration field. Adjust the port number in the `PostgreSQL port` field if needed.
+
+6. Set the password that you specified in step 1 in the `PostgreSQL user password` field.'),
+('10358',NULL,'Apache ActiveMQ by JMX','3','-1','2','','','Apache ActiveMQ by JMX','0',NULL,'The template to monitor Apache ActiveMQ by Zabbix that work without any external scripts.
+The metrics are collected by JMX.
+You can set macro values and add macros with context for specific brokers or destinations following macro description.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/411049-discussion-thread-for-official-zabbix-template-amq
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','c87e0a2e0683483ab7c6f3c380e9f840','APACHE ACTIVEMQ BY JMX','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+Metrics are collected by JMX.
+
+1. Enable and configure JMX access to Apache ActiveMQ.
+ See documentation for [instructions](https://activemq.apache.org/jmx.html).
+2. Set values in host wizard configuration field `JMX user`, `JMX password` and `JMX port`.'),
+('10359',NULL,'Aranet Cloud','3','-1','2','','','Aranet Cloud','0',NULL,'Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','af21edc47557400583e537904ea632aa','ARANET CLOUD','Zabbix','8.0-1',NULL,'0','1','## Overview
+This Zabbix template enables monitoring of Aranet Cloud sensors via the Aranet Cloud API. It collects temperature, humidity, CO₂, and other environmental metrics from linked devices, providing real-time data visualization, alerting, and historical trends within Zabbix. Easy to configure and ideal for smart building, greenhouse, or industrial monitoring setups.'),
+('10360',NULL,'Microsoft Exchange Server 2016 by Zabbix agent','3','-1','2','','','Microsoft Exchange Server 2016 by Zabbix agent','0',NULL,'The template to monitor Microsoft Exchange Server 2016 by Zabbix that works without any external scripts.
+The metrics are collected by Zabbix agent.
+Recommended to use it with "OS Windows by Zabbix agent" template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/415007-discussion-thread-for-official-zabbix-template-microsoft-exchange
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','cbf70ed444394566bcf213dd63d4d352','MICROSOFT EXCHANGE SERVER 2016 BY ZABBIX AGENT','Zabbix','8.0-1',NULL,'0','1',E'## Overview
+
+Official Template for Microsoft Exchange Server 2016.
+
+
+## Setup
+
+Metrics are collected by Zabbix agent.
+
+1\\. Import the template into Zabbix.
+
+2\\. Link the imported template to a host with MS Exchange.
+
+Note that template doesn''t provide information about Windows services state. Recommended to use it with "OS Windows by Zabbix agent" template.'),
+('10361',NULL,'Microsoft Exchange Server 2016 by Zabbix agent active','3','-1','2','','','Microsoft Exchange Server 2016 by Zabbix agent active','0',NULL,'The template to monitor Microsoft Exchange Server 2016 by Zabbix that works without any external scripts.
+The metrics are collected by Zabbix agent active.
+Recommended to use it with "OS Windows by Zabbix agent active" template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/415007-discussion-thread-for-official-zabbix-template-microsoft-exchange
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','a0e05ca631034676821b7e0e1ce25488','MICROSOFT EXCHANGE SERVER 2016 BY ZABBIX AGENT ACTIVE','Zabbix','8.0-1',NULL,'0','1',E'## Overview
+
+Official Template for Microsoft Exchange Server 2016.
+
+
+## Setup
+
+Metrics are collected by Zabbix agent active.
+
+1\\. Import the template into Zabbix.
+
+2\\. Link the imported template to a host with MS Exchange.
+
+Note that template doesn''t provide information about Windows services state. Recommended to use it with "OS Windows by Zabbix agent active" template.'),
+('10362',NULL,'GitLab by HTTP','3','-1','2','','','GitLab by HTTP','0',NULL,'Get GitLab metrics by HTTP agent from Prometheus metrics endpoint.
+
+To access the metrics, the client IP address must be explicitly allowed. See https://docs.gitlab.com/ee/administration/monitoring/ip_whitelist.html.
+Or second method, using token variable from http://your.gitlab.address/admin/health_check (fill {$GITLAB.HEALTH.TOKEN} macro with variable path like "?token=your_token").
+Don''t forget change macros {$GITLAB.URL}.
+Some metrics may not be collected depending on your Gitlab instance version and configuration. See (Gitlab''s documentation[)https://docs.gitlab.com/ee/administration/monitoring/prometheus/gitlab_metrics.html] for further information about its metric collection.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','f445dac89ff74deabaae9dcb84815998','GITLAB BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed to monitor GitLab by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template `GitLab by HTTP` — collects metrics by an HTTP agent from the GitLab `/-/metrics` endpoint.
+See https://docs.gitlab.com/ee/administration/monitoring/prometheus/gitlab_metrics.html.
+
+
+## Setup
+
+This template works with self-hosted GitLab instances. Internal service metrics are collected from the GitLab `/-/metrics` endpoint.
+To access metrics following two methods are available:
+1. Explicitly allow monitoring instance IP address in gitlab [whitelist configuration](https://docs.gitlab.com/ee/administration/monitoring/ip_whitelist.html).
+2. Get token from Gitlab `Admin -> Monitoring -> Health check` page: http://your.gitlab.address/admin/health_check; Use this token in host wizard configuration field ` GitLab health check token path` as variable path, like: `?token=your_token`.
+Remember to change the host wizard configuration field `GitLab instance URL`.
+
+
+*NOTE.* Some metrics may not be collected depending on your Gitlab instance version and configuration. See [Gitlab''s documentation](https://docs.gitlab.com/ee/administration/monitoring/prometheus/gitlab_metrics.html) for further information about its metric collection.'),
+('10363',NULL,'Hadoop by HTTP','3','-1','2','','','Hadoop by HTTP','0',NULL,'The template gets the Hadoop metrics from cluster''s hosts (ResourceManager, NodeManagers, NameNode, DataNodes) by HTTP agent. You should define the IP address (or FQDN) and Web-UI port for the ResourceManager in {$HADOOP.RESOURCEMANAGER.HOST} and {$HADOOP.RESOURCEMANAGER.PORT} macros and for the NameNode in {$HADOOP.NAMENODE.HOST} and {$HADOOP.NAMENODE.PORT} macros respectively. Macros can be set in the template or overridden at the host level.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/413459-discussion-thread-for-official-zabbix-template-hadoop
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e129aeba7c814bf189772cf5919b4bbb','HADOOP BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template for monitoring Hadoop over HTTP that works without any external scripts.
+It collects metrics by polling the Hadoop API remotely using an HTTP agent and JSONPath preprocessing.
+Zabbix server (or proxy) execute direct requests to ResourceManager, NodeManagers, NameNode, DataNodes APIs.
+All metrics are collected at once, thanks to the Zabbix bulk data collection.
+
+## Setup
+
+You should define the IP address (or FQDN) and Web-UI port for the ResourceManager in `ResourceManager host` and `ResourceManager Web UI port` host wizard configuration fields and for the NameNode in `NameNode host` and `NameNode Web UI port` host wizard configuration fields respectively.'),
+('10364',NULL,'Apache Kafka by JMX','3','-1','2','','','Apache Kafka by JMX','0',NULL,'Official JMX Template for Apache Kafka.
+ The metrics are collected by JMX.
+ You can set {$KAFKA.USER} and {$KAFKA.PASSWORD} macros in the template for using on the host level.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','2eb43a3c9666467683b9ce09d2bd26d7','APACHE KAFKA BY JMX','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+Metrics are collected by JMX.
+
+1. Enable and configure JMX access to Apache Kafka. See documentation for [instructions](https://kafka.apache.org/documentation/#remote_jmx).
+2. Set the user name and password in host wizard configuration fields `Username` and `Password`.'),
+('10365',NULL,'HashiCorp Vault by HTTP','3','-1','2','','','HashiCorp Vault by HTTP','0',NULL,'Get HashiCorp Vault metrics from Vault API HTTP Prometheus metrics endpoint.
+
+Some metrics may not be collected depending on your Vault instance version and configuration.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','2f82248e411340429d390e8389850401','HASHICORP VAULT BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor HashiCorp Vault by Zabbix that work without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+Template `Vault by HTTP` — collects metrics by HTTP agent from `/sys/metrics` API endpoint.
+See https://www.vaultproject.io/api-docs/system/metrics.
+
+## Setup
+
+> See [Zabbix template operation](https://www.zabbix.com/documentation/8.0/manual/config/templates_out_of_the_box/http) for basic instructions.
+
+Configure Vault API. See [Vault Configuration](https://www.vaultproject.io/docs/configuration).
+Create a Vault service token and set it to the host wizard configuration field `Vault auth token`.'),
+('10366',NULL,'VMware FQDN','3','-1','2','','','VMware FQDN','0',NULL,'You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/.
+
+Note: To enable discovery of hardware sensors of VMware Hypervisors, set the macro ''{$VMWARE.HV.SENSOR.DISCOVERY}'' to the value ''true'' on the discovered host level.
+
+Note: To create custom performance counter see documentation: https://www.zabbix.com/documentation/8.0/manual/vm_monitoring/vmware_keys#footnotes.
+
+Note: To get all supported counters and generate path for custom performance counter see documentation: https://www.zabbix.com/documentation/8.0/manual/appendix/items/perf_counters.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','ca02e82e6c414d0aa7aedc8d78468a49','VMWARE FQDN','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template set is designed for the effortless deployment of VMware vCenter and ESX hypervisor monitoring and doesn''t require any external scripts.
+
+- The template "VMware Guest" is used in discovery and normally should not be manually linked to a host.
+- The template "VMware Hypervisor" can be used in discovery as well as manually linked to a host.
+
+For additional information, please see [Zabbix documentation on VM monitoring](https://www.zabbix.com/documentation/8.0/manual/vm_monitoring).
+
+## Setup
+
+1. Compile Zabbix server with the required options (`--with-libxml2` and `--with-libcurl`).
+2. Set the `StartVMwareCollectors` option in the Zabbix server configuration file to "1" or more.
+3. Create a new host.
+4. If you want to use a separate user for monitoring, make sure that the user is a member of the `SystemConfiguration.ReadOnly` and `vStatsGroup` groups.
+Set the host wizard configuration fields required for VMware authentication: `VMware URL`, `VMware username` and `VMware password`.
+5. Link the template to the host created earlier.
+
+Note: To enable discovery of hardware sensors of VMware hypervisors, set the host wizard configuration field `Monitoring of hardware sensors` to the selected state.
+
+Additional resources:
+- How to [create a custom performance counter](https://www.zabbix.com/documentation/8.0/manual/vm_monitoring/vmware_keys#footnotes).
+- How to get all supported counters and [generate a path for the custom performance counter](https://www.zabbix.com/documentation/8.0/manual/appendix/items/perf_counters).'),
+('10369',NULL,'Zookeeper by HTTP','3','-1','2','','','Zookeeper by HTTP','0',NULL,'This template is designed for the effortless deployment of Apache Zookeeper monitoring by Zabbix via HTTP and doesn''t require any external scripts.
+
+This template works with standalone and cluster instances. Metrics are collected from each Zookeeper node by requests to AdminServer
+
+Setup:
+
+1. Enable the AdminServer and configure the parameters according to the official documentation:
+https://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_adminserver_config
+
+2. Set the hostname or IP address of the Apache Zookeeper host in the ''{$ZOOKEEPER.HOST}'' macro. You can also change the ''{$ZOOKEEPER.COMMAND_URL}'', ''{$ZOOKEEPER.PORT}'' and ''{$ZOOKEEPER.SCHEME}'' macros if necessary.
+
+You can discuss this template or leave feedback on our forum:
+https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','b606eda347ea4663a33ad4d12a482750','ZOOKEEPER BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed for the effortless deployment of Apache Zookeeper monitoring by Zabbix via HTTP and doesn''t require any external scripts.
+
+This template works with standalone and cluster instances. Metrics are collected from each Zookeeper node by requests to AdminServer.
+
+## Setup
+
+1. Enable the AdminServer and configure the parameters according to the [`official documentation`](https://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_adminserver_config).
+
+2. Set the hostname or IP address of the Apache Zookeeper host in the `Address` host wizard configuration field. You can also change the `Command URL`, `Port` and `Scheme` if necessary.'),
+('10370',NULL,'Apache Cassandra by JMX','3','-1','2','','','Apache Cassandra by JMX','0',NULL,'The template to monitor Apache Cassandra by Zabbix that work without any external scripts.
+It works with both standalone and cluster instances.
+The metrics are collected by JMX.
+You can set {$CASSANDRA.USER} and {$CASSANDRA.PASSWORD} macros in the template for using on the host level.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/410057-discussion-thread-for-official-zabbix-template-apache-cassandra
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','5c42de26643c4b43b23a11159df021ce','APACHE CASSANDRA BY JMX','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+This template works with standalone and cluster instances.
+Metrics are collected by JMX.
+
+1. Enable and configure JMX access to Apache cassandra.
+ See documentation for [instructions](https://cassandra.apache.org/doc/latest/operating/security.html#jmx-access).
+2. Set the user name and password in host wizard configuration fields `Username` and `Password`.'),
+('10371',NULL,'Morningstar ProStar MPPT by SNMP','3','-1','2','','','Morningstar ProStar MPPT by SNMP','0',NULL,'MIBs used:
+PROSTAR-MPPT
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','b84324c2a40a496dbbb379bbf5dde8d5','MORNINGSTAR PROSTAR MPPT BY SNMP','Zabbix','8.0-2',NULL,'0','1',''),
+('10372',NULL,'Morningstar ProStar PWM by SNMP','3','-1','2','','','Morningstar ProStar PWM by SNMP','0',NULL,'MIBs used:
+PROSTAR-PWM
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','24bed6339f0a492fab86fe757394b937','MORNINGSTAR PROSTAR PWM BY SNMP','Zabbix','8.0-2',NULL,'0','1',''),
+('10373',NULL,'Morningstar SunSaver MPPT by SNMP','3','-1','2','','','Morningstar SunSaver MPPT by SNMP','0',NULL,'MIBs used:
+SUNSAVER-MPPT
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','f1336fd88ab0415a9c02892a71e50032','MORNINGSTAR SUNSAVER MPPT BY SNMP','Zabbix','8.0-2',NULL,'0','1',''),
+('10374',NULL,'Morningstar SureSine by SNMP','3','-1','2','','','Morningstar SureSine by SNMP','0',NULL,'MIBs used:
+SURESINE
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','3bbfe42c78c74f04a2565431fbdd19e2','MORNINGSTAR SURESINE BY SNMP','Zabbix','8.0-2',NULL,'0','1',''),
+('10375',NULL,'Morningstar TriStar MPPT 600V by SNMP','3','-1','2','','','Morningstar TriStar MPPT 600V by SNMP','0',NULL,'MIBs used:
+TRISTAR-MPPT
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','2d20a2fbd540492089fdcafc8feb60e3','MORNINGSTAR TRISTAR MPPT 600V BY SNMP','Zabbix','8.0-2',NULL,'0','1',''),
+('10376',NULL,'Morningstar TriStar MPPT by SNMP','3','-1','2','','','Morningstar TriStar MPPT by SNMP','0',NULL,'MIBs used:
+TRISTAR-MPPT
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','07b32152c3654e8ead4c1eeae24efa8f','MORNINGSTAR TRISTAR MPPT BY SNMP','Zabbix','8.0-2',NULL,'0','1',''),
+('10377',NULL,'Morningstar TriStar PWM by SNMP','3','-1','2','','','Morningstar TriStar PWM by SNMP','0',NULL,'MIBs used:
+TRISTAR
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','230fa9f7c1774821bbe6cdcbbba5cbc6','MORNINGSTAR TRISTAR PWM BY SNMP','Zabbix','8.0-2',NULL,'0','1',''),
+('10378',NULL,'NetApp FAS3220 by SNMP','3','-1','2','','','NetApp FAS3220 by SNMP','0',NULL,'The template to monitor SAN NetApp FAS3220 cluster by Zabbix SNMP agent.
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+NETAPP-MIB
+IF-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/416694-discussion-thread-for-official-zabbix-template-netapp-fas3220
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e118ab11c1ec4f9cbe21dfce1441c0f6','NETAPP FAS3220 BY SNMP','Zabbix','8.0-2',NULL,'0','1',''),
+('10379',NULL,'Jenkins by HTTP','3','-1','2','','','Jenkins by HTTP','0',NULL,'Get Jenkins metrics by HTTP agent.
+Metrics are collected by requests to Metrics API. Install Metrics plugin and configure access to the Metrics Servlet by issuing API key.
+Don''t forget to change macros {$JENKINS.URL}, {$JENKINS.USER}, {$JENKINS.API.TOKEN}, {$JENKINS.API.KEY}.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','2ef2f2eb75ee4a0bae839e22aa76e5fc','JENKINS BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor Apache Jenkins by Zabbix that work without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+## Setup
+
+Metrics are collected by requests to [Metrics API](https://plugins.jenkins.io/metrics/).
+For common metrics:
+ Install and configure Metrics plugin parameters according [official documentations](https://plugins.jenkins.io/metrics/). Do not forget to configure access to the Metrics Servlet by issuing API key and change host wizard configuration field `API key`.
+
+For monitoring computers and builds:
+ Create API token for monitoring user according [official documentations](https://www.jenkins.io/doc/book/system-administration/authenticating-scripted-clients/) and change host wizard configuration field `Username`, `Token` and `URL`.'),
+('10380',NULL,'Hikvision camera by HTTP','3','-1','2','','','Hikvision camera by HTTP','0',NULL,'This template is designed for the effortless deployment of Hikvision cameras monitoring by Zabbix via HTTP and doesn''t require any external scripts.
+
+Sample device overview page:
+https://www.hikvision.com/en/products/IP-Products/Network-Cameras/
+
+Setup:
+
+1. Set the hostname or IP address of the Hikvision ISAPI host in the ''{$HIKVISION_ISAPI_HOST}'' macro.
+
+2. Set the user name and password in the ''{$PASSWORD}'' and ''{$USER}'' macros.
+
+3. Change other macros according to your camera configuration if necessary.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','3fb4020df2984b0ab64dfd8355ff5c65','HIKVISION CAMERA BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed for the effortless deployment of Hikvision cameras monitoring by Zabbix via HTTP and doesn''t require any external scripts.
+
+[`Sample device overview page`](https://www.hikvision.com/en/products/IP-Products/Network-Cameras/)
+
+## Setup
+
+1. Set the hostname or IP address of the Hikvision ISAPI host in the `Address` host wizard configuration field.
+
+2. Set the user name and password in the `Password` and `Username` host wizard configuration fields.
+
+3. Change other host wizard configuration fields according to your camera configuration if necessary.'),
+('10381',NULL,'Ignite by JMX','3','-1','2','','','Ignite by JMX','0',NULL,'The template to monitor Apache Ignite by Zabbix that work without any external scripts.
+ It works with both standalone and cluster instances.
+ The metrics are discoverable and collected by JMX.
+ Current JMX tree hierarchy contains classloader by default. Add the following jvm option `-DIGNITE_MBEAN_APPEND_CLASS_LOADER_ID=false`to will exclude one level with Classloader name.
+ You can set {$IGNITE.USER} and {$IGNITE.PASSWORD} macros in the template for using on the host level.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','ab05dbb15ff047f192782f617f0627ac','IGNITE BY JMX','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+Official JMX Template for Apache Ignite computing platform.
+This template is based on the original template developed by Igor Akkuratov, Senior Engineer at GridGain Systems and Apache Ignite Contributor.
+
+## Setup
+
+This template works with standalone and cluster instances. Metrics are collected by JMX. All metrics are discoverable.
+
+1. Enable and configure JMX access to Apache Ignite. See documentation for [instructions](https://docs.oracle.com/javase/8/docs/technotes/guides/management/agent.html). Current JMX tree hierarchy contains classloader by default. Add the following jvm option `-DIGNITE_MBEAN_APPEND_CLASS_LOADER_ID=false`to will exclude one level with Classloader name. You can configure Cache and Data Region metrics which you want using [official guide](https://ignite.apache.org/docs/latest/monitoring-metrics/configuring-metrics).
+2. Set the user name and password in host wizard configuration fields `Username` and `Password`.'),
+('10382',NULL,'Microsoft SharePoint by HTTP','3','-1','2','','','Microsoft SharePoint by HTTP','0',NULL,'Overview:
+Template receives data via HTTP Agent.
+Setup:
+Create a new host.
+Define macros according to your Sharepoint web portal.
+It is recommended to fill in the values of the filter macros to avoid getting redundant data.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','8d5fe5b4ebb64255a2429b34c7dd3681','MICROSOFT SHAREPOINT BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed for the effortless deployment of Microsoft SharePoint monitoring by Zabbix via HTTP and doesn''t require any external scripts.
+
+SharePoint includes a Representational State Transfer (REST) service. Developers can perform read operations from their SharePoint Add-ins, solutions, and client applications, using REST web technologies and standard Open Data Protocol (OData) syntax. Details in
+https://docs.microsoft.com/ru-ru/sharepoint/dev/sp-add-ins/get-to-know-the-sharepoint-rest-service?tabs=csom
+
+## Setup
+
+Create a new host.
+Define host wizard configuration fields according to your Sharepoint web portal.
+It is recommended to fill in the values of the filter host wizard configuration fields to avoid getting redundant data.'),
+('10385',NULL,'Huawei OceanStor 5300 V5 by SNMP','3','-1','2','','','Huawei OceanStor 5300 V5 by SNMP','0',NULL,'The template to monitor SAN Huawei OceanStor 5300 V5 by Zabbix SNMP agent.
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/418855-discussion-thread-for-official-zabbix-template-huawei-oceanstor
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','c5564dd58c394b969d5365cc5de3e7f8','HUAWEI OCEANSTOR 5300 V5 BY SNMP','Zabbix','8.0-2',NULL,'0','1',''),
+('10386',NULL,'MongoDB node by Zabbix agent 2','3','-1','2','','','MongoDB node by Zabbix agent 2','0',NULL,'Get MongoDB metrics from plugin for the zabbix-agent2.
+ 1. Setup and configure zabbix-agent2 compiled with the MongoDB monitoring plugin.
+ 2. Set the {$MONGODB.CONNSTRING} such as or named session.
+ 3. Set the user name and password in host macros ({$MONGODB.USER}, {$MONGODB.PASSWORD}) if you want to override parameters from the Zabbix agent configuration file.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/420659-discussion-thread-for-official-zabbix-template-db-mongodb
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','81aa8c5ab5594f77a2b26fb7f5094048','MONGODB NODE BY ZABBIX AGENT 2','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor single MongoDB server by Zabbix that work without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+`MongoDB node by Zabbix Agent 2` — collects metrics by polling zabbix-agent2.
+
+## Setup
+
+1. Setup and configure zabbix-agent2 compiled with the MongoDB monitoring plugin.
+2. Set the `Connection string` such as or named session.
+3. Set the user name and password in host wizard configuration fields (`Username`, `Password`) if you want to override parameters from the Zabbix agent configuration file.
+
+**Note**, depending on the number of DBs and collections discovery operation may be expensive. Use filters with host wizard configuration fields `Databases filter (include)`, `Databases filter (exclude)`, `Collections filter (include)`, `Collections filter (exclude)`.
+
+Test availability: `zabbix_get -s mongodb.node -k ''mongodb.ping["{$MONGODB.CONNSTRING}","{$MONGODB.USER}","{$MONGODB.PASSWORD}"]"`'),
+('10387',NULL,'MongoDB cluster by Zabbix agent 2','3','-1','2','','','MongoDB cluster by Zabbix agent 2','0',NULL,'Get MongoDB metrics from plugin for the zabbix-agent2.
+ 1. Setup and configure zabbix-agent2 compiled with the MongoDB monitoring plugin.
+ 2. Set the {$MONGODB.CONNSTRING} such as or named session.
+ 3. Set the user name and password in host macros ({$MONGODB.USER}, {$MONGODB.PASSWORD}) if you want to override parameters from the Zabbix agent configuration file.
+
+ All sharded Mongodb nodes (mongod) will be discovered with attached template "MongoDB node".
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/420659-discussion-thread-for-official-zabbix-template-db-mongodb
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','d38b271797bd41f2ad8c79d83b9d8d9c','MONGODB CLUSTER BY ZABBIX AGENT 2','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor MongoDB sharded cluster by Zabbix that work without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+`MongoDB cluster by Zabbix agent 2` — collects metrics from mongos proxy(router) by polling zabbix-agent2.
+
+## Setup
+
+1. Setup and configure zabbix-agent2 compiled with the MongoDB monitoring plugin.
+2. Set the `Connection string` such as or named session of mongos proxy(router).
+3. Set the user name and password in host wizard configuration fields (`Username`, `Password`) if you want to override parameters from the Zabbix agent configuration file.
+
+**Note**, depending on the number of DBs and collections discovery operation may be expensive. Use filters with host wizard configuration fields `Databases filter (include)`, `Databases filter (exclude)`, `Collections filter (include)`, `Collections filter (exclude)`.
+
+All sharded Mongodb nodes (mongod) will be discovered with attached template "MongoDB node by Zabbix agent 2".
+
+
+Test availability: `zabbix_get -s mongos.node -k ''mongodb.ping["{$MONGODB.CONNSTRING}","{$MONGODB.USER}","{$MONGODB.PASSWORD}"]"`'),
+('10390',NULL,'Cisco Catalyst 3750V2-24FS by SNMP','3','-1','2','','','Cisco Catalyst 3750V2-24FS by SNMP','0',NULL,'Template Cisco Catalyst 3750V2-24FS
+
+ MIBs used:
+ CISCO-MEMORY-POOL-MIB
+ IF-MIB
+ EtherLike-MIB
+ SNMPv2-MIB
+ CISCO-PROCESS-MIB
+ CISCO-ENVMON-MIB
+ ENTITY-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/418396-discussion-thread-for-official-zabbix-templates-for-cisco
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','6ff896f545e043cc98de6d98698d41df','CISCO CATALYST 3750V2-24FS BY SNMP','Zabbix','8.0-3',NULL,'0','1','## Overview
+
+
+> Courtesy of Cisco Systems, Inc. Unauthorized use not permitted.
+
+The Cisco Catalyst 3750 Series switches are a premier line of enterprise-class, stackable, multilayer switches that provide high availability, security, and quality of service (QoS) to enhance the operation of the network. Its innovative unified stack management raises the bar in stack management, redundancy, and failover.
+
+https://www.cisco.com/c/en/us/support/switches/catalyst-3750v2-24fs-switch/model.html
+
+## Setup
+
+Refer to the vendor documentation.'),
+('10391',NULL,'Cisco Catalyst 3750V2-24PS by SNMP','3','-1','2','','','Cisco Catalyst 3750V2-24PS by SNMP','0',NULL,'Template Cisco Catalyst 3750V2-24PS
+
+ MIBs used:
+ CISCO-MEMORY-POOL-MIB
+ IF-MIB
+ EtherLike-MIB
+ SNMPv2-MIB
+ CISCO-PROCESS-MIB
+ CISCO-ENVMON-MIB
+ ENTITY-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/418396-discussion-thread-for-official-zabbix-templates-for-cisco
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','4583f0c3bc894251a6c5e7129cb5b9aa','CISCO CATALYST 3750V2-24PS BY SNMP','Zabbix','8.0-3',NULL,'0','1','## Overview
+
+
+> Courtesy of Cisco Systems, Inc. Unauthorized use not permitted.
+
+The Cisco Catalyst 3750 Series switches are a premier line of enterprise-class, stackable, multilayer switches that provide high availability, security, and quality of service (QoS) to enhance the operation of the network. Its innovative unified stack management raises the bar in stack management, redundancy, and failover.
+
+https://www.cisco.com/c/en/us/support/switches/catalyst-3750v2-24ps-switch/model.html
+
+## Setup
+
+Refer to the vendor documentation.'),
+('10392',NULL,'Cisco Catalyst 3750V2-24TS by SNMP','3','-1','2','','','Cisco Catalyst 3750V2-24TS by SNMP','0',NULL,'Template Cisco Catalyst 3750V2-24TS
+
+ MIBs used:
+ CISCO-MEMORY-POOL-MIB
+ IF-MIB
+ EtherLike-MIB
+ SNMPv2-MIB
+ CISCO-PROCESS-MIB
+ CISCO-ENVMON-MIB
+ ENTITY-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/418396-discussion-thread-for-official-zabbix-templates-for-cisco
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','30d084c6b7844b7cab6cf820b00bb7b2','CISCO CATALYST 3750V2-24TS BY SNMP','Zabbix','8.0-3',NULL,'0','1','## Overview
+
+
+> Courtesy of Cisco Systems, Inc. Unauthorized use not permitted.
+
+The Cisco Catalyst 3750 Series switches are a premier line of enterprise-class, stackable, multilayer switches that provide high availability, security, and quality of service (QoS) to enhance the operation of the network. Its innovative unified stack management raises the bar in stack management, redundancy, and failover.
+
+https://www.cisco.com/c/en/us/support/switches/catalyst-3750v2-24ts-switch/model.html
+
+## Setup
+
+Refer to the vendor documentation.'),
+('10393',NULL,'Cisco Catalyst 3750V2-48PS by SNMP','3','-1','2','','','Cisco Catalyst 3750V2-48PS by SNMP','0',NULL,'Template Cisco Catalyst 3750V2-48PS
+
+ MIBs used:
+ CISCO-MEMORY-POOL-MIB
+ IF-MIB
+ EtherLike-MIB
+ SNMPv2-MIB
+ CISCO-PROCESS-MIB
+ CISCO-ENVMON-MIB
+ ENTITY-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/418396-discussion-thread-for-official-zabbix-templates-for-cisco
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','ea096c13a09b4d7a9be0aab1cec95206','CISCO CATALYST 3750V2-48PS BY SNMP','Zabbix','8.0-3',NULL,'0','1','## Overview
+
+
+> Courtesy of Cisco Systems, Inc. Unauthorized use not permitted.
+
+The Cisco Catalyst 3750 Series switches are a premier line of enterprise-class, stackable, multilayer switches that provide high availability, security, and quality of service (QoS) to enhance the operation of the network. Its innovative unified stack management raises the bar in stack management, redundancy, and failover.
+
+https://www.cisco.com/c/en/us/support/switches/catalyst-3750v2-48ps-switch/model.html
+
+## Setup
+
+Refer to the vendor documentation.'),
+('10394',NULL,'Cisco Catalyst 3750V2-48TS by SNMP','3','-1','2','','','Cisco Catalyst 3750V2-48TS by SNMP','0',NULL,'Template Cisco Catalyst 3750V2-48TS
+
+ MIBs used:
+ CISCO-MEMORY-POOL-MIB
+ IF-MIB
+ EtherLike-MIB
+ SNMPv2-MIB
+ CISCO-PROCESS-MIB
+ CISCO-ENVMON-MIB
+ ENTITY-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/418396-discussion-thread-for-official-zabbix-templates-for-cisco
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','f744679600844c07b2b4eedda9bc3d0c','CISCO CATALYST 3750V2-48TS BY SNMP','Zabbix','8.0-3',NULL,'0','1','## Overview
+
+
+> Courtesy of Cisco Systems, Inc. Unauthorized use not permitted.
+
+The Cisco Catalyst 3750 Series switches are a premier line of enterprise-class, stackable, multilayer switches that provide high availability, security, and quality of service (QoS) to enhance the operation of the network. Its innovative unified stack management raises the bar in stack management, redundancy, and failover.
+
+https://www.cisco.com/c/en/us/support/switches/catalyst-3750v2-48ts-switch/model.html
+
+## Setup
+
+Refer to the vendor documentation.'),
+('10395',NULL,'APC UPS by SNMP','3','-1','2','','','APC UPS by SNMP','0',NULL,'Template Power APC UPS
+
+MIBs used:
+HOST-RESOURCES-MIB
+PowerNet-MIB
+SNMPv2-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/420730-discussion-thread-for-official-zabbix-template-apc-ups
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','3ec55c9966624ef5bc1b50502812d581','APC UPS BY SNMP','Zabbix','8.0-2',NULL,'0','1',E'## Overview
+
+The template to monitor APC UPS with NMC by Zabbix SNMP agent.
+Note: please, use the latest version of the firmware for your NMC in order for the template to work correctly.
+
+
+## Setup
+
+1\\. Create a host for APC UPS management IP as SNMPv2 interface.
+
+2\\. Link the template to the host.
+
+3\\. Customize host wizard configuration field values if needed.'),
+('10396',NULL,'NetApp AFF A700 by HTTP','3','-1','2','','','NetApp AFF A700 by HTTP','0',NULL,'The template to monitor SAN NetApp AFF A700 cluster by Zabbix HTTP agent.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','79267c69f54a4e59b4152aba4e8c4bd5','NETAPP AFF A700 BY HTTP','Zabbix','8.0-2',NULL,'0','1',''),
+('10397',NULL,'TiDB PD by HTTP','3','-1','2','','','TiDB PD by HTTP','0',NULL,'The template to monitor PD server of TiDB cluster by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+Don''t forget to change the macros {$PD.URL}, {$PD.PORT}.
+
+Template `TiDB PD by HTTP` — collects metrics by HTTP agent from PD /metrics endpoint and from monitoring API.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','43596328d4d74a5592906a9e08e3fd96','TIDB PD BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor PD server of TiDB cluster by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+Template `TiDB PD by HTTP` — collects metrics by HTTP agent from PD /metrics endpoint and from monitoring API.
+See https://docs.pingcap.com/tidb/stable/tidb-monitoring-api.
+
+
+## Setup
+
+This template works with PD server of TiDB cluster.
+Internal service metrics are collected from PD /metrics endpoint and from monitoring API.
+See https://docs.pingcap.com/tidb/stable/tidb-monitoring-api.
+Don''t forget to change the host wizard configuration fields `Address`, `Port`.'),
+('10398',NULL,'TiDB by HTTP','3','-1','2','','','TiDB by HTTP','0',NULL,'The template to monitor TiDB server of TiDB cluster by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+Don''t forget to change the macros {$TIDB.URL}, {$TIDB.PORT}.
+
+Template `TiDB by HTTP` — collects metrics by HTTP agent from PD /metrics endpoint and from monitoring API.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','8ec72ebbe3204d7789429640abcac610','TIDB BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor TiDB server of TiDB cluster by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+Template `TiDB by HTTP` — collects metrics by HTTP agent from PD /metrics endpoint and from monitoring API.
+See https://docs.pingcap.com/tidb/stable/tidb-monitoring-api.
+
+
+## Setup
+
+This template works with TiDB server of TiDB cluster.
+Internal service metrics are collected from TiDB /metrics endpoint and from monitoring API.
+See https://docs.pingcap.com/tidb/stable/tidb-monitoring-api.
+Don''t forget to change the host wizard configuration fields `Address`, `Port`.'),
+('10399',NULL,'TiDB TiKV by HTTP','3','-1','2','','','TiDB TiKV by HTTP','0',NULL,'The template to monitor TiKV server of TiDB cluster by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+Don''t forget to change the macros {$TIKV.URL}, {$TIKV.PORT}.
+
+Template `TiDB TiKV by HTTP` — collects metrics by HTTP agent from TiKV /metrics endpoint.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','3a0bbbb2ec0a4c58bba3ba3a3d6ce660','TIDB TIKV BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor TiKV server of TiDB cluster by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+Template `TiDB TiKV by HTTP` — collects metrics by HTTP agent from TiKV /metrics endpoint.
+
+
+## Setup
+
+This template works with TiKV server of TiDB cluster.
+Internal service metrics are collected from TiKV /metrics endpoint.
+Don''t forget to change the host wizard configuration fields `Address`, `Port`.'),
+('10400',NULL,'APC UPS Galaxy 3500 by SNMP','3','-1','2','','','APC UPS Galaxy 3500 by SNMP','0',NULL,'Template Power APC UPS Galaxy 3500
+
+MIBs used:
+HOST-RESOURCES-MIB
+PowerNet-MIB
+SNMPv2-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/420730-discussion-thread-for-official-zabbix-template-apc-ups
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','5d3971cd973b46e7915d7ae0750bac57','APC UPS GALAXY 3500 BY SNMP','Zabbix','8.0-2',NULL,'0','1',E'## Overview
+
+The template to monitor APC UPS Galaxy 3500 by Zabbix SNMP agent.
+Note: please, use the latest version of the firmware for your NMC in order for the template to work correctly.
+
+
+## Setup
+
+1\\. Create a host for APC UPS Galaxy 3500 management IP as SNMPv2 interface.
+
+2\\. Link the template to the host.
+
+3\\. Customize host wizard configuration field values if needed.'),
+('10401',NULL,'APC Smart-UPS 2200 RM by SNMP','3','-1','2','','','APC Smart-UPS 2200 RM by SNMP','0',NULL,'Template Power APC Smart-UPS 2200 RM
+
+MIBs used:
+HOST-RESOURCES-MIB
+PowerNet-MIB
+SNMPv2-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/420730-discussion-thread-for-official-zabbix-template-apc-ups
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e8c0b2c40e884f1598d86f3edf020ea7','APC SMART-UPS 2200 RM BY SNMP','Zabbix','8.0-2',NULL,'0','1',E'## Overview
+
+The template to monitor APC Smart-UPS 2200 RM by Zabbix SNMP agent.
+Note: please, use the latest version of the firmware for your NMC in order for the template to work correctly.
+
+
+## Setup
+
+1\\. Create a host for APC Smart-UPS 2200 RM management IP as SNMPv2 interface.
+
+2\\. Link the template to the host.
+
+3\\. Customize host wizard configuration field values if needed.'),
+('10402',NULL,'APC Smart-UPS 3000 XLM by SNMP','3','-1','2','','','APC Smart-UPS 3000 XLM by SNMP','0',NULL,'Template Power APC Smart-UPS 3000 XLM
+
+MIBs used:
+HOST-RESOURCES-MIB
+PowerNet-MIB
+SNMPv2-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/420730-discussion-thread-for-official-zabbix-template-apc-ups
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','eafd78764fde4110b9e46ae184f327ba','APC SMART-UPS 3000 XLM BY SNMP','Zabbix','8.0-2',NULL,'0','1',E'## Overview
+
+The template to monitor APC Smart-UPS 3000 XLM by Zabbix SNMP agent.
+Note: please, use the latest version of the firmware for your NMC in order for the template to work correctly.
+
+
+## Setup
+
+1\\. Create a host for APC Smart-UPS 3000 XLM management IP as SNMPv2 interface.
+
+2\\. Link the template to the host.
+
+3\\. Customize host wizard configuration field values if needed.'),
+('10403',NULL,'APC Smart-UPS RT 1000 RM XL by SNMP','3','-1','2','','','APC Smart-UPS RT 1000 RM XL by SNMP','0',NULL,'Template Power APC Smart-UPS RT 1000 RM XL
+
+MIBs used:
+HOST-RESOURCES-MIB
+PowerNet-MIB
+SNMPv2-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/420730-discussion-thread-for-official-zabbix-template-apc-ups
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','340ec6917c274ead8fab36925e57f30a','APC SMART-UPS RT 1000 RM XL BY SNMP','Zabbix','8.0-2',NULL,'0','1',E'## Overview
+
+The template to monitor APC Smart-UPS RT 1000 RM XL by Zabbix SNMP agent.
+Note: please, use the latest version of the firmware for your NMC in order for the template to work correctly.
+
+
+## Setup
+
+1\\. Create a host for APC Smart-UPS RT 1000 RM XL management IP as SNMPv2 interface.
+
+2\\. Link the template to the host.
+
+3\\. Customize host wizard configuration field values if needed.'),
+('10404',NULL,'APC Smart-UPS RT 1000 XL by SNMP','3','-1','2','','','APC Smart-UPS RT 1000 XL by SNMP','0',NULL,'Template Power APC Smart-UPS RT 1000 XL
+
+MIBs used:
+HOST-RESOURCES-MIB
+PowerNet-MIB
+SNMPv2-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/420730-discussion-thread-for-official-zabbix-template-apc-ups
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','32d3c78ff44c4c3c9ff5b893ad7f5fc9','APC SMART-UPS RT 1000 XL BY SNMP','Zabbix','8.0-2',NULL,'0','1',E'## Overview
+
+The template to monitor APC Smart-UPS RT 1000 XL by Zabbix SNMP agent.
+Note: please, use the latest version of the firmware for your NMC in order for the template to work correctly.
+
+
+## Setup
+
+1\\. Create a host for APC Smart-UPS RT 1000 XL management IP as SNMPv2 interface.
+
+2\\. Link the template to the host.
+
+3\\. Customize host wizard configuration field values if needed.'),
+('10406',NULL,'APC Smart-UPS SRT 8000 by SNMP','3','-1','2','','','APC Smart-UPS SRT 8000 by SNMP','0',NULL,'Template Power APC Smart-UPS SRT 8000
+
+MIBs used:
+HOST-RESOURCES-MIB
+PowerNet-MIB
+SNMPv2-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/420730-discussion-thread-for-official-zabbix-template-apc-ups
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','b3caafda8c5345cc832ac3be3cefa615','APC SMART-UPS SRT 8000 BY SNMP','Zabbix','8.0-2',NULL,'0','1',E'## Overview
+
+The template to monitor APC Smart-UPS SRT 8000 by Zabbix SNMP agent.
+Note: please, use the latest version of the firmware for your NMC in order for the template to work correctly.
+
+
+## Setup
+
+1\\. Create a host for APC Smart-UPS SRT 8000 management IP as SNMPv2 interface.
+
+2\\. Link the template to the host.
+
+3\\. Customize host wizard configuration field values if needed.'),
+('10407',NULL,'APC UPS Symmetra LX by SNMP','3','-1','2','','','APC UPS Symmetra LX by SNMP','0',NULL,'Template Power APC UPS Symmetra LX
+
+MIBs used:
+HOST-RESOURCES-MIB
+PowerNet-MIB
+SNMPv2-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/420730-discussion-thread-for-official-zabbix-template-apc-ups
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','0b9a899ff8f1467c9fdf999d02b9fd77','APC UPS SYMMETRA LX BY SNMP','Zabbix','8.0-2',NULL,'0','1',E'## Overview
+
+The template to monitor APC UPS Symmetra LX by Zabbix SNMP agent.
+Note: please, use the latest version of the firmware for your NMC in order for the template to work correctly.
+
+
+## Setup
+
+1\\. Create a host for APC UPS Symmetra LX management IP as SNMPv2 interface.
+
+2\\. Link the template to the host.
+
+3\\. Customize host wizard configuration field values if needed.'),
+('10408',NULL,'APC UPS Symmetra RM by SNMP','3','-1','2','','','APC UPS Symmetra RM by SNMP','0',NULL,'Template Power APC UPS Symmetra RM
+
+MIBs used:
+HOST-RESOURCES-MIB
+PowerNet-MIB
+SNMPv2-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/420730-discussion-thread-for-official-zabbix-template-apc-ups
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','1dac0a88c3774315b90622a48031e369','APC UPS SYMMETRA RM BY SNMP','Zabbix','8.0-2',NULL,'0','1',E'## Overview
+
+The template to monitor APC UPS Symmetra RM by Zabbix SNMP agent.
+Note: please, use the latest version of the firmware for your NMC in order for the template to work correctly.
+
+
+## Setup
+
+1\\. Create a host for APC UPS Symmetra RM management IP as SNMPv2 interface.
+
+2\\. Link the template to the host.
+
+3\\. Customize host wizard configuration field values if needed.'),
+('10409',NULL,'APC UPS Symmetra RX by SNMP','3','-1','2','','','APC UPS Symmetra RX by SNMP','0',NULL,'Template Power APC UPS Symmetra RX
+
+MIBs used:
+HOST-RESOURCES-MIB
+PowerNet-MIB
+SNMPv2-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/420730-discussion-thread-for-official-zabbix-template-apc-ups
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','4ffb0f9103084384a98379ed533865e9','APC UPS SYMMETRA RX BY SNMP','Zabbix','8.0-2',NULL,'0','1',E'## Overview
+
+The template to monitor APC UPS Symmetra RX by Zabbix SNMP agent.
+Note: please, use the latest version of the firmware for your NMC in order for the template to work correctly.
+
+
+## Setup
+
+1\\. Create a host for APC UPS Symmetra RX management IP as SNMPv2 interface.
+
+2\\. Link the template to the host.
+
+3\\. Customize host wizard configuration field values if needed.'),
+('10410',NULL,'WildFly Domain by JMX','3','-1','2','','','WildFly Domain by JMX','0',NULL,'Official JMX Template for WildFly.
+The metrics are collected by JMX. This template works with Domain Controller.
+You can set {$WILDFLY.USER} and {$WILDFLY.PASSWORD} macros in the template for using on the host level.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','4b27e636b6ad4ce68511d344d5604999','WILDFLY DOMAIN BY JMX','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+Official JMX Template for WildFly Domain Controller.
+
+
+## Setup
+
+Metrics are collected by JMX.
+This template works with Domain Controller.
+
+1. Enable and configure JMX access to WildFly. See documentation for [instructions](https://docs.wildfly.org/23/Admin_Guide.html#JMX).
+2. Copy jboss-client.jar from `/(wildfly,EAP,Jboss,AS)/bin/client` in to directory `/usr/share/zabbix-java-gateway/lib`
+3. Restart Zabbix Java gateway
+4. Set the user name and password in host wizard configuration fields `Username` and `Password`.
+Depending on your server setup, you may need to specify a custom JMX scheme in host wizard configuration field `Protocol` (default: remote+http)'),
+('10411',NULL,'WildFly Server by JMX','3','-1','2','','','WildFly Server by JMX','0',NULL,'Official JMX Template for WildFly.
+The metrics are collected by JMX. This template works with standalone and domain instances.
+You can set {$WILDFLY.USER} and {$WILDFLY.PASSWORD} macros in the template for using on the host level.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','2bf5827343f0420792ad953f290baa05','WILDFLY SERVER BY JMX','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+Official JMX Template for WildFly server.
+
+
+## Setup
+
+Metrics are collected by JMX.
+This template works with standalone and domain instances.
+
+1. Enable and configure JMX access to WildFly. See documentation for [instructions](https://docs.wildfly.org/23/Admin_Guide.html#JMX).
+2. Copy jboss-client.jar from `/(wildfly,EAP,Jboss,AS)/bin/client` in to directory `/usr/share/zabbix-java-gateway/lib`
+3. Restart Zabbix Java gateway
+4. Set the user name and password in host wizard configuration fields `Username` and `Password`.
+Depending on your server setup, you may need to specify a custom JMX scheme in host wizard configuration field `Protocol` (default: remote+http)'),
+('10412',NULL,'APC Smart-UPS SRT 5000 by SNMP','3','-1','2','','','APC Smart-UPS SRT 5000 by SNMP','0',NULL,'Template Power APC Smart-UPS SRT 5000
+
+MIBs used:
+HOST-RESOURCES-MIB
+PowerNet-MIB
+SNMPv2-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/420730-discussion-thread-for-official-zabbix-template-apc-ups
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','8ec76aeb703747a5affdf435bc12f572','APC SMART-UPS SRT 5000 BY SNMP','Zabbix','8.0-2',NULL,'0','1',E'## Overview
+
+The template to monitor APC Smart-UPS SRT 5000 by Zabbix SNMP agent.
+Note: please, use the latest version of the firmware for your NMC in order for the template to work correctly.
+
+
+## Setup
+
+1\\. Create a host for APC Smart-UPS SRT 5000 management IP as SNMPv2 interface.
+
+2\\. Link the template to the host.
+
+3\\. Customize host wizard configuration field values if needed.'),
+('10413',NULL,'Website certificate by Zabbix agent 2','3','-1','2','','','Website certificate by Zabbix agent 2','0',NULL,'The template to monitor TLS/SSL certificate on the website by Zabbix agent 2 that works without any external scripts.
+
+Zabbix agent 2 with the WebCertificate plugin requests certificate using the web.certificate.get key and returns JSON with certificate attributes.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/428309-discussion-thread-for-official-zabbix-template-tls-ssl-certificates-monitoring
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','5630ec1b1baf449abe1bc5521f85fe6c','WEBSITE CERTIFICATE BY ZABBIX AGENT 2','Zabbix','8.0-1',NULL,'0','1',E'## Overview
+
+This template is for monitoring a TLS/SSL certificate of a website via Zabbix agent 2, and it works without any external scripts.
+Zabbix agent 2 requests the certificate via the `web.certificate.get` key through the WebCertificate plugin and returns a JSON with certificate attributes.
+
+## Setup
+
+1\\. Set up and configure `zabbix-agent2` with the WebCertificate plugin.
+
+2\\. Test availability: `zabbix_get -s -k web.certificate.get[]`
+
+3\\. Create a host with a Zabbix agent interface.
+
+4\\. Link the template to the host.
+
+5\\. Customize the values of the host wizard configuration field `DNS`, `IP`, and `Port`. `DNS` is a required parameter in the Zabbix agent 2 `web.certificate.get` key, so it must have at least one value set. Other host wizard configuration field may be set as needed (details below). Note that multiple values can be specified, separated by commas. The corresponding values in other host wizard configuration field are processed in the order they are listed (see the table below for examples):
+
+| host wizard configuration field | Value |
+|------------------------|--------------------------------|
+|DNS|hostname_01,hostname_02,hostname_03|
+|Port |port_01,,port_03|
+|IP |,ip_02|
+
+As shown in the example above, the following websites will be discovered:
+
+- Website with the host name `hostname_01` - the host name itself will be used for connection (because the address is set to an empty string); the port is `port_01`.
+- Website with the host name `hostname_02` - will also be used for SNI verification; the address `ip_02` will be used for connection, and the port will default to 443 (because it is set to an empty string).
+- Website the with host name `hostname_03` - the host name itself will be used for connection (because the address is not set and treated as an empty string); the port is `port_03`.
+
+For additional details, please refer to official documentation about the Zabbix agent 2 `web.certificate.get` key:
+https://www.zabbix.com/documentation/8.0/manual/config/items/itemtypes/zabbix_agent/zabbix_agent2#web.certificate.get'),
+('10414',NULL,'Cloudflare by HTTP','3','-1','2','','','Cloudflare by HTTP','0',NULL,'The template to monitor Cloudflare to see your web traffic and DNS metrics.
+It works without any external scripts and uses Script item.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','08ef3d687d754b0aba17e1dcbd77d4bd','CLOUDFLARE BY HTTP','Zabbix','8.0-1',NULL,'0','1',E'## Setup
+
+1\\. Create a host, for example mywebsite.com, for a site in your Cloudflare account.
+
+2\\. Link the template to the host.
+
+3\\. Customize the values of `Cloudflare API token`, `Cloudflare zone ID` host wizard configuration field.
+ Cloudflare API Tokens are available in your Cloudflare account under My Profile > API Tokens.
+ Zone ID is available in your Cloudflare account under Account Home > Site.'),
+('10415',NULL,'NGINX Plus by HTTP','3','-1','2','','','NGINX Plus by HTTP','0',NULL,'Get Nginx Plus metrics by HTTP agent.
+Metrics are collected by requests to Nginx Plus API.
+Don''t forget to change macros {$NGINX.API.ENDPOINT}.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','8cad0f2564694416b60bd8a414948641','NGINX PLUS BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed for the effortless deployment of Nginx Plus monitoring by Zabbix via HTTP and doesn''t require any external scripts.
+
+> The monitoring data of the live activity is generated by the [NGINX Plus API](http://nginx.org/en/docs/http/ngx_http_api_module.html).
+
+## Setup
+
+1. Enable the NGINX Plus API.
+> Refer to the [vendor documentation](https://www.nginx.com/products/nginx/live-activity-monitoring/).
+2. Set the {$NGINX.API.ENDPOINT} such as `://://`.
+
+**Note** that depending on the number of zones and upstreams discovery operation may be expensive.
+Therefore, use the following filters with these host wizard configuration fields:
+
+- `HTTP server zones filter (include)`
+- `HTTP server zones filter (exclude)`
+- `HTTP location zones filter (include)`
+- `HTTP location zones filter (exclude)`
+- `HTTP upstreams filter (include)`
+- `HTTP upstreams filter (exclude)`
+- `Stream server zones filter (include)`
+- `Stream server zones filter (exclude)`
+- `Stream upstreams filter (include)`
+- `Stream upstreams filter (exclude)`
+- `Resolvers filter (include)`
+- `Resolvers filter (exclude)`'),
+('10416',NULL,'Systemd by Zabbix agent 2','3','-1','2','','','Systemd by Zabbix agent 2','0',NULL,'Get systemd units metrics from plugin for the zabbix-agent2.
+ 1. Setup and configure zabbix-agent2 compiled with the Systemd monitoring plugin.
+ 2. Set filters with macros if you want to override default filter parameters.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','90ac276995294a6aa88462c032d2ddaf','SYSTEMD BY ZABBIX AGENT 2','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+1. Setup and configure zabbix-agent2 compiled with the Systemd monitoring plugin.
+2. Set filters with host wizard configuration fields if you want to override default filter parameters.'),
+('10417',NULL,'GridGain by JMX','3','-1','2','','','GridGain by JMX','0',NULL,'The template to monitor GridGain In-Memory Computing Platform by Zabbix that work without any external scripts.
+ It works with both standalone and cluster instances.
+ The metrics are discoverable and collected by JMX.
+ Current JMX tree hierarchy contains classloader by default. Add the following jvm option `-DIGNITE_MBEAN_APPEND_CLASS_LOADER_ID=false`to will exclude one level with Classloader name.
+ You can set {$GRIDGAIN.USER} and {$GRIDGAIN.PASSWORD} macros in the template for using on the host level.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','47d87c39c121429b98a18f641aa443ea','GRIDGAIN BY JMX','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+Official JMX Template for GridGain In-Memory Computing Platform.
+This template is based on the original template developed by Igor Akkuratov, Senior Engineer at GridGain Systems and GridGain In-Memory Computing Platform Contributor.
+
+## Setup
+
+This template works with standalone and cluster instances. Metrics are collected by JMX. All metrics are discoverable.
+
+1. Enable and configure JMX access to GridGain In-Memory Computing Platform. See documentation for [instructions](https://docs.oracle.com/javase/8/docs/technotes/guides/management/agent.html). Current JMX tree hierarchy contains classloader by default. Add the following jvm option `-DIGNITE_MBEAN_APPEND_CLASS_LOADER_ID=false`to will exclude one level with Classloader name. You can configure Cache and Data Region metrics which you want using [official guide](https://www.gridgain.com/docs/latest/administrators-guide/monitoring-metrics/configuring-metrics).
+2. Set the user name and password in host wizard configuration fields `Username` and `Password`.'),
+('10418',NULL,'Cisco ASAv by SNMP','3','-1','2','','','Cisco ASAv by SNMP','0',NULL,'Template Net Cisco ASAv
+
+MIBs used:
+CISCO-PORT-MIB
+CISCO-MEMORY-POOL-MIB
+CISCO-REMOTE-ACCESS-MONITOR-MIB
+IF-MIB
+RFC1213-MIB
+CISCO-PROCESS-MIB
+ENTITY-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/418396-discussion-thread-for-official-zabbix-templates-for-cisco
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','75d009cd4dc84ee7a8fc479fa2fbaeee','CISCO ASAV BY SNMP','Zabbix','8.0-3',NULL,'0','1','## Overview
+
+Secure Firewall ASA Virtual is the virtualized option of popular Secure Firewall ASA solution and offers security in traditional physical data centers and private and public clouds.
+Learn more about Cisco ASAv: https://www.cisco.com/c/en/us/products/collateral/security/adaptive-security-virtual-appliance-asav/adapt-security-virtual-appliance-ds.html'),
+('10419',NULL,'F5 Big-IP by SNMP','3','-1','2','','','F5 Big-IP by SNMP','0',NULL,'MIBs used:
+RFC1213-MIB
+F5-BIGIP-LOCAL-MIB
+F5-BIGIP-SYSTEM-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','44c2c2d94a4447c6a924386640e4854a','F5 BIG-IP BY SNMP','Zabbix','8.0-5',NULL,'0','1',''),
+('10420',NULL,'ZYXEL AAM1212-51 IES-612 by SNMP','3','-1','2','','','ZYXEL AAM1212-51 IES-612 by SNMP','0',NULL,'ZYXEL AAM1212-51 / IES-612
+
+MIBs used:
+RFC1213-MIB
+HOST-RESOURCES-MIB
+ADSL-LINE-MIB
+ZYXEL-IESCOMMON-MIB
+IF-MIB
+
+Known Issues:
+
+ Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+ Version: all versions firmware
+ Device: ZYXEL AAM1212-51 / IES-612
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/422668-discussion-thread-for-official-zabbix-templates-for-zyxel
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','3a71dcdcfe0b4a0e8284d8939d335cce','ZYXEL AAM1212-51 IES-612 BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+http://origin-eu.zyxel.com/products_services/ies_1248_51v.shtml?t=p
+
+### Known Issues
+
+Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+Version: all versions firmware
+Device: ZYXEL AAM1212-51 / IES-612'),
+('10421',NULL,'ZYXEL ES3500-8PD by SNMP','3','-1','2','','','ZYXEL ES3500-8PD by SNMP','0',NULL,'ZYXEL ES3500-8PD
+
+MIBs used:
+RFC1213-MIB
+HOST-RESOURCES-MIB
+ZYXEL-ES3500-8PD-MIB
+IF-MIB
+
+Known Issues:
+
+ Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+ Version: all versions firmware
+ Device: ZYXEL ES3500-8PD
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/422668-discussion-thread-for-official-zabbix-templates-for-zyxel
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','b8a6f34fd5c447b1b9310746a96f4e80','ZYXEL ES3500-8PD BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+https://service-provider.zyxel.com/emea/en/products/carrier-and-access-switches/access-switches/mes3500-series
+
+### Known Issues
+
+Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+Version: all versions firmware
+Device: ZYXEL ES3500-8PD'),
+('10422',NULL,'ZYXEL GS-4012F by SNMP','3','-1','2','','','ZYXEL GS-4012F by SNMP','0',NULL,'ZYXEL GS-4012F
+
+MIBs used:
+ZYXEL-GS4012F-MIB
+RFC1213-MIB
+HOST-RESOURCES-MIB
+IF-MIB
+
+Known Issues:
+
+ Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+ Version: all versions firmware
+ Device: ZYXEL GS-4012F
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/422668-discussion-thread-for-official-zabbix-templates-for-zyxel
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','73f123bb9ffe4587a0269c7e8752b2ed','ZYXEL GS-4012F BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+https://service-provider.zyxel.com/global/en/products/carrier-and-access-switches/access-switches/mgs-3712f
+
+### Known Issues
+
+Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+Version: all versions firmware
+Device: ZYXEL GS-4012F'),
+('10423',NULL,'ZYXEL IES-500x by SNMP','3','-1','2','','','ZYXEL IES-500x by SNMP','0',NULL,'ZYXEL IES-500x
+
+MIBs used:
+RFC1213-MIB
+HOST-RESOURCES-MIB
+ADSL-LINE-MIB
+ZYXEL-IES5000-MIB
+IF-MIB
+
+Known Issues:
+
+ Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+ Version: all versions firmware
+ Device: ZYXEL IES-500x
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/422668-discussion-thread-for-official-zabbix-templates-for-zyxel
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','3db86b0d235e4c7b80f7d6144ca08925','ZYXEL IES-500X BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+https://service-provider.zyxel.com/global/en/products/msansdslams/central-msans/chassis-msans/ies-5000-series
+
+### Known Issues
+
+Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+Version: all versions firmware
+Device: ZYXEL IES-500x'),
+('10424',NULL,'ZYXEL IES-6000 by SNMP','3','-1','2','','','ZYXEL IES-6000 by SNMP','0',NULL,'ZYXEL IES-6000
+
+MIBs used:
+RFC1213-MIB
+HOST-RESOURCES-MIB
+ADSL-LINE-MIB
+ZYXEL-IES5000-MIB
+IF-MIB
+
+Known Issues:
+
+ Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+ Version: all versions firmware
+ Device: ZYXEL IES-6000
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/422668-discussion-thread-for-official-zabbix-templates-for-zyxel
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','3645654baaf04f11927b171bcb048349','ZYXEL IES-6000 BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+https://service-provider.zyxel.com/global/en/products/msansdslams/central-msans/chassis-msans/ies-6000-series
+
+### Known Issues
+
+Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+Version: all versions firmware
+Device: ZYXEL IES-6000'),
+('10425',NULL,'ZYXEL IES1248-51 by SNMP','3','-1','2','','','ZYXEL IES1248-51 by SNMP','0',NULL,'ZYXEL IES1248-51
+
+MIBs used:
+RFC1213-MIB
+HOST-RESOURCES-MIB
+ADSL-LINE-MIB
+ZYXEL-IESCOMMON-MIB
+IF-MIB
+
+Known Issues:
+
+ Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+ Version: all versions firmware
+ Device: ZYXEL IES1248-51
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/422668-discussion-thread-for-official-zabbix-templates-for-zyxel
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','8e6d7067cd094e56a52db999b3199edc','ZYXEL IES1248-51 BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+http://origin-eu.zyxel.com/products_services/ies_1248_51v.shtml?t=p
+
+### Known Issues
+
+Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+Version: all versions firmware
+Device: ZYXEL IES1248-51'),
+('10426',NULL,'ZYXEL MES-3528 by SNMP','3','-1','2','','','ZYXEL MES-3528 by SNMP','0',NULL,'ZYXEL MES-3528
+
+MIBs used:
+RFC1213-MIB
+HOST-RESOURCES-MIB
+ZYXEL-MES3528-MIB
+IF-MIB
+
+Known Issues:
+
+ Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+ Version: all versions firmware
+ Device: ZYXEL MES-3528
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/422668-discussion-thread-for-official-zabbix-templates-for-zyxel
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','249de8d8d21e4dda9c3f766ab6201378','ZYXEL MES-3528 BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+https://service-provider.zyxel.com/emea/en/products/carrier-and-access-switches/access-switches/mes3500-series
+
+### Known Issues
+
+Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+Version: all versions firmware
+Device: ZYXEL MES-3528'),
+('10427',NULL,'ZYXEL MES3500-10 by SNMP','3','-1','2','','','ZYXEL MES3500-10 by SNMP','0',NULL,'ZYXEL MES3500-10
+
+MIBs used:
+RFC1213-MIB
+HOST-RESOURCES-MIB
+ZYXEL-MES3500-10-MIB
+IF-MIB
+
+Known Issues:
+
+ Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+ Version: all versions firmware
+ Device: ZYXEL MES3500-10
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/422668-discussion-thread-for-official-zabbix-templates-for-zyxel
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','21a95afef0e74fb19691693090403d1d','ZYXEL MES3500-10 BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+https://service-provider.zyxel.com/emea/en/products/carrier-and-access-switches/access-switches/mes3500-series
+
+### Known Issues
+
+Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+Version: all versions firmware
+Device: ZYXEL MES3500-10'),
+('10428',NULL,'ZYXEL MES3500-24 by SNMP','3','-1','2','','','ZYXEL MES3500-24 by SNMP','0',NULL,'ZYXEL MES3500-24
+
+MIBs used:
+RFC1213-MIB
+HOST-RESOURCES-MIB
+ZYXEL-MES3500-24-MIB
+IF-MIB
+
+Known Issues:
+
+ Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+ Version: all versions firmware
+ Device: ZYXEL MES3500-24
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/422668-discussion-thread-for-official-zabbix-templates-for-zyxel
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','292970ad91204722b5e5cb3233fc0026','ZYXEL MES3500-24 BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+https://service-provider.zyxel.com/emea/en/products/carrier-and-access-switches/access-switches/mes3500-series
+
+### Known Issues
+
+Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+Version: all versions firmware
+Device: ZYXEL MES3500-24'),
+('10429',NULL,'ZYXEL MGS-3712 by SNMP','3','-1','2','','','ZYXEL MGS-3712 by SNMP','0',NULL,'ZYXEL MGS-3712
+
+MIBs used:
+RFC1213-MIB
+HOST-RESOURCES-MIB
+ZYXEL-MGS3712F-MIB
+IF-MIB
+
+Known Issues:
+
+ Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+ Version: all versions firmware
+ Device: ZYXEL MGS-3712
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/422668-discussion-thread-for-official-zabbix-templates-for-zyxel
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','8ea7299983f24d0a913606e334f0e526','ZYXEL MGS-3712 BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+https://service-provider.zyxel.com/global/en/products/carrier-and-access-switches/access-switches/MGS-3712f
+
+### Known Issues
+
+Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+Version: all versions firmware
+Device: ZYXEL MGS-3712'),
+('10430',NULL,'ZYXEL MGS-3712F by SNMP','3','-1','2','','','ZYXEL MGS-3712F by SNMP','0',NULL,'ZYXEL MGS-3712F
+
+MIBs used:
+RFC1213-MIB
+HOST-RESOURCES-MIB
+ZYXEL-MGS3712F-MIB
+IF-MIB
+
+Known Issues:
+
+ Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+ Version: all versions firmware
+ Device: ZYXEL MGS-3712F
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/422668-discussion-thread-for-official-zabbix-templates-for-zyxel
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','01deb47efa1f4a9092de67fd61820a7d','ZYXEL MGS-3712F BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+https://service-provider.zyxel.com/global/en/products/carrier-and-access-switches/access-switches/mgs-3712f
+
+### Known Issues
+
+Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+Version: all versions firmware
+Device: ZYXEL MGS-3712F'),
+('10431',NULL,'ZYXEL MES3500-24S by SNMP','3','-1','2','','','ZYXEL MES3500-24S by SNMP','0',NULL,'ZYXEL MES3500-24S
+
+MIBs used:
+ZYXEL-TRANSCEIVER-MIB
+IF-MIB
+RFC1213-MIB
+HOST-RESOURCES-MIB
+ZYXEL-HW-MONITOR-MIB
+ZYXEL-PORT-MIB
+ZYXEL-ES-COMMON
+
+Known Issues:
+
+ Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+ Version: all versions firmware
+ Device: ZYXEL MGS3520-28
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/422668-discussion-thread-for-official-zabbix-templates-for-zyxel
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','89eef2fe23964f44bf9aec6d00e39efd','ZYXEL MES3500-24S BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+https://service-provider.zyxel.com/emea/en/products/carrier-and-access-switches/access-switches/mes3500-series
+
+### Known Issues
+
+Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+Version: all versions firmware
+Device: ZYXEL MGS3520-28'),
+('10432',NULL,'ZYXEL MGS3520-28x by SNMP','3','-1','2','','','ZYXEL MGS3520-28x by SNMP','0',NULL,'ZYXEL MGS3520-28x
+
+MIBs used:
+ZYXEL-TRANSCEIVER-MIB
+IF-MIB
+RFC1213-MIB
+HOST-RESOURCES-MIB
+ZYXEL-HW-MONITOR-MIB
+ZYXEL-PORT-MIB
+ZYXEL-ES-COMMON
+
+Known Issues:
+
+ Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+ Version: all versions firmware
+ Device: ZYXEL MGS3520-28
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/422668-discussion-thread-for-official-zabbix-templates-for-zyxel
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','9cc843a085bb4ee5af0dc4d764a7eee9','ZYXEL MGS3520-28X BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+https://service-provider.zyxel.com/emea/en/products/carrier-and-access-switches/access-switches/mgs3520-series
+
+### Known Issues
+
+Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+Version: all versions firmware
+Device: ZYXEL MGS3520-28'),
+('10433',NULL,'ZYXEL XGS-4728F by SNMP','3','-1','2','','','ZYXEL XGS-4728F by SNMP','0',NULL,'ZYXEL XGS-4728F
+
+MIBs used:
+RFC1213-MIB
+HOST-RESOURCES-MIB
+ZYXEL-XGS4728F-MIB
+IF-MIB
+
+Known Issues:
+
+ Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+ Version: all versions firmware
+ Device: ZYXEL XGS-4728F
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/422668-discussion-thread-for-official-zabbix-templates-for-zyxel
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','ab18a5665b7d4bed876881b5c4e8ce51','ZYXEL XGS-4728F BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+https://www.zyxel.com/products_services/xgs_4728f.shtml
+
+### Known Issues
+
+Description: Incorrect handling of SNMP bulk requests. Disable the use of bulk requests in the SNMP interface settings.
+Version: all versions firmware
+Device: ZYXEL XGS-4728F'),
+('10434',NULL,'Cisco UCS Manager by SNMP','3','-1','2','','','Cisco UCS Manager by SNMP','0',NULL,'This is a template for Cisco UCS Manager monitoring via Zabbix SNMP Agent that works without any external scripts.
+
+
+MIBs used:
+CISCO-UNIFIED-COMPUTING-COMPUTE-MIB
+CISCO-UNIFIED-COMPUTING-EQUIPMENT-MIB
+IF-MIB
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+CISCO-UNIFIED-COMPUTING-PROCESSOR-MIB
+CISCO-UNIFIED-COMPUTING-STORAGE-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/418396-discussion-thread-for-official-zabbix-templates-for-cisco
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','d5eb4ce08a334098a85e6e02c534be90','CISCO UCS MANAGER BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+Cisco UCS® Manager provides unified, embedded management of all software and hardware components of the Cisco Unified Computing System™ (Cisco UCS) across multiple chassis and rack servers. It enables server, fabric, and storage provisioning as well as,
+device discovery, inventory, configuration, diagnostics, monitoring, fault detection, auditing, and statistics collection.
+This is a template for Cisco UCS Manager monitoring via Zabbix SNMP Agent that works without any external scripts.
+You can download UCS MIB files there ftp://ftp.cisco.com/pub/mibs/ucs-mibs/.'),
+('10435',NULL,'DELL PowerEdge R720 by HTTP','3','-1','2','','','DELL PowerEdge R720 by HTTP','0',NULL,'Template for DELL PowerEdge R720 servers with iDRAC 8/9 firmware 4.32 and later and Redfish API enabled.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/426752-discussion-thread-for-official-zabbix-dell-templates
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','9643f22821104f809e2486be83e1816e','DELL POWEREDGE R720 BY HTTP','Zabbix','8.0-2',NULL,'0','1',E'## Overview
+
+This is a template for monitoring DELL PowerEdge R720 servers with iDRAC 8/9 firmware 4.32 (and later) with Redfish API enabled via Zabbix script items. This template works without any external scripts.
+
+## Setup
+
+1\\. Enable Redfish API in the Dell iDRAC interface of your server.
+
+2\\. Create a user for monitoring with read-only permissions in the Dell iDRAC interface.
+
+3\\. Create a host for Dell server with iDRAC IP as the Zabbix agent interface.
+
+4\\. Link the template to the host.
+
+5\\. Customize the values of the `{$DELL.HTTP.API.URL}`, `{$DELL.HTTP.API.USER}`, and `{$DELL.HTTP.API.PASSWORD}` macros.
+
+> NOTE! If you are experiencing timeouts on some of the items that are executing requests, adjust the `{$DELL.HTTP.REQUEST.TIMEOUT}` macro accordingly.'),
+('10436',NULL,'DELL PowerEdge R720 by SNMP','3','-1','2','','','DELL PowerEdge R720 by SNMP','0',NULL,'Template for DELL PowerEdge R720 servers with iDRAC version 7 and later.
+
+MIBs used:
+HOST-RESOURCES-MIB
+IDRAC-MIB-SMIv2
+SNMPv2-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/426752-discussion-thread-for-official-zabbix-dell-templates
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','fe5b8448661f41b9a6d948fccd7f9045','DELL POWEREDGE R720 BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This is a template for monitoring DELL PowerEdge R720 servers with iDRAC version 7 (and later) via Zabbix SNMP agent that works without any external scripts.'),
+('10437',NULL,'DELL PowerEdge R740 by HTTP','3','-1','2','','','DELL PowerEdge R740 by HTTP','0',NULL,'Template for DELL PowerEdge R740 servers with iDRAC 8/9 firmware 4.32 and later and Redfish API enabled.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/426752-discussion-thread-for-official-zabbix-dell-templates
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','3f707f39c32a4b6e8b214c38a260f6f9','DELL POWEREDGE R740 BY HTTP','Zabbix','8.0-2',NULL,'0','1',E'## Overview
+
+This is a template for monitoring DELL PowerEdge R740 servers with iDRAC 8/9 firmware 4.32 (and later) with Redfish API enabled via Zabbix script items. This template works without any external scripts.
+
+## Setup
+
+1\\. Enable Redfish API in the Dell iDRAC interface of your server.
+
+2\\. Create a user for monitoring with read-only permissions in the Dell iDRAC interface.
+
+3\\. Create a host for Dell server with iDRAC IP as the Zabbix agent interface.
+
+4\\. Link the template to the host.
+
+5\\. Customize the values of the `{$DELL.HTTP.API.URL}`, `{$DELL.HTTP.API.USER}`, and `{$DELL.HTTP.API.PASSWORD}` macros.
+
+> NOTE! If you are experiencing timeouts on some of the items that are executing requests, adjust the `{$DELL.HTTP.REQUEST.TIMEOUT}` macro accordingly.'),
+('10438',NULL,'DELL PowerEdge R740 by SNMP','3','-1','2','','','DELL PowerEdge R740 by SNMP','0',NULL,'Template for DELL PowerEdge R740 servers with iDRAC version 7 and later.
+
+MIBs used:
+HOST-RESOURCES-MIB
+IDRAC-MIB-SMIv2
+SNMPv2-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/426752-discussion-thread-for-official-zabbix-dell-templates
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','9fde0e1c36f8453da72f97535d4e74ca','DELL POWEREDGE R740 BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This is a template for monitoring DELL PowerEdge R740 servers with iDRAC version 7 (and later) via Zabbix SNMP agent that works without any external scripts.'),
+('10439',NULL,'DELL PowerEdge R820 by HTTP','3','-1','2','','','DELL PowerEdge R820 by HTTP','0',NULL,'Template for DELL PowerEdge R820 servers with iDRAC 8/9 firmware 4.32 and later and Redfish API enabled.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/426752-discussion-thread-for-official-zabbix-dell-templates
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','1e9fe6b88c7542638c0f5d94484858b2','DELL POWEREDGE R820 BY HTTP','Zabbix','8.0-2',NULL,'0','1',E'## Overview
+
+This is a template for monitoring DELL PowerEdge R820 servers with iDRAC 8/9 firmware 4.32 (and later) with Redfish API enabled via Zabbix script items. This template works without any external scripts.
+
+## Setup
+
+1\\. Enable Redfish API in the Dell iDRAC interface of your server.
+
+2\\. Create a user for monitoring with read-only permissions in the Dell iDRAC interface.
+
+3\\. Create a host for Dell server with iDRAC IP as the Zabbix agent interface.
+
+4\\. Link the template to the host.
+
+5\\. Customize the values of the `{$DELL.HTTP.API.URL}`, `{$DELL.HTTP.API.USER}`, and `{$DELL.HTTP.API.PASSWORD}` macros.
+
+> NOTE! If you are experiencing timeouts on some of the items that are executing requests, adjust the `{$DELL.HTTP.REQUEST.TIMEOUT}` macro accordingly.'),
+('10440',NULL,'DELL PowerEdge R820 by SNMP','3','-1','2','','','DELL PowerEdge R820 by SNMP','0',NULL,'Template for DELL PowerEdge R820 servers with iDRAC version 7 and later.
+
+MIBs used:
+HOST-RESOURCES-MIB
+IDRAC-MIB-SMIv2
+SNMPv2-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/426752-discussion-thread-for-official-zabbix-dell-templates
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','d41c5d0fa91545d68cced1b5dabe4bf1','DELL POWEREDGE R820 BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This is a template for monitoring DELL PowerEdge R820 servers with iDRAC version 7 (and later) via Zabbix SNMP agent that works without any external scripts.'),
+('10441',NULL,'DELL PowerEdge R840 by HTTP','3','-1','2','','','DELL PowerEdge R840 by HTTP','0',NULL,'Template for DELL PowerEdge R840 servers with iDRAC 8/9 firmware 4.32 and later and Redfish API enabled.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/426752-discussion-thread-for-official-zabbix-dell-templates
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','20147f00f92d4240aab0b70cf578c022','DELL POWEREDGE R840 BY HTTP','Zabbix','8.0-2',NULL,'0','1',E'## Overview
+
+This is a template for monitoring DELL PowerEdge R840 servers with iDRAC 8/9 firmware 4.32 (and later) with Redfish API enabled via Zabbix script items. This template works without any external scripts.
+
+## Setup
+
+1\\. Enable Redfish API in the Dell iDRAC interface of your server.
+
+2\\. Create a user for monitoring with read-only permissions in the Dell iDRAC interface.
+
+3\\. Create a host for Dell server with iDRAC IP as the Zabbix agent interface.
+
+4\\. Link the template to the host.
+
+5\\. Customize the values of the `{$DELL.HTTP.API.URL}`, `{$DELL.HTTP.API.USER}`, and `{$DELL.HTTP.API.PASSWORD}` macros.
+
+> NOTE! If you are experiencing timeouts on some of the items that are executing requests, adjust the `{$DELL.HTTP.REQUEST.TIMEOUT}` macro accordingly.'),
+('10442',NULL,'DELL PowerEdge R840 by SNMP','3','-1','2','','','DELL PowerEdge R840 by SNMP','0',NULL,'Template for DELL PowerEdge R840 servers with iDRAC version 7 and later.
+
+MIBs used:
+HOST-RESOURCES-MIB
+IDRAC-MIB-SMIv2
+SNMPv2-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/426752-discussion-thread-for-official-zabbix-dell-templates
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','fc834b8da8864678b55557e9a237eac9','DELL POWEREDGE R840 BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This is a template for monitoring DELL PowerEdge R840 servers with iDRAC version 7 (and later) via Zabbix SNMP agent that works without any external scripts.'),
+('10443',NULL,'HPE ProLiant BL460 by SNMP','3','-1','2','','','HPE ProLiant BL460 by SNMP','0',NULL,'Template for HPE ProLiant BL460 servers with HP iLO version 4 and later.
+
+MIBs used:
+HOST-RESOURCES-MIB
+CPQHLTH-MIB
+SNMPv2-MIB
+CPQNIC-MIB
+CPQSINFO-MIB
+CPQIDA-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','172ec7e51f1c4a6ba49baffbab3dda97','HPE PROLIANT BL460 BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This is a template for monitoring HPE ProLiant BL460 servers with HP iLO version 4 and later via Zabbix SNMP agent that works without any external scripts.'),
+('10444',NULL,'HPE ProLiant BL920 by SNMP','3','-1','2','','','HPE ProLiant BL920 by SNMP','0',NULL,'Template for HPE ProLiant BL920 servers with HP iLO version 4 and later.
+
+MIBs used:
+HOST-RESOURCES-MIB
+CPQHLTH-MIB
+SNMPv2-MIB
+CPQNIC-MIB
+CPQSINFO-MIB
+CPQIDA-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','586119e5e27e4062a3cce8601ecb8d71','HPE PROLIANT BL920 BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This is a template for monitoring HPE ProLiant BL920 servers with HP iLO version 4 and later via Zabbix SNMP agent that works without any external scripts.'),
+('10445',NULL,'HPE ProLiant DL360 by SNMP','3','-1','2','','','HPE ProLiant DL360 by SNMP','0',NULL,'Template for HPE ProLiant DL360 servers with HP iLO version 4 and later.
+
+MIBs used:
+HOST-RESOURCES-MIB
+CPQHLTH-MIB
+SNMPv2-MIB
+CPQNIC-MIB
+CPQSINFO-MIB
+CPQIDA-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','60cb9ccb922e4fd194a1d9573db10237','HPE PROLIANT DL360 BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This is a template for monitoring HPE ProLiant DL360 servers with HP iLO version 4 and later via Zabbix SNMP agent that works without any external scripts.'),
+('10446',NULL,'HPE ProLiant DL380 by SNMP','3','-1','2','','','HPE ProLiant DL380 by SNMP','0',NULL,'Template for HPE ProLiant DL380 servers with HP iLO version 4 and later.
+
+MIBs used:
+HOST-RESOURCES-MIB
+CPQHLTH-MIB
+SNMPv2-MIB
+CPQNIC-MIB
+CPQSINFO-MIB
+CPQIDA-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','379aaf7e87574debb4f5c3947a22ec68','HPE PROLIANT DL380 BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This is a template for monitoring HPE ProLiant DL380 servers with HP iLO version 4 and later via Zabbix SNMP agent that works without any external scripts.'),
+('10447',NULL,'Travis CI by HTTP','3','-1','2','','','Travis CI by HTTP','0',NULL,'Template for monitoring Travis CI https://travis-ci.com
+You must set {$TRAVIS.API.TOKEN} and {$TRAVIS.API.URL} macros.
+ {$TRAVIS.API.TOKEN} is a Travis API authentication token located in User -> Settings -> API authentication.
+ {$TRAVIS.API.URL} could be in 2 different variations:
+ - for a private project : api.travis-ci.com
+ - for an enterprise projects: api.example.com (where you replace example.com with the domain Travis CI is running on)
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','8cdbe00a2a3046ee962d28d32567968a','TRAVIS CI BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor Travis CI by Zabbix that work without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+
+## Setup
+
+You must set `Token` and `Address` host wizard configuration fields.
+`Token` is a Travis API authentication token located in User -> Settings -> API authentication.
+`Address` could be in 2 different variations:
+ - for a private project : api.travis-ci.com
+ - for an enterprise projects: api.example.com (where you replace example.com with the domain Travis CI is running on)'),
+('10448',NULL,'InfluxDB by HTTP','3','-1','2','','','InfluxDB by HTTP','0',NULL,'Get InfluxDB metrics by HTTP agent from Prometheus metrics endpoint.
+For organization discovery template need to use Authorization via API token. See docs: https://docs.influxdata.com/influxdb/v2.0/security/tokens/
+
+Don''t forget change macros {$INFLUXDB.URL}, {$INFLUXDB.API.TOKEN}.
+Some metrics may not be collected depending on your InfluxDB instance version and configuration.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','a6fe3640b23544e7ae15d438b38ce1cd','INFLUXDB BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+This template works with self-hosted InfluxDB instances. Internal service metrics are collected from InfluxDB /metrics endpoint.
+For organization discovery template need to use Authorization via API token. See docs: https://docs.influxdata.com/influxdb/v2.0/security/tokens/
+
+Don''t forget to change the host wizard configuration fields `InfluxDB instance URL`, `InfluxDB API token`.
+*NOTE.* Some metrics may not be collected depending on your InfluxDB instance version and configuration.'),
+('10449',NULL,'MikroTik CCR1009-7G-1C-1SPC by SNMP','3','-1','2','','','MikroTik CCR1009-7G-1C-1S+PC by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik CCR1009-7G-1C-1S+PC.
+
+7x Gigabit Ethernet, 1x Combo port (SFP or Gigabit Ethernet), 1xSFP+ cage, 9
+cores x 1GHz CPU, 2GB RAM, LCD panel, passive cooling desktop enclosure, SmartCard
+slot, RouterOS L6, PSU
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','d596d6d231bf49c08890aa3ff135ecc6','MIKROTIK CCR1009-7G-1C-1S+PC BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik CCR1009-7G-1C-1S+PC.
+
+7x Gigabit Ethernet, 1x Combo port (SFP or Gigabit Ethernet), 1xSFP+ cage, 9 cores x 1GHz CPU, 2GB RAM, LCD panel, passive cooling desktop enclosure, SmartCard slot, RouterOS L6, PSU'),
+('10450',NULL,'MikroTik CCR1009-7G-1C-1S by SNMP','3','-1','2','','','MikroTik CCR1009-7G-1C-1S+ by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik CCR1009-7G-1C-1S+.
+
+1U rackmount, 7x Gigabit Ethernet, 1x Combo port (SFP or Gigabit Ethernet),
+1xSFP+ cage, 9 cores x 1.2GHz CPU, 2GB RAM, LCD panel, Dual Power supplies,
+SmartCard slot, RouterOS L6
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','a809695fbc784b75adcd4833c86bca8d','MIKROTIK CCR1009-7G-1C-1S+ BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik CCR1009-7G-1C-1S+.
+
+1U rackmount, 7x Gigabit Ethernet, 1x Combo port (SFP or Gigabit Ethernet), 1xSFP+ cage, 9 cores x 1.2GHz CPU, 2GB RAM, LCD panel, Dual Power supplies, SmartCard slot, RouterOS L6'),
+('10451',NULL,'MikroTik CCR1009-7G-1C-PC by SNMP','3','-1','2','','','MikroTik CCR1009-7G-1C-PC by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik CCR1009-7G-1C-PC.
+
+7x Gigabit Ethernet, 1x Combo port (SFP or Gigabit Ethernet), 9 cores x 1GHz
+CPU, 1GB RAM, passive cooling case, RouterOS L6
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','012e7043ff9849e197c42bf41cdf4d9a','MIKROTIK CCR1009-7G-1C-PC BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik CCR1009-7G-1C-PC.
+
+7x Gigabit Ethernet, 1x Combo port (SFP or Gigabit Ethernet), 9 cores x 1GHz CPU, 1GB RAM, passive cooling case, RouterOS L6'),
+('10452',NULL,'MikroTik CCR1016-12G by SNMP','3','-1','2','','','MikroTik CCR1016-12G by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik CCR1016-12G.
+
+1U rackmount, 12x Gigabit Ethernet, LCD, 16 cores x 1.2GHz CPU, 2GB RAM, 17.8mpps
+fastpath, Up to 12Gbit/s throughput, RouterOS L6, Dual PSU
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','5ed19d1f74224588bf5f53ac47003acc','MIKROTIK CCR1016-12G BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik CCR1016-12G.
+
+1U rackmount, 12x Gigabit Ethernet, LCD, 16 cores x 1.2GHz CPU, 2GB RAM, 17.8mpps fastpath, Up to 12Gbit/s throughput, RouterOS L6, Dual PSU'),
+('10453',NULL,'MikroTik CCR1016-12S-1S by SNMP','3','-1','2','','','MikroTik CCR1016-12S-1S+ by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik CCR1016-12S-1S+.
+
+1U rackmount, 12xSFP cage, 1xSFP+ cage, 16 cores x 1.2GHz CPU, 2GB RAM, LCD
+panel, Dual Power supplies, RouterOS L6
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','654910b270d9464f863ed085ba7302ce','MIKROTIK CCR1016-12S-1S+ BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik CCR1016-12S-1S+.
+
+1U rackmount, 12xSFP cage, 1xSFP+ cage, 16 cores x 1.2GHz CPU, 2GB RAM, LCD panel, Dual Power supplies, RouterOS L6'),
+('10454',NULL,'MikroTik CCR1036-12G-4S-EM by SNMP','3','-1','2','','','MikroTik CCR1036-12G-4S-EM by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik CCR1036-12G-4S-EM.
+
+1U rackmount, 12x Gigabit Ethernet, 4xSFP cages, LCD, 36 cores x 1.2GHz CPU,
+8GB RAM, 24 mpps fastpath, Up to 16Gbit/s throughput, RouterOS L6, Dual PSU
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','930c0e0534a9424fb01f2b6218d8ce59','MIKROTIK CCR1036-12G-4S-EM BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik CCR1036-12G-4S-EM.
+
+1U rackmount, 12x Gigabit Ethernet, 4xSFP cages, LCD, 36 cores x 1.2GHz CPU, 8GB RAM, 24 mpps fastpath, Up to 16Gbit/s throughput, RouterOS L6, Dual PSU'),
+('10455',NULL,'MikroTik CCR1036-12G-4S by SNMP','3','-1','2','','','MikroTik CCR1036-12G-4S by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik CCR1036-12G-4S.
+
+1U rackmount, 12x Gigabit Ethernet, 4xSFP cages, LCD, 36 cores x 1.2GHz CPU,
+4GB RAM, 24 mpps fastpath, Up to 16Gbit/s throughput, RouterOS L6, Dual PSU
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','82b428ad78d34988b93f3d577f2b6adc','MIKROTIK CCR1036-12G-4S BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik CCR1036-12G-4S.
+
+1U rackmount, 12x Gigabit Ethernet, 4xSFP cages, LCD, 36 cores x 1.2GHz CPU, 4GB RAM, 24 mpps fastpath, Up to 16Gbit/s throughput, RouterOS L6, Dual PSU'),
+('10456',NULL,'MikroTik CCR1036-8G-2SEM by SNMP','3','-1','2','','','MikroTik CCR1036-8G-2S+EM by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik CCR1036-8G-2S+EM.
+
+1U rackmount, 8x Gigabit Ethernet, 2xSFP+ cages, LCD, 36 cores x 1.2GHz CPU,
+8GB RAM, 41.5mpps fastpath, Up to 28Gbit/s throughput, RouterOS L6, Dual PSU
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','7b3ecb24366f4685970df8e1143323f0','MIKROTIK CCR1036-8G-2S+EM BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik CCR1036-8G-2S+EM.
+
+1U rackmount, 8x Gigabit Ethernet, 2xSFP+ cages, LCD, 36 cores x 1.2GHz CPU, 8GB RAM, 41.5mpps fastpath, Up to 28Gbit/s throughput, RouterOS L6, Dual PSU'),
+('10457',NULL,'MikroTik CCR1036-8G-2S by SNMP','3','-1','2','','','MikroTik CCR1036-8G-2S+ by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik CCR1036-8G-2S+.
+
+1U rackmount, 8x Gigabit Ethernet, 2xSFP+ cages, LCD, 36 cores x 1.2GHz CPU,
+4GB RAM, 41.5mpps fastpath, Up to 28Gbit/s throughput, RouterOS L6, Dual PSU
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','7f44e67e3f564ec9894c9142d7276553','MIKROTIK CCR1036-8G-2S+ BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik CCR1036-8G-2S+.
+
+1U rackmount, 8x Gigabit Ethernet, 2xSFP+ cages, LCD, 36 cores x 1.2GHz CPU, 4GB RAM, 41.5mpps fastpath, Up to 28Gbit/s throughput, RouterOS L6, Dual PSU'),
+('10458',NULL,'MikroTik CCR1072-1G-8S by SNMP','3','-1','2','','','MikroTik CCR1072-1G-8S+ by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik CCR1072-1G-8S+.
+
+1U rackmount, 1x Gigabit Ethernet, 8xSFP+ cages, LCD, 72 cores x 1GHz CPU, 16GB
+RAM, up to 120 million packets per second, 80Gbps throughput, RouterOS L6
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e7894db1c4c94e0f8715977e751368b3','MIKROTIK CCR1072-1G-8S+ BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik CCR1072-1G-8S+.
+
+1U rackmount, 1x Gigabit Ethernet, 8xSFP+ cages, LCD, 72 cores x 1GHz CPU, 16GB RAM, up to 120 million packets per second, 80Gbps throughput, RouterOS L6'),
+('10459',NULL,'MikroTik CCR2004-16G-2S by SNMP','3','-1','2','','','MikroTik CCR2004-16G-2S+ by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik CCR2004-16G-2S+.
+
+This powerful and affordable router crushes all previous CCR models in single-core
+performance. 16x Gigabit Ethernet ports, 2x10G SFP+ cages, active cooling and
+the best single-core performance per watt & best overall performance per watt
+among all the CCR devices.
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','ab871d051e304f83950171c5243aa4db','MIKROTIK CCR2004-16G-2S+ BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik CCR2004-16G-2S+.
+
+This powerful and affordable router crushes all previous CCR models in single-core performance. 16x Gigabit Ethernet ports, 2x10G SFP+ cages, active cooling and the best single-core performance per watt & best overall performance per watt among all the CCR devices.'),
+('10460',NULL,'MikroTik CCR2004-1G-12S2XS by SNMP','3','-1','2','','','MikroTik CCR2004-1G-12S+2XS by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik CCR2004-1G-12S+2XS.
+
+The Connectivity Router - your best companion when it comes to SFP, SFP+ and
+SFP28 management! 1, 10 and 25 Gbps ports in a single device to make your life
+easier.
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','f2efeb94f4bd4ed9ab34a973c0363eb8','MIKROTIK CCR2004-1G-12S+2XS BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik CCR2004-1G-12S+2XS.
+
+The Connectivity Router - your best companion when it comes to SFP, SFP+ and SFP28 management! 1, 10 and 25 Gbps ports in a single device to make your life easier.'),
+('10461',NULL,'MikroTik CRS106-1C-5S by SNMP','3','-1','2','','','MikroTik CRS106-1C-5S by SNMP','0',NULL,'The template for monitoring Switch MikroTik CRS106-1C-5S.
+
+Smart Switch, 5x SFP cages, 1x Combo port (SFP or Gigabit Ethernet), 400MHz
+CPU, 128MB RAM, desktop case, RouterOS L5
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','20ea139663264c21bca0dcecf2e95589','MIKROTIK CRS106-1C-5S BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CRS106-1C-5S.
+
+Smart Switch, 5x SFP cages, 1x Combo port (SFP or Gigabit Ethernet), 400MHz CPU, 128MB RAM, desktop case, RouterOS L5'),
+('10462',NULL,'MikroTik CRS109-8G-1S-2HnD-IN by SNMP','3','-1','2','','','MikroTik CRS109-8G-1S-2HnD-IN by SNMP','0',NULL,'The template for monitoring Switch MikroTik CRS109-8G-1S-2HnD-IN.
+
+8x Gigabit Smart Switch, 1x SFP cage, LCD, 802.11b/g/n Dual Chain wireless,
+600MHz CPU, 128MB RAM, Metal desktop case, RouterOS L5, supports 10-57V, 802.3af/at
+compliant
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','fac16383680c4454be48b6db870d975e','MIKROTIK CRS109-8G-1S-2HND-IN BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CRS109-8G-1S-2HnD-IN.
+
+8x Gigabit Smart Switch, 1x SFP cage, LCD, 802.11b/g/n Dual Chain wireless, 600MHz CPU, 128MB RAM, Metal desktop case, RouterOS L5, supports 10-57V, 802.3af/at compliant'),
+('10463',NULL,'MikroTik CRS112-8G-4S-IN by SNMP','3','-1','2','','','MikroTik CRS112-8G-4S-IN by SNMP','0',NULL,'The template for monitoring Switch MikroTik CRS112-8G-4S-IN.
+
+8x Gigabit Ethernet Smart Switch, 4x SFP cages, 400MHz CPU, 128MB RAM, desktop
+case, RouterOS L5
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','8d7d49fd0b3f4b1f9046dc0e94457931','MIKROTIK CRS112-8G-4S-IN BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CRS112-8G-4S-IN.
+
+8x Gigabit Ethernet Smart Switch, 4x SFP cages, 400MHz CPU, 128MB RAM, desktop case, RouterOS L5'),
+('10464',NULL,'MikroTik CRS112-8P-4S-IN by SNMP','3','-1','2','','','MikroTik CRS112-8P-4S-IN by SNMP','0',NULL,'The template for monitoring Switch MikroTik CRS112-8P-4S-IN.
+
+8x Gigabit Ethernet Smart Switch with PoE-out, 4x SFP cages, 400MHz CPU, 128MB
+RAM, desktop case, RouterOS L5
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','538ec67ce01341a9b281dbd86d86d2a2','MIKROTIK CRS112-8P-4S-IN BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CRS112-8P-4S-IN.
+
+8x Gigabit Ethernet Smart Switch with PoE-out, 4x SFP cages, 400MHz CPU, 128MB RAM, desktop case, RouterOS L5'),
+('10465',NULL,'MikroTik CRS125-24G-1S-2HnD-IN by SNMP','3','-1','2','','','MikroTik CRS125-24G-1S-2HnD-IN by SNMP','0',NULL,'The template for monitoring Switch MikroTik CRS125-24G-1S-2HnD-IN.
+
+24x Gigabit Ethernet layer 3 Smart Switch, 1x SFP cage, LCD, 802.11b/g/n Dual
+Chain wireless, 600MHz CPU, 128MB RAM, Metal desktop case, RouterOS L5
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','c8db153405704d859ba5ee19f08b46f3','MIKROTIK CRS125-24G-1S-2HND-IN BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CRS125-24G-1S-2HnD-IN.
+
+24x Gigabit Ethernet layer 3 Smart Switch, 1x SFP cage, LCD, 802.11b/g/n Dual Chain wireless, 600MHz CPU, 128MB RAM, Metal desktop case, RouterOS L5'),
+('10466',NULL,'MikroTik CRS212-1G-10S-1SIN by SNMP','3','-1','2','','','MikroTik CRS212-1G-10S-1S+IN by SNMP','0',NULL,'The template for monitoring Switch MikroTik CRS212-1G-10S-1S+IN.
+
+Smart Switch, 1x Gigabit LAN, 10x SFP cages, 1x SFP+ cage, LCD, 400MHz CPU,
+64MB RAM, Metal desktop case, RouterOS L5
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','cdb6ebceb1174bada392dd24889b14d9','MIKROTIK CRS212-1G-10S-1S+IN BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CRS212-1G-10S-1S+IN.
+
+Smart Switch, 1x Gigabit LAN, 10x SFP cages, 1x SFP+ cage, LCD, 400MHz CPU, 64MB RAM, Metal desktop case, RouterOS L5'),
+('10467',NULL,'MikroTik CRS305-1G-4SIN by SNMP','3','-1','2','','','MikroTik CRS305-1G-4S+IN by SNMP','0',NULL,'The template for monitoring Switch MikroTik CRS305-1G-4S+IN.
+
+Five-port desktop switch with one Gigabit Ethernet port and four SFP+ 10Gbps
+ports
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','223101f878704022a04c30c3ff066e3f','MIKROTIK CRS305-1G-4S+IN BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CRS305-1G-4S+IN.
+
+Five-port desktop switch with one Gigabit Ethernet port and four SFP+ 10Gbps ports'),
+('10468',NULL,'MikroTik CRS309-1G-8SIN by SNMP','3','-1','2','','','MikroTik CRS309-1G-8S+IN by SNMP','0',NULL,'The template for monitoring Switch MikroTik CRS309-1G-8S+IN.
+
+Desktop switch with one Gigabit Ethernet port and eight SFP+ 10Gbps ports
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','bcc01f2b466345c4bcbe0cea1a7884d1','MIKROTIK CRS309-1G-8S+IN BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CRS309-1G-8S+IN.
+
+Desktop switch with one Gigabit Ethernet port and eight SFP+ 10Gbps ports'),
+('10469',NULL,'MikroTik CRS312-4C8XG-RM by SNMP','3','-1','2','','','MikroTik CRS312-4C+8XG-RM by SNMP','0',NULL,'The template for monitoring Switch MikroTik CRS312-4C+8XG-RM.
+
+Switch of the future: the first MikroTik product with 10G RJ45 Ethernet ports
+and SFP+
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','8da94e2f01ff46e28becf0b08ff09ace','MIKROTIK CRS312-4C+8XG-RM BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CRS312-4C+8XG-RM.
+
+Switch of the future: the first MikroTik product with 10G RJ45 Ethernet ports and SFP+'),
+('10470',NULL,'MikroTik CRS317-1G-16SRM by SNMP','3','-1','2','','','MikroTik CRS317-1G-16S+RM by SNMP','0',NULL,'The template for monitoring Switch MikroTik CRS317-1G-16S+RM.
+
+Smart Switch, 1 x Gigabit LAN, 16 x SFP+ cages, Dual Core 800MHz CPU, 1GB RAM,
+1U rackmount passive cooling case, Dual Power Supplies
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','f474ff823fe84d689b9e4c6a4f0ce59e','MIKROTIK CRS317-1G-16S+RM BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CRS317-1G-16S+RM.
+
+Smart Switch, 1 x Gigabit LAN, 16 x SFP+ cages, Dual Core 800MHz CPU, 1GB RAM, 1U rackmount passive cooling case, Dual Power Supplies'),
+('10471',NULL,'MikroTik CRS326-24G-2SIN by SNMP','3','-1','2','','','MikroTik CRS326-24G-2S+IN by SNMP','0',NULL,'The template for monitoring Switch MikroTik CRS326-24G-2S+IN.
+
+24 Gigabit ports, 2 SFP+ cages and a desktop case – server room power for your
+home!
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','c5f41fe0f54f470f9e304384838f150a','MIKROTIK CRS326-24G-2S+IN BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CRS326-24G-2S+IN.
+
+24 Gigabit ports, 2 SFP+ cages and a desktop case – server room power for your home!'),
+('10472',NULL,'MikroTik CRS326-24G-2SRM by SNMP','3','-1','2','','','MikroTik CRS326-24G-2S+RM by SNMP','0',NULL,'The template for monitoring Switch MikroTik CRS326-24G-2S+RM.
+
+24 Gigabit port switch with 2 x SFP+ cages in 1U rackmount case, Dual boot (RouterOS
+or SwitchOS)
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','bc80883918ac4f879427ca145122b5cb','MIKROTIK CRS326-24G-2S+RM BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CRS326-24G-2S+RM.
+
+24 Gigabit port switch with 2 x SFP+ cages in 1U rackmount case, Dual boot (RouterOS or SwitchOS)'),
+('10473',NULL,'MikroTik CRS326-24S2QRM by SNMP','3','-1','2','','','MikroTik CRS326-24S+2Q+RM by SNMP','0',NULL,'The template for monitoring Switch MikroTik CRS326-24S+2Q+RM.
+
+Our fastest switch for the most demanding setups
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e7ed0e0cbd0b439394f6498ea90dc31d','MIKROTIK CRS326-24S+2Q+RM BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CRS326-24S+2Q+RM.
+
+Our fastest switch for the most demanding setups'),
+('10474',NULL,'MikroTik CRS328-24P-4SRM by SNMP','3','-1','2','','','MikroTik CRS328-24P-4S+RM by SNMP','0',NULL,'The template for monitoring Switch MikroTik CRS328-24P-4S+RM.
+
+24 port Gigabit Ethernet router/switch with four 10Gbps SFP+ ports in 1U rackmount
+case, Dual Boot and PoE output, 500W
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','dcf88bca5aaf4123a10eb3daab28a9af','MIKROTIK CRS328-24P-4S+RM BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CRS328-24P-4S+RM.
+
+24 port Gigabit Ethernet router/switch with four 10Gbps SFP+ ports in 1U rackmount case, Dual Boot and PoE output, 500W'),
+('10475',NULL,'MikroTik CRS328-4C-20S-4SRM by SNMP','3','-1','2','','','MikroTik CRS328-4C-20S-4S+RM by SNMP','0',NULL,'The template for monitoring Switch MikroTik CRS328-4C-20S-4S+RM.
+
+Smart Switch, 20 x SFP cages, 4 x SFP+ cages, 4 x Combo ports (Gigabit Ethernet
+or SFP), 800MHz CPU, 512MB RAM, 1U rackmount case, Dual Power Supplies, RouterOS
+L5 or SwitchOS (Dual Boot)
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','6742f5ed33ca4c19b8e61203770e5fe5','MIKROTIK CRS328-4C-20S-4S+RM BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CRS328-4C-20S-4S+RM.
+
+Smart Switch, 20 x SFP cages, 4 x SFP+ cages, 4 x Combo ports (Gigabit Ethernet or SFP), 800MHz CPU, 512MB RAM, 1U rackmount case, Dual Power Supplies, RouterOS L5 or SwitchOS (Dual Boot)'),
+('10476',NULL,'MikroTik CRS354-48G-4S2QRM by SNMP','3','-1','2','','','MikroTik CRS354-48G-4S+2Q+RM by SNMP','0',NULL,'The template for monitoring Switch MikroTik CRS354-48G-4S+2Q+RM.
+
+Best price and best performance on the market – this 48 port switch will rock
+any setup, including 40 Gbps devices!
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','d1c1ab5db2c34c17ae3541407f8b7faa','MIKROTIK CRS354-48G-4S+2Q+RM BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CRS354-48G-4S+2Q+RM.
+
+Best price and best performance on the market – this 48 port switch will rock any setup, including 40 Gbps devices!'),
+('10477',NULL,'MikroTik CRS354-48P-4S2QRM by SNMP','3','-1','2','','','MikroTik CRS354-48P-4S+2Q+RM by SNMP','0',NULL,'The template for monitoring Switch MikroTik CRS354-48P-4S+2Q+RM.
+
+The 48 port champion you’ve been waiting for - now with PoE-out!
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','fa5e5e131eb34bbea1b1f7b2352a853d','MIKROTIK CRS354-48P-4S+2Q+RM BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CRS354-48P-4S+2Q+RM.
+
+The 48 port champion you’ve been waiting for - now with PoE-out!'),
+('10478',NULL,'MikroTik CSS326-24G-2SRM by SNMP','3','-1','2','','','MikroTik CSS326-24G-2S+RM by SNMP','0',NULL,'The template for monitoring Switch MikroTik CSS326-24G-2S+RM.
+
+SwOS powered 24 port Gigabit Ethernet switch with two SFP+ ports in 1U rackmount
+case
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','75ada0d6fb22416a9e6e5f44c2c3f64a','MIKROTIK CSS326-24G-2S+RM BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CSS326-24G-2S+RM.
+
+SwOS powered 24 port Gigabit Ethernet switch with two SFP+ ports in 1U rackmount case'),
+('10479',NULL,'MikroTik CSS610-8G-2SIN by SNMP','3','-1','2','','','MikroTik CSS610-8G-2S+IN by SNMP','0',NULL,'The template for monitoring Switch MikroTik CSS610-8G-2S+IN.
+
+Eight 1G Ethernet ports and two SFP+ ports for 10G fiber connectivity. Portable,
+powerful and extremely cost-effective - this switch is an instant classic!
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','8d22b4d1a9c6457fbd6fd959263f91db','MIKROTIK CSS610-8G-2S+IN BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik CSS610-8G-2S+IN.
+
+Eight 1G Ethernet ports and two SFP+ ports for 10G fiber connectivity. Portable, powerful and extremely cost-effective - this switch is an instant classic!'),
+('10480',NULL,'MikroTik FiberBox by SNMP','3','-1','2','','','MikroTik FiberBox by SNMP','0',NULL,'The template for monitoring Switch MikroTik FiberBox.
+
+An outdoor switch with five SFP ports
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','2bd6f566391d49dab6bee184522ab5fa','MIKROTIK FIBERBOX BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik FiberBox.
+
+An outdoor switch with five SFP ports'),
+('10481',NULL,'MikroTik PowerBox Pro by SNMP','3','-1','2','','','MikroTik PowerBox Pro by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik PowerBox Pro.
+
+Five Gigabit Ethernet Router with 4xPoE-out ports, SFP cage and outdoor enclosure
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','c03e1ab0128a4ae1847bc04a34f5634e','MIKROTIK POWERBOX PRO BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik PowerBox Pro.
+
+Five Gigabit Ethernet Router with 4xPoE-out ports, SFP cage and outdoor enclosure'),
+('10482',NULL,'MikroTik PowerBox by SNMP','3','-1','2','','','MikroTik PowerBox by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik PowerBox.
+
+650MHz CPU, 64MB RAM, 5xEthernet with PoE output for four ports, RouterOS L4,
+outdoor case, PSU
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','0c7b3c03a5854f868b56f3ab63e2d3f7','MIKROTIK POWERBOX BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik PowerBox.
+
+650MHz CPU, 64MB RAM, 5xEthernet with PoE output for four ports, RouterOS L4, outdoor case, PSU'),
+('10483',NULL,'MikroTik RB1100AHx4 Dude Edition by SNMP','3','-1','2','','','MikroTik RB1100AHx4 Dude Edition by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik RB1100AHx4 Dude Edition.
+
+Powerful 1U rackmount router with 13x Gigabit Ethernet ports, 60GB M.2 drive
+for Dude database
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','fac50638cb77468598c29a6a47520c24','MIKROTIK RB1100AHX4 DUDE EDITION BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik RB1100AHx4 Dude Edition.
+
+Powerful 1U rackmount router with 13x Gigabit Ethernet ports, 60GB M.2 drive for Dude database'),
+('10484',NULL,'MikroTik RB1100AHx4 by SNMP','3','-1','2','','','MikroTik RB1100AHx4 by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik RB1100AHx4.
+
+Powerful 1U rackmount router with 13x Gigabit Ethernet ports
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','3dfd1a55987848e5aa6ffe92c228f63b','MIKROTIK RB1100AHX4 BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik RB1100AHx4.
+
+Powerful 1U rackmount router with 13x Gigabit Ethernet ports'),
+('10485',NULL,'MikroTik RB2011UiAS-IN by SNMP','3','-1','2','','','MikroTik RB2011UiAS-IN by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik RB2011UiAS-IN.
+
+Desktop metal case, 5xEthernet, 5xGigabit Ethernet, USB, LCD, PoE out on port
+10, 600MHz CPU, 128MB RAM, RouterOS L5
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','8cf537f34600403b9de31d3db4eb2a1d','MIKROTIK RB2011UIAS-IN BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik RB2011UiAS-IN.
+
+Desktop metal case, 5xEthernet, 5xGigabit Ethernet, USB, LCD, PoE out on port 10, 600MHz CPU, 128MB RAM, RouterOS L5'),
+('10486',NULL,'MikroTik RB2011UiAS-RM by SNMP','3','-1','2','','','MikroTik RB2011UiAS-RM by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik RB2011UiAS-RM.
+
+1U rackmount, 5xEthernet, 5xGigabit Ethernet, USB, LCD, PoE out on port 10,
+600MHz CPU, 128MB RAM, RouterOS L5
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','969cf5dca58f47f0b271ccf62ef79c13','MIKROTIK RB2011UIAS-RM BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik RB2011UiAS-RM.
+
+1U rackmount, 5xEthernet, 5xGigabit Ethernet, USB, LCD, PoE out on port 10, 600MHz CPU, 128MB RAM, RouterOS L5'),
+('10487',NULL,'MikroTik RB2011iL-IN by SNMP','3','-1','2','','','MikroTik RB2011iL-IN by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik RB2011iL-IN.
+
+Desktop metal case, 5xEthernet, 5xGigabit Ethernet, PoE out on port 10, 600MHz
+CPU, 64MB RAM, RouterOS L4
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','141438a05f904b518c7d3ddfbbabf91f','MIKROTIK RB2011IL-IN BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik RB2011iL-IN.
+
+Desktop metal case, 5xEthernet, 5xGigabit Ethernet, PoE out on port 10, 600MHz CPU, 64MB RAM, RouterOS L4'),
+('10488',NULL,'MikroTik RB2011iL-RM by SNMP','3','-1','2','','','MikroTik RB2011iL-RM by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik RB2011iL-RM.
+
+1U rackmount, 5xEthernet, 5xGigabit Ethernet, PoE out on port 10, 600MHz CPU,
+64MB RAM, RouterOS L4
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','6d9737c72e5540d39e3553b773a587b1','MIKROTIK RB2011IL-RM BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik RB2011iL-RM.
+
+1U rackmount, 5xEthernet, 5xGigabit Ethernet, PoE out on port 10, 600MHz CPU, 64MB RAM, RouterOS L4'),
+('10489',NULL,'MikroTik RB2011iLS-IN by SNMP','3','-1','2','','','MikroTik RB2011iLS-IN by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik RB2011iLS-IN.
+
+Desktop metal case, 5xEthernet, 5xGigabit Ethernet, SFP cage, PoE out on port
+10, 600MHz CPU, 64MB RAM, RouterOS L4
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','318fd61c22fa4f1a92a71376814d6c32','MIKROTIK RB2011ILS-IN BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik RB2011iLS-IN.
+
+Desktop metal case, 5xEthernet, 5xGigabit Ethernet, SFP cage, PoE out on port 10, 600MHz CPU, 64MB RAM, RouterOS L4'),
+('10490',NULL,'MikroTik RB260GSP by SNMP','3','-1','2','','','MikroTik RB260GSP by SNMP','0',NULL,'The template for monitoring Switch MikroTik RB260GSP.
+
+5x Gigabit PoE out Ethernet Smart Switch, SFP cage, plastic case, SwOS
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','5331ecc3be9f47d6a8eb0732ae141239','MIKROTIK RB260GSP BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik RB260GSP.
+
+5x Gigabit PoE out Ethernet Smart Switch, SFP cage, plastic case, SwOS'),
+('10491',NULL,'MikroTik RB260GS by SNMP','3','-1','2','','','MikroTik RB260GS by SNMP','0',NULL,'The template for monitoring Switch MikroTik RB260GS.
+
+5x Gigabit Ethernet Smart Switch, SFP cage, plastic case, SwOS
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','1a74dd95e7244493a1b13b94fe9dd9e8','MIKROTIK RB260GS BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik RB260GS.
+
+5x Gigabit Ethernet Smart Switch, SFP cage, plastic case, SwOS'),
+('10492',NULL,'MikroTik RB3011UiAS-RM by SNMP','3','-1','2','','','MikroTik RB3011UiAS-RM by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik RB3011UiAS-RM.
+
+1U rackmount, 10xGigabit Ethernet, SFP, USB 3.0, LCD, PoE out on port 10, 2x1.4GHz
+CPU, 1GB RAM, RouterOS L5
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','cc762a057f0f467ab571b6d76a9bb278','MIKROTIK RB3011UIAS-RM BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik RB3011UiAS-RM.
+
+1U rackmount, 10xGigabit Ethernet, SFP, USB 3.0, LCD, PoE out on port 10, 2x1.4GHz CPU, 1GB RAM, RouterOS L5'),
+('10493',NULL,'MikroTik RB4011iGSRM by SNMP','3','-1','2','','','MikroTik RB4011iGS+RM by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik RB4011iGS+RM.
+
+Powerful 10xGigabit port router with a Quad-core 1.4Ghz CPU, 1GB RAM, SFP+ 10Gbps
+cage and desktop case with rack ears
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','780c4a9a657e42fc83f1ab9a535f5184','MIKROTIK RB4011IGS+RM BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik RB4011iGS+RM.
+
+Powerful 10xGigabit port router with a Quad-core 1.4Ghz CPU, 1GB RAM, SFP+ 10Gbps cage and desktop case with rack ears'),
+('10494',NULL,'MikroTik RB5009UGSIN by SNMP','3','-1','2','','','MikroTik RB5009UG+S+IN by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik RB5009UG+S+IN.
+
+The ultimate heavy-duty home lab router with USB 3.0, 1G and 2.5G Ethernet and
+a 10G SFP+ cage. You can mount four of these new routers in a single 1U rackmount
+space! Unprecedented processing power in such a small form factor.
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','7b6f7a12a6b449ca926e74c894eca354','MIKROTIK RB5009UG+S+IN BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik RB5009UG+S+IN.
+
+The ultimate heavy-duty home lab router with USB 3.0, 1G and 2.5G Ethernet and a 10G SFP+ cage. You can mount four of these new routers in a single 1U rackmount space! Unprecedented processing power in such a small form factor.'),
+('10495',NULL,'MikroTik hEX PoE lite by SNMP','3','-1','2','','','MikroTik hEX PoE lite by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik hEX PoE lite.
+
+5xEthernet with PoE output for four ports, USB, 650MHz CPU, 64MB RAM, RouterOS
+L4
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','a5ddacdd5ac64b82bf5183769cc03e8c','MIKROTIK HEX POE LITE BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik hEX PoE lite.
+
+5xEthernet with PoE output for four ports, USB, 650MHz CPU, 64MB RAM, RouterOS L4'),
+('10496',NULL,'MikroTik hEX PoE by SNMP','3','-1','2','','','MikroTik hEX PoE by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik hEX PoE.
+
+5x Gigabit Ethernet with PoE output for four ports, SFP, USB, 800MHz CPU, 128MB
+RAM, RouterOS L4
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','ff57532daf924030b364e3b75acb74c4','MIKROTIK HEX POE BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik hEX PoE.
+
+5x Gigabit Ethernet with PoE output for four ports, SFP, USB, 800MHz CPU, 128MB RAM, RouterOS L4'),
+('10497',NULL,'MikroTik hEX S by SNMP','3','-1','2','','','MikroTik hEX S by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik hEX S.
+
+5x Gigabit Ethernet, SFP, Dual Core 880MHz CPU, 256MB RAM, USB, microSD, RouterOS
+L4, IPsec hardware encryption support and The Dude server package
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','7802db8c2f9c4a7eba7b381b8f3fa5c5','MIKROTIK HEX S BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik hEX S.
+
+5x Gigabit Ethernet, SFP, Dual Core 880MHz CPU, 256MB RAM, USB, microSD, RouterOS L4, IPsec hardware encryption support and The Dude server package'),
+('10498',NULL,'MikroTik hEX lite by SNMP','3','-1','2','','','MikroTik hEX lite by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik hEX lite.
+
+5x Ethernet, Small plastic case, 850MHz CPU, 64MB RAM, Most affordable MPLS
+router, RouterOS L4
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','2785d83763c641a7a7937b516665d93a','MIKROTIK HEX LITE BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik hEX lite.
+
+5x Ethernet, Small plastic case, 850MHz CPU, 64MB RAM, Most affordable MPLS router, RouterOS L4'),
+('10499',NULL,'MikroTik hEX by SNMP','3','-1','2','','','MikroTik hEX by SNMP','0',NULL,'The template for monitoring Ethernet router MikroTik hEX.
+
+5x Gigabit Ethernet, Dual Core 880MHz CPU, 256MB RAM, USB, microSD, RouterOS
+L4
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','68c2034014f24115ae9e910962530472','MIKROTIK HEX BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Ethernet router MikroTik hEX.
+
+5x Gigabit Ethernet, Dual Core 880MHz CPU, 256MB RAM, USB, microSD, RouterOS L4'),
+('10500',NULL,'MikroTik netPower 15FR by SNMP','3','-1','2','','','MikroTik netPower 15FR by SNMP','0',NULL,'The template for monitoring Switch MikroTik netPower 15FR.
+
+An outdoor 18 port switch with 15 reverse PoE ports and SFP. Cut costs, not
+speed - choose GPEN over GPON!
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','f1928e12f9554599a9adb516f38b6bf6','MIKROTIK NETPOWER 15FR BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik netPower 15FR.
+
+An outdoor 18 port switch with 15 reverse PoE ports and SFP. Cut costs, not speed - choose GPEN over GPON!'),
+('10501',NULL,'MikroTik netPower 16P by SNMP','3','-1','2','','','MikroTik netPower 16P by SNMP','0',NULL,'The template for monitoring Switch MikroTik netPower 16P.
+
+An outdoor 18 port switch with 16 Gigabit PoE-out ports and 2 SFP+. Power all
+your access points anywhere!
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','b126aaf4499d49d7b4fcee0329b7dea7','MIKROTIK NETPOWER 16P BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik netPower 16P.
+
+An outdoor 18 port switch with 16 Gigabit PoE-out ports and 2 SFP+. Power all your access points anywhere!'),
+('10502',NULL,'MikroTik netPower Lite 7R by SNMP','3','-1','2','','','MikroTik netPower Lite 7R by SNMP','0',NULL,'The template for monitoring Switch MikroTik netPower Lite 7R.
+
+An outdoor reverse PoE switch with Gigabit Ethernet and 10G SFP+ ports.
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+MIKROTIK-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','1782caa5bf724f66a23e7dbb96ef7ba2','MIKROTIK NETPOWER LITE 7R BY SNMP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template for monitoring Switch MikroTik netPower Lite 7R.
+
+An outdoor reverse PoE switch with Gigabit Ethernet and 10G SFP+ ports.'),
+('10503',NULL,'VeloCloud SD-WAN by HTTP','3','-1','2','','','VeloCloud SD-WAN by HTTP','0',NULL,'Template for monitoring VeloCloud SD-WAN https://www.arista.com/en/support/velocloud-resources
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e1ca624566424496bff9d90c261ab37b','VELOCLOUD SD-WAN BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+- This template provides monitoring capabilities for VeloCloud SD-WAN using the API.
+- It works without any external scripts and uses the script item.
+
+## Setup
+
+1. Create an API token in the VeloCloud SD-WAN Orchestrator.
+> See [Arista documentation](https://www.arista.com/en/global-settings-guide-vc-6-4/sase-6-4-user-management) for details.
+
+2. Link the template to a host.
+3. Set the following fields: `API token`, `API URL`.
+
+**Note**: By default, the `Enterprise ID` field is empty. In this case, data will be retrieved for all Enterprises (privileges required: READ ENTERPRISE and READ EDGE).
+If you need to monitor only one Enterprise, fill in this field (requires only READ EDGE privileges).'),
+('10504',NULL,'Kubernetes API server by HTTP','3','-1','2','','','Kubernetes API server by HTTP','0',NULL,'Get Kubernetes API server metrics by HTTP agent from Prometheus metrics endpoint.
+
+Don''t forget change macros {$KUBE.API.SERVER.URL}, {$KUBE.API.TOKEN}.
+Some metrics may not be collected depending on your Kubernetes API server instance version and configuration.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','85ce114c802e4e28a5f3597e07d07032','KUBERNETES API SERVER BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+The template to monitor Kubernetes API server that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+Template `Kubernetes API server by HTTP` - collects metrics by HTTP agent from API server /metrics endpoint.
+
+## Setup
+
+Internal service metrics are collected from /metrics endpoint.
+Template needs to use Authorization via API token.
+
+Set the following fields: `Kubernetes API server URL`, `API Authorization Token`.
+
+**Note:** Some metrics may not be collected depending on your Kubernetes API server instance version and configuration.'),
+('10505',NULL,'Kubernetes Controller manager by HTTP','3','-1','2','','','Kubernetes Controller manager by HTTP','0',NULL,'Get Kubernetes Controller manager metrics by HTTP agent from Prometheus metrics endpoint.
+
+Don''t forget change macros {$KUBE.API.SERVER.URL}.
+Some metrics may not be collected depending on your Kubernetes Controller manager instance version and configuration.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','2420a8a4fda74fbc81743aed69fafa3b','KUBERNETES CONTROLLER MANAGER BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor Kubernetes Controller manager by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+Template `Kubernetes Controller manager by HTTP` - collects metrics by HTTP agent from Controller manager /metrics endpoint.
+
+## Setup
+
+Internal service metrics are collected from /metrics endpoint.
+Template needs to use Authorization via API token.
+
+Set the following fields: `Metrics endpoint URL`, `API Authorization Token`.
+
+**Note:** You might need to set the `--binding-address` option for Controller Manager to the address where Zabbix proxy can reach it.
+For example, for clusters created with `kubeadm` it can be set in the following manifest file (changes will be applied immediately):
+
+- /etc/kubernetes/manifests/kube-controller-manager.yaml
+
+**Note:** Some metrics may not be collected depending on your Kubernetes Controller manager instance version and configuration.'),
+('10506',NULL,'Kubernetes Kubelet by HTTP','3','-1','2','','','Kubernetes Kubelet by HTTP','0',NULL,'Get Kubernetes kubelet metrics by HTTP agent from Prometheus metrics endpoint.
+
+Don''t forget change macros {$KUBE.KUBELET.URL}, {$KUBE.API.TOKEN}.
+Some metrics may not be collected depending on your Kubernetes API server instance version and configuration.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e785916967c14544b59c3644c3edda3a','KUBERNETES KUBELET BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor Kubernetes Kubelet by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+Template `Kubernetes Kubelet by HTTP` - collects metrics by HTTP agent from Kubelet /metrics endpoint.
+
+## Setup
+
+Internal service metrics are collected from /metrics endpoint.
+Template needs to use Authorization via API token.
+
+Set the following fields: `Kubelet URL`, `API Authorization Token`.
+
+**Note:** Some metrics may not be collected depending on your Kubernetes instance version and configuration.'),
+('10507',NULL,'Kubernetes nodes by HTTP','3','-1','2','','','Kubernetes nodes by HTTP','0',NULL,'Get Kubernetes nodes metrics by HTTP.
+Metrics are collected by requests to Kubernetes API.
+
+Don''t forget to read the README.md for the correct setup of the template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','f397be2340734d24bc666102fbe184a5','KUBERNETES NODES BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+The template to monitor Kubernetes nodes that work without any external scripts.
+It works without external scripts and uses the script item to make HTTP requests to the Kubernetes API.
+
+Change the values according to the environment in the file $HOME/zabbix_values.yaml.
+
+For example:
+
+## Enables use of **Zabbix proxy**
+ enabled: false
+
+Set the field: `Kubernetes API URL` such as `://:`.
+
+Get the generated service account token using the command:
+
+`kubectl get secret zabbix-zabbix-helm-chart -n monitoring -o jsonpath={.data.token} | base64 -d`
+
+Then set it to the field: `API Authorization Token`.
+
+Set up the fields to filter the metrics of discovered nodes.
+
+
+## Setup
+
+Install the [Zabbix Helm Chart](https://git.zabbix.com/projects/ZT/repos/kubernetes-helm/browse?at=refs%2Fheads%2Fmaster) in your Kubernetes cluster.
+
+Set the following fields: `Kubernetes API URL` such as `://:`.
+
+Get the generated service account token using the command:
+
+`kubectl get secret zabbix-zabbix-helm-chart -n monitoring -o jsonpath={.data.token} | base64 -d`
+
+Then set it to the field: `API Authorization Token`.
+
+Set `Nodes Endpoint Name` with Zabbix agent''s endpoint name. See `kubectl -n monitoring get ep`. Default: `zabbix-zabbix-helm-chrt-agent`.
+
+Set up the fields to filter the metrics of discovered nodes and host creation based on host prototypes:
+
+- `Node Matches Filter`
+- `Node Exclusion Filter`
+- `Node Role Matches Filter`
+- `Node Role Exclusion Filter`
+
+Set up fields to filter pod metrics by namespace:
+
+- `Pod Namespace Matches Filter`
+- `Pod Namespace Exclusion Filter`
+
+**Note:** If you have a large cluster, it is highly recommended to set a filter for discoverable pods.
+
+You can use the `Node Labels Filter`, `Pod Labels Filter`, `Node Annotations Filter` and `Pod Annotations Filter` fields for advanced filtering of nodes and pods by labels and annotations.
+
+Notes about labels and annotations filters:
+
+- Values should be specified separated by commas and must have the key/value form with support for regular expressions in the value (`key1: value, key2: regexp`).
+- ECMAScript syntax is used for regular expressions.
+- Filters are applied if such a label key exists for the entity that is being filtered (it means that if you specify a key in a filter, entities which do not have this key will not be affected by the filter and will still be discovered, and only entities containing that key will be filtered by the value).
+- You can also use the exclamation point symbol (`!`) to invert the filter (`!key: value`).
+
+For example: `kubernetes.io/hostname: kubernetes-node[5-25], !node-role.kubernetes.io/ingress: .*`. As a result, the nodes 5-25 without the "ingress" role will be discovered.
+
+
+See the Kubernetes documentation for details about labels and annotations:
+
+-
+-
+
+**Note:** the discovered nodes will be created as separate hosts in Zabbix with the Linux template automatically assigned to them.'),
+('10509',NULL,'Kubernetes Scheduler by HTTP','3','-1','2','','','Kubernetes Scheduler by HTTP','0',NULL,'Get Kubernetes Scheduler metrics by HTTP agent from Prometheus metrics endpoint.
+
+Don''t forget change macros {$KUBE.API.SERVER.URL}.
+Some metrics may not be collected depending on your Kubernetes Scheduler instance version and configuration.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','ece96efdf0a045b99ede7978fa9366d6','KUBERNETES SCHEDULER BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor Kubernetes Scheduler by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+Template `Kubernetes Scheduler by HTTP` - collects metrics by HTTP agent from Scheduler /metrics endpoint.
+
+## Setup
+
+Internal service metrics are collected from /metrics endpoint.
+Template needs to use Authorization via API token.
+
+Set the following fields: `Scheduler metrics endpoint URL`, `API Authorization Token`.
+
+**Note:** You might need to set the `--binding-address` option for Scheduler to the address where Zabbix proxy can reach it.
+For example, for clusters created with `kubeadm` it can be set in the following manifest file (changes will be applied immediately):
+
+- /etc/kubernetes/manifests/kube-scheduler.yaml
+
+**Note:** Some metrics may not be collected depending on your Kubernetes Scheduler instance version and configuration.'),
+('10510',NULL,'Kubernetes cluster state by HTTP','3','-1','2','','','Kubernetes cluster state by HTTP','0',NULL,'Get Kubernetes state metrics by HTTP.
+Metrics are collected by requests to Kubernetes API.
+
+Don''t forget to read the README.md for the correct setup of the template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','07695028a2ba4b66a5414797bec791df','KUBERNETES CLUSTER STATE BY HTTP','Zabbix','8.0-3',NULL,'0','1','## Overview
+
+The template to monitor Kubernetes state.
+It works without external scripts and uses the script item to make HTTP requests to the Kubernetes API.
+
+Template `Kubernetes cluster state by HTTP` - collects metrics by HTTP agent from kube-state-metrics endpoint and Kubernetes API.
+
+**Note:** Some metrics may not be collected depending on your Kubernetes version and configuration.
+
+## Setup
+
+Install the [Zabbix Helm Chart](https://git.zabbix.com/projects/ZT/repos/kubernetes-helm/browse?at=refs%2Fheads%2Fmaster) in your Kubernetes cluster.
+Internal service metrics are collected from kube-state-metrics endpoint.
+
+Template needs to use authorization via API token.
+
+Set the `Kubernetes API URL` such as `://:`.
+
+Get the generated service account token using the command:
+
+`kubectl get secret zabbix-zabbix-helm-chart -n monitoring -o jsonpath={.data.token} | base64 -d`
+
+Then set it to the field: `API Authorization Token`.
+Set `State Endpoint Name` with Kube state metrics endpoint name. See `kubectl -n monitoring get ep`. Default: `zabbix-kube-state-metrics`.
+
+**Note:** If you wish to monitor Controller Manager and Scheduler components, you might need to set the `--binding-address` option for them to the address where Zabbix proxy can reach them.
+For example, for clusters created with `kubeadm` it can be set in the following manifest files (changes will be applied immediately):
+
+- /etc/kubernetes/manifests/kube-controller-manager.yaml
+- /etc/kubernetes/manifests/kube-scheduler.yaml
+
+Depending on your Kubernetes distribution, you might need to adjust `Control Plane Taint` field (for example, set it to `node-role.kubernetes.io/master` for OpenShift).
+
+**Note:** Some metrics may not be collected depending on your Kubernetes version and configuration.
+
+Set up the fields to filter the metrics of discovered Kubelets by node names:
+
+- `Kubelet Node Matches Filter`
+- `Kubelet Node Exclude Filter`
+
+Set up fields to filter metrics by namespace:
+
+- `Namespace Matches Filter`
+- `Namespace Exclude Filter`
+
+Set up fields to filter node metrics by nodename:
+
+- `Node Matches Filter`
+- `Node Exclude Filter`
+
+**Note:** If you have a large cluster, it is highly recommended to set a filter for discoverable namespaces.
+
+You can use the `Kubelet Labels Filter` and `Kubelet Annotations Filter` fields for advanced filtering of kubelets by node labels and annotations.
+
+Notes about labels and annotations filters:
+
+- Values should be specified separated by commas and must have the key/value form with support for regular expressions in the value (`key1: value, key2: regexp`).
+- ECMAScript syntax is used for regular expressions.
+- Filters are applied if such label key exists for the entity that is being filtered (it means that if you specify a key in the filter, entities that do not have this key will not be affected by the filter and will still be discovered, and only entities containing that key will be filtered by the value).
+- You can also use the exclamation point symbol (`!`) to invert the filter (`!key: value`).
+
+For example: `kubernetes.io/hostname: kubernetes-node[5-25], !node-role.kubernetes.io/ingress: .*`. As a result, the kubelets on nodes 5-25 without the "ingress" role will be discovered.
+
+
+See the Kubernetes documentation for details about labels and annotations:
+
+-
+-
+
+You can also set up evaluation periods for replica mismatch triggers (Deployments, ReplicaSets, StatefulSets) with the field `Replica Mismatch Evaluation Period`, which supports context and regular expressions.'),
+('10515',NULL,'PFSense by SNMP','3','-1','2','','','PFSense by SNMP','0',NULL,'Template for monitoring pfSense by SNMP
+Setup:
+ 1. Enable SNMP daemon at Services in pfSense web interface https://docs.netgate.com/pfsense/en/latest/services/snmp.html
+ 2. Setup firewall rule to get access from Zabbix proxy or Zabbix server by SNMP https://docs.netgate.com/pfsense/en/latest/firewall/index.html#managing-firewall-rules
+ 3. Link template to the host
+
+
+MIBs used:
+BEGEMOT-PF-MIB
+HOST-RESOURCES-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','16f281aeb8904d3db8b66dda94611fcc','PFSENSE BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+Template for monitoring pfSense by SNMP
+
+## Setup
+
+1. Import template into Zabbix
+2. Enable SNMP daemon at Services in pfSense web interface https://docs.netgate.com/pfsense/en/latest/services/snmp.html
+3. Setup firewall rule to get access from Zabbix proxy or Zabbix server by SNMP https://docs.netgate.com/pfsense/en/latest/firewall/index.html#managing-firewall-rules
+4. Link template to the host'),
+('10516',NULL,'OpenWeatherMap by HTTP','3','-1','2','','','OpenWeatherMap by HTTP','0',NULL,'Get weather metrics from OpenWeatherMap current weather API by HTTP.
+It works without any external scripts and uses the Script item.
+
+Setup:
+ 1. Create a host.
+
+ 2. Link the template to the host.
+
+ 3. Customize the values of {$OPENWEATHERMAP.API.TOKEN} and {$LOCATION} macros.
+ OpenWeatherMap API Tokens are available in your OpenWeatherMap account https://home.openweathermap.org/api_keys.
+ Locations can be set by few ways:
+ - by geo coordinates (for example: 56.95,24.0833)
+ - by location name (for example: Riga)
+ - by location ID. Link to the list of city ID: http://bulk.openweathermap.org/sample/city.list.json.gz
+ - by zip/post code with a country code (for example: 94040,us)
+ A few locations can be added to the macro at the same time by "|" delimiter.
+ For example: 43.81821,7.76115|Riga|2643743|94040,us.
+ Please note that API requests by city name, zip-codes and city id will be deprecated soon.
+
+ Language and units macros can be customized too if necessary.
+ List of available languages: https://openweathermap.org/current#multi.
+ Available units of measurement are: standard, metric and imperial https://openweathermap.org/current#data.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','8098b3c157ab456abd55d3840eef79c1','OPENWEATHERMAP BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+1. Create a host.
+
+2. Link the template to the host.
+
+3. Customize the values of `Token` and `Location` host wizard configuration fields.
+ OpenWeatherMap API Tokens are available in your OpenWeatherMap account https://home.openweathermap.org/api_keys.
+ Locations can be set by few ways:
+ - by geo coordinates (for example: 56.95,24.0833)
+ - by location name (for example: Riga)
+ - by location ID. Link to the list of city ID: http://bulk.openweathermap.org/sample/city.list.json.gz
+ - by zip/post code with a country code (for example: 94040,us)
+ A few locations can be added to the host wizard configuration field at the same time by `|` delimiter.
+ For example: `43.81821,7.76115|Riga|2643743|94040,us`.
+ Please note that API requests by city name, zip-codes and city id will be deprecated soon.
+
+ Language and units host wizard configuration fields can be customized too if necessary.
+ List of available languages: https://openweathermap.org/current#multi.
+ Available units of measurement are: standard, metric and imperial https://openweathermap.org/current#data.'),
+('10517',NULL,'Proxmox VE by HTTP','3','-1','2','','','Proxmox VE by HTTP','0',NULL,'Proxmox VE is a complete open-source platform for enterprise virtualization.
+It tightly integrates two virtualization technologies: KVM for virtual machines
+and LXC for containers, on a single platform.
+This template is designed for the effortless deployment of Proxmox VE monitoring by Zabbix via HTTP and doesn''t require any external scripts.
+
+Proxmox VE uses a REST like API. The concept is described in Resource Oriented Architecture (ROA).
+
+Check the API documentation for details:
+https://pve.proxmox.com/pve-docs/api-viewer/index.html
+
+Setup:
+
+1. Create an API token for the monitoring user. Important note: for security reasons, it is recommended to create a separate user (Datacenter - Permissions).
+
+Please provide the necessary access levels for both the User and the Token:
+
+* /cluster/resources
+* /cluster/status
+* /access/users
+* /nodes
+* /nodes/{#NODE.NAME}/apt/update
+* /nodes/{#NODE.NAME}/certificates/info
+* /nodes/{#NODE.NAME}/disks/list
+* /nodes/{#NODE.NAME}/disks/smart?disk={#DISK.NAME}
+* /nodes/{#NODE.NAME}/hardware/pci
+* /nodes/{#NODE.NAME}/hardware/usb
+* /nodes/{#NODE.NAME}/lxc
+* /nodes/{#NODE.NAME}/lxc/{#LXC.VMID}/status/current
+* /nodes/{#NODE.NAME}/qemu
+* /nodes/{#NODE.NAME}/qemu/{#QEMU.VMID}/agent/get-fsinfo
+* /nodes/{#NODE.NAME}/qemu/{#QEMU.VMID}/agent/get-osinfo
+* /nodes/{#NODE.NAME}/qemu/{#QEMU.VMID}/agent/get-time
+* /nodes/{#NODE.NAME}/qemu/{#QEMU.VMID}/agent/get-timezone
+* /nodes/{#NODE.NAME}/qemu/{#QEMU.VMID}/agent/info
+* /nodes/{#NODE.NAME}/qemu/{#QEMU.VMID}/agent/network-get-interfaces
+* /nodes/{#NODE.NAME}/qemu/{#QEMU.VMID}/status/current
+* /nodes/{#NODE.NAME}/storage
+* /nodes/{#NODE.NAME}/time
+* /nodes/{#NODE.NAME}/version
+
+2. Copy the resulting Token ID and Secret into the host macros ''{$PVE.TOKEN.ID}'' and ''{$PVE.TOKEN.SECRET}''.
+
+3. Set the hostname or IP address of the Proxmox VE API host in the ''{$PVE.URL.HOST}'' macro. You can also change the API port in the ''{$PVE.URL.PORT}'' macro if necessary.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','4958b76448d74ff1b6d7d6280449beee','PROXMOX VE BY HTTP','Zabbix','8.0-3',NULL,'0','1','## Overview
+
+Proxmox VE is a complete open-source platform for enterprise virtualization.
+It tightly integrates two virtualization technologies: KVM for virtual machines
+and LXC for containers, on a single platform.
+
+## Setup
+
+To use this template, you need to have a Proxmox VE server set up and accessible via HTTP.
+Ensure that you have the necessary API access configured on your Proxmox VE server.
+Check the [`API documentation`](https://pve.proxmox.com/pve-docs/api-viewer/index.html) for details.
+
+1. Create an API token for the monitoring user. Important note: for security reasons, it is recommended to create a separate user (Datacenter - Permissions).
+
+Please provide the necessary access levels for both the User and the Token:
+
+ * /cluster/resources
+ * /cluster/status
+ * /access/users
+ * /nodes
+ * /nodes/{#NODE.NAME}/apt/update
+ * /nodes/{#NODE.NAME}/certificates/info
+ * /nodes/{#NODE.NAME}/disks/list
+ * /nodes/{#NODE.NAME}/disks/smart?disk={#DISK.NAME}
+ * /nodes/{#NODE.NAME}/hardware/pci
+ * /nodes/{#NODE.NAME}/hardware/usb
+ * /nodes/{#NODE.NAME}/lxc
+ * /nodes/{#NODE.NAME}/lxc/{#LXC.VMID}/status/current
+ * /nodes/{#NODE.NAME}/qemu
+ * /nodes/{#NODE.NAME}/qemu/{#QEMU.VMID}/agent/get-fsinfo
+ * /nodes/{#NODE.NAME}/qemu/{#QEMU.VMID}/agent/get-osinfo
+ * /nodes/{#NODE.NAME}/qemu/{#QEMU.VMID}/agent/get-time
+ * /nodes/{#NODE.NAME}/qemu/{#QEMU.VMID}/agent/get-timezone
+ * /nodes/{#NODE.NAME}/qemu/{#QEMU.VMID}/agent/info
+ * /nodes/{#NODE.NAME}/qemu/{#QEMU.VMID}/agent/network-get-interfaces
+ * /nodes/{#NODE.NAME}/qemu/{#QEMU.VMID}/status/current
+ * /nodes/{#NODE.NAME}/storage
+ * /nodes/{#NODE.NAME}/time
+ * /nodes/{#NODE.NAME}/version
+
+2. Copy the resulting Token ID and Secret into `Proxmox VE API Token ID` and `Proxmox VE API Token Secret`.
+
+3. Set the hostname or IP address of the Proxmox API VE host in the `Proxmox VE Host`. You can also change the API port in the `Proxmox VE Port` if necessary.'),
+('10518',NULL,'TrueNAS CORE by SNMP','3','-1','2','','','TrueNAS CORE by SNMP','0',NULL,'Template for monitoring TrueNAS CORE by SNMP.
+
+Setup:
+1. Import the template into Zabbix.
+2. Enable SNMP daemon at Services in TrueNAS CORE web interface: https://www.truenas.com/docs/core/uireference/services/snmpscreen/
+3. Link the template to the host.
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+UCD-DISKIO-MIB
+UCD-SNMP-MIB
+FREENAS-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','28e31ef9402d4c1ba2fbc730a288d2d8','TRUENAS CORE BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+Template for monitoring TrueNAS CORE by SNMP.
+
+## Setup
+
+1. Import the template into Zabbix.
+2. Enable SNMP daemon at Services in TrueNAS CORE web interface: https://www.truenas.com/docs/core/uireference/services/snmpscreen/
+3. Link the template to the host.'),
+('10519',NULL,'CockroachDB by HTTP','3','-1','2','','','CockroachDB by HTTP','0',NULL,'The template to monitor CockroachDB nodes by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template collects metrics by HTTP agent from Prometheus endpoint and health endpoints.
+
+Internal node metrics are collected from Prometheus /_status/vars endpoint.
+Node health metrics are collected from /health and /health?ready=1 endpoints.
+The template doesn''t require usage of session token.
+
+Note, that some metrics may not be collected depending on your CockroachDB version and configuration.
+
+Setup:
+
+Set the hostname or IP address of the CockroachDB node host in the ''{$COCKROACHDB.API.HOST}'' macro. You can also change the port in the ''{$COCKROACHDB.API.PORT}'' macro and the scheme in the ''{$COCKROACHDB.API.SCHEME}'' macro if necessary.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','36116d8675da47b8a678193969d5a787','COCKROACHDB BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor CockroachDB nodes by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template collects metrics by HTTP agent from Prometheus endpoint and health endpoints.
+
+Internal node metrics are collected from Prometheus /_status/vars endpoint.
+Node health metrics are collected from /health and /health?ready=1 endpoints.
+The template doesn''t require usage of session token.
+
+**Note**, that some metrics may not be collected depending on your CockroachDB version and configuration.
+
+## Setup
+
+Set the hostname or IP address of the CockroachDB node host in the `CockroachDB host` host wizard configuration field. You can also change the port in the `CockroachDB port` and the scheme in the `Request scheme` if necessary.'),
+('10520',NULL,'Envoy Proxy by HTTP','3','-1','2','','','Envoy Proxy by HTTP','0',NULL,'Get Envoy Proxy metrics by HTTP agent from metrics endpoint.
+https://www.envoyproxy.io/docs/envoy/v1.20.0/operations/stats_overview
+
+Don''t forget to change macros {$ENVOY.URL}, {$ENVOY.METRICS.PATH}.
+Some metrics may not be collected depending on your Envoy Proxy instance version and configuration.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','0368ca599bbb49729587b9c43ac83084','ENVOY PROXY BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor Envoy Proxy by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+Template `Envoy Proxy by HTTP` - collects metrics by HTTP agent from metrics endpoint `Metrics scrape path` endpoint (default: /stats/prometheus).
+
+## Setup
+
+Internal service metrics are collected from `Metrics scrape path` endpoint (default: /stats/prometheus).
+https://www.envoyproxy.io/docs/envoy/v1.20.0/operations/stats_overview
+
+Don''t forget to change host wizard configuration fields `Instance URL`, `Metrics scrape path`.
+
+*NOTE.* Some metrics may not be collected depending on your Envoy Proxy instance version and configuration.'),
+('10521',NULL,'HashiCorp Consul Node by HTTP','3','-1','2','','','HashiCorp Consul Node by HTTP','0',NULL,'Get HashiCorp Consul Node metrics by HTTP agent from metrics endpoint.
+
+Don''t forget to change macros {$CONSUL.NODE.API.URL}, {$CONSUL.TOKEN}.
+Some metrics may not be collected depending on your HashiCorp Consul instance version and configuration.
+More information about metrics you can find in official documentation: https://www.consul.io/docs/agent/telemetry
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','884bdbeea93c4be0a11a2c92a5f8adce','HASHICORP CONSUL NODE BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor HashiCorp Consul by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+Do not forget to enable Prometheus format for export metrics.
+See [documentation](https://www.consul.io/docs/agent/options#telemetry-prometheus_retention_time).
+More information about metrics you can find in [official documentation](https://www.consul.io/docs/agent/telemetry).
+
+Template `HashiCorp Consul Node by HTTP` — collects metrics by HTTP agent from /v1/agent/metrics endpoint.
+
+## Setup
+
+Internal service metrics are collected from /v1/agent/metrics endpoint.
+Do not forget to enable Prometheus format for export metrics. See [documentation](https://www.consul.io/docs/agent/options#telemetry-prometheus_retention_time).
+Template need to use Authorization via API token.
+
+Don''t forget to change host wizard configuration field `Address`, `Token`.
+
+More information about metrics you can find in [official documentation](https://www.consul.io/docs/agent/telemetry).
+
+This template support [Consul namespaces](https://www.consul.io/docs/enterprise/namespaces). You can set host wizard configuration field {$CONSUL.LLD.FILTER.SERVICE_NAMESPACE.MATCHES}, {$CONSUL.LLD.FILTER.SERVICE_NAMESPACE.NOT_MATCHES} if you want to filter discovered services by namespace.
+In case of Open Source version service namespace will be set to ''None''.
+
+*NOTE.* Some metrics may not be collected depending on your HashiCorp Consul instance version and configuration.
+*NOTE.* You maybe are interested in Envoy Proxy by HTTP [template](../../envoy_proxy_http).'),
+('10522',NULL,'HashiCorp Consul Cluster by HTTP','3','-1','2','','','HashiCorp Consul Cluster by HTTP','0',NULL,'Get HashiCorp Consul Cluster services and nodes by HTTP agent from API endpoints.
+
+Don''t forget to change macros {$CONSUL.CLUSTER.URL}, {$CONSUL.TOKEN}.
+Some metrics may not be collected depending on your HashiCorp Consul instance version and configuration.
+More information about metrics you can find in official documentation: https://www.consul.io/docs/agent/telemetry
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','3db29bb6b2b14fa289ba7915264efcdf','HASHICORP CONSUL CLUSTER BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor HashiCorp Consul by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+Template `HashiCorp Consul Cluster by HTTP` — collects metrics by HTTP agent from API endpoints.
+More information about metrics you can find in [official documentation](https://www.consul.io/docs/agent/telemetry).
+
+## Setup
+
+Template need to use Authorization via API token.
+
+Don''t forget to change host wizard configuration field `Address`, `Token`.
+
+This template support [Consul namespaces](https://www.consul.io/docs/enterprise/namespaces). You can set host wizard configuration field `Consul service namespace`, if you are interested in only one service namespace. Do not specify this host wizard configuration field to get all of services.
+In case of Open Source version leave this host wizard configuration field empty.
+
+*NOTE.* Some metrics may not be collected depending on your HashiCorp Consul instance version and configuration.
+*NOTE.* You maybe are interested in Envoy Proxy by HTTP [template](../../envoy_proxy_http).'),
+('10524',NULL,'HPE MSA 2040 Storage by HTTP','3','-1','2','','','HPE MSA 2040 Storage by HTTP','0',NULL,'The template to monitor HPE MSA 2040 by HTTP.
+It works without any external scripts and uses the script item.
+
+Setup:
+1. Create a user with a monitor role on the storage, for example "zabbix".
+2. Link the template to a host.
+3. Set the hostname or IP address of the host in the {$HPE.MSA.API.HOST} macro and configure the username and password in the {$HPE.MSA.API.USERNAME} and {$HPE.MSA.API.PASSWORD} macros.
+4. Change the {$HPE.MSA.API.SCHEME} and {$HPE.MSA.API.PORT} macros if needed.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','be10b1140fce4cc08247260b71bcd037','HPE MSA 2040 STORAGE BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor HPE MSA 2040 by HTTP.
+It works without any external scripts and uses the script item.
+
+## Setup
+
+1. Create a user with a monitor role on the storage, for example "zabbix".
+2. Link the template to a host.
+3. Set the hostname or IP address of the host in the `Address` and configure the username and password in the `Username` and `Password` host wizard configuration fields.
+4. Change the `Scheme` and `Port` if needed.'),
+('10525',NULL,'HPE MSA 2060 Storage by HTTP','3','-1','2','','','HPE MSA 2060 Storage by HTTP','0',NULL,'The template to monitor HPE MSA 2060 by HTTP.
+It works without any external scripts and uses the script item.
+
+Setup:
+1. Create a user with a monitor role on the storage, for example "zabbix".
+2. Link the template to a host.
+3. Set the hostname or IP address of the host in the {$HPE.MSA.API.HOST} macro and configure the username and password in the {$HPE.MSA.API.USERNAME} and {$HPE.MSA.API.PASSWORD} macros.
+4. Change the {$HPE.MSA.API.SCHEME} and {$HPE.MSA.API.PORT} macros if needed.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','10537641cfa3416ab0f1451cdb61d804','HPE MSA 2060 STORAGE BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor HPE MSA 2060 by HTTP.
+It works without any external scripts and uses the script item.
+
+## Setup
+
+1. Create a user with a monitor role on the storage, for example "zabbix".
+2. Link the template to a host.
+3. Set the hostname or IP address of the host in the `Address` and configure the username and password in the `Username` and `Password` host wizard configuration fields.
+4. Change the `Scheme` and `Port` if needed.'),
+('10526',NULL,'HPE Primera by HTTP','3','-1','2','','','HPE Primera by HTTP','0',NULL,'The template to monitor HPE Primera by HTTP.
+It works without any external scripts and uses the script item.
+
+Setup:
+ 1. Create a user on the storage with a browse role and enable it for all domains, for example "zabbix".
+ 2. The WSAPI server does not start automatically.
+ - Log in to the CLI as Super, Service, or any role granted the wsapi_set right.
+ - Start the WSAPI server by command: `startwsapi`.
+ - To check WSAPI state use command: `showwsapi`.
+ 3. Link template to the host.
+ 4. Set the hostname or IP address of the host in the {$HPE.PRIMERA.API.HOST} macro and configure the username and password in the {$HPE.PRIMERA.API.USERNAME} and {$HPE.PRIMERA.API.PASSWORD} macros.
+ 5. Change the {$HPE.PRIMERA.API.SCHEME} and {$HPE.PRIMERA.API.PORT} macros if needed.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','b8750c02b5624c6889979b129735bd56','HPE PRIMERA BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor HPE Primera by HTTP.
+It works without any external scripts and uses the script item.
+
+## Setup
+
+1. Create a user on the storage with a browse role and enable it for all domains, for example "zabbix".
+2. The WSAPI server does not start automatically.
+ Log in to the CLI as Super, Service, or any role granted the wsapi_set right.
+ Start the WSAPI server by command: `startwsapi`.
+ To check WSAPI state use command: `showwsapi`.
+3. Link template to the host.
+3. Set the hostname or IP address of the host in the `Address` and configure the username and password in the `Username` and `Password` host wizard configuration fields.
+4. Change the `Scheme` and `Port` if needed.'),
+('10527',NULL,'AWS EC2 by HTTP','3','-1','2','','','AWS EC2 by HTTP','0',NULL,'Get AWS EC2 and attached AWS EBS volumes metrics and uses the script item to make HTTP requests to the CloudWatch API.
+Don''t forget to read the README.md for the correct setup of the template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','7af6d68b223a43d4bf8526cc5dc3fe2e','AWS EC2 BY HTTP','Zabbix','8.0-3',NULL,'0','1','## Overview
+
+The template to monitor AWS EC2 and attached AWS EBS volumes by HTTP via Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+**Note:** This template uses the GetMetricData CloudWatch API calls to list and retrieve metrics.
+For more information, please refer to the [CloudWatch pricing](https://aws.amazon.com/cloudwatch/pricing/) page.
+
+Additional information about metrics and used API methods:
+* [Full metrics list related to EBS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using_cloudwatch_ebs.html)
+* [Full metrics list related to EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html)
+* [DescribeAlarms API method](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)
+* [DescribeVolumes API method](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVolumes.html)
+
+
+## Setup
+
+The template get AWS EC2 and attached AWS EBS volumes metrics and uses the script item to make HTTP requests to the CloudWatch API.
+Before using the template, you need to create an IAM policy with the necessary permissions for the Zabbix role in your AWS account.
+
+### Required Permissions
+Add the following required permissions to your Zabbix IAM policy in order to collect Amazon EC2 metrics.
+
+```json
+{
+ "Version":"2012-10-17",
+ "Statement":[
+ {
+ "Action":[
+ "ec2:DescribeVolumes",
+ "cloudwatch:"DescribeAlarms",
+ "cloudwatch:GetMetricData"
+ ],
+ "Effect":"Allow",
+ "Resource":"*"
+ }
+ ]
+ }
+```
+
+### Access Key Authorization
+
+If you are using access key authorization, you need to generate an access key and secret key for an IAM user with the necessary permissions:
+
+1. Create an IAM user with programmatic access.
+2. Attach the required policy to the IAM user.
+3. Generate an access key and secret key.
+4. Use the generated credentials in the host wizard configuration fields `Access key ID` and `Secret access key`.
+
+### Assume Role Authorization
+For using assume role authorization, add the appropriate permissions to the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "sts:AssumeRole",
+ "Resource": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "ec2:DescribeVolumes",
+ "cloudwatch:"DescribeAlarms",
+ "cloudwatch:GetMetricData"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+#### Trust Relationships for Assume Role Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "AWS": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ "Action": "sts:AssumeRole"
+ }
+ ]
+}
+```
+Set the following fields: `Access key ID`, `Secret access key`, `STS Region`, `ARN assume role`.
+
+### Role-Based Authorization
+If you are using role-based authorization, set the appropriate permissions:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "iam:PassRole",
+ "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
+ },
+ {
+ "Sid": "VisualEditor1",
+ "Effect": "Allow",
+ "Action": [
+ "ec2:DescribeVolumes",
+ "cloudwatch:"DescribeAlarms",
+ "cloudwatch:GetMetricData"
+ "ec2:AssociateIamInstanceProfile",
+ "ec2:ReplaceIamInstanceProfileAssociation"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+#### Trust Relationships for Role-Based Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "Service": [
+ "ec2.amazonaws.com"
+ ]
+ },
+ "Action": [
+ "sts:AssumeRole"
+ ]
+ }
+ ]
+}
+```
+
+**Note**: Using role-based authorization is only possible when you use a Zabbix server or proxy inside AWS.
+
+For more information, see the [EC2 policies](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-iam.html) on the AWS website.
+
+Set the following fields: `Authorization method`, `AWS Region`, `EC2 instance ID`.
+
+For more information about managing access keys, see [official documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).'),
+('10528',NULL,'OPNsense by SNMP','3','-1','2','','','OPNsense by SNMP','0',NULL,'Template for monitoring OPNsense by SNMP
+Setup:
+ 1. Enable bsnmpd daemon by creating new config file "/etc/rc.conf.d/bsnmpd" with the following content:
+ bsnmpd_enable="YES"
+ 2. Uncomment the following lines in "/etc/snmpd.config" file to enable required SNMP modules:
+ begemotSnmpdModulePath."hostres" = "/usr/lib/snmp_hostres.so"
+ begemotSnmpdModulePath."pf" = "/usr/lib/snmp_pf.so"
+ 3. Start bsnmpd daemon with the following command:
+ /etc/rc.d/bsnmpd start
+ 4. Setup a firewall rule to get access from Zabbix proxy or Zabbix server by SNMP (https://docs.opnsense.org/manual/firewall.html).
+ 5. Link the template to a host.
+
+
+MIBs used:
+BEGEMOT-PF-MIB
+HOST-RESOURCES-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','0c94915edb4c41bf8c627dddb4f68f5a','OPNSENSE BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+Template for monitoring OPNsense by SNMP
+
+## Setup
+
+1. Enable bsnmpd daemon by creating new config file "/etc/rc.conf.d/bsnmpd" with the following content:
+bsnmpd_enable="YES"
+2. Uncomment the following lines in "/etc/snmpd.config" file to enable required SNMP modules:
+begemotSnmpdModulePath."hostres" = "/usr/lib/snmp_hostres.so"
+begemotSnmpdModulePath."pf" = "/usr/lib/snmp_pf.so"
+3. Start bsnmpd daemon with the following command:
+/etc/rc.d/bsnmpd start
+4. Setup a firewall rule to get access from Zabbix proxy or Zabbix server by SNMP (https://docs.opnsense.org/manual/firewall.html).
+5. Link the template to a host.'),
+('10529',NULL,'AWS RDS instance by HTTP','3','-1','2','','','AWS RDS instance by HTTP','0',NULL,'The template gets AWS RDS instance metrics and uses the script item to make HTTP requests to the CloudWatch API.
+Don''t forget to read the README.md for the correct setup of the template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','c6d9475847f44d9193f8253e5995b8f8','AWS RDS INSTANCE BY HTTP','Zabbix','8.0-3',NULL,'0','1','## Overview
+
+The template to monitor AWS RDS instance by HTTP via Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+**Note:** This template uses the GetMetricData CloudWatch API calls to list and retrieve metrics.
+For more information, please refer to the [CloudWatch pricing](https://aws.amazon.com/cloudwatch/pricing/) page.
+
+Additional information about metrics and used API methods:
+
+* [Full metrics list related to RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-metrics.html)
+* [Full metrics list related to Amazon Aurora](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.AuroraMySQL.Monitoring.Metrics.html#Aurora.AuroraMySQL.Monitoring.Metrics.instances)
+* [DescribeAlarms API method](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)
+
+
+## Setup
+
+The template get AWS RDS instance metrics and uses the script item to make HTTP requests to the CloudWatch API.
+Before using the template, you need to create an IAM policy with the necessary permissions for the Zabbix role in your AWS account.
+
+### Required Permissions
+Add the following required permissions to your Zabbix IAM policy in order to collect Amazon RDS metrics.
+
+```json
+{
+ "Version":"2012-10-17",
+ "Statement":[
+ {
+ "Action":[
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "rds:DescribeEvents",
+ "rds:DescribeDBInstances"
+ ],
+ "Effect":"Allow",
+ "Resource":"*"
+ }
+ ]
+ }
+```
+
+### Access Key Authorization
+
+If you are using access key authorization, you need to generate an access key and secret key for an IAM user with the necessary permissions:
+
+1. Create an IAM user with programmatic access.
+2. Attach the required policy to the IAM user.
+3. Generate an access key and secret key.
+4. Use the generated credentials in the host wizard configuration fields `Access key ID` and `Secret access key`.
+
+### Assume Role Authorization
+For using assume role authorization, add the appropriate permissions to the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "sts:AssumeRole",
+ "Resource": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "rds:DescribeEvents",
+ "rds:DescribeDBInstances"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+#### Trust Relationships for Assume Role Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "AWS": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ "Action": "sts:AssumeRole"
+ }
+ ]
+}
+```
+Set the following fields: `Access key ID`, `Secret access key`, `STS Region`, `ARN assume role`.
+
+### Role-Based Authorization
+If you are using role-based authorization, set the appropriate permissions:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "iam:PassRole",
+ "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
+ },
+ {
+ "Sid": "VisualEditor1",
+ "Effect": "Allow",
+ "Action": [
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "rds:DescribeEvents",
+ "rds:DescribeDBInstances",
+ "ec2:AssociateIamInstanceProfile",
+ "ec2:ReplaceIamInstanceProfileAssociation"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+#### Trust Relationships for Role-Based Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "Service": [
+ "ec2.amazonaws.com"
+ ]
+ },
+ "Action": [
+ "sts:AssumeRole"
+ ]
+ }
+ ]
+}
+```
+
+**Note**: Using role-based authorization is only possible when you use a Zabbix server or proxy inside AWS.
+
+Set the following fields: `Authorization method`, `AWS Region`, `RDS DB Instance identifier`.
+
+For more information about managing access keys, see [official documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).'),
+('10530',NULL,'AWS S3 bucket by HTTP','3','-1','2','','','AWS S3 bucket by HTTP','0',NULL,'The template gets AWS S3 bucket metrics and uses the script item to make HTTP requests to the CloudWatch API.
+Don''t forget to read the README.md for the correct setup of the template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','a14ab6b4e80643fe8daa9d7288658f79','AWS S3 BUCKET BY HTTP','Zabbix','8.0-3',NULL,'0','1','## Overview
+
+The template to monitor AWS S3 bucket by HTTP via Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+**Note:** This template uses the GetMetricData CloudWatch API calls to list and retrieve metrics.
+For more information, please refer to the [CloudWatch pricing](https://aws.amazon.com/cloudwatch/pricing/) page.
+
+Additional information about metrics and used API methods:
+
+* [Full metrics list related to S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/metrics-dimensions.html)
+* [DescribeAlarms API method](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)
+
+## Setup
+
+The template gets AWS S3 metrics and uses the script item to make HTTP requests to the CloudWatch API.
+Before using the template, you need to create an IAM policy for the Zabbix role in your AWS account with the necessary permissions.
+
+### Required Permissions
+Add the following required permissions to your Zabbix IAM policy in order to collect Amazon S3 metrics.
+
+```json
+{
+ "Version":"2012-10-17",
+ "Statement":[
+ {
+ "Action":[
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "s3:GetMetricsConfiguration"
+ ],
+ "Effect":"Allow",
+ "Resource":"*"
+ }
+ ]
+ }
+```
+
+### Access Key Authorization
+
+If you are using access key authorization, you need to generate an access key and secret key for an IAM user with the necessary permissions:
+
+1. Create an IAM user with programmatic access.
+2. Attach the required policy to the IAM user.
+3. Generate an access key and secret key.
+4. Use the generated credentials in the host wizard configuration fields `Access key ID` and `Secret access key`.
+
+### Assume role authorization
+For using assume role authorization, add the appropriate permissions to the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "sts:AssumeRole",
+ "Resource": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "s3:GetMetricsConfiguration"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+#### Trust Relationships for Assume Role Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "AWS": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ "Action": "sts:AssumeRole"
+ }
+ ]
+}
+```
+Set the following fields: `Access key ID`, `Secret access key`, `STS Region`, `ARN assume role`.
+
+### Role-Based Authorization
+If you are using role-based authorization, set the appropriate permissions:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "iam:PassRole",
+ "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
+ },
+ {
+ "Sid": "VisualEditor1",
+ "Effect": "Allow",
+ "Action": [
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "s3:GetMetricsConfiguration",
+ "ec2:AssociateIamInstanceProfile",
+ "ec2:ReplaceIamInstanceProfileAssociation"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+#### Trust Relationships for Role-Based Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "Service": [
+ "ec2.amazonaws.com"
+ ]
+ },
+ "Action": [
+ "sts:AssumeRole"
+ ]
+ }
+ ]
+}
+```
+
+**Note**: Using role-based authorization is only possible when you use a Zabbix server or proxy inside AWS.
+
+To gather Request metrics, [enable Requests metrics](https://docs.aws.amazon.com/AmazonS3/latest/userguide/cloudwatch-monitoring.html) on your Amazon S3 buckets from the AWS console.
+
+You can also define a filter for the Request metrics using a shared prefix, object tag, or access point.
+
+Set the following fields: `Authorization method`, `S3 bucket name`.
+
+For more information about managing access keys, see [official documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).'),
+('10531',NULL,'Azure by HTTP','3','-1','2','','','Azure by HTTP','0',NULL,'This template is designed to monitor Microsoft Azure by HTTP.
+It works without any external scripts and uses the script item.
+Currently the template supports the discovery of virtual machines (VMs), Cosmos DB for MongoDB, storage accounts, Microsoft SQL, MySQL, and PostgreSQL servers.
+
+Setup:
+ 1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+ See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
+ 2. Link the template to a host.
+ 3. Configure the macros: `{$AZURE.APP.ID}`, `{$AZURE.PASSWORD}`, `{$AZURE.TENANT.ID}`, and `{$AZURE.SUBSCRIPTION.ID}`.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','fa58228fee8a4e34a7c6503950d1c615','AZURE BY HTTP','Zabbix','8.0-3',NULL,'0','1','## Overview
+
+- This template is designed to monitor Microsoft Azure by HTTP.
+- It works without any external scripts and uses the script item.
+- Currently, the template supports the discovery of virtual machines (VMs), VM scale sets, Cosmos DB for MongoDB, storage accounts, Microsoft SQL, MySQL, and PostgreSQL servers.
+
+## Setup
+
+1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+
+> See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
+
+2. Link the template to a host.
+3. Configure the host wizard configuration fields: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`.'),
+('10532',NULL,'Azure Virtual Machine by HTTP','3','-1','2','','','Azure Virtual Machine by HTTP','0',NULL,'This template is designed to monitor Microsoft Azure virtual machines (VMs) by HTTP.
+It works without any external scripts and uses the script item.
+
+Setup:
+ 1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+ See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
+ 2. Link the template to a host.
+ 3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','820fa4a1565c43e4aac07a691a5bface','AZURE VIRTUAL MACHINE BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is designed to monitor Microsoft Azure virtual machines (VMs) by HTTP.
+It works without any external scripts and uses the script item.
+
+## Setup
+
+1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+
+> See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
+
+2. Link the template to a host.
+3. Configure the host wizard configuration fields: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure virtual machine ID`.'),
+('10534',NULL,'HPE Synergy by HTTP','3','-1','2','','','HPE Synergy by HTTP','0',NULL,'This template is designed to monitor HPE Synergy by HTTP.
+It works without any external scripts and uses the script item.
+
+Setup:
+ 1. Link template to the host.
+ 2. Set the hostname or IP address of the host in the {$HPE.SYNERGY.API.HOST} macro and configure the username and password in the {$HPE.SYNERGY.API.USERNAME} and {$HPE.SYNERGY.API.PASSWORD} macros.
+ 3. Change the {$HPE.SYNERGY.API.SCHEME} and {$HPE.SYNERGY.API.PORT} macros if needed.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','0ffde4421f524bcbac2f47fec87c0f95','HPE SYNERGY BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+The template to monitor HPE Synergy by HTTP.
+It works without any external scripts and uses the script item.
+
+## Setup
+
+1. Link template to the host.
+2. Set the hostname or IP address of the host in the `API host` and configure the username and password in the `API username` and `API password` host wizard configuration fields.
+3. Change the `API scheme` and `API port` host wizard configuration fields if needed.'),
+('10535',NULL,'AWS by HTTP','3','-1','2','','','AWS by HTTP','0',NULL,'Get AWS EC2, RDS and S3 instances, AWS ECS clusters, AWS Elastic Load Balancing, Backup vaults. Don''t forget to read the README.md for the correct setup of the template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','c60e5929ab474f67bbe67dc6b04e709d','AWS BY HTTP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+This template is designed for the effortless deployment of AWS monitoring by Zabbix via HTTP and doesn''t require any external scripts.
+- Currently, the template supports the discovery of EC2 and RDS instances, ECS clusters, ELB, Lambda, S3 buckets and Backup vaults.
+
+## Setup
+
+Before using the template, you need to create an IAM policy for the Zabbix role in your AWS account with the necessary permissions.
+
+### Required Permissions
+Add the following required permissions to your Zabbix IAM policy in order to collect metrics.
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Action": [
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "ec2:DescribeInstances",
+ "ec2:DescribeVolumes",
+ "ec2:DescribeRegions",
+ "rds:DescribeEvents",
+ "rds:DescribeDBInstances",
+ "ecs:DescribeClusters",
+ "ecs:ListServices",
+ "ecs:ListTasks",
+ "ecs:ListClusters",
+ "s3:ListAllMyBuckets",
+ "s3:GetBucketLocation",
+ "s3:GetMetricsConfiguration",
+ "elasticloadbalancing:DescribeLoadBalancers",
+ "elasticloadbalancing:DescribeTargetGroups",
+ "ec2:DescribeSecurityGroups",
+ "lambda:ListFunctions",
+ "backup:ListBackupVaults",
+ "backup:ListBackupJobs",
+ "backup:ListCopyJobs",
+ "backup:ListRestoreJobs"
+ ],
+ "Effect": "Allow",
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+### Access Key Authorization
+
+If you are using access key authorization, you need to generate an access key and secret key for an IAM user with the necessary permissions:
+
+1. Create an IAM user with programmatic access.
+2. Attach the required policy to the IAM user.
+3. Generate an access key and secret key.
+4. Use the generated credentials in `Access key ID` and `Secret access key`.
+
+### Assume Role Authorization
+For using assume role authorization, add the appropriate permissions to the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "sts:AssumeRole",
+ "Resource": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "ec2:DescribeInstances",
+ "ec2:DescribeVolumes",
+ "ec2:DescribeRegions",
+ "rds:DescribeEvents",
+ "rds:DescribeDBInstances",
+ "ecs:DescribeClusters",
+ "ecs:ListServices",
+ "ecs:ListTasks",
+ "ecs:ListClusters",
+ "s3:ListAllMyBuckets",
+ "s3:GetBucketLocation",
+ "s3:GetMetricsConfiguration",
+ "ec2:AssociateIamInstanceProfile",
+ "ec2:ReplaceIamInstanceProfileAssociation",
+ "elasticloadbalancing:DescribeLoadBalancers",
+ "elasticloadbalancing:DescribeTargetGroups",
+ "ec2:DescribeSecurityGroups",
+ "lambda:ListFunctions",
+ "backup:ListBackupVaults",
+ "backup:ListBackupJobs",
+ "backup:ListCopyJobs",
+ "backup:ListRestoreJobs"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+#### Trust Relationships for Assume Role Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "AWS": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ "Action": "sts:AssumeRole"
+ }
+ ]
+}
+```
+Set the following fields: `Access key ID`, `Secret access key`, `STS Region`, `ARN assume role`.
+
+### Role-Based Authorization
+If you are using role-based authorization, add the appropriate permissions:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "iam:PassRole",
+ "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "ec2:DescribeInstances",
+ "ec2:DescribeVolumes",
+ "ec2:DescribeRegions",
+ "rds:DescribeEvents",
+ "rds:DescribeDBInstances",
+ "ecs:DescribeClusters",
+ "ecs:ListServices",
+ "ecs:ListTasks",
+ "ecs:ListClusters",
+ "s3:ListAllMyBuckets",
+ "s3:GetBucketLocation",
+ "s3:GetMetricsConfiguration",
+ "ec2:AssociateIamInstanceProfile",
+ "ec2:ReplaceIamInstanceProfileAssociation",
+ "elasticloadbalancing:DescribeLoadBalancers",
+ "elasticloadbalancing:DescribeTargetGroups",
+ "ec2:DescribeSecurityGroups",
+ "lambda:ListFunctions",
+ "backup:ListBackupVaults",
+ "backup:ListBackupJobs",
+ "backup:ListCopyJobs",
+ "backup:ListRestoreJobs"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+#### Trust Relationships for Role-Based Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "Service": [
+ "ec2.amazonaws.com"
+ ]
+ },
+ "Action": [
+ "sts:AssumeRole"
+ ]
+ }
+ ]
+}
+```
+
+**Note**: Using role-based authorization is only possible when you use a Zabbix server or proxy inside AWS.
+
+To gather Request metrics, enable [Requests metrics](https://docs.aws.amazon.com/AmazonS3/latest/userguide/cloudwatch-monitoring.html) on your Amazon S3 buckets from the AWS console.
+
+Choose a method of authorization (field of `Authorization method`).
+
+For more information about managing access keys, see [official documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).
+
+Additional information about the metrics and used API methods:
+* [Full metrics list related to EBS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using_cloudwatch_ebs.html)
+* [Full metrics list related to EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html)
+* [Full metrics list related to RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-metrics.html)
+* [Full metrics list related to Amazon Aurora](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.AuroraMySQL.Monitoring.Metrics.html#Aurora.AuroraMySQL.Monitoring.Metrics.instances)
+* [Full metrics list related to S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/metrics-dimensions.html)
+* [Full metrics list related to ECS](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cloudwatch-metrics.html)
+* [Full metrics list related to ELB ALB](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html)
+* [Full metrics list related to Backup vault](https://docs.aws.amazon.com/aws-backup/latest/devguide/API_BackupVaultListMember.html)
+* [Full metrics list related to Backup jobs](https://docs.aws.amazon.com/aws-backup/latest/devguide/API_BackupJob.html)
+* [DescribeAlarms API method](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)
+* [DescribeVolumes API method](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVolumes.html)
+* [DescribeLoadBalancers API method](https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_DescribeLoadBalancers.html)'),
+('10539',NULL,'Azure MySQL Flexible Server by HTTP','3','-1','2','','','Azure MySQL Flexible Server by HTTP','0',NULL,'This template is designed to monitor Microsoft Azure MySQL flexible servers by HTTP.
+It works without any external scripts and uses the script item.
+
+Setup:
+ 1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+ See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
+ 2. Link the template to a host.
+ 3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','ec92c7b0b1d14946b6ac61de89357199','AZURE MYSQL FLEXIBLE SERVER BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is designed to monitor Microsoft Azure MySQL flexible servers by HTTP.
+It works without any external scripts and uses the script item.
+
+## Setup
+
+1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+
+> See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
+
+2. Link the template to a host.
+3. Configure the host wizard configuration fields: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure MySQL server ID`.'),
+('10540',NULL,'Azure MySQL Single Server by HTTP','3','-1','2','','','Azure MySQL Single Server by HTTP','0',NULL,'This template is designed to monitor Microsoft Azure MySQL single servers by HTTP.
+It works without any external scripts and uses the script item.
+
+Setup:
+ 1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+ See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
+ 2. Link the template to a host.
+ 3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','c1396bf1e8cf46f6a407e88ddceef0b8','AZURE MYSQL SINGLE SERVER BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is designed to monitor Microsoft Azure MySQL single servers by HTTP.
+It works without any external scripts and uses the script item.
+
+## Setup
+
+1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+
+> See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
+
+2. Link the template to a host.
+3. Configure the host wizard configuration fields: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure MySQL server ID`.'),
+('10543',NULL,'Azure PostgreSQL Flexible Server by HTTP','3','-1','2','','','Azure PostgreSQL Flexible Server by HTTP','0',NULL,'This template is designed to monitor Microsoft Azure PostgreSQL flexible servers by HTTP.
+It works without any external scripts and uses the script item.
+
+Setup:
+ 1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+ See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
+ 2. Link the template to a host.
+ 3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','35ef29f24158444097272d2ea7fa6044','AZURE POSTGRESQL FLEXIBLE SERVER BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is designed to monitor Microsoft Azure PostgreSQL flexible servers by HTTP.
+It works without any external scripts and uses the script item.
+
+## Setup
+
+1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+
+> See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
+
+2. Link the template to a host.
+3. Configure the host wizard configuration fields: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure PostgreSQL server ID`.'),
+('10544',NULL,'Azure PostgreSQL Single Server by HTTP','3','-1','2','','','Azure PostgreSQL Single Server by HTTP','0',NULL,'This template is designed to monitor Microsoft Azure PostgreSQL servers by HTTP.
+It works without any external scripts and uses the script item.
+
+Setup:
+ 1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+ See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
+ 2. Link the template to a host.
+ 3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','d023e2cd326c486f908e3e361d1fe157','AZURE POSTGRESQL SINGLE SERVER BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is designed to monitor Microsoft Azure PostgreSQL servers by HTTP.
+It works without any external scripts and uses the script item.
+
+## Setup
+
+1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+
+> See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
+
+2. Link the template to a host.
+3. Configure the host wizard configuration fields: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure PostgreSQL server ID`.'),
+('10546',NULL,'Cisco Meraki dashboard by HTTP','3','-1','2','','','Cisco Meraki dashboard by HTTP','0',NULL,'Template for monitoring Cisco Meraki dashboard https://meraki.cisco.com/products/meraki-dashboard/
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','2fca6b60914b4fa98132b1a7885ab014','CISCO MERAKI DASHBOARD BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+You must set `Meraki API token` and `Meraki API URL` host wizard configuration fields.
+
+Create the token in the Meraki dashboard (see Meraki [documentation](https://developer.cisco.com/meraki/api-latest/#!authorization/authorization) for instructions). Set this token as `Meraki API token` host wizard configuration field value in Zabbix.
+
+Set your Meraki dashboard URL as `Meraki API URL` host wizard configuration field value in Zabbix (e.g., api.meraki.com/api/v1).
+
+Set filters with host wizard configuration fields if you want to override default filter parameters.'),
+('10547',NULL,'Cisco Meraki device by HTTP','3','-1','2','','','Cisco Meraki device by HTTP','0',NULL,'Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','2cae7d2eeca04e6fa7419759ac9ad814','CISCO MERAKI DEVICE BY HTTP','Zabbix','8.0-4',NULL,'0','1','## Setup
+
+This template is used in low-level discovery and will be auto-assigned to host prototypes. Additional configuration is not required.'),
+('10548',NULL,'Cisco Meraki organization by HTTP','3','-1','2','','','Cisco Meraki organization by HTTP','0',NULL,'Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','39e2f742d0b24ea489b7f61d27a5df1c','CISCO MERAKI ORGANIZATION BY HTTP','Zabbix','8.0-3',NULL,'0','1','## Setup
+
+This template is used in low-level discovery and will be auto-assigned to host prototypes. Additional configuration is not required.'),
+('10551',NULL,'Cisco Nexus 9000 Series by SNMP','3','-1','2','','','Cisco Nexus 9000 Series by SNMP','0',NULL,'Template Cisco Nexus 9000 Series
+
+ MIBs used:
+ CISCO-ENHANCED-MEMPOOL-MIB
+ CISCO-ENTITY-FRU-CONTROL-MIB
+ CISCO-ENTITY-SENSOR-MIB
+ CISCO-PROCESS-MIB
+ ENTITY-MIB
+ EtherLike-MIB
+ IF-MIB
+ SNMPv2-MIB
+ SNMP-FRAMEWORK-MIB
+ CISCO-IMAGE-MIB
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/418396-discussion-thread-for-official-zabbix-templates-for-cisco
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','80fc469750f84061924662a98c33580c','CISCO NEXUS 9000 SERIES BY SNMP','Zabbix','8.0-3',NULL,'0','1','## Overview
+
+This template is designed to monitor `Cisco Nexus 9000 Series Switches`.
+> See [Cisco support documentation](https://www.cisco.com/c/en/us/support/switches/nexus-9000-series-switches/series.html) for details.
+
+## Setup
+
+> Refer to the [vendor documentation](https://www.cisco.com/c/en/us/support/switches/nexus-9000-series-switches/products-installation-and-configuration-guides-list.html) for details.'),
+('10552',NULL,'Control-M enterprise manager by HTTP','3','-1','2','','','Control-M enterprise manager by HTTP','0',NULL,'This template is designed to get metrics from the Control-M Enterprise Manager using the Control-M Automation API with HTTP agent.
+
+This template monitors active Service Level Agreement (SLA) services, discovers Control-M servers using Low Level Discovery and also creates host prototypes for them in conjunction with the `Control-M server by HTTP` template.
+
+To use this template, macros `{$API.TOKEN}` and `{$API.URI.ENDPOINT}` need to be set.
+
+> See [Zabbix template operation](https://www.zabbix.com/documentation/8.0/manual/config/templates_out_of_the_box/http) for basic instructions.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','24b64f6d22b446dabecc86ee3f199004','CONTROL-M ENTERPRISE MANAGER BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+The template to monitor Control-M by Zabbix that work without any external scripts.
+
+
+## Setup
+
+This template is intended to be used on Control-M Enterprise Manager instances.
+
+It monitors:
+* active SLA services;
+* discovers Control-M servers using Low Level Discovery;
+* creates host prototypes for discovered servers with the `Control-M server by HTTP` template.
+
+To use this template, you must set host wizard configuration fields: **API token** and **API endpoint URL**.
+
+To access the API token, use one of the following Control-M interfaces:
+
+> [Control-M WEB user interface](https://documents.bmc.com/supportu/controlm-saas/en-US/Documentation/Creating_an_API_Token.htm);
+
+> [Control-M command line interface tool CTM](https://docs.bmc.com/docs/saas-api/authentication-service-941879068.html).
+
+`API endpoint URL` - is the Control-M Automation API endpoint for the API requests, including your server IP, or DNS address, Automation API port and path.
+
+For example, `https://monitored.controlm.instance:8443/automation-api`.'),
+('10553',NULL,'Control-M server by HTTP','3','-1','2','','','Control-M server by HTTP','0',NULL,'This template is designed to get metrics from the Control-M server using the Control-M Automation API with HTTP agent.
+
+This template monitors server statistics, discovers jobs and agents using Low Level Discovery.
+
+To use this template, macros `{$API.TOKEN}`, `{$API.URI.ENDPOINT}`, and `{$SERVER.NAME}` need to be set.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','c077d6c381904e94a4df88136588b551','CONTROL-M SERVER BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed to get metrics from the Control-M server using the Control-M Automation API with HTTP agent.
+
+This template monitors server statistics, discovers jobs and agents using Low Level Discovery.
+
+To use this template, host wizard configuration field `API token`, `API endpoint URL`, and `Server name` need to be set.
+
+
+## Setup
+
+This template is primarily intended for using in conjunction with the `Control-M enterprise manager by HTTP` template in order to create host prototypes.
+
+It monitors:
+* server statistics;
+* discovers jobs using Low Level Discovery;
+* discovers agents using Low Level Discovery.
+
+However, if you wish to monitor the Control-M server separately with this template, you must set the following host wizard configuration field: **API token**, **API endpoint URL**, and **Server name**.
+
+To access the `API token` host wizard configuration field, use one of the following interfaces:
+
+> [Control-M WEB user interface](https://documents.bmc.com/supportu/controlm-saas/en-US/Documentation/Creating_an_API_Token.htm);
+
+> [Control-M command line interface tool CTM](https://docs.bmc.com/docs/saas-api/authentication-service-941879068.html).
+
+`API endpoint URL` - is the Control-M Automation API endpoint for the API requests, including your server IP, or DNS address, the Automation API port and path.
+
+For example, `https://monitored.controlm.instance:8443/automation-api`.
+
+`Server name` - is the name of the Control-M server to be monitored.'),
+('10555',NULL,'Veeam Backup and Replication by HTTP','3','-1','2','','','Veeam Backup and Replication by HTTP','0',NULL,'This template is designed to monitor Veeam Backup and Replication.
+
+NOTE: The RESTful API may not be available for some editions, see (https://www.veeam.com/licensing-pricing.html) for more details.
+
+Setup:
+ 1. Create a user to monitor the service or use an existing read-only account.
+ See (https://helpcenter.veeam.com/docs/backup/vbr_rest/reference/vbr-rest-v1-rev2.html?ver=110#tag/Login/operation/CreateToken!path=grant_type&t=request) for more details.
+ 2. Link the template to a host.
+ 3. Configure the following macros: {$VEEAM.API.URL}, {$VEEAM.USER}, and {$VEEAM.PASSWORD}.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','738085dde4e749d49199e5e6fd4d56ab','VEEAM BACKUP AND REPLICATION BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed to monitor Veeam Backup and Replication.
+It works without any external scripts and uses the script item.
+
+***NOTE:*** Since the RESTful API may not be available for some editions, the template will only work with the following editions of Veeam Backup and Replication:
+
+1. Veeam Universal License (VUL) editions:
+* Foundation
+* Advanced
+* Premium
+
+2. Veeam Socket License editions:
+* Enterprise Plus Socket
+
+> See [Veeam Data Platform Feature Comparison](https://www.veeam.com/licensing-pricing.html) for more details.
+
+## Setup
+
+1. Create a user to monitor the service or use an existing read-only account.
+> See [Veeam Help Center](https://helpcenter.veeam.com/docs/backup/vbr_rest/reference/vbr-rest-v1-rev2.html?ver=110#tag/Login/operation/CreateToken!path=grant_type&t=request) for more details.
+2. Link the template to a host.
+3. Configure the following host wizard configuration fields: `Address`, `Username`, and `Password`.'),
+('10556',NULL,'Veeam Backup Enterprise Manager by HTTP','3','-1','2','','','Veeam Backup Enterprise Manager by HTTP','0',NULL,'This template is designed to monitor Veeam Backup Enterprise Manager.
+
+NOTE: The REST API may not be available for some editions, see (https://www.veeam.com/licensing-pricing.html) for more details.
+
+Setup:
+ 1. Create a user to monitor the service, or use an existing read-only account.
+ Similarly to the user authentication in the Veeam Backup Enterprise Manager Web UI,
+ the client authentication in the REST API dictates which operations a client is allowed to perform when working with the REST API.
+ That is, if the client is authenticated using an account that does not have enough permissions to perform some actions, it will not be able to execute them.
+ You can also obtain the collected jobs if you are logged in under an account having only `Portal Administrator` role.
+ See (https://helpcenter.veeam.com/docs/backup/em_rest/http_authentication.html?ver=110) for more details.
+ 2. Link the template to a host.
+ 3. Configure the following macros: {$VEEAM.MANAGER.API.URL}, {$VEEAM.MANAGER.USER}, {$VEEAM.MANAGER.PASSWORD}.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','2ce384bafd524db5b910d7f55bca1fbb','VEEAM BACKUP ENTERPRISE MANAGER BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+It works without any external scripts and uses the script item.
+
+***NOTE:*** Veeam Backup Enterprise Manager REST API may not be available for some editions, the template will only work with the following editions of Veeam Backup and Replication:
+
+1. Veeam Universal License (VUL) editions:
+* Foundation
+* Advanced
+* Premium
+
+2. Veeam Socket License editions:
+* Enterprise Socket
+* Enterprise Plus Socket
+
+> See [Veeam Data Platform Feature Comparison](https://www.veeam.com/licensing-pricing.html) for more details.
+
+## Setup
+
+> See [Zabbix template operation](https://www.zabbix.com/documentation/8.0/manual/config/templates_out_of_the_box/http) for basic instructions.
+
+1. Create a user to monitor the service, or use an existing read-only account.
+ Similarly to the user authentication in the Veeam Backup Enterprise Manager Web UI,
+ the client authentication in the REST API dictates which operations a client is allowed to perform when working with the REST API.
+ That is, if the client is authenticated using an account that does not have enough permissions to perform some actions, it will not be able to execute them.
+ You can also obtain the collected jobs if you are logged in under an account having only `Portal Administrator` role.
+> See [Veeam Help Center](https://helpcenter.veeam.com/docs/backup/em_rest/http_authentication.html?ver=110) for more details.
+2. Link the template to a host.
+3. Configure the following host wizard configuration fields: `Address`, `Username`, and `Password`.'),
+('10557',NULL,'Azure Microsoft SQL Database by HTTP','3','-1','2','','','Azure Microsoft SQL Database by HTTP','0',NULL,'This template is designed to monitor Microsoft SQL databases by HTTP.
+It works without any external scripts and uses the script item.
+
+Setup:
+ 1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+ See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
+ 2. Link the template to a host.
+ 3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','2d8b9329b5d04cdf85bf17d2d0db2b29','AZURE MICROSOFT SQL DATABASE BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is designed to monitor Microsoft SQL databases by HTTP.
+It works without any external scripts and uses the script item.
+
+## Setup
+
+1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+
+> See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
+
+2. Link the template to a host.
+3. Configure the host wizard configuration fields: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure MSSQL database ID`.'),
+('10558',NULL,'Azure Microsoft SQL Serverless Database by HTTP','3','-1','2','','','Azure Microsoft SQL Serverless Database by HTTP','0',NULL,'This template is designed to monitor Microsoft SQL serverless databases by HTTP.
+It works without any external scripts and uses the script item.
+
+Setup:
+ 1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+ See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
+ 2. Link the template to a host.
+ 3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','5175afdf713744d9a81ce53864ccfc1d','AZURE MICROSOFT SQL SERVERLESS DATABASE BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is designed to monitor Microsoft SQL serverless databases by HTTP.
+It works without any external scripts and uses the script item.
+
+## Setup
+
+1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+
+> See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
+
+2. Link the template to a host.
+3. Configure the host wizard configuration fields: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure MSSQL database ID`.'),
+('10560',NULL,'OS processes by Zabbix agent','3','-1','2','','','OS processes by Zabbix agent','0',NULL,'Get processes metrics using item proc.get by Zabbix agent.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','0f6889282f6048e2b1370e569e578985','OS PROCESSES BY ZABBIX AGENT','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed to monitor processes by Zabbix that work without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+For example, by specifying "zabbix" as host wizard configuration field value, you can monitor all zabbix processes.
+
+## Setup
+
+Install and setup [Zabbix agent](https://www.zabbix.com/documentation/8.0/manual/installation/install_from_packages).
+
+Custom processes set in host wizard configuration fields:
+
+- Processes name filter (include)
+- Processes name filter (exclude)'),
+('10561',NULL,'Zabbix agent','3','-1','2','','','Zabbix agent','0',NULL,'Use this template for agents reachable from Zabbix server/proxy (passive mode).
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','8aa4557f6c3f4aadbc03447fca3af9f6','ZABBIX AGENT','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+Set the timeout value after which the agent is considered unavailable.'),
+('10562',NULL,'Zabbix agent active','3','-1','2','','','Zabbix agent active','0',NULL,'Use this template instead of ''Zabbix agent'' for agents running in active mode only.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','650bec3f2f364a478b82317396949459','ZABBIX AGENT ACTIVE','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+Set the timeout value after which the agent is considered unavailable and threshold value of time since the last data was received from the agent.'),
+('10563',NULL,'Generic by SNMP','3','-1','2','','','Generic by SNMP','0',NULL,'Template Module Generic
+
+MIBs used:
+HOST-RESOURCES-MIB
+SNMPv2-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','4cb1aabe2b704b5c882963c2ef87d8f6','GENERIC BY SNMP','Zabbix','8.0-3',NULL,'0','1','## Setup
+
+Set the time interval for the SNMP availability trigger.'),
+('10564',NULL,'ICMP Ping','3','-1','2','','','ICMP Ping','0',NULL,'Template Net ICMP Ping
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','37e5eb5606bc4abba66c8b20381a1e8a','ICMP PING','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+Set `Threshold of ICMP packet loss` and `Threshold of the average ICMP response`.'),
+('10565',NULL,'SMART by Zabbix agent 2','3','-1','2','','','SMART by Zabbix agent 2','0',NULL,E'The template for monitoring S.M.A.R.T. attributes of physical disk that works without any external scripts. It collects metrics by Zabbix agent 2 version 5.0 and later with Smartmontools version 7.1 and later. Disk discovery LLD rule finds all HDD, SSD, NVMe disks with S.M.A.R.T. enabled. Attribute discovery LLD rule have pre-defined Vendor Specific Attributes for each disk, and will be discovered if attribute is present.
+
+Setup:
+
+1. Install Zabbix agent 2 and Smartmontools 7.1 or newer.
+
+2. Ensure the path to the "smartctl" executable is correctly specified. You can either provide the full path to the executable (e.g., "/usr/sbin/smartctl" on Linux or "C:\\Program Files\\smartctl\\smartctl.exe" on Windows) in the configuration file or ensure that the folder containing the "smartctl" executable is added to the system''s environment variables ("PATH"). This applies to both Linux and Windows systems.
+
+Example for Linux:
+Plugins.Smart.Path=/usr/sbin/smartctl
+
+Example for Windows:
+Plugins.Smart.Path="C:\\Program Files\\smartctl\\smartctl.exe"
+
+3. Grant Zabbix agent 2 super/admin user privileges for the "smartctl" utility (not required for Windows). Example for Linux (add the line that grants execution of the "smartctl" utility without the password):
+
+- Run the "visudo" command to edit the "sudoers" file:
+sudo visudo
+
+- Add the permission line and save the changes:
+zabbix ALL=(ALL) NOPASSWD:/usr/sbin/smartctl
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/415662-discussion-thread-for-official-zabbix-smart-disk-monitoring
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','7b6c6228b25f4586b42cd1bf37ff8034','SMART BY ZABBIX AGENT 2','Zabbix','8.0-3',NULL,'0','1',E'## Overview
+
+This template is designed for the effortless deployment of SMART monitoring by Zabbix via Zabbix agent 2 and doesn''t require any external scripts.
+
+It collects metrics by Zabbix agent 2 version 5.0 and later with Smartmontools version 7.1 and later.
+Disk discovery LLD rule finds all HDD, SSD, NVMe disks with S.M.A.R.T. enabled. Attribute discovery LLD rule have pre-defined Vendor Specific Attributes for each disk, and will be discovered if attribute is present.
+
+## Setup
+
+1. Install Zabbix agent 2 and Smartmontools 7.1 or newer.
+
+2. Ensure the path to the `smartctl` executable is correctly specified. You can either provide the full path to the executable (e.g., `/usr/sbin/smartctl` on Linux or `C:\\Program Files\\smartctl\\smartctl.exe` on Windows) in the configuration file or ensure that the folder containing the `smartctl` executable is added to the system''s environment variables (`PATH`). This applies to both Linux and Windows systems.
+
+Example for Linux:
+
+`Plugins.Smart.Path=/usr/sbin/smartctl`
+
+Example for Windows:
+
+`Plugins.Smart.Path="C:\\Program Files\\smartctl\\smartctl.exe"`
+
+3. Grant Zabbix agent 2 super/admin user privileges for the `smartctl` utility (not required for Windows). Example for Linux (add the line that grants execution of the `smartctl` utility without the password):
+
+- Run the `visudo` command to edit the `sudoers` file:
+
+`sudo visudo`
+
+- Add the permission line and save the changes:
+
+`zabbix ALL=(ALL) NOPASSWD:/usr/sbin/smartctl`
+
+Plugin [parameters list](https://www.zabbix.com/documentation/8.0/manual/appendix/config/zabbix_agent2_plugins/smart_plugin).'),
+('10566',NULL,'SMART by Zabbix agent 2 active','3','-1','2','','','SMART by Zabbix agent 2 active','0',NULL,E'The template for monitoring S.M.A.R.T. attributes of physical disk that works without any external scripts. It collects metrics by Zabbix agent 2 version 5.0 and later with Smartmontools version 7.1 and later. Disk discovery LLD rule finds all HDD, SSD, NVMe disks with S.M.A.R.T. enabled. Attribute discovery LLD rule have pre-defined Vendor Specific Attributes for each disk, and will be discovered if attribute is present.
+
+Setup:
+
+1. Install Zabbix agent 2 and Smartmontools 7.1 or newer.
+
+2. Ensure the path to the "smartctl" executable is correctly specified. You can either provide the full path to the executable (e.g., "/usr/sbin/smartctl" on Linux or "C:\\Program Files\\smartctl\\smartctl.exe" on Windows) in the configuration file or ensure that the folder containing the "smartctl" executable is added to the system''s environment variables ("PATH"). This applies to both Linux and Windows systems.
+
+Example for Linux:
+Plugins.Smart.Path=/usr/sbin/smartctl
+
+Example for Windows:
+Plugins.Smart.Path="C:\\Program Files\\smartctl\\smartctl.exe"
+
+3. Grant Zabbix agent 2 super/admin user privileges for the "smartctl" utility (not required for Windows). Example for Linux (add the line that grants execution of the "smartctl" utility without the password):
+
+- Run the "visudo" command to edit the "sudoers" file:
+sudo visudo
+
+- Add the permission line and save the changes:
+zabbix ALL=(ALL) NOPASSWD:/usr/sbin/smartctl
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/415662-discussion-thread-for-official-zabbix-smart-disk-monitoring
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e518b1340ce44d7389d2cc7c304a97b4','SMART BY ZABBIX AGENT 2 ACTIVE','Zabbix','8.0-3',NULL,'0','1',E'## Overview
+
+This template is designed for the effortless deployment of SMART monitoring by Zabbix via Zabbix agent 2 active and doesn''t require any external scripts.
+
+It collects metrics by Zabbix agent 2 version 5.0 and later with Smartmontools version 7.1 and later.
+Disk discovery LLD rule finds all HDD, SSD, NVMe disks with S.M.A.R.T. enabled. Attribute discovery LLD rule have pre-defined Vendor Specific Attributes for each disk, and will be discovered if attribute is present.
+
+## Setup
+
+1. Install Zabbix agent 2 and Smartmontools 7.1 or newer.
+
+2. Ensure the path to the `smartctl` executable is correctly specified. You can either provide the full path to the executable (e.g., `/usr/sbin/smartctl` on Linux or `C:\\Program Files\\smartctl\\smartctl.exe` on Windows) in the configuration file or ensure that the folder containing the `smartctl` executable is added to the system''s environment variables (`PATH`). This applies to both Linux and Windows systems.
+
+Example for Linux:
+
+`Plugins.Smart.Path=/usr/sbin/smartctl`
+
+Example for Windows:
+
+`Plugins.Smart.Path="C:\\Program Files\\smartctl\\smartctl.exe"`
+
+3. Grant Zabbix agent 2 super/admin user privileges for the `smartctl` utility (not required for Windows). Example for Linux (add the line that grants execution of the `smartctl` utility without the password):
+
+- Run the `visudo` command to edit the `sudoers` file:
+
+`sudo visudo`
+
+- Add the permission line and save the changes:
+
+`zabbix ALL=(ALL) NOPASSWD:/usr/sbin/smartctl`
+
+Plugin [parameters list](https://www.zabbix.com/documentation/8.0/manual/appendix/config/zabbix_agent2_plugins/smart_plugin).'),
+('10568',NULL,'Azure Cosmos DB for MongoDB by HTTP','3','-1','2','','','Azure Cosmos DB for MongoDB by HTTP','0',NULL,'This template is designed to monitor Microsoft Azure Cosmos DB for MongoDB by HTTP.
+It works without any external scripts and uses the script item.
+
+Setup:
+ 1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+ See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
+ 2. Link the template to a host.
+ 3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','29325098807848aa928b4192ad5e020f','AZURE COSMOS DB FOR MONGODB BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+
+> See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
+
+2. Link the template to a host.
+3. Configure the host wizard configuration fields: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure Cosmos DB ID`.'),
+('10570',NULL,'GCP by HTTP','3','-1','2','','','GCP by HTTP','0',NULL,'Discover GCP Compute Engine/Cloud SQL Instances and Compute Engine project quota metrics.
+Don''t forget to read the README.md for the correct setup of the template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','4e1e9372a5fe4297936210bc4fc4b1c0','GCP BY HTTP','Zabbix','8.0-3',NULL,'0','1',E'## Overview
+
+This template is designed to monitor Google Cloud Platform (GCP) using Zabbix.
+It works without any external scripts and uses the script item.
+
+The template currently supports the discovery of [Compute Engine](https://cloud.google.com/compute)/[Cloud SQL](https://cloud.google.com/sql)/[Cloud Run services](https://cloud.google.com/run) and Compute Engine project quota metrics.
+
+
+## Setup
+
+1. Enable the Stackdriver Monitoring API for the GCP project you wish to monitor.
+>More on [enabling Monitoring API](https://cloud.google.com/monitoring/api/enable-api).
+2. Create a service account in Google Cloud Console for the same GCP project.
+>More on [managing service accounts](https://cloud.google.com/iam/docs/creating-managing-service-accounts).
+3. Create and download the service account key in JSON format.
+>More on [service account keys](https://cloud.google.com/iam/docs/creating-managing-service-account-keys).
+4. If you want to monitor Cloud SQL services - don''t forget to activate the Cloud SQL Admin API.
+>More on [Cloud SQL Admin API](https://cloud.google.com/sql/docs/mysql/admin-api).
+5. For monitoring Cloud Run services - activate the Cloud Run Admin API.
+>More on [Cloud Run APIs](https://docs.cloud.google.com/run/docs/apis).
+6. Copy the `project_id`, `private_key_id`, `private_key`, `client_email` from the JSON key file and add them to their corresponding host wizard configuration fields `GCP project ID`, `Private key id`, `Private key data`, `Client e-mail` in host wizard configuration fields.
+
+**Notes**
+
+ - Make sure that you''re creating the Google Cloud Console service account using the credentials with the Project Owner/Project IAM Admin/Service Account Admin role.
+
+ - The service account JSON key file can only be downloaded **once**: regenerate it if the previous key has been lost.
+
+ - The service account should have Project Viewer permissions or granular permissions for the GCP Compute Engine API/GCP Cloud SQL/Cloud Run Viewer.
+
+ - You can copy and paste `private_key` string data from the Service Account JSON key file as is, or replace the new line metasymbol (`\\n`) with actual line breaks.
+
+>Refer to the [vendor documentation](https://cloud.google.com/iam/docs/manage-access-service-accounts) on managing access to service accounts.
+
+**IMPORTANT**
+
+ - The Zabbix secret authorization token (used for GCP API authentication) is defined as a plain text in host prototype settings by default due to template export/import limitations. It is highly recommended to change the user macro `{$GCP.AUTH.TOKEN}` value type to `SECRET` for all host prototypes after importing the *GCP by HTTP* template.
+
+ - All the discovered instances/quotas/metrics are related to a particular GCP project. To monitor several GCP projects, create their corresponding service accounts and Zabbix hosts.
+
+ - The GCP Access Token is available for 1 hour (3600 seconds) after the generation request.
+
+ - To avoid GCP token inconsistencies between the Zabbix database and Zabbix server configuration cache, do not set the Zabbix server configuration parameter `CacheUpdateFrequency` above 45 minutes, and do not set the GCP authorization item update interval above 1 hour (the maximum `CacheUpdateFrequency` value).
+
+More on metrics and used API methods:
+
+ - [Compute Engine](https://docs.cloud.google.com/monitoring/api/metrics_gcp_c#gcp-compute)
+
+ - [Cloud SQL](https://docs.cloud.google.com/monitoring/api/metrics_gcp_c#gcp-cloudsql)
+
+ - [Cloud Run](https://docs.cloud.google.com/monitoring/api/metrics_gcp_p_z#gcp-run)'),
+('10571',NULL,'GCP Cloud SQL MSSQL by HTTP','3','-1','2','','','GCP Cloud SQL MSSQL by HTTP','0',NULL,'Get GCP Cloud SQL MSSQL instances monitoring with script item usage to perform HTTP requests to Google Cloud Platform Monitoring API.
+This template will be automatically connected to discovered entities with all their required parameters pre-defined.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','507d70db18554a4e9ee5e09bb29bc85f','GCP CLOUD SQL MSSQL BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+This template is used in low-level discovery and will be auto-assigned to host prototypes. Additional configuration is not required.'),
+('10572',NULL,'GCP Cloud SQL MSSQL Replica by HTTP','3','-1','2','','','GCP Cloud SQL MSSQL Replica by HTTP','0',NULL,'Get GCP Cloud SQL MSSQL monitoring for read-only replicas with script item usage to perform HTTP requests to Google Cloud Platform Monitoring API.
+This template will be automatically connected to discovered entities with all their required parameters pre-defined.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','54f0ffb538d94a9bb8062df3e63c4cb6','GCP CLOUD SQL MSSQL REPLICA BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+This template is used in low-level discovery and will be auto-assigned to host prototypes. Additional configuration is not required.'),
+('10573',NULL,'GCP Cloud SQL MySQL by HTTP','3','-1','2','','','GCP Cloud SQL MySQL by HTTP','0',NULL,'Get GCP Cloud SQL MySQL instances monitoring with script item usage to perform HTTP requests to Google Cloud Platform Monitoring API.
+This template will be automatically connected to discovered entities with all their required parameters pre-defined.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','38456af4aedd4b168ec3fa4ad2acb256','GCP CLOUD SQL MYSQL BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+This template is used in low-level discovery and will be auto-assigned to host prototypes. Additional configuration is not required.'),
+('10574',NULL,'GCP Cloud SQL MySQL Replica by HTTP','3','-1','2','','','GCP Cloud SQL MySQL Replica by HTTP','0',NULL,'Get GCP Cloud SQL MySQL monitoring for read-only replicas with script item usage to perform HTTP requests to Google Cloud Platform Monitoring API.
+This template will be automatically connected to discovered entities with all their required parameters pre-defined.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','9d7871c093f9489293421396b9fea668','GCP CLOUD SQL MYSQL REPLICA BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+This template is used in low-level discovery and will be auto-assigned to host prototypes. Additional configuration is not required.'),
+('10575',NULL,'GCP Cloud SQL PostgreSQL by HTTP','3','-1','2','','','GCP Cloud SQL PostgreSQL by HTTP','0',NULL,'Get GCP Cloud SQL PostgreSQL instances monitoring with script item usage to perform HTTP requests to Google Cloud Platform Monitoring API.
+This template will be automatically connected to discovered entities with all their required parameters pre-defined.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e74c1e12f82e4d9880a368b53f5e65a4','GCP CLOUD SQL POSTGRESQL BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+This template is used in low-level discovery and will be auto-assigned to host prototypes. Additional configuration is not required.'),
+('10576',NULL,'GCP Cloud SQL PostgreSQL Replica by HTTP','3','-1','2','','','GCP Cloud SQL PostgreSQL Replica by HTTP','0',NULL,'Get GCP Cloud SQL PostgreSQL monitoring for read-only replicas with script item usage to perform HTTP requests to Google Cloud Platform Monitoring API.
+This template will be automatically connected to discovered entities with all their required parameters pre-defined.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','b43a7c5f1d1d43d28e2eb8f0a9f6f16f','GCP CLOUD SQL POSTGRESQL REPLICA BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+This template is used in low-level discovery and will be auto-assigned to host prototypes. Additional configuration is not required.'),
+('10577',NULL,'GCP Compute Engine Instance by HTTP','3','-1','2','','','GCP Compute Engine Instance by HTTP','0',NULL,'Discover GCP Compute Engine instances by HTTP with script item usage.
+This template will be automatically connected to discovered entities with all their required parameters pre-defined.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','6d2443db49e54d59a82b9b525f2424ef','GCP COMPUTE ENGINE INSTANCE BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+This template is used in low-level discovery and will be auto-assigned to host prototypes. Additional configuration is not required.'),
+('10582',NULL,'AWS Cost Explorer by HTTP','3','-1','2','','','AWS Cost Explorer by HTTP','0',NULL,'The template gets AWS Cost Explorer metrics and uses the script item to make HTTP requests to the Cost Explorer API.
+The Cost Explorer API can access the historical data over up to 12 months and the data for current month.
+Don''t forget to read the README.md for the correct setup of the template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','dce23cdaef364e139efa580d8a304ffe','AWS COST EXPLORER BY HTTP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template to monitor AWS Cost Explorer by HTTP via Zabbix, which works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+**Note:** This template uses the Cost Explorer API calls to list and retrieve metrics.
+For more information, please refer to the [Cost Explorer pricing](https://aws.amazon.com/aws-cost-management/aws-cost-explorer/pricing/) page.
+
+
+## Setup
+
+Before using the template, you need to create an IAM policy for the Zabbix role in your AWS account with the necessary permissions.
+
+* [IAM policies for AWS Cost Management](https://docs.aws.amazon.com/cost-management/latest/userguide/billing-permissions-ref.html)
+
+### Required Permissions
+Add the following required permissions to your Zabbix IAM policy in order to collect metrics.
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Action": [
+ "ce:GetDimensionValues",
+ "ce:GetCostAndUsage"
+ ],
+ "Effect": "Allow",
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+### Access Key Authorization
+
+If you are using access key authorization, you need to generate an access key and secret key for an IAM user with the necessary permissions:
+
+1. Create an IAM user with programmatic access.
+2. Attach the required policy to the IAM user.
+3. Generate an access key and secret key.
+4. Use the generated credentials in the host wizard configuration fields `Access key ID` and `Secret access key`.
+
+### Assume Role Authorization
+For using assume role authorization, add the appropriate permissions to the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "sts:AssumeRole",
+ "Resource": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "ce:GetDimensionValues",
+ "ce:GetCostAndUsage"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+#### Trust Relationships for Assume Role Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "AWS": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ "Action": "sts:AssumeRole"
+ }
+ ]
+}
+```
+Set the following fields: `Access key ID`, `Secret access key`, `STS Region`, `ARN assume role`.
+
+### Role-Based Authorization
+If you are using role-based authorization, add the appropriate permissions:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "iam:PassRole",
+ "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "ce:GetDimensionValues",
+ "ce:GetCostAndUsage",
+ "ec2:AssociateIamInstanceProfile",
+ "ec2:ReplaceIamInstanceProfileAssociation"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+#### Trust Relationships for Role-Based Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "Service": [
+ "ec2.amazonaws.com"
+ ]
+ },
+ "Action": [
+ "sts:AssumeRole"
+ ]
+ }
+ ]
+}
+```
+
+**Note**: Using role-based authorization is only possible when you use a Zabbix server or proxy inside AWS.
+
+Choose a method of authorization (field of `Authorization method`).
+
+For more information about managing access keys, see the [official documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).
+
+Additional information about metrics and used API methods:
+
+* [Describe AWS Cost Explore API actions](https://docs.aws.amazon.com/aws-cost-management/latest/APIReference/API_Operations.html).'),
+('10583',NULL,'AWS ECS Cluster by HTTP','3','-1','2','','','AWS ECS Cluster by HTTP','0',NULL,'The template gets AWS ECS Cluster metrics and uses the script item to make HTTP requests to the CloudWatch API.
+Don''t forget to read the README.md for the correct setup of the template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','c94105c23220452baed03ba87f09ca12','AWS ECS CLUSTER BY HTTP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template to monitor AWS ECS Serverless Cluster by HTTP via Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+**Note:** This template uses the GetMetricData CloudWatch API calls to list and retrieve metrics.
+For more information, please refer to the [CloudWatch pricing](https://aws.amazon.com/cloudwatch/pricing/) page.
+
+Additional information about the metrics and used API methods:
+
+* [Full metrics list related to ECS](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Insights-metrics-ECS.html)
+* [DescribeAlarms API method](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)
+
+## Setup
+
+The template gets AWS ECS metrics and uses the script item to make HTTP requests to the CloudWatch API.
+Before using the template, you need to create an IAM policy for the Zabbix role in your AWS account with the necessary permissions.
+
+### Required Permissions
+Add the following required permissions to your Zabbix IAM policy in order to collect Amazon ECS metrics.
+
+```json
+{
+ "Version":"2012-10-17",
+ "Statement":[
+ {
+ "Action":[
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "ecs:ListServices"
+ ],
+ "Effect":"Allow",
+ "Resource":"*"
+ }
+ ]
+ }
+```
+
+### Access Key Authorization
+
+If you are using access key authorization, you need to generate an access key and secret key for an IAM user with the necessary permissions:
+
+1. Create an IAM user with programmatic access.
+2. Attach the required policy to the IAM user.
+3. Generate an access key and secret key.
+4. Use the generated credentials in the host wizard configuration fields `Access key ID` and `Secret access key`.
+
+### Assume role authorization
+For using assume role authorization, add the appropriate permissions to the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "sts:AssumeRole",
+ "Resource": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "ecs:ListServices"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+#### Trust Relationships for Assume Role Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "AWS": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ "Action": "sts:AssumeRole"
+ }
+ ]
+}
+```
+Set the following fields: `Access key ID`, `Secret access key`, `STS Region`, `ARN assume role`.
+
+### Role-Based Authorization
+If you are using role-based authorization, set the appropriate permissions:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "iam:PassRole",
+ "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
+ },
+ {
+ "Sid": "VisualEditor1",
+ "Effect": "Allow",
+ "Action": [
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "ecs:ListServices",
+ "ec2:AssociateIamInstanceProfile",
+ "ec2:ReplaceIamInstanceProfileAssociation"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+#### Trust Relationships for Role-Based Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "Service": [
+ "ec2.amazonaws.com"
+ ]
+ },
+ "Action": [
+ "sts:AssumeRole"
+ ]
+ }
+ ]
+}
+```
+
+**Note**: Using role-based authorization is only possible when you use a Zabbix server or proxy inside AWS.
+
+Set the following host wizard configuration fields `Authorization method`, `AWS Region`, `ECS cluster name`.
+
+For more information about managing access keys, see [official documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).'),
+('10584',NULL,'AWS ECS Serverless Cluster by HTTP','3','-1','2','','','AWS ECS Serverless Cluster by HTTP','0',NULL,'The template gets AWS ECS Serverless Cluster metrics and uses the script item to make HTTP requests to the CloudWatch API.
+Don''t forget to read the README.md for the correct setup of the template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','5e225ad1c2cc4d0bbf75586e7bf8871b','AWS ECS SERVERLESS CLUSTER BY HTTP','Zabbix','8.0-4',NULL,'0','1','## Overview
+
+The template to monitor AWS ECS Serverless Cluster by HTTP via Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+**Note:** This template uses the GetMetricData CloudWatch API calls to list and retrieve metrics.
+For more information, please refer to the [CloudWatch pricing](https://aws.amazon.com/cloudwatch/pricing/) page.
+
+Additional information about the metrics and used API methods:
+
+* [Full metrics list related to ECS](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Insights-metrics-ECS.html)
+* [DescribeAlarms API method](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)
+
+## Setup
+
+The template gets AWS ECS metrics and uses the script item to make HTTP requests to the CloudWatch API.
+Before using the template, you need to create an IAM policy for the Zabbix role in your AWS account with the necessary permissions.
+
+### Required Permissions
+Add the following required permissions to your Zabbix IAM policy in order to collect Amazon ECS metrics.
+
+```json
+{
+ "Version":"2012-10-17",
+ "Statement":[
+ {
+ "Action":[
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "ecs:ListServices"
+ ],
+ "Effect":"Allow",
+ "Resource":"*"
+ }
+ ]
+ }
+```
+
+### Access Key Authorization
+
+If you are using access key authorization, you need to generate an access key and secret key for an IAM user with the necessary permissions:
+
+1. Create an IAM user with programmatic access.
+2. Attach the required policy to the IAM user.
+3. Generate an access key and secret key.
+4. Use the generated credentials in the host wizard configuration fields `Access key ID` and `Secret access key`.
+
+### Assume role authorization
+For using assume role authorization, add the appropriate permissions to the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "sts:AssumeRole",
+ "Resource": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "ecs:ListServices"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+#### Trust Relationships for Assume Role Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "AWS": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ "Action": "sts:AssumeRole"
+ }
+ ]
+}
+```
+Set the following fields: `Access key ID`, `Secret access key`, `STS Region`, `ARN assume role`.
+
+### Role-Based Authorization
+If you are using role-based authorization, set the appropriate permissions:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "iam:PassRole",
+ "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
+ },
+ {
+ "Sid": "VisualEditor1",
+ "Effect": "Allow",
+ "Action": [
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "ecs:ListServices",
+ "ec2:AssociateIamInstanceProfile",
+ "ec2:ReplaceIamInstanceProfileAssociation"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+#### Trust Relationships for Role-Based Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "Service": [
+ "ec2.amazonaws.com"
+ ]
+ },
+ "Action": [
+ "sts:AssumeRole"
+ ]
+ }
+ ]
+}
+```
+
+**Note**: Using role-based authorization is only possible when you use a Zabbix server or proxy inside AWS.
+
+Set the following host wizard configuration fields `Authorization method`, `AWS Region`, `ECS cluster name`.
+
+For more information about managing access keys, see [official documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).'),
+('10586',NULL,'OpenStack by HTTP','3','-1','2','','','OpenStack by HTTP','0',NULL,'Requests OpenStack API access token and discovers available OpenStack services using OpenStack Identity API by HTTP using script item and creates host prototypes for them.
+
+Template uses OpenStack application credentials for authorization.
+
+Zabbix currently supports OpenStack Nova service.
+
+Read the template documentation prior to using this template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','4e3fb27f028e4c35b8c9fc43b11c07d7','OPENSTACK BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+This is a master template that needs to be assigned to a host, and it will discover all OpenStack services supported by Zabbix automatically.
+
+Before using this template it is recommended to create a separate monitoring user on OpenStack that will have access to specific API resources. Zabbix uses OpenStack application credentials for authorization, as it is a more secure method than a username and password-based authentication.
+
+Below are instructions and examples on how to set up a user on OpenStack that will be used by Zabbix. Examples use the OpenStack CLI (command-line interface) tool, but this can also be done from OpenStack Horizon (web interface).
+
+> **If using the CLI tool, make sure you have the OpenStack RC file for your project with a user that has rights to create other users, roles, etc., and source it**, for example, `. zabbix-admin-openrc.sh`.
+>
+> The OpenStack RC file can be obtained from Horizon.
+
+The project that needs to be monitored is assumed to be already present in OpenStack. In the following examples, a project named `zabbix` is used:
+
+```
+# openstack project list
++----------------------------------+--------------------+
+| ID | Name |
++----------------------------------+--------------------+
+| 28d6bb25d62b4e7e8c2d59ce056a0334 | service |
+| 4688a19e02324c42a34220e9b6a2407e | admin |
+| bc78db4bb2044148a0abf90be512fa12 | zabbix |
++----------------------------------+--------------------+
+```
+
+1. After the project name is noted, a monitoring user needs to be created. This can be done by executing an `openstack user create` command:
+
+```
+# openstack user create --project zabbix --password-prompt zabbix-monitoring
+User Password:
+Repeat User Password:
++---------------------+----------------------------------+
+| Field | Value |
++---------------------+----------------------------------+
+| default_project_id | bc78db4bb2044148a0abf90be512fa12 |
+| domain_id | default |
+| enabled | True |
+| id | abd3eda9a29244568b1801e4825b6d71 |
+| name | zabbix-monitoring |
+| options | {} |
+| password_expires_at | None |
++---------------------+----------------------------------+
+```
+
+2. When the monitoring user is created, it needs to be assigned a role. But first, a monitoring-specific role needs to be created:
+
+```
+# openstack role create --description "A role for Zabbix monitoring user" monitoring
++-------------+-----------------------------------+
+| Field | Value |
++-------------+-----------------------------------+
+| description | A role for Zabbix monitoring user |
+| domain_id | None |
+| id | 93577a7f13184cf7af76f7bdecf7f6ee |
+| name | monitoring |
+| options | {} |
++-------------+-----------------------------------+
+```
+
+3. Then assign this newly created role to the monitoring user created in Step 1:
+```
+# openstack role add --user zabbix-monitoring --project zabbix monitoring
+```
+
+4. Verify that the role has been assigned correctly. There should be one role only:
+
+```
+# openstack role assignment list --user zabbix-monitoring --project zabbix --names
++------------+---------------------------+-------+----------------+--------+--------+-----------+
+| Role | User | Group | Project | Domain | System | Inherited |
++------------+---------------------------+-------+----------------+--------+--------+-----------+
+| monitoring | zabbix-monitoring@Default | | zabbix@Default | | | False |
++------------+---------------------------+-------+----------------+--------+--------+-----------+
+```
+
+5. Get the OpenStack RC file for the monitoring user in this project, source it, and generate application credentials:
+```
+# openstack application credential create --description "Application credential for Zabbix monitoring" zabbix-app-cred
+ +--------------+----------------------------------------------------------------------------------------+
+ | Field | Value |
+ +--------------+----------------------------------------------------------------------------------------+
+ | description | Application credential for Zabbix monitoring |
+ | expires_at | None |
+ | id | c8087b91354249f3b157a50fc5ecfb3c |
+ | name | zabbix-app-cred |
+ | project_id | bc78db4bb2044148a0abf90be512fa12 |
+ | roles | monitoring |
+ | secret | E1kC-s8QTWUaIpmexF18GW-FL3TI9-HXoexdExvGsw7uOhb3SEFW1zDa1qTs80Vqn-2xgviIPRuYOCDp2NDVUg |
+ | system | None |
+ | unrestricted | False |
+ | user_id | abd3eda9a29244568b1801e4825b6d71 |
+ +--------------+----------------------------------------------------------------------------------------+
+```
+
+While creating the application credential, it is also possible to define __access rules__ using the `--access-rules` flag, which offers even more fine-grained access to various API endpoints.
+This is optional and up to the user to decide if such rules are needed.
+
+Once the application credential is created, the values of `id` and `secret` need to be set as host wizard configuration field values:
+
+* value of `id` in `App credential ID`;
+* value of `secret` in `App credential password`.
+
+
+At this point, the monitoring user will not be able to access any resources on OpenStack, therefore some access rights need to be defined.
+Access rights are set using policies. Each service has its own policy file, therefore **further steps for setting up policies, are mentioned in the template documentation of each supported service**, e.g., __OpenStack Nova by HTTP__.'),
+('10587',NULL,'OpenStack Nova by HTTP','3','-1','2','','','OpenStack Nova by HTTP','0',NULL,'Discovers and monitors project limits, servers, services, hypervisors, availability zones, hypervisors and tenants with OpenStack Compute API by HTTP using script and HTTP agent items.
+
+This template receives token and service URL from parent host, therefore no additional configuration is necessary.
+
+Read the template documentation prior to using this template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','ff637e001b91472d8730eb7f10e65800','OPENSTACK NOVA BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+This template is not meant to be used independently. A host with the __OpenStack by HTTP__ template will discover the __Nova__ service automatically and create a host prototype with this template assigned to it.
+
+If needed, you can specify an HTTP proxy for the template to use by changing the value of `HTTP proxy` host wizard configuration field.
+
+For tenant usage statistics, it is possible to choose a custom time period for which the data will be queried. This can be set with the `Tenant usage period` host wizard configuration field value.
+The value can be one of the following:
+
+* `y` - current year until now;
+
+* `m` - current month until now (default value);
+
+* `w` - current week until now;
+
+* `d` - current day until now;
+
+This template discovers servers (instances) present in the project and monitors their statuses, but, depending on different use cases, most likely it is not necessary to monitor all servers.
+To filter which servers to monitor, set the `Server name filter (include)` and `Server name filter (exclude)` host wizard configuration field values accordingly. This logic also applies to other low-level discovery rules.
+
+**OpenStack configuration**
+
+For the OpenStack monitoring user to be able to access the API resources used in this template, it is needed to configure the policy file for OpenStack Nova.
+
+On the OpenStack server, open the `/etc/nova/policy.json` file in your favorite text editor.
+
+In this file, assign the following target resources to the role that the monitoring user uses:
+```
+{
+ "os_compute_api:servers:index": "role:monitoring",
+ "os_compute_api:servers:show": "role:monitoring",
+ "os_compute_api:os-services:list": "role:monitoring",
+ "os_compute_api:os-hypervisors:list-detail": "role:monitoring",
+ "os_compute_api:os-availability-zone:detail": "role:monitoring",
+ "os_compute_api:os-simple-tenant-usage:list": "role:monitoring"
+}
+```
+
+If some role is already assigned to the target, it is possible to add another role with `or`, for example, `role:firstRole or role:monitoring`.
+
+Note that a restart of OpenStack Nova services might be needed for these new changes to be applied.'),
+('10589',NULL,'PostgreSQL by ODBC','3','-1','2','','','PostgreSQL by ODBC','0',NULL,'This template is designed for the effortless deployment of PostgreSQL monitoring by Zabbix via ODBC and doesn''t require any external scripts.
+
+Setup:
+
+1. Create the PostgreSQL user for monitoring (`` at your discretion) and inherit permissions from the default role `pg_monitor`:
+CREATE USER zbx_monitor WITH PASSWORD '''' INHERIT;
+GRANT pg_monitor TO zbx_monitor;
+
+2. Edit the `pg_hba.conf` configuration file to allow TCP connections for the user `zbx_monitor`. You can check the PostgreSQL documentation for examples (https://www.postgresql.org/docs/current/auth-pg-hba-conf.html).
+
+3. Install the PostgreSQL ODBC driver.
+
+4. Set up the connection string with the `{$PG.CONNSTRING.ODBC}` macro. The minimum required parameters are:
+- `Driver=` - set the name of the driver which will be used for monitoring (from the `odbcinst.ini` file) or specify the path to the driver file (for example `/usr/lib64/psqlodbcw.so`);
+- `Servername=` - set the host name or IP address of the PostgreSQL instance;
+- `Port=` - adjust the port number if needed.
+
+If you want to use SSL/TLS encryption to protect communications with the remote PostgreSQL instance, you can also specify encryption parameters here.
+
+It is assumed that you set up the PostgreSQL instance to work in the desired encryption mode. Check the PostgreSQL documentation (https://www.postgresql.org/docs/current/ssl-tcp.html) for details.
+
+For example, to enable required encryption in transport mode without identity checks, the connection string could look like this (replace `` with the address of the PostgreSQL instance):
+Servername=;Port=5432;Driver=/usr/lib64/psqlodbcw.so;SSLmode=require
+
+5. Set the password that you specified in step 1 in the macro `{$PG.PASSWORD}`.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/384190-%C2%A0discussion-thread-for-official-zabbix-template-db-postgresql
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e0a7c3e725c445228b03116dc6114fe9','POSTGRESQL BY ODBC','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+1. Create the PostgreSQL user for monitoring (`` at your discretion) and inherit permissions from the default role `pg_monitor`:
+
+```sql
+CREATE USER zbx_monitor WITH PASSWORD '''' INHERIT;
+GRANT pg_monitor TO zbx_monitor;
+```
+
+2. Edit the `pg_hba.conf` configuration file to allow TCP connections for the user `zbx_monitor`. For example, you could add one of the following rows to allow local connections from the same host:
+
+```bash
+# TYPE DATABASE USER ADDRESS METHOD
+ host all zbx_monitor localhost trust
+ host all zbx_monitor 127.0.0.1/32 md5
+ host all zbx_monitor ::1/128 scram-sha-256
+```
+
+For more information please read the PostgreSQL documentation `https://www.postgresql.org/docs/current/auth-pg-hba-conf.html`.
+
+3. Install the PostgreSQL ODBC driver. Check the [`Zabbix documentation`](https://www.zabbix.com/documentation/8.0/manual/config/items/itemtypes/odbc_checks/) for details about ODBC checks and [`recommended parameters page`](https://www.zabbix.com/documentation/8.0/manual/config/items/itemtypes/odbc_checks/unixodbc_postgresql).
+
+4. Set up the connection string in the `PostgreSQL connection string` host wizard configuration field. The minimum required parameters are:
+
+- `Driver=` - set the name of the driver which will be used for monitoring (from the `odbcinst.ini` file) or specify the path to the driver file (for example `/usr/lib64/psqlodbcw.so`);
+- `Servername=` - set the host name or IP address of the PostgreSQL instance;
+- `Port=` - adjust the port number if needed.
+
+**Note:** if you want to use SSL/TLS encryption to protect communications with the remote PostgreSQL instance, you can also specify encryption parameters here.
+
+It is assumed that you set up the PostgreSQL instance to work in the desired encryption mode. Check the [`PostgreSQL documentation`](https://www.postgresql.org/docs/current/ssl-tcp.html) for details.
+
+For example, to enable required encryption in transport mode without identity checks, the connection string could look like this (replace `` with the address of the PostgreSQL instance):
+
+```
+Servername=;Port=5432;Driver=/usr/lib64/psqlodbcw.so;SSLmode=require
+```
+
+5. Set the password that you specified in step 1 in the `PostgreSQL user password` field.'),
+('10590',NULL,'Cisco SD-WAN by HTTP','3','-1','2','','','Cisco SD-WAN by HTTP','0',NULL,'Discover Cisco SD-WAN devices by HTTP with script item usage.
+
+Setup:
+1. Put your username and password from Cisco SD-WAN vManage into {$SDWAN.API.USERNAME} and {$SDWAN.API.PASSWORD} macros.
+2. Set your Cisco SD-WAN vManage URL as {$SDWAN.API.URL} macro value.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e5cf4e7ac41a470b99e4262d1c5ee104','CISCO SD-WAN BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+1. Put your username and password from Cisco SD-WAN vManage into `API username` and `API password` host wizard configuration fields.
+2. Set your Cisco SD-WAN vManage URL as `API URL` host wizard configuration field value.
+
+**NOTES**
+
+ The Cisco SD-WAN API token will be generated automatically by the Authentication item every `Authentication update interval`.
+ Don''t change the `Authentication update interval` host wizard configuration field value if it''s not required.
+
+ The generated Cisco SD-WAN API token and the session ID will be used in all Cisco SD-WAN templates and items.
+ These values will be kept in `{$SDWAN.AUTH.TOKEN}` and `{$SDWAN.AUTH.SESSION}` macros of each discovered host.
+
+**IMPORTANT**
+
+ Values of {$SDWAN.AUTH.TOKEN} and {$SDWAN.AUTH.SESSION} macros are stored as plain (not secret) text by default.
+
+>Please, refer to the [vendor documentation](https://www.cisco.com/c/en/us/td/docs/routers/sdwan/configuration/sdwan-xe-gs-book/cisco-sd-wan-API-cross-site-request-forgery-prevention.html) about the Cisco SD-WAN REST API Token-Based Authentication.'),
+('10591',NULL,'Cisco SD-WAN device by HTTP','3','-1','2','','','Cisco SD-WAN device by HTTP','0',NULL,'Get Cisco SD-WAN devices monitoring with script item usage to perform HTTP requests to Cisco SD-WAN API.
+This template will be automatically connected to discovered entities with all required parameters pre-defined.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e1e25df663204b099f2597caf89a0678','CISCO SD-WAN DEVICE BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+This template is used in low-level discovery and will be auto-assigned to host prototypes. Additional configuration is not required.'),
+('10593',NULL,'Mantis BT by HTTP','3','-1','2','','','Mantis BT by HTTP','0',NULL,'Get Mantis BT issues by HTTP.
+Metrics are collected by requests to Mantis BT API.
+Please change macros {$MANTIS.URL} and {$MANTIS.TOKEN}.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','2c96393f8f2945c1a9f03f86adf5eb57','MANTIS BT BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+1. Generate the API token in Mantis BT. Use this [manual](https://support.mantishub.com/hc/en-us/articles/215787323-Connecting-to-MantisHub-APIs-using-API-Tokens) for detailed instructions.
+2. Change values for the `MantisBT URL` and `MantisBT Token` host wizard configuration fields.'),
+('10594',NULL,'HashiCorp Nomad by HTTP','3','-1','2','','','HashiCorp Nomad by HTTP','0',NULL,'Discover HashiCorp Nomad servers and clients automatically.
+
+Don''t forget to change macro {$NOMAD.ENDPOINT.API.URL}, {$NOMAD.TOKEN} values.
+
+You can discuss this template or leave feedback on our forum: https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','f74adf26d9ab44ada318002d31fd2881','HASHICORP NOMAD BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed to monitor HashiCorp Nomad by Zabbix.
+It works without any external scripts.
+Currently the template supports Nomad servers and clients discovery.
+
+## Setup
+
+1. Create a synthetic Nomad host. It should be one of the Nomad cluster members, load-balancing service (if cluster is used) or a single node in a selected Nomad region.
+2. Define the `API endpoint URL` host wizard configuration field value with correct web protocol, host and port.
+3. Prepare an ACL token with `node:read`, `namespace:read-job`, `agent:read` and `management` permissions applied. Define the `Authentication token` host wizard configuration field value.
+> Refer to the vendor documentation about [`Nomad native ACL`](https://developer.hashicorp.com/nomad/tutorials/access-control/access-control-policies) or [`Nomad Vault-generated tokens`](https://developer.hashicorp.com/nomad/tutorials/access-control/vault-nomad-secrets) if you have the HashiCorp Vault integration configured.
+
+**Additional information**:
+
+* Synthetic Nomad host will be used just as an endpoint for servers and clients discovery (general cluster information), it will not be monitored as a Nomad server or client, so that to prevent duplicate entities.
+* If you''re not using ACL - skip 3rd setup step.
+* The Nomad servers/clients discovery is limited by region. If you''re using multi-region cluster- create one synthetic host per region.
+* The Nomad server/client templates are ready for separate usage. Feel free to use if you prefer manual host creation.
+
+**Useful links**
+* [HashiCorp Nomad multi-region federation](https://developer.hashicorp.com/nomad/tutorials/manage-clusters/federation)
+* [HashiCorp Nomad agent API reference](https://developer.hashicorp.com/nomad/api-docs/agent)
+* [HashiCorp Nomad raft operator API reference](https://developer.hashicorp.com/nomad/api-docs/operator/raft)
+* [HashiCorp Nomad nodes API reference](https://developer.hashicorp.com/nomad/api-docs/nodes)'),
+('10595',NULL,'HashiCorp Nomad Client by HTTP','3','-1','2','','','HashiCorp Nomad Client by HTTP','0',NULL,'Get HashiCorp Nomad client metrics by HTTP from metrics endpoint.
+
+More information about metrics is available in the official documentation: https://developer.hashicorp.com/nomad/docs/operations/metrics-reference.
+
+You can discuss this template or leave feedback on our forum: https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','44eac6a1abe34999b85ad6d0e40073fd','HASHICORP NOMAD CLIENT BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed to monitor HashiCorp Nomad clients by Zabbix.
+It works without any external scripts.
+
+## Setup
+
+1. Enable telemetry in HashiCorp Nomad agent configuration file. Set the Prometheus metrics format.
+>Refer to the [`vendor documentation`](https://developer.hashicorp.com/nomad/docs/configuration/telemetry).
+2. Prepare an ACL token with `node:read`, `namespace:read-job` permissions applied. Define the `{$NOMAD.TOKEN}` host wizard configuration field value.
+> Refer to the vendor documentation about [`Nomad native ACL`](https://developer.hashicorp.com/nomad/tutorials/access-control/access-control-policies) or [`Nomad Vault-generated tokens`](https://developer.hashicorp.com/nomad/tutorials/access-control/vault-nomad-secrets) if you''re using integration with HashiCorp Vault.
+3. Set the values for the `Nomad API scheme` and `Nomad API port` host wizard configuration fields to define the common Nomad API web schema and connection port.
+
+**Additional information**:
+
+* You have to prepare an additional ACL token only if you wish to monitor Nomad clients as separate entities. If you''re using clients discovery - token will be inherited from the master host linked to the HashiCorp Nomad by HTTP template.
+
+* If you''re not using ACL - skip 2nd setup step.
+
+* The Nomad clients use the default web schema - `HTTP` and default API port - `4646`. If you''re using clients discovery and you need to re-define macros for the particular host created from prototype, use the context macros like {{$NOMAD.CLIENT.API.SCHEME:`NECESSARY.IP`}} or/and {{$NOMAD.CLIENT.API.PORT:`NECESSARY.IP`}} on master host or template level.
+* Some metrics may not be collected depending on your HashiCorp Nomad agent version and configuration.
+
+**Useful links**:
+
+* [HashiCorp Nomad metrics list](https://developer.hashicorp.com/nomad/docs/operations/metrics-reference)
+* [HashiCorp Nomad telemetry configuration reference](https://developer.hashicorp.com/nomad/docs/configuration/telemetry)
+* [HashiCorp Nomad metrics API reference](https://developer.hashicorp.com/nomad/api-docs/metrics)
+* [HashiCorp Nomad nodes API reference](https://developer.hashicorp.com/nomad/api-docs/nodes)
+* [HashiCorp Nomad allocations API reference](https://developer.hashicorp.com/nomad/api-docs/allocations)
+* [Zabbix user macros with context](https://www.zabbix.com/documentation/8.0/manual/config/macros/user_macros_context)'),
+('10596',NULL,'HashiCorp Nomad Server by HTTP','3','-1','2','','','HashiCorp Nomad Server by HTTP','0',NULL,'Get HashiCorp Nomad server metrics by HTTP from metrics endpoint.
+
+More information about metrics is available in the official documentation: https://developer.hashicorp.com/nomad/docs/operations/metrics-reference.
+
+You can discuss this template or leave feedback on our forum: https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','8598d0e2bd6f4903832ec91b7b300062','HASHICORP NOMAD SERVER BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed to monitor HashiCorp Nomad servers by Zabbix.
+It works without any external scripts.
+
+## Setup
+
+1. Enable telemetry in HashiCorp Nomad agent configuration file. Set the Prometheus metrics format.
+>Refer to the [`vendor documentation`](https://developer.hashicorp.com/nomad/docs/configuration/telemetry).
+2. Set the values for the `Nomad API scheme` and `Nomad API port` host wizard configuration fields to define the common Nomad API web schema and connection port.
+
+**Additional information**:
+
+* The Nomad servers use the default web schema - `HTTP` and default API port - `4646`. If you''re using servers discovery and you need to re-define macros for the particular host created from prototype, use the context macros like {{$NOMAD.SERVER.API.SCHEME:`NECESSARY.IP`}} or/and {{$NOMAD.SERVER.API.PORT:`NECESSARY.IP`}} on master host or template level.
+* Some metrics may not be collected depending on your HashiCorp Nomad agent version, configuration and cluster role.
+* Don''t forget to define the `Redundant server count` host wizard configuration field value, based on your cluster nodes amount to configure the failure tolerance triggers correctly.
+
+**Useful links**:
+
+* [HashiCorp Nomad metrics list](https://developer.hashicorp.com/nomad/docs/operations/metrics-reference)
+* [HashiCorp Nomad telemetry configuration reference](https://developer.hashicorp.com/nomad/docs/configuration/telemetry)
+* [HashiCorp Nomad metrics API reference](https://developer.hashicorp.com/nomad/api-docs/metrics)
+* [HashiCorp Nomad agent API reference](https://developer.hashicorp.com/nomad/api-docs/agent#query-self)
+* [HashiCorp Nomad cluster failure tolerance reference](https://developer.hashicorp.com/nomad/docs/concepts/consensus#deployment-table)
+* [Zabbix user macros with context](https://www.zabbix.com/documentation/8.0/manual/config/macros/user_macros_context)'),
+('10599',NULL,'Acronis Cyber Protect Cloud by HTTP','3','-1','2','','','Acronis Cyber Protect Cloud by HTTP','0',NULL,'Requests Acronis Cyber Protect Cloud API access token and creates host prototype for MSP.
+
+Template uses HTTP item to query Acronis Cyber Protect Cloud API client for authorization.
+
+Read the template documentation prior to using this template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','d0571c5f2c204b7ab244843040288a35','ACRONIS CYBER PROTECT CLOUD BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+This is a master template that needs to be assigned to a host, and it will automatically create MSP host prototype, which will monitor Acronis Cyber Protect Cloud metrics.
+
+Before using this template it is required to create a new MSP-level API client for Zabbix to use. To do that, sign into your Acronis Cyber Protect Cloud WEB interface, navigate to `Settings` -> `API clients` and create new API client.
+You will be shown credentials for this API client. These credentials need to be entered in the following host wizard configuration field:
+
+* `API client ID` - enter `Client ID` here;
+
+* `API client secret` - enter `Secret` here;
+
+* `Datacenter URL` - enter `Data center URL`
+
+This is all the configuration needed for this integration.'),
+('10600',NULL,'Acronis Cyber Protect Cloud MSP by HTTP','3','-1','2','','','Acronis Cyber Protect Cloud MSP by HTTP','0',NULL,'Discovers and monitors alerts, clients, devices using HTTP agent items.
+
+This template receives API token and datacenter URL from parent host, therefore no additional configuration is necessary.
+
+Read the template documentation prior to using this template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','bf3107deff3a4aabab1e1c0ee71a3281','ACRONIS CYBER PROTECT CLOUD MSP BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+This template is not meant to be used independently. A host with the `Acronis Cyber Protect Cloud by HTTP` template will request API token and automatically create a host prototype with this template assigned to it.
+
+If needed, you can specify an HTTP proxy for the template to use by changing the value of `HTTP proxy` host wizard configuration field.
+
+Device discovery trigger prototypes that check services which have failed to run, have trigger time offset host wizard configuration field:
+
+* `Antimalware scan offset (sec)`
+
+* `Backup run offset (sec)`
+
+* `Vulnerability assessment offset (sec)`
+
+* `Patch management offset (sec)`
+
+Using these macros, their respective triggers can be offset in both directions. For example, if you wish to make
+sure that the trigger fires only when the current time is at least 3 minutes over the next scheduled antimalware
+scan, then set the value of `{$ACRONIS.CPC.OFFSET.SCHEDULED.ANTIMALWARE}` host wizard configuration field to `-180`.
+This is the default behaviour.'),
+('10602',NULL,'Nextcloud by HTTP','3','-1','2','','','Nextcloud by HTTP','0',NULL,'This template is designed for monitoring Nextcloud by HTTP via Zabbix, and it works without any external scripts.
+ Nextcloud is a suite of client-server software for creating and using file hosting services.
+ For more information, see the [`official documentation`](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-api-overview.html#)
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','34f386276a094e8e9a6e46653fdf05b1','NEXTCLOUD BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is designed for monitoring Nextcloud by HTTP via Zabbix, and it works without any external scripts.
+Nextcloud is a suite of client-server software for creating and using file hosting services.
+For more information, see the [`official documentation`](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-api-overview.html#)
+
+
+## Setup
+
+Set host wizard configuration fields `Username`, `Password`, `Address`.
+The user must be included in the Administrators group.'),
+('10603',NULL,'FortiGate by HTTP','3','-1','2','','','FortiGate by HTTP','0',NULL,'The template for monitoring FortiGate Next Generation Firewall by HTTP.
+
+1. On the FortiGate GUI, select System > Admin Profiles > Create New.
+2. Enter a profile name (ex. zabbix_ro) and enable all the Read permissions. Please note the profile name, it will be used a bit later.
+3. Go to System > Administrators > Create New > REST API Admin.
+4. Enter the API-user''s name and select the profile name you created in step 2.
+5. The trusted host can be specified to ensure that only Zabbix server can reach the FortiGate.
+6. Click OK and an API token will be generated. Make a note of the API token as it''s only shown once and cannot be retrieved.
+7. Put the API token into {$FGATE.API.TOKEN} macro.
+8. Set your FortiGate GUI IP/FQDN as {$FGATE.API.FQDN} macro value.
+9. If FortiGate GUI uses HTTPS, put "https" value into {$FGATE.SCHEME} macro and "443" into {$FGATE.API.PORT} macro.
+10. If FortiGate GUI port differs from the standard one, specify it in {$FGATE.API.PORT} macro.
+
+NOTE: Starting from template version ''8.0-2'', the API token is used in the request header. For older template versions (where the API token is passed in the URL query parameter), when using FortiGate v7.4.5+, you must enable the following global setting:
+https://docs.fortinet.com/document/fortigate/7.6.4/administration-guide/940602/using-apis
+
+For added security, it is strongly recommended to use the latest template version, which passes the API token in the request header instead of the URL parameter.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e56c9577c225476eb6d8f1c2f5dc90a5','FORTIGATE BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+1. On the FortiGate GUI, select `System > Admin Profiles > Create New`.
+2. Enter a profile name (ex. zabbix_ro) and enable all the Read permissions. Please note the profile name, it will be used a bit later.
+3. Go to `System > Administrators > Create New > REST API Admin`.
+4. Enter the API-user''s name and select the profile name you created in step 2.
+5. The trusted host can be specified to ensure that only Zabbix server can reach the FortiGate.
+6. Click OK and an API token will be generated. Make a note of the API token as it''s only shown once and cannot be retrieved.
+7. Put the API token into `Token` host wizard configuration field.
+8. Set your FortiGate GUI IP/FQDN as `Address` host wizard configuration field value.
+9. If FortiGate GUI uses HTTPS, put **https** value into `Scheme` and **443** into `Port` host wizard configuration fields.
+10. If FortiGate GUI port differs from the standard one, specify it in `Port` host wizard configuration field.
+
+**NOTE**: Starting from template version ''8.0-2'', the API token is used in the request header. For older template versions (where the API token is passed in the URL query parameter), when using FortiGate v7.4.5+, you must enable the following global setting:
+[Using APIs](https://docs.fortinet.com/document/fortigate/7.6.4/administration-guide/940602/using-apis)
+
+For added security, it is strongly recommended to use the latest template version, which passes the API token in the request header instead of the URL parameter.
+
+Please, refer to the [vendor documentation](https://docs.fortinet.com/document/fortigate/7.6.4/administration-guide/399023/rest-api-administrator) about the FortiGate REST API Authentication.'),
+('10604',NULL,'FortiGate by SNMP','3','-1','2','','','FortiGate by SNMP','0',NULL,'The template for monitoring FortiGate firewall by SNMP.
+
+MIBs used:
+HOST-RESOURCES-MIB
+FORTINET-FORTIGATE-MIB
+FORTINET-CORE-MIB
+SNMPv2-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','1f38deb487fc4a8d965e407ba7c5247f','FORTIGATE BY SNMP','Zabbix','8.0-3',NULL,'0','1',''),
+('10605',NULL,'HPE iLO by HTTP','3','-1','2','','','HPE iLO by HTTP','0',NULL,'This template is designed for the effortless deployment of HPE iLO monitoring by Zabbix via iLO RESTful API and doesn''t require any external scripts.
+
+Setup:
+
+1. Create the iLO user for monitoring (for example, `zbx_monitor`). The user will only need to have the `Login` privilege, which can be assigned manually or by assigning the `ReadOnly` role to the user.
+2. Set the iLO API endpoint URL in the `{$ILO.URL}` macro in the format `://[:port]/` (port is optional).
+3. Set the name of the user that you created in step 1 in the `{$ILO.USER}` macro.
+4. Set the password of the user that you created in step 1 in the `{$ILO.PASSWORD}` macro.
+
+For more details about HPE Redfish services, refer to the official documentation:
+https://servermanagementportal.ext.hpe.com/docs/redfishservices/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','d50f6dcfc3e44244a0fc9fd933607024','HPE ILO BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed for the effortless deployment of HPE iLO monitoring by Zabbix via iLO RESTful API and doesn''t require any external scripts.
+
+For more details about HPE Redfish services, refer to the [`official documentation`](https://servermanagementportal.ext.hpe.com/docs/redfishservices/).
+
+## Setup
+
+1. Create the iLO user for monitoring (for example, `zbx_monitor`). The user will only need to have the `Login` privilege, which can be assigned manually or by assigning the `ReadOnly` role to the user.
+2. Set the iLO API endpoint URL in the `Address` host wizard configuration field in the format `://[:port]/` (port is optional).
+3. Set the name of the user that you created in step 1 in the `Username` host wizard configuration field.
+4. Set the password of the user that you created in step 1 in the `Password` host wizard configuration field.'),
+('10606',NULL,'Azure Cost Management by HTTP','3','-1','2','','','Azure Cost Management by HTTP','0',NULL,'This template is designed to monitor Microsoft Cost Management by HTTP.
+It works without any external scripts and uses the script item.
+
+Setup:
+ 1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+ See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
+ 2. Link the template to a host.
+ 3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','c0263df8d8c14d30b24afcf45a6a354f','AZURE COST MANAGEMENT BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is designed to monitor Microsoft Cost Management by HTTP.
+It works without any external scripts and uses the script item.
+
+## Setup
+
+1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+
+> See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
+
+2. Link the template to a host.
+3. Configure the host wizard configuration fields: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`.'),
+('10607',NULL,'AWS ELB Application Load Balancer by HTTP','3','-1','2','','','AWS ELB Application Load Balancer by HTTP','0',NULL,'The template is designed to monitor AWS ELB Application Load Balancer by HTTP via Zabbix, and it works without any external scripts.
+Don''t forget to read the README.md for the correct setup of the template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','f59c8b4156ec4386a7c724534ddd384d','AWS ELB APPLICATION LOAD BALANCER BY HTTP','Zabbix','8.0-3',NULL,'0','1','## Overview
+
+*Please scroll down for AWS ELB Network Load Balancer by HTTP.*
+
+The template is designed to monitor AWS ELB Application Load Balancer by HTTP via Zabbix, and it works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+This template uses the GetMetricData CloudWatch API calls to list and retrieve metrics.
+For more information, please refer to the [CloudWatch pricing](https://aws.amazon.com/cloudwatch/pricing/) page.
+
+Additional information about metrics and API methods used in the template:
+* [Full metrics list related to AWS ELB Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html)
+* [DescribeAlarms API method](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)
+* [DescribeTargetGroups API method](https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_DescribeTargetGroups.html)
+
+
+## Setup
+
+The template gets AWS ELB Application Load Balancer metrics and uses the script item to make HTTP requests to the CloudWatch API.
+
+Before using the template, you need to create an IAM policy with the necessary permissions for the Zabbix role in your AWS account. For more information, visit the [ELB policies page](https://docs.aws.amazon.com/elasticloadbalancing/latest/userguide/elb-api-permissions.html) on the AWS website.
+
+### Required Permissions
+Add the following required permissions to your Zabbix IAM policy in order to collect AWS ELB Application Load Balancer metrics.
+
+```json
+{
+ "Version":"2012-10-17",
+ "Statement":[
+ {
+ "Action":[
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "elasticloadbalancing:DescribeTargetGroups"
+ ],
+ "Effect":"Allow",
+ "Resource":"*"
+ }
+ ]
+ }
+```
+
+### Access Key Authorization
+
+If you are using access key authorization, you need to generate an access key and secret key for an IAM user with the necessary permissions:
+
+1. Create an IAM user with programmatic access.
+2. Attach the required policy to the IAM user.
+3. Generate an access key and secret key.
+4. Use the generated credentials in the host wizard configuration fields `Access key ID` and `Secret access key`.
+
+### Assume role authorization
+For using assume role authorization, add the appropriate permissions to the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "sts:AssumeRole",
+ "Resource": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "elasticloadbalancing:DescribeTargetGroups"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+#### Trust Relationships for Assume Role Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "AWS": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ "Action": "sts:AssumeRole"
+ }
+ ]
+}
+```
+Set the following fields: `Access key ID`, `Secret access key`, `STS Region`, `ARN assume role`.
+
+### Role-Based Authorization
+If you are using role-based authorization, set the appropriate permissions:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "iam:PassRole",
+ "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
+ },
+ {
+ "Sid": "VisualEditor1",
+ "Effect": "Allow",
+ "Action": [
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "elasticloadbalancing:DescribeTargetGroups",
+ "ec2:AssociateIamInstanceProfile",
+ "ec2:ReplaceIamInstanceProfileAssociation"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+#### Trust Relationships for Role-Based Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "Service": [
+ "ec2.amazonaws.com"
+ ]
+ },
+ "Action": [
+ "sts:AssumeRole"
+ ]
+ }
+ ]
+}
+```
+
+**Note**: Using role-based authorization is only possible when you use a Zabbix server or proxy inside AWS.
+
+Set the following fields: `Authorization method`, `AWS Region`, and `Load Balancer ARN`.
+
+For more information about managing access keys, see [official AWS documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).'),
+('10609',NULL,'MSSQL by Zabbix agent 2','3','-1','2','','','MSSQL by Zabbix agent 2','0',NULL,'This template is designed for the effortless deployment of MSSQL monitoring by Zabbix via Zabbix agent 2 and uses a loadable plugin to run SQL queries.
+
+Setup:
+
+1. Deploy Zabbix agent 2 with the MSSQL plugin.
+
+ For more information, see MSSQL plugin documentation: https://git.zabbix.com/projects/AP/repos/mssql/browse
+
+ The MSSQL plugin must be updated to a version equal to or above 8.0.0
+
+ Loadable plugin requires installation of one of the following:
+
+ - Separate package
+
+ - Binary file
+
+ - Compilation from sources: https://www.zabbix.com/documentation/8.0/manual/extensions/plugins/build
+
+2. Create an MSSQL user for monitoring.
+
+ View Server State and View Any Definition permissions should be granted to the user.
+ Grant this user read permissions to the sysjobschedules, sysjobhistory, and sysjobs tables.
+
+ For more information, see MSSQL documentation:
+
+ - Create a database user: https://docs.microsoft.com/en-us/sql/relational-databases/security/authentication-access/create-a-database-user?view=sql-server-ver16
+
+ - GRANT Server Permissions: https://docs.microsoft.com/en-us/sql/t-sql/statements/grant-server-permissions-transact-sql?view=sql-server-ver16
+
+ - Configure a User to Create and Manage SQL Server Agent Jobs: https://docs.microsoft.com/en-us/sql/ssms/agent/configure-a-user-to-create-and-manage-sql-server-agent-jobs?view=sql-server-ver16
+
+3. Set the user name and password in the host macros ({$MSSQL.USER} and {$MSSQL.PASSWORD}).
+
+4. Set the connection string for the MSSQL instance in the {$MSSQL.URI} macro as a URI, such as , or specify the named session - .
+
+The "Service''s TCP port state" item uses the {$MSSQL.HOST} and {$MSSQL.PORT} macros to check the availability of the MSSQL instance, change these if necessary. Keep in mind that if dynamic ports are used on the MSSQL server side, this check will not work correctly.
+
+Note: You can use the context macros {$MSSQL.BACKUP_FULL.USED}, {$MSSQL.BACKUP_LOG.USED}, and {$MSSQL.BACKUP_DIFF.USED} to disable backup age triggers for a certain database. If set to a value other than "1", the trigger expression for the backup age will not fire.
+
+Note: Since version 7.2.0, you can also connect to the MSSQL instance using its name. To do this, set the connection string in the {$MSSQL.URI} macro as .
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','75fc96367e8d4588ba8314145fc12d35','MSSQL BY ZABBIX AGENT 2','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+1. Create a monitoring user on MSSQL for Zabbix to connect to:
+ - for MSSQL Server 2022
+ ```sql
+ CREATE LOGIN zabbix WITH PASSWORD = ''password''
+ GRANT VIEW SERVER PERFORMANCE STATE TO zabbix
+ GRANT VIEW ANY DEFINITION TO zabbix
+ USE msdb
+ CREATE USER zabbix FOR LOGIN zabbix
+ GRANT EXECUTE ON msdb.dbo.agent_datetime TO zabbix
+ GRANT SELECT ON msdb.dbo.sysjobactivity TO zabbix
+ GRANT SELECT ON msdb.dbo.sysjobservers TO zabbix
+ GRANT SELECT ON msdb.dbo.sysjobs TO zabbix
+ GO
+ ```
+ - for MSSQL versions 2017 and 2019
+ ```sql
+ CREATE LOGIN zabbix WITH PASSWORD = ''password''
+ GRANT VIEW SERVER STATE TO zabbix
+ GRANT VIEW ANY DEFINITION TO zabbix
+ USE msdb
+ CREATE USER zabbix FOR LOGIN zabbix
+ GRANT EXECUTE ON msdb.dbo.agent_datetime TO zabbix
+ GRANT SELECT ON msdb.dbo.sysjobactivity TO zabbix
+ GRANT SELECT ON msdb.dbo.sysjobservers TO zabbix
+ GRANT SELECT ON msdb.dbo.sysjobs TO zabbix
+ GO
+ ```
+
+ To allow Zabbix to query SQL Server Agent job information, a dedicated login must be created and granted the required permissions through T-SQL:
+ - **VIEW SERVER STATE** is required for Microsoft SQL Server 2017 and 2019
+ - **VIEW SERVER PERFORMANCE STATE** is required for Microsoft SQL Server 2022
+ - **VIEW ANY DEFINITION** allows access to object definitions and metadata
+ - **SELECT** allows the user to read data from the sysjobschedules, sysjobhistory, and sysjobs tables in the msdb database
+
+
+ For more information, see MSSQL documentation:
+ - [Create a database user](https://docs.microsoft.com/en-us/sql/relational-databases/security/authentication-access/create-a-database-user?view=sql-server-ver16)
+ - [GRANT Server Permissions](https://docs.microsoft.com/en-us/sql/t-sql/statements/grant-server-permissions-transact-sql?view=sql-server-ver16)
+ - [Configure a User to Create and Manage SQL Server Agent Jobs](https://docs.microsoft.com/en-us/sql/ssms/agent/configure-a-user-to-create-and-manage-sql-server-agent-jobs?view=sql-server-ver16)
+
+2. Set the username and password in the `MSSQL user` and `MSSQL password` host wizard configuration fields.
+3. Set the connection string for the MSSQL instance in the `MSSQL URI` host wizard configuration field as a URI, such as ``, or specify the named session - ``.
+
+ The `Service''s TCP port state` item uses the `MSSQL address` and `MSSQL TCP port` host wizard configuration fields to check the availability of the MSSQL instance, change these if necessary. Keep in mind that if dynamic ports are used on the MSSQL server side, this check will not work correctly.
+
+ Additional notes:
+ - You can use the `Monitoring of full backup`, `Monitoring of log backup`, and `Monitoring of differential backup` host wizard configuration fields to disable backup age triggers. If set to unselected state, the trigger expression for the backup age will not fire.
+ - Since version 7.2.0, you can also connect to the MSSQL instance using its name. To do this, set the connection string in the `MSSQL URI` host wizard configuration field as ``.'),
+('10610',NULL,'YugabyteDB by HTTP','3','-1','2','','','YugabyteDB by HTTP','0',NULL,'This template is designed for the deployment of YugabyteDB monitoring by Zabbix via HTTP and doesn''t require any external scripts.
+
+To set up the template:
+
+1. Set your account ID as a value of the {$YUGABYTEDB.ACCOUNT.ID} macro. The account ID is the unique identifier for your customer account in YugabyteDB Managed. You can access the account ID from your profile in the YugabyteDB Managed user interface. To get your account ID, log in to YugabyteDB Managed and click the user profile icon.
+See YugabyteDB documentation for instructions:
+https://yugabyte.stoplight.io/docs/managed-apis/tvsjh28t5ivmw-getting-started#account-id
+
+2. Set your project ID as a value of the {$YUGABYTEDB.PROJECT.ID} macro. The project ID is the unique identifier for a YugabyteDB Managed project. You can access the project ID from your profile in the YugabyteDB Managed user interface (along with the account ID).
+See YugabyteDB documentation for instructions:
+https://yugabyte.stoplight.io/docs/managed-apis/tvsjh28t5ivmw-getting-started#project-id
+
+3. Generate the API access token and specify it as a value of the {$YUGABYTEDB.ACCESS.TOKEN} macro.
+See YugabyteDB documentation for instructions:
+https://docs.yugabyte.com/preview/yugabyte-cloud/managed-automation/managed-apikeys/#create-an-api-key
+
+NOTE: If needed, you can specify a HTTP proxy for the template to use by changing the value of the {$YUGABYTEDB.PROXY} user macro.
+
+IMPORTANT! The value of the {$YUGABYTEDB.ACCESS.TOKEN} macro is stored as plain (not secret) text by default.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','bc056b1724e748bba50928f8cc605f8e','YUGABYTEDB BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed for the deployment of YugabyteDB monitoring by Zabbix via HTTP and doesn''t require any external scripts.
+
+## Setup
+
+1. Set your account ID as a value of the `Account ID` host wizard configuration field. The account ID is the unique identifier for your customer account in YugabyteDB Managed. You can access the account ID from your profile in the YugabyteDB Managed user interface. To get your account ID, log in to YugabyteDB Managed and click the user profile icon. See [YugabyteDB documentation](https://yugabyte.stoplight.io/docs/managed-apis/tvsjh28t5ivmw-getting-started#account-id) for instructions.
+
+2. Set your project ID as a value of the `Project ID` host wizard configuration field. The project ID is the unique identifier for a YugabyteDB Managed project. You can access the project ID from your profile in the YugabyteDB Managed user interface (along with the account ID). See [YugabyteDB documentation](https://yugabyte.stoplight.io/docs/managed-apis/tvsjh28t5ivmw-getting-started#project-id) for instructions.
+
+3. Generate the API access token and specify it as a value of the `API token` host wizard configuration field. See [YugabyteDB documentation](https://docs.yugabyte.com/preview/yugabyte-cloud/managed-automation/managed-apikeys/#create-an-api-key) for instructions.
+
+*NOTE* If needed, you can specify a HTTP proxy for the template to use by changing the value of the `HTTP proxy` host wizard configuration field.
+
+**IMPORTANT**
+
+ The value of the `{$YUGABYTEDB.ACCESS.TOKEN}` macro is stored as plain (not secret) text by default.'),
+('10611',NULL,'YugabyteDB Cluster by HTTP','3','-1','2','','','YugabyteDB Cluster by HTTP','0',NULL,'This template is designed for the deployment of YugabyteDB clusters monitoring by Zabbix via HTTP and doesn''t require any external scripts. This template will be automatically connected to discovered entities with all required parameters pre-defined.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','f5fff9a83f774f4688692ad58aa35d45','YUGABYTEDB CLUSTER BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+This template is used in low-level discovery and will be auto-assigned to host prototypes. Additional configuration is not required.'),
+('10613',NULL,'Check Point Next Generation Firewall by SNMP','3','-1','2','','','Check Point Next Generation Firewall by SNMP','0',NULL,'The template for monitoring Check Point Quantum Next Generation Firewall Security Gateway by SNMP.
+
+MIBs used:
+HOST-RESOURCES-MIB
+CHECKPOINT-MIB
+UCD-SNMP-MIB
+SNMPv2-MIB
+IF-MIB
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','3a7ff6eb19bb4a42b5b5b34a7179b30c','CHECK POINT NEXT GENERATION FIREWALL BY SNMP','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+> Refer to vendor [documentation](https://support.checkpoint.com/results/sk/sk90860).'),
+('10614',NULL,'Oracle Cloud Autonomous Database by HTTP','3','-1','2','','','Oracle Cloud Autonomous Database by HTTP','0',NULL,'This template monitors Oracle Cloud Infrastructure (OCI) autonomous database (serverless) resources.
+
+This template is not meant to be used independently, but together with Oracle Cloud by HTTP as a template for
+LLD host prototypes.
+
+Read the template documentation prior to using this template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','178645e229484bcf9cb030dc1edccebb','ORACLE CLOUD AUTONOMOUS DATABASE BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+This template is used in low-level discovery and will be auto-assigned to host prototypes. Additional configuration is not required.'),
+('10615',NULL,'Oracle Cloud Block Volume by HTTP','3','-1','2','','','Oracle Cloud Block Volume by HTTP','0',NULL,'This template monitors Oracle Cloud Infrastructure (OCI) block volume resources.
+
+This template is not meant to be used independently, but together with Oracle Cloud by HTTP as a template for
+LLD host prototypes.
+
+Read the template documentation prior to using this template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','8afa1796d280425b99c7ea36900dac24','ORACLE CLOUD BLOCK VOLUME BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+This template is used in low-level discovery and will be auto-assigned to host prototypes. Additional configuration is not required.'),
+('10616',NULL,'Oracle Cloud Boot Volume by HTTP','3','-1','2','','','Oracle Cloud Boot Volume by HTTP','0',NULL,'Monitor Oracle Cloud Infrastructure (OCI) boot volume.
+
+This template is not meant to be used independently, but instead with Oracle Cloud by HTTP as a template for
+LLD host prototypes.
+
+Read the template documentation prior to using this template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e5486d98ff414c1391de1bd369a7f9db','ORACLE CLOUD BOOT VOLUME BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+This template is used in low-level discovery and will be auto-assigned to host prototypes. Additional configuration is not required.'),
+('10617',NULL,'Oracle Cloud by HTTP','3','-1','2','','','Oracle Cloud by HTTP','0',NULL,'Monitor resources of Oracle Cloud Infrastructure (OCI) services.
+
+This template handles discovery of various OCI services.
+
+Read the template documentation prior to using this template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','057558a26d934b4683d73a7058499d62','ORACLE CLOUD BY HTTP','Zabbix','8.0-0',NULL,'0','1','## Overview
+
+This template is designed as a master template that discovers various Oracle Cloud Infrastructure (OCI) services
+and resources, such as:
+
+* OCI Compute;
+
+* OCI Autonomous Database (serverless);
+
+* OCI Object Storage;
+
+* OCI Virtual Cloud Networks (VCNs);
+
+* OCI Block Volumes;
+
+* OCI Boot Volumes.
+
+For communication with OCI, this template utilizes script items which execute HTTP `GET` and `POST` requests.
+`POST` requests are required for OCI Monitoring API as it utilizes Monitoring Query Language (MQL) which uses an
+HTTP request body for queries.
+
+
+## Setup
+
+## Required setup
+
+For this template to work, it needs authentication details to use in requests. To acquire this information, see
+the following steps:
+
+1. Log into your administrator account in Oracle Cloud Console.
+
+2. Create a new user that will be used by Zabbix for monitoring.
+
+3. Create a new security policy and assign a previously created user to it.
+
+4. This policy will contain a set of rules that will give monitoring user access to specific resources in your
+OCI. Make sure to add the following rules to the policy:
+
+ ```
+ Allow group ''zabbix_api'' to read metrics in tenancy
+ Allow group ''zabbix_api'' to read instances in tenancy
+ Allow group ''zabbix_api'' to read subnets in tenancy
+ Allow group ''zabbix_api'' to read vcns in tenancy
+ Allow group ''zabbix_api'' to read vnic-attachments in tenancy
+ Allow group ''zabbix_api'' to read volumes in tenancy
+ Allow group ''zabbix_api'' to read objectstorage-namespaces in tenancy
+ Allow group ''zabbix_api'' to read buckets in tenancy
+ Allow group ''zabbix_api'' to read autonomous-databases in tenancy
+ ```
+
+ In this example, `zabbix_api` is the name of the previously created monitoring user. Rename it to your
+monitoring user''s name.
+
+5. Generate an API key pair for your monitoring user - open your monitoring user profile and on the left side,
+press `API keys` and then, `Add API key` (if generating a new key pair, do not forget to save the private key).
+
+6. After this, Oracle Cloud Console will provide additional information that is required for access, such as:
+
+ * Tenancy OCID;
+
+ * User OCID;
+
+ * Fingerprint;
+
+ * Region.
+
+ > Save this information somewhere or keep this window open. This information will be required in later steps.
+
+7. In Zabbix, create a new host and assign this template to it (Oracle Cloud by HTTP).
+
+8. In host wizard configuration fields please set next values (from step #6):
+
+ * `OCID tenancy` - set the tenancy OCID value;
+
+ * `OCID user` - set the user OCID value;
+
+ * `Fingerprint` - set the fingerprint value;
+
+ * `Private key` - copy and paste the contents of private key file here.
+
+9. After the authentication credentials are entered, you need to identify the OCI API endpoints that match your
+region (as provided by Oracle Cloud Console in step #6).
+To do so, you can use the OCI [API Reference and Endpoints](https://docs.public.oneportal.content.oci.oraclecloud.com/en-us/iaas/api/#/) list, where each API service has a dedicated page with the respective API endpoints.
+
+ The required API service endpoints are:
+
+ * [Core Services API](https://docs.public.oneportal.content.oci.oraclecloud.com/en-us/iaas/api/#/en/iaas/20160918/);
+
+ * [Database Service API](https://docs.public.oneportal.content.oci.oraclecloud.com/en-us/iaas/api/#/en/database/20160918/);
+
+ * [Object Storage Service API](https://docs.public.oneportal.content.oci.oraclecloud.com/en-us/iaas/api/#/en/objectstorage/20160918/);
+
+ * [Monitoring API](https://docs.public.oneportal.content.oci.oraclecloud.com/en-us/iaas/api/#/en/monitoring/20180401/).
+
+10. When the API endpoints are identified, you need to set them in host wizard configuration fields (similarly to step #8):
+
+ * `Core Services host` - Core Services API endpoint, for example, `iaas.eu-stockholm-1.oraclecloud.com`;
+
+ * `Database Service host` - Database Service API endpoint, for example, `database.eu-stockholm-1.oraclecloud.com`;
+
+ * `Object Storage host` - Object Storage Service API endpoint, for example, `objectstorage.eu-stockholm-1.oraclecloud.com`;
+
+ * `Monitoring host` - Monitoring API endpoint, for example, `telemetry.eu-stockholm-1.oraclecloud.com`;
+
+ > IMPORTANT! API Endpoint URLs need to be entered without the HTTP scheme (`https://`).
+
+11. Once you''ve completed adding the host to Zabbix, and it will automatically discover services and monitor them.
+
+## Optional setup
+
+#### Example
+
+1. In Oracle Cloud Console, add a free-form tag to a resource, for example, a compute instance.
+The tag key will be `location_group` and the tag value will be `eu-north-1`.
+
+2. Open the Oracle Cloud by HTTP template in Zabbix and go to "Discovery rules".
+Find "Compute instances discovery" and open it.
+
+3. Under "LLD macros", add a new macro that will represent this location group tag, for example:
+`{#LOCATION_GROUP}` `$.tags.location_group`.
+
+4. Under the "Filters" tab, there will already be filters regarding the compute instance name and state.
+Click "Add" to add a new filter and define the previously created LLD macro and add a matching pattern and
+value, for example, `{#LOCATION_GROUP}` `matches` `eu-north-*`.
+
+5. The next time `Compute instances discovery` is executed, it will only discover OCI compute instances that
+have the free-form tag `location_group` that matches the regex of `eu-north-*`. You can also experiment with
+the LLD filter pattern matching value to receive different matching results for a specified value.'),
+('10618',NULL,'Oracle Cloud Compute by HTTP','3','-1','2','','','Oracle Cloud Compute by HTTP','0',NULL,'This template monitors Oracle Cloud Infrastructure (OCI) single compute instance resources and discovers attached
+virtual network interface cards (VNICs) and monitors their resources.
+
+This template is not meant to be used independently, but together with Oracle Cloud by HTTP as a template for
+LLD host prototypes.
+
+Read the template documentation prior to using this template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e6b0aada359944d09ee4bd46c1a55587','ORACLE CLOUD COMPUTE BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Setup
+
+This template is used in low-level discovery and will be auto-assigned to host prototypes. Additional configuration is not required.'),
+('10619',NULL,'Oracle Cloud Networking by HTTP','3','-1','2','','','Oracle Cloud Networking by HTTP','0',NULL,'This template monitors Oracle Cloud Infrastructure (OCI) single virtual network card availability and discovers
+attached subnets and monitors their availability.
+
+This template is not meant to be used independently, but together with Oracle Cloud by HTTP as a template for
+LLD host prototypes.
+
+Read the template documentation prior to using this template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','62d99b55585e41dd89736f5f46074dcb','ORACLE CLOUD NETWORKING BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+This template is used in low-level discovery and will be auto-assigned to host prototypes. Additional configuration is not required.'),
+('10620',NULL,'Oracle Cloud Object Storage by HTTP','3','-1','2','','','Oracle Cloud Object Storage by HTTP','0',NULL,'This template monitors Oracle Cloud Infrastructure (OCI) object storage resources.
+
+This template is not meant to be used independently, but together with Oracle Cloud by HTTP as a template for
+LLD host prototypes.
+
+Read the template documentation prior to using this template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','e8f89476695848e99ba900a5664d290b','ORACLE CLOUD OBJECT STORAGE BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Setup
+
+This template is used in low-level discovery and will be auto-assigned to host prototypes. Additional configuration is not required.'),
+('10627',NULL,'AWS ELB Network Load Balancer by HTTP','3','-1','2','','','AWS ELB Network Load Balancer by HTTP','0',NULL,'The template is designed to monitor AWS ELB Network Load Balancer by HTTP via Zabbix, and it works without any external scripts.
+Don''t forget to read the README.md for the correct setup of the template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','4c7d0c6e342b40458611bdb6e9dd958f','AWS ELB NETWORK LOAD BALANCER BY HTTP','Zabbix','8.0-3',NULL,'0','1','## Overview
+
+The template is designed to monitor AWS ELB Network Load Balancer by HTTP via Zabbix, and it works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+This template uses the GetMetricData CloudWatch API calls to list and retrieve metrics.
+For more information, please refer to the [CloudWatch pricing](https://aws.amazon.com/cloudwatch/pricing/) page.
+
+Additional information about metrics and API methods used in the template:
+* [Full metrics list related to AWS ELB Network Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-cloudwatch-metrics.html)
+* [DescribeAlarms API method](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)
+* [DescribeTargetGroups API method](https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_DescribeTargetGroups.html)
+
+
+## Setup
+
+The template gets AWS ELB Network Load Balancer metrics and uses the script item to make HTTP requests to the CloudWatch API.
+
+Before using the template, you need to create an IAM policy with the necessary permissions for the Zabbix role in your AWS account. For more information, visit the [ELB policies page](https://docs.aws.amazon.com/elasticloadbalancing/latest/userguide/elb-api-permissions.html) on the AWS website.
+
+### Required Permissions
+Add the following required permissions to your Zabbix IAM policy in order to collect AWS ELB Network Load Balancer metrics.
+
+```json
+{
+ "Version":"2012-10-17",
+ "Statement":[
+ {
+ "Action":[
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "elasticloadbalancing:DescribeTargetGroups"
+ ],
+ "Effect":"Allow",
+ "Resource":"*"
+ }
+ ]
+ }
+```
+
+### Access Key Authorization
+
+If you are using access key authorization, you need to generate an access key and secret key for an IAM user with the necessary permissions:
+
+1. Create an IAM user with programmatic access.
+2. Attach the required policy to the IAM user.
+3. Generate an access key and secret key.
+4. Use the generated credentials in the host wizard configuration fields `Access key ID` and `Secret access key`.
+
+### Assume role authorization
+For using assume role authorization, add the appropriate permissions to the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "sts:AssumeRole",
+ "Resource": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "elasticloadbalancing:DescribeTargetGroups"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+#### Trust Relationships for Assume Role Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "AWS": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ "Action": "sts:AssumeRole"
+ }
+ ]
+}
+```
+Set the following fields: `Access key ID`, `Secret access key`, `STS Region`, `ARN assume role`.
+
+### Role-Based Authorization
+If you are using role-based authorization, set the appropriate permissions:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "iam:PassRole",
+ "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
+ },
+ {
+ "Sid": "VisualEditor1",
+ "Effect": "Allow",
+ "Action": [
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "elasticloadbalancing:DescribeTargetGroups",
+ "ec2:AssociateIamInstanceProfile",
+ "ec2:ReplaceIamInstanceProfileAssociation"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+#### Trust Relationships for Role-Based Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "Service": [
+ "ec2.amazonaws.com"
+ ]
+ },
+ "Action": [
+ "sts:AssumeRole"
+ ]
+ }
+ ]
+}
+```
+
+**Note**: Using role-based authorization is only possible when you use a Zabbix server or proxy inside AWS.
+
+Set the following fields: `Authorization method`, `AWS Region`, and `Load Balancer ARN`.
+
+For more information about managing access keys, see [official AWS documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).'),
+('10628',NULL,'Website by Browser','3','-1','2','','','Website by Browser','0',NULL,'The template to monitor a website''s availability and performance on the website by Browser.
+
+Zabbix server uses a web browser to perform navigation and collect performance metrics.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','2526dce71d714e31bd545e96370c67b2','WEBSITE BY BROWSER','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+
+
+## Setup
+
+Install WebDriver.
+For more information, please refer to the [Selenium WebDriver](https://www.selenium.dev/documentation/webdriver/) page.
+Run selenium-server.
+Add in configuration file WebDriver interface HTTP[S] URL. For example http://localhost:4444'),
+('10629',NULL,'GitHub repository by HTTP','3','-1','2','','','GitHub repository by HTTP','0',NULL,'This template is designed for the effortless deployment of GitHub repository monitoring by Zabbix via GitHub REST API and doesn''t require any external scripts.
+
+For more details about GitHub REST API, refer to the official documentation:
+https://docs.github.com/en/rest?apiVersion=2022-11-28
+
+Setup:
+
+1. Create an access token for monitoring
+
+One of the simplest ways to send authenticated requests is to use a personal access token - either a classic or a fine-grained one:
+https://docs.github.com/en/rest/authentication/authenticating-to-the-rest-api?apiVersion=2022-11-28#authenticating-with-a-personal-access-token
+
+Classic personal access token
+
+You can create a new classic personal access token by following the instructions in the official documentation:
+https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic
+
+For public repositories, no additional permission scopes are required. For monitoring to work on private repositories, the "repo" scope must be set to have full control of private repositories.
+
+Additional information about OAuth scopes is available in the official documentation:
+https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps#available-scopes
+
+Note that authenticated users must have admin access to the repository and the "repo" scope must be set to get information about self-hosted runners:
+https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#list-self-hosted-runners-for-a-repository
+
+Fine-grained personal access token
+
+Alternatively, you can use a fine-grained personal access token:
+https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token
+
+In order to use fine-grained tokens to monitor organization-owned repositories, organizations must opt in to fine-grained personal access tokens and set up a personal access token policy:
+https://docs.github.com/en/organizations/managing-programmatic-access-to-your-organization/setting-a-personal-access-token-policy-for-your-organization
+
+The fine-grained token needs to have the following permissions set to provide access to the repository resources:
+- "Actions" repository permissions (read);
+- "Administration" repository permissions (read);
+- "Contents" repository permissions (read);
+- "Issues" repository permissions (read);
+- "Metadata" repository permissions (read);
+- "Pull requests" repository permissions (read).
+
+2. Set the access token that you''ve created in step 1 in the "{$GITHUB.API.TOKEN}" macro
+3. Change the API URL in the "{$GITHUB.API.URL}" macro if needed (for self-hosted installations)
+4. Set the repository owner name in the "{$GITHUB.REPO.OWNER}" macro
+5. Set the repository name in the "{$GITHUB.REPO.NAME}" macro
+6. Set the LLD rule filters if needed (you may want to use it to also stay within rate limits as on large repositories, LLD rules may generate a lot of script items)
+
+Note: Update intervals and timeouts for script items can be changed individually via "{$GITHUB.INTERVAL}" and "{$GITHUB.TIMEOUT}" macros with context. Depending on the repository being monitored, it can be adjusted if needed (if you are exceeding rate limits, you can increase update intervals for some script items to stay within per hour request limits). But be aware that it may also affect the triggers (check whether the item is used in triggers and adjust thresholds and/or evaluation periods if needed).
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','11144543d1144a3693aa0b97a1c20dac','GITHUB REPOSITORY BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is designed for the effortless deployment of GitHub repository monitoring by Zabbix via GitHub REST API and doesn''t require any external scripts.
+
+For more details about GitHub REST API, refer to the [official documentation](https://docs.github.com/en/rest?apiVersion=2022-11-28).
+
+## Setup
+
+GitHub limits the number of REST API requests that you can make within a specific amount of time, which also depends on whether you are authenticated or not, the plan, and the token type used. Many REST API endpoints require authentication or return additional information if you are authenticated. Additionally, you can make more requests per hour when you are authenticated.
+
+Additional information is available in the official documentation:
+- [Regarding authentication](https://docs.github.com/en/rest/authentication/authenticating-to-the-rest-api?apiVersion=2022-11-28#about-authentication)
+- [Rate limits for the REST API](https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28)
+
+1. **Create an access token for monitoring**
+
+One of the simplest ways to send authenticated requests is to use a [personal access token](https://docs.github.com/en/rest/authentication/authenticating-to-the-rest-api?apiVersion=2022-11-28#authenticating-with-a-personal-access-token) - either a classic or a fine-grained one.
+
+**Classic personal access token**
+
+You can create a new classic personal access token by following the [instructions in the official documentation](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic).
+
+For public repositories, no additional permission scopes are required. For monitoring to work on private repositories, the `repo` scope must be set to have full control of private repositories.
+
+Additional information about OAuth scopes is available in the [official documentation](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps#available-scopes).
+
+Note that authenticated users must have admin access to the repository and the `repo` scope must be set to get information about [self-hosted runners](https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#list-self-hosted-runners-for-a-repository).
+
+**Fine-grained personal access token**
+
+Alternatively, you can use a [fine-grained personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token).
+
+In order to use fine-grained tokens to monitor organization-owned repositories, [organizations must opt in to fine-grained personal access tokens and set up a personal access token policy](https://docs.github.com/en/organizations/managing-programmatic-access-to-your-organization/setting-a-personal-access-token-policy-for-your-organization).
+
+The fine-grained token needs to have the following permissions set to provide access to the repository resources:
+- "Actions" repository permissions (read);
+- "Administration" repository permissions (read);
+- "Contents" repository permissions (read);
+- "Issues" repository permissions (read);
+- "Metadata" repository permissions (read);
+- "Pull requests" repository permissions (read).
+
+2. **Set the access token** that you''ve created in step 1 in the `Access token` host wizard configuration field
+3. **Change the API URL** in the `API URL` host wizard configuration field if needed (for self-hosted installations)
+4. **Set the repository owner name** in the `Repository owner` host wizard configuration field
+5. **Set the repository name** in the `Repository name` host wizard configuration field
+6. **Set the LLD rule filters** if needed (you may want to use them to stay within rate limits as on large repositories, LLD rules may generate a lot of script items):
+- Filter repository branches by name: `Branch name filter (include)`, `Branch name filter (exclude)`;
+- Filter repository workflows by name: `Workflow name filter (include)`, `Workflow name filter (exclude)`;
+- Filter repository workflows by state: `Workflow state filter (include)`, `Workflow state filter (exclude)`;
+- Filter self-hosted runners by name: `Self-hosted runner name filter (include)`, `Self-hosted runner name filter (exclude)`;
+- Filter self-hosted runners by OS: `Self-hosted runner OS filter (include)`, `Self-hosted runner OS filter (exclude)`.
+
+Note: Update intervals and timeouts for script items can be changed individually via `Data update interval` and `API timeout` host wizard configuration fields with context. Depending on the repository being monitored, it can be adjusted if needed (if you are exceeding rate limits, you can increase update intervals for some script items to stay within per hour request limits). But be aware that it may also affect the triggers (check whether the item is used in triggers and adjust thresholds and/or evaluation periods if needed).'),
+('10630',NULL,'Jira Data Center by JMX','3','-1','2','','','Jira Data Center by JMX','0',NULL,'This template is used for monitoring Jira Data Center health. It is designed for standalone operation for on-premises Jira installations.
+
+This template uses a single data source, JMX, which requires JMX RMI setup of your Jira application and Java Gateway setup on the Zabbix side.
+If you need "Garbage collector" and "Web server" monitoring, add "Generic Java JMX" and "Apache Tomcat by JMX" templates on the same host.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback
+
+Setup:
+ Metrics are collected by JMX.
+ 0. Deploy the Zabbix Java Gateway component ([instructions](https://www.zabbix.com/documentation/8.0/manual/concepts/java)).
+ 1. Enable and configure JMX access to Jira Data Center. See documentation for [instructions](https://confluence.atlassian.com/adminjiraserver/live-monitoring-using-the-jmx-interface-939707304.html).
+ 2. Assign the "Jira Data Center by JMX" template to the host with a JMX interface.
+ 2. If your Jira installation requires authentication for JMX, set the values in the host macros `{$JMX.USERNAME}` and `{$JMX.PASSWORD}`.
+ 3. (Optional) Set custom macro values and add macros with context for specific metrics following the macro description.
+ 4. (Optional) Assign the "Generic Java JMX" template for garbage collector monitoring.
+ 5. (Optional) Assign the "Apache Tomcat by JMX" template for web server monitoring.
+
+tested_on:
+ - Jira Data Center 9.14.1
+ - Jira Data Center 9.12.4
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','a7f0c853c6634b1dacaaf43c2a0d9375','JIRA DATA CENTER BY JMX','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is used for monitoring Jira Data Center health. It is designed for standalone operation for on-premises Jira installations.
+
+This template uses a single data source, JMX, which requires JMX RMI setup of your Jira application and Java Gateway setup on the Zabbix side.
+If you need "Garbage collector" and "Web server" monitoring, add "Generic Java JMX" and "Apache Tomcat by JMX" templates on the same host.
+
+## Setup
+
+Metrics are collected by JMX.
+0. Deploy the Zabbix Java Gateway component ([instructions](https://www.zabbix.com/documentation/8.0/manual/concepts/java)).
+1. Enable and configure JMX access to Jira Data Center. See documentation for [instructions](https://confluence.atlassian.com/adminjiraserver/live-monitoring-using-the-jmx-interface-939707304.html).
+2. Assign the "Jira Data Center by JMX" template to the host with a JMX interface.
+2. If your Jira installation requires authentication for JMX, set the values in the host wizard configuration fields `JMX user` and `JMX password`.
+3. (Optional) Set custom host wizard configuration field values and add macros with context for specific metrics following the macro description.
+4. (Optional) Assign the "Generic Java JMX" template for garbage collector monitoring.
+5. (Optional) Assign the "Apache Tomcat by JMX" template for web server monitoring.'),
+('10631',NULL,'Microsoft 365 reports by HTTP','3','-1','2','','','Microsoft 365 reports by HTTP','0',NULL,'This template is designed to monitor Microsoft 365 reports by HTTP. It works without any external scripts and uses script items.
+The template uses endpoints in the Microsoft Graph API to gather daily metrics from weekly reports.
+The template is meant to be used as a long-term trend monitoring tool.
+
+Setup:
+ 1. Register the app with Microsoft Entra ID.
+ 2. Configure Microsoft Graph application permissions on the app ID:
+ `Reports.Read.All` - required for app usage and activity metrics
+ `ServiceHealth.Read.All` - required for service discovery and service status metrics
+ 3. Request administrator consent.
+ 4. Configure the macros: `{$MS365.APP.ID}`, `{$MS365.PASSWORD}`, `{$MS365.TENANT.ID}`.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','03e93dc9a8194a17958544a056d02316','MICROSOFT 365 REPORTS BY HTTP','Zabbix','8.0-3',NULL,'0','1','## Overview
+
+- This template is designed to monitor Microsoft 365 by HTTP. It works without any external scripts and uses script items.
+- The template uses endpoints in the Microsoft Graph API to gather daily metrics from weekly reports.
+- The template is meant to be used as a long-term trend monitoring tool.
+
+## Setup
+
+1. Register the app with your Microsoft Entra ID.
+2. Configure Microsoft Graph application permissions on the app ID:
+ - `Reports.Read.All` - required for app usage and activity metrics
+ - `ServiceHealth.Read.All` - required for service discovery and service status metrics
+3. Request administrator consent.
+4. Configure the host wizard configuration fields: `Application ID`, `Password`, `Tenant ID`.'),
+('10632',NULL,'AWS Lambda by HTTP','3','-1','2','','','AWS Lambda by HTTP','0',NULL,'The template is designed to monitor AWS Lambda by HTTP via Zabbix, and it works without any external scripts.
+Don''t forget to read the README.md for the correct setup of the template.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','fd36e0a231d343d38a95d1ed789584ca','AWS LAMBDA BY HTTP','Zabbix','8.0-3',NULL,'0','1','## Overview
+
+This template uses the GetMetricData CloudWatch API calls to list and retrieve metrics.
+For more information, please refer to the [CloudWatch pricing](https://aws.amazon.com/cloudwatch/pricing/) page.
+
+Additional information about metrics and API methods used in the template:
+* [Full metrics list related to AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-metrics.html)
+* [DescribeAlarms API method](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html)
+
+
+## Setup
+
+The template gets AWS Lambda metrics and uses the script item to make HTTP requests to the CloudWatch API.
+
+Before using the template, you need to create an IAM policy with the necessary permissions for the Zabbix role in your AWS account. For more information, visit the [Lambda permissions page](https://docs.aws.amazon.com/lambda/latest/dg/lambda-permissions.html) on the AWS website.
+
+### Required Permissions
+Add the following required permissions to your Zabbix IAM policy in order to collect AWS Lambda metrics.
+
+```json
+{
+ "Version":"2012-10-17",
+ "Statement":[
+ {
+ "Action":[
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData"
+ ],
+ "Effect":"Allow",
+ "Resource":"*"
+ }
+ ]
+ }
+```
+
+### Access Key Authorization
+
+If you are using access key authorization, you need to generate an access key and secret key for an IAM user with the necessary permissions:
+
+1. Create an IAM user with programmatic access.
+2. Attach the required policy to the IAM user.
+3. Generate an access key and secret key.
+4. Use the generated credentials in the host wizard configuration fields `Access key ID` and `Secret access key`.
+
+### Assume role authorization
+For using assume role authorization, add the appropriate permissions to the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "sts:AssumeRole",
+ "Resource": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+#### Trust Relationships for Assume Role Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "AWS": "arn:aws:iam::{Account}:user/{UserName}"
+ },
+ "Action": "sts:AssumeRole"
+ }
+ ]
+}
+```
+Set the following fields: `Access key ID`, `Secret access key`, `STS Region`, `ARN assume role`.
+
+### Role-Based Authorization
+If you are using role-based authorization, set the appropriate permissions:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "iam:PassRole",
+ "Resource": "arn:aws:iam::<<--account-id-->>:role/<<--role_name-->>"
+ },
+ {
+ "Sid": "VisualEditor1",
+ "Effect": "Allow",
+ "Action": [
+ "cloudwatch:DescribeAlarms",
+ "cloudwatch:GetMetricData",
+ "ec2:AssociateIamInstanceProfile",
+ "ec2:ReplaceIamInstanceProfileAssociation"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
+#### Trust Relationships for Role-Based Authorization
+Next, add a principal to the trust relationships of the role you are using:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "Service": [
+ "ec2.amazonaws.com"
+ ]
+ },
+ "Action": [
+ "sts:AssumeRole"
+ ]
+ }
+ ]
+}
+```
+
+**Note**: Using role-based authorization is only possible when you use a Zabbix server or proxy inside AWS.
+
+Set the following fields: `Authorization method`, `AWS Region`, and `Lambda function ARN`.
+
+For more information about managing access keys, see the [official AWS documentation](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys).'),
+('10634',NULL,'Azure VM Scale Set by HTTP','3','-1','2','','','Azure VM Scale Set by HTTP','0',NULL,'This template is designed to monitor Microsoft Azure virtual machine scale sets by HTTP.
+It works without any external scripts and uses the script item.
+
+Setup:
+ 1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+ See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
+ 2. Link the template to a host.
+ 3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','d0fd5d346b1740dda9d3a976371789dd','AZURE VM SCALE SET BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is designed to monitor Microsoft Azure virtual machine scale sets by HTTP.
+It works without any external scripts and uses the script item.
+
+## Setup
+
+1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+
+> See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
+
+2. Link the template to a host.
+3. Configure the host wizard configuration fields: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure scale set ID`.'),
+('10636',NULL,'Huawei OceanStor Dorado by SNMP','3','-1','2','','','Huawei OceanStor Dorado by SNMP','0',NULL,'This template is developed to monitor SAN Huawei OceanStor Dorado via the Zabbix SNMP agent.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/418855-discussion-thread-for-official-zabbix-template-huawei-oceanstor
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','521d864fe8574f19b350f7ddbe259042','HUAWEI OCEANSTOR DORADO BY SNMP','Zabbix','8.0-3',NULL,'0','1','## setup:
+1. Create a host for Huawei OceanStor Dorado with the controller management IP as the SNMP interface.
+
+2. Link the template to the host.
+
+3. Customize macro values if needed.
+
+## overview:
+This template is developed to monitor SAN Huawei OceanStor Dorado via the Zabbix SNMP agent.'),
+('10637',NULL,'Apache by Zabbix agent active','3','-1','2','','','Apache by Zabbix agent active','0',NULL,'Get metrics from mod_status module using HTTP agent.
+https://httpd.apache.org/docs/current/mod/mod_status.html
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/384764-discussion-thread-for-official-zabbix-template-apache
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','aa3286a824464020863ead141e8f0afc','APACHE BY ZABBIX AGENT ACTIVE','Zabbix','8.0-0',NULL,'0','1','## Overview
+
+This template is designed for the effortless deployment of Apache monitoring by Zabbix via Zabbix agent and doesn''t require any external scripts.
+The template `Apache by Zabbix agent` - collects metrics by polling [mod_status](https://httpd.apache.org/docs/current/mod/mod_status.html) locally with Zabbix agent:
+
+```text
+127.0.0.1
+ServerVersion: Apache/2.4.41 (Unix)
+ServerMPM: event
+Server Built: Aug 14 2019 00:35:10
+CurrentTime: Friday, 16-Aug-2019 12:38:40 UTC
+RestartTime: Wednesday, 14-Aug-2019 07:58:26 UTC
+ParentServerConfigGeneration: 1
+ParentServerMPMGeneration: 0
+ServerUptimeSeconds: 189613
+ServerUptime: 2 days 4 hours 40 minutes 13 seconds
+Load1: 4.60
+Load5: 1.20
+Load15: 0.47
+Total Accesses: 27860
+Total kBytes: 33011
+Total Duration: 54118
+CPUUser: 18.02
+CPUSystem: 31.76
+CPUChildrenUser: 0
+CPUChildrenSystem: 0
+CPULoad: .0262535
+Uptime: 189613
+ReqPerSec: .146931
+BytesPerSec: 178.275
+BytesPerReq: 1213.33
+DurationPerReq: 1.9425
+BusyWorkers: 7
+IdleWorkers: 93
+Processes: 4
+Stopping: 0
+BusyWorkers: 7
+IdleWorkers: 93
+ConnsTotal: 13
+ConnsAsyncWriting: 0
+ConnsAsyncKeepAlive: 5
+ConnsAsyncClosing: 0
+Scoreboard: ...
+
+```
+
+It also uses Zabbix agent to collect `Apache` Linux process statistics such as CPU usage, memory usage, and whether the process is running or not.
+
+## Setup
+
+See the setup instructions for [mod_status](https://httpd.apache.org/docs/current/mod/mod_status.html).
+
+Check the availability of the module with this command line: `httpd -M 2>/dev/null | grep status_module`
+
+This is an example configuration of the Apache web server:
+
+```text
+
+ SetHandler server-status
+ Require host example.com
+
+```
+
+If you use another path, then do not forget to change the `Apache status page path` host wizard configuration field.'),
+('10638',NULL,'Website certificate by Zabbix agent 2 active','3','-1','2','','','Website certificate by Zabbix agent 2 active','0',NULL,'The template to monitor TLS/SSL certificate on the website by Zabbix agent 2 that works without any external scripts.
+
+Zabbix agent 2 with the WebCertificate plugin requests certificate using the web.certificate.get key and returns JSON with certificate attributes.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/428309-discussion-thread-for-official-zabbix-template-tls-ssl-certificates-monitoring
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','de38542cf4f24fafab33520677f392c4','WEBSITE CERTIFICATE BY ZABBIX AGENT 2 ACTIVE','Zabbix','8.0-1',NULL,'0','1',E'## Overview
+
+This template is for monitoring a TLS/SSL certificate of a website via Zabbix agent 2, and it works without any external scripts.
+Zabbix agent 2 requests the certificate via the `web.certificate.get` key through the WebCertificate plugin and returns a JSON with certificate attributes.
+
+## Setup
+
+1\\. Set up and configure `zabbix-agent2` with the WebCertificate plugin.
+
+2\\. Test availability: `zabbix_get -s -k web.certificate.get[]`
+
+3\\. Create a host with a Zabbix agent interface.
+
+4\\. Link the template to the host.
+
+5\\. Customize the values of the host wizard configuration field `DNS`, `IP`, and `Port`. `DNS` is a required parameter in the Zabbix agent 2 `web.certificate.get` key, so it must have at least one value set. Other host wizard configuration field may be set as needed (details below). Note that multiple values can be specified, separated by commas. The corresponding values in other host wizard configuration field are processed in the order they are listed (see the table below for examples):
+
+| host wizard configuration field | Value |
+|------------------------|--------------------------------|
+|DNS|hostname_01,hostname_02,hostname_03|
+|Port |port_01,,port_03|
+|IP |,ip_02|
+
+As shown in the example above, the following websites will be discovered:
+
+- Website with the host name `hostname_01` - the host name itself will be used for connection (because the address is set to an empty string); the port is `port_01`.
+- Website with the host name `hostname_02` - will also be used for SNI verification; the address `ip_02` will be used for connection, and the port will default to 443 (because it is set to an empty string).
+- Website the with host name `hostname_03` - the host name itself will be used for connection (because the address is not set and treated as an empty string); the port is `port_03`.
+
+For additional details, please refer to official documentation about the Zabbix agent 2 `web.certificate.get` key:
+https://www.zabbix.com/documentation/8.0/manual/config/items/itemtypes/zabbix_agent/zabbix_agent2#web.certificate.get'),
+('10639',NULL,'Nginx by Zabbix agent active','3','-1','2','','','Nginx by Zabbix agent active','0',NULL,'Get metrics from stub status module using Zabbix agent running on Linux
+https://nginx.ru/en/docs/http/ngx_http_stub_status_module.html
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/384765-discussion-thread-for-official-zabbix-template-nginx
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','d2cebb67b4d94a12a072db85e7be6a33','NGINX BY ZABBIX AGENT ACTIVE','Zabbix','8.0-0',NULL,'0','1','## Overview
+
+This template is developed to monitor Nginx by Zabbix that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template `Nginx by Zabbix agent` - collects metrics by polling the [Module ngx_http_stub_status_module](https://nginx.ru/en/docs/http/ngx_http_stub_status_module.html) locally with Zabbix agent:
+
+```text
+Active connections: 291
+server accepts handled requests
+16630948 16630948 31070465
+Reading: 6 Writing: 179 Waiting: 106
+```
+
+Note that this template doesn''t support HTTPS and redirects (limitations of `web.page.get`).
+
+It also uses Zabbix agent to collect `Nginx` Linux process statistics, such as CPU usage, memory usage and whether the process is running or not.
+
+
+## Setup
+
+See the setup instructions for [ngx_http_stub_status_module](https://nginx.ru/en/docs/http/ngx_http_stub_status_module.html).
+Test the availability of the `http_stub_status_module` `nginx -V 2>&1 | grep -o with-http_stub_status_module`.
+
+Example configuration of Nginx:
+```text
+location = /basic_status {
+ stub_status;
+ allow 127.0.0.1;
+ allow ::1;
+ deny all;
+}
+```
+
+If you use another location, then don''t forget to change the `Nginx status page path` host wizard configuration field.
+
+Example answer from Nginx:
+```text
+Active connections: 291
+server accepts handled requests
+16630948 16630948 31070465
+Reading: 6 Writing: 179 Waiting: 106
+```
+
+Note that this template doesn''t support https and redirects (limitations of web.page.get).'),
+('10640',NULL,'Nutanix Cluster Prism Element by HTTP','3','-1','2','','','Nutanix Cluster Prism Element by HTTP','0',NULL,'Prism Element: It is a service already built into the platform for every Nutanix cluster deployed. It provides the ability to fully configure, manage, and monitor Nutanix clusters running any hypervisors, however, It only manages the cluster it is part of.
+
+This template is designed for the effortless deployment of Nutanix Cluster Prism Element monitoring and doesn''t require any external scripts.
+
+This template can be used in discovery, as well as manually linked to a host - to do so, attach it to the host and manually set the value of the ''{$NUTANIX.CLUSTER.UUID}'' macro.
+
+More details can be found in the official documentation:
+ - on retrieving UUIDs: https://www.nutanixbible.com/19b-cli.html
+ - on the Nutanix Prism Element REST API: https://www.nutanix.dev/api_reference/apis/prism_v2.html
+ - on differences between Nutanix API versions: https://www.nutanix.dev/api-versions/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','b6027e374e424481951ca2256099515c','NUTANIX CLUSTER PRISM ELEMENT BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed for the effortless deployment of Nutanix Cluster Prism Element monitoring and doesn''t require any external scripts.
+
+This template can be used in discovery, as well as manually linked to a host - to do so, attach it to the host and manually set the value of the `Cluster UUID` host wizard configuration field.
+
+More details can be found in the official documentation:
+- on retrieving [UUIDs](https://www.nutanixbible.com/19b-cli.html);
+- on the [Nutanix Prism Element REST API](https://www.nutanix.dev/api_reference/apis/prism_v2.html);
+- on differences between [Nutanix API versions](https://www.nutanix.dev/api-versions/).
+
+## Setup
+
+1. Create a new Nutanix user and add the role "Viewer"
+2. Create a new host
+3. Link the template to the host created earlier
+4. Set the host wizard configuration fields required for getting data:
+```text
+API IP
+API port
+```
+5. Set the host wizard configuration fields with the login and password of the Nutanix user created earlier:
+```text
+API username
+API password
+```
+6. Set the host wizard configuration fields with the UUID of the Nutanix Cluster:
+```text
+Cluster UUID
+```'),
+('10641',NULL,'Nutanix Host Prism Element by HTTP','3','-1','2','','','Nutanix Host Prism Element by HTTP','0',NULL,'Prism Element: It is a service already built into the platform for every Nutanix cluster deployed. It provides the ability to fully configure, manage, and monitor Nutanix clusters running any hypervisors, however, It only manages the cluster it is part of.
+
+This template is designed for the effortless deployment of Nutanix Host Prism Element monitoring and doesn''t require any external scripts.
+
+This template can be used in discovery, as well as manually linked to a host - to do so, attach it to the host and manually set the value of the ''{$NUTANIX.HOST.UUID}'' macro.
+
+More details can be found in the official documentation:
+ - on retrieving UUIDs: https://www.nutanixbible.com/19b-cli.html
+ - on the Nutanix Prism Element REST API: https://www.nutanix.dev/api_reference/apis/prism_v2.html
+ - on differences between Nutanix API versions: https://www.nutanix.dev/api-versions/
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','8ab5387c8887435587cce8383b2fc6c5','NUTANIX HOST PRISM ELEMENT BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed for the effortless deployment of Nutanix Host Prism Element monitoring and doesn''t require any external scripts.
+
+This template can be used in discovery, as well as manually linked to a host - to do so, attach it to the host and manually set the value of the `Host UUID` host wizard configuration field.
+
+More details can be found in the official documentation:
+- on retrieving [UUIDs](https://www.nutanixbible.com/19b-cli.html);
+- on the [Nutanix Prism Element REST API](https://www.nutanix.dev/api_reference/apis/prism_v2.html);
+- on differences between [Nutanix API versions](https://www.nutanix.dev/api-versions/).
+
+## Setup
+
+1. Create a new Nutanix user and add the role "Viewer"
+2. Create a new host
+3. Link the template to the host created earlier
+4. Set the host wizard configuration fields required for getting data:
+```text
+API IP
+API port
+```
+5. Set the host wizard configuration fields with the login and password of the Nutanix user created earlier:
+```text
+API username
+API password
+```
+6. Set the host wizard configuration fields with the UUID of the Nutanix Host:
+```text
+Host UUID
+```'),
+('10642',NULL,'Nutanix Prism Element by HTTP','3','-1','2','','','Nutanix Prism Element by HTTP','0',NULL,'Prism Element: It is a service already built into the platform for every Nutanix cluster deployed. It provides the ability to fully configure, manage, and monitor Nutanix clusters running any hypervisors, however, it only manages the cluster it is part of.
+
+This template is designed for the effortless deployment of Nutanix Prism Element monitoring and doesn''t require any external scripts.
+
+The templates "Nutanix Host Prism Element by HTTP" and "Nutanix Cluster Prism Element by HTTP" can be used in discovery, as well as manually linked to a host.
+
+More details can be found in the official documentation:
+ - on the Nutanix Prism Element REST API: https://www.nutanix.dev/api_reference/apis/prism_v2.html
+ - on the differences between Nutanix API versions: https://www.nutanix.dev/api-versions/
+ - on the differences between Nutanix Prism Element REST API and Nutanix Prism Central REST API: https://next.nutanix.com/how-it-works-22/differences-between-prism-element-prism-central-and-prism-pro-37137
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','0bb43a48a33f48ad910441384486edb4','NUTANIX PRISM ELEMENT BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed for the effortless deployment of Nutanix Prism Element monitoring and doesn''t require any external scripts.
+
+The templates "Nutanix Host Prism Element by HTTP" and "Nutanix Cluster Prism Element by HTTP" can be used in discovery, as well as manually linked to a host.
+
+More details can be found in the official documentation:
+- [on the Nutanix Prism Element REST API](https://www.nutanix.dev/api_reference/apis/prism_v2.html);
+- [on differences between Nutanix API versions](https://www.nutanix.dev/api-versions/).
+
+## Setup
+
+1. Create a new Nutanix user and add the role "Viewer"
+2. Create a new host
+3. Link the template to host created earlier
+4. Set the host wizard configuration fields required for getting data:
+```text
+API IP
+API port
+```
+5. Set the host wizard configuration fields with the login and password of the Nutanix user created earlier:
+```text
+API username
+API password
+```'),
+('10645',NULL,'PHP-FPM by Zabbix agent active','3','-1','2','','','PHP-FPM by Zabbix agent active','0',NULL,'Get PHP-FPM metrics using Zabbix agent running on Linux.
+
+Note that depending on your OS distribution, the PHP-FPM process name may vary. Please, check the actual name in the line "Name" from /proc//status file (https://www.zabbix.com/documentation/8.0/manual/appendix/items/proc_mem_num_notes) and change {$PHP_FPM.PROCESS.NAME.PARAMETER} macro if needed.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','a9e83f950e9f41a78474d523c8376338','PHP-FPM BY ZABBIX AGENT ACTIVE','Zabbix','8.0-1',NULL,'0','1',E'## Overview
+
+This template is developed to monitor the FastCGI Process Manager (PHP-FPM) by Zabbix agent that works without any external scripts.
+Most of the metrics are collected in one go, thanks to Zabbix bulk data collection.
+
+The template `PHP-FPM by Zabbix agent` - collects metrics by polling the PHP-FPM status-page locally with Zabbix agent.
+
+Note that this template doesn''t support HTTPS and redirects (limitations of `web.page.get`).
+
+It also uses Zabbix agent to collect `php-fpm` Linux process statistics, such as CPU usage, memory usage, and whether the process is running or not.
+
+## Setup
+
+Note that depending on your OS distribution, the PHP-FPM executable/service name can vary. RHEL-like distributions usually name both process and service as `php-fpm`, while for Debian/Ubuntu based distributions it may include the version, for example: executable name - `php-fpm8.2`, systemd service name - `php8.2-fpm`. Adjust the following instructions accordingly if needed.
+
+1. Open the PHP-FPM configuration file and enable the status page as shown.
+ ```
+ pm.status_path = /status
+ ping.path = /ping
+ ```
+
+2. Validate the syntax to ensure it is correct before you reload the service. Replace the `` in the command if needed.
+ ```
+ $ php-fpm -t
+ ```
+ or
+ ```
+ $ php-fpm -t
+ ```
+
+3. Reload the `php-fpm` service to make the change active. Replace the `` in the command if needed.
+ ```
+ $ systemctl reload php-fpm
+ ```
+ or
+ ```
+ $ systemctl reload php-fpm
+ ```
+
+4. Next, edit the configuration of your web server.
+
+If you use Nginx, edit the configuration file of your Nginx server block (virtual host) and add the location block below it.
+ ```
+ # Enable php-fpm status page
+ location ~ ^/(status|ping)$ {
+ ## disable access logging for request if you prefer
+ access_log off;
+
+ ## Only allow trusted IPs for security, deny everyone else
+ # allow 127.0.0.1;
+ # allow 1.2.3.4; # your IP here
+ # deny all;
+
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ fastcgi_index index.php;
+ include fastcgi_params;
+ ## Now the port or socket of the php-fpm pool we want the status of
+ fastcgi_pass 127.0.0.1:9000;
+ # fastcgi_pass unix:/run/php-fpm/your_socket.sock;
+ }
+ ```
+If you use Apache, edit the configuration file of the virtual host and add the following location blocks.
+ ```
+
+ Require ip 127.0.0.1
+ # Require ip 1.2.3.4 # Your IP here
+ # Adjust the path to the socket if needed
+ ProxyPass "unix:/run/php-fpm/www.sock|fcgi://localhost/status"
+
+
+
+ Require ip 127.0.0.1
+ # Require ip 1.2.3.4 # Your IP here
+ # Adjust the path to the socket if needed
+ ProxyPass "unix:/run/php-fpm/www.sock|fcgi://localhost/ping"
+
+ ```
+5. Check the web server configuration syntax. The command may vary depending on the OS distribution and web server.
+ ```
+ $ nginx -t
+ ```
+ or
+ ```
+ $ httpd -t
+ ```
+ or
+ ```
+ $ apachectl configtest
+ ```
+
+6. Reload the web server configuration. The command may vary depending on the OS distribution and web server.
+ ```
+ $ systemctl reload nginx
+ ```
+ or
+ ```
+ $ systemctl reload httpd
+ ```
+ or
+ ```
+ $ systemctl reload apache2
+ ```
+
+7. Verify that the pages are available with these commands.
+ ```
+ curl -L 127.0.0.1/status
+ curl -L 127.0.0.1/ping
+ ```
+
+Depending on your OS distribution, the PHP-FPM process name may vary as well. Please check the actual name in the line "Name" from /proc/\\/status file (https://www.zabbix.com/documentation/8.0/manual/appendix/items/proc_mem_num_notes) and change the `Process name` host wizard configuration field if needed.
+
+If you use another location of the status/ping pages, don''t forget to change the `Status page path/Ping page path` host wizard configuration field.
+
+If you use another web server port or scheme for the location of the PHP-FPM status/ping pages, don''t forget to change the host wizard configuration fields `Scheme` and `PHP-FPM port`.'),
+('10646',NULL,'MySQL by Zabbix agent 2 active','3','-1','2','','','MySQL by Zabbix agent 2 active','0',NULL,'Requirements for template operation:
+
+1. Create a MySQL user for monitoring. For example:
+
+CREATE USER ''zbx_monitor''@''%'' IDENTIFIED BY '''';
+GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW ON *.* TO ''zbx_monitor''@''%'';
+
+For more information please read the MySQL documentation https://dev.mysql.com/doc/refman/8.0/en/grant.html.
+
+NOTE: In order to collect replication metrics, MariaDB Enterprise Server 10.5.8-5 and above and MariaDB Community Server 10.5.9 and above require the SLAVE MONITOR privilege to be set for the monitoring user:
+
+GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW,SLAVE MONITOR ON *.* TO ''zbx_monitor''@''%'';
+
+For more information please read the MariaDB documentation https://mariadb.com/docs/server/ref/mdb/privileges/SLAVE_MONITOR/.
+
+2. Set in the {$MYSQL.DSN} macro the data source name of the MySQL instance either session name from Zabbix agent 2 configuration file or URI.
+Examples: MySQL1, tcp://localhost:3306, tcp://172.16.0.10, unix:/var/run/mysql.sock
+For more information about MySQL Unix socket file please read the MySQL documentation https://dev.mysql.com/doc/refman/8.0/en/problems-with-mysql-sock.html.
+
+3. If you had set URI in the {$MYSQL.DSN}, please define the user name and password in host macros ({$MYSQL.USER} and {$MYSQL.PASSWORD}).
+Leave macros {$MYSQL.USER} and {$MYSQL.PASSWORD} empty if you use a session name. Set the user name and password in the Plugins.Mysql.<...> section of your Zabbix agent 2 configuration file.
+For more information about configuring the Zabbix MySQL plugin please read the documentation https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/src/go/plugins/mysql/README.md.
+
+NOTE: In order to use this template for monitoring MySQL version 8.4 and later, Zabbix agent 2 version 8.0.0 and later should be used.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/384189-discussion-thread-for-official-zabbix-template-db-mysql.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','51ffd432b9324ce2b04e1d4dc4122d16','MYSQL BY ZABBIX AGENT 2 ACTIVE','Zabbix','8.0-4',NULL,'0','1','## Setup
+
+**NOTE:** In order to use this template for monitoring MySQL version 8.4 and later, Zabbix agent 2 version 8.0.0 and later should be used.
+
+1. Create a MySQL user for monitoring (`` at your discretion):
+
+```text
+CREATE USER ''zbx_monitor''@''%'' IDENTIFIED BY '''';
+GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW ON *.* TO ''zbx_monitor''@''%'';
+```
+
+For more information, please see MySQL documentation https://dev.mysql.com/doc/refman/8.0/en/grant.html
+
+**NOTE:** In order to collect replication metrics, MariaDB Enterprise Server 10.5.8-5 and above and MariaDB Community Server 10.5.9 and above require the `SLAVE MONITOR` privilege to be set for the monitoring user:
+
+```text
+GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW,SLAVE MONITOR ON *.* TO ''zbx_monitor''@''%'';
+```
+
+For more information please read the MariaDB documentation https://mariadb.com/docs/server/ref/mdb/privileges/SLAVE_MONITOR/
+
+2. Set in the `MySQL DSN` host wizard configuration field the data source name of the MySQL instance either session name from Zabbix agent 2 configuration file or URI.
+**Examples:** MySQL1, tcp://localhost:3306, tcp://172.16.0.10, unix:/var/run/mysql.sock
+For more information about MySQL Unix socket file, see the MySQL documentation https://dev.mysql.com/doc/refman/8.0/en/problems-with-mysql-sock.html.
+
+3. If you had set URI in the `MySQL DSN` field, define the user name and password in `MySQL user` and `MySQL password` host wizard configuration fields.
+Leave fields `MySQL user` and `MySQL password` empty if you use a session name. Set the user name and password in the Plugins.Mysql.<...> section of your Zabbix agent 2 configuration file.
+For more information about configuring the Zabbix MySQL plugin, see the documentation https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/src/go/plugins/mysql/README.md.'),
+('10647',NULL,'MySQL by Zabbix agent active','3','-1','2','','','MySQL by Zabbix agent active','0',NULL,E'Requirements for template operation:
+
+1. Install Zabbix agent and MySQL client. If necessary, add the path to the ''mysql'' and ''mysqladmin'' utilities to the global environment variable PATH.
+
+2. Copy the ''template_db_mysql.conf'' file with user parameters into folder with Zabbix agent configuration (/etc/zabbix/zabbix_agentd.d/ by default). Don''t forget to restart Zabbix agent.
+
+3. Create the MySQL user that will be used for monitoring ('''' at your discretion). For example:
+
+CREATE USER ''zbx_monitor''@''%'' IDENTIFIED BY '''';
+GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW ON *.* TO ''zbx_monitor''@''%'';
+
+For more information, please see MySQL documentation (https://dev.mysql.com/doc/refman/8.0/en/grant.html).
+
+NOTE: In order to collect replication metrics, MariaDB Enterprise Server 10.5.8-5 and above and MariaDB Community Server 10.5.9 and above require the SLAVE MONITOR privilege to be set for the monitoring user:
+
+GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW,SLAVE MONITOR ON *.* TO ''zbx_monitor''@''%'';
+
+For more information, please read the MariaDB documentation (https://mariadb.com/docs/server/ref/mdb/privileges/SLAVE_MONITOR/).
+
+4. Create ''.my.cnf'' configuration file in the home directory of Zabbix agent for Linux distributions (/var/lib/zabbix by default) or ''my.cnf'' in c:\\ for Windows. For example:
+
+[client]
+protocol=tcp
+user=''zbx_monitor''
+password=''''
+
+For more information, please see MySQL documentation (https://dev.mysql.com/doc/refman/8.0/en/option-files.html).
+
+NOTE: Linux distributions that use SELinux may require additional steps for access configuration.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/384189-discussion-thread-for-official-zabbix-template-db-mysql
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','1ae69b01417849b180717f62ad7819d6','MYSQL BY ZABBIX AGENT ACTIVE','Zabbix','8.0-3',NULL,'0','1',E'## Setup
+
+1. Install MySQL client. If necessary, add the path to the `mysql` and `mysqladmin` utilities to the global environment variable PATH.
+2. Copy the `template_db_mysql.conf` file with user parameters into folder with Zabbix agent configuration (/etc/zabbix/zabbix_agentd.d/ by default). Don''t forget to restart Zabbix agent.
+3. Create the MySQL user that will be used for monitoring (`` at your discretion). For example:
+
+```text
+CREATE USER ''zbx_monitor''@''%'' IDENTIFIED BY '''';
+GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW ON *.* TO ''zbx_monitor''@''%'';
+```
+
+For more information, please see [`MySQL documentation`](https://dev.mysql.com/doc/refman/8.0/en/grant.html).
+
+4. Create `.my.cnf` configuration file in the home directory of Zabbix agent for Linux distributions (/var/lib/zabbix by default) or `my.cnf` in c:\\ for Windows. For example:
+
+```text
+[client]
+protocol=tcp
+user=''zbx_monitor''
+password=''''
+```
+
+For more information, please see [`MySQL documentation`](https://dev.mysql.com/doc/refman/8.0/en/option-files.html).
+
+**NOTE:** In order to collect replication metrics, MariaDB Enterprise Server 10.5.8-5 and above and MariaDB Community Server 10.5.9 and above require the `SLAVE MONITOR` privilege to be set for the monitoring user:
+
+```text
+GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW,SLAVE MONITOR ON *.* TO ''zbx_monitor''@''%'';
+```
+
+For more information, please read the [`MariaDB documentation`](https://mariadb.com/docs/server/ref/mdb/privileges/SLAVE_MONITOR/).
+
+NOTE: Linux distributions that use SELinux may require additional steps for access configuration.
+
+For example, the following rule could be added to the SELinux policy:
+
+```text
+# cat < zabbix_home.te
+module zabbix_home 1.0;
+
+require {
+ type zabbix_agent_t;
+ type zabbix_var_lib_t;
+ type mysqld_etc_t;
+ type mysqld_port_t;
+ type mysqld_var_run_t;
+ class file { open read };
+ class tcp_socket name_connect;
+ class sock_file write;
+}
+
+#============= zabbix_agent_t ==============
+
+allow zabbix_agent_t zabbix_var_lib_t:file read;
+allow zabbix_agent_t zabbix_var_lib_t:file open;
+allow zabbix_agent_t mysqld_etc_t:file read;
+allow zabbix_agent_t mysqld_port_t:tcp_socket name_connect;
+allow zabbix_agent_t mysqld_var_run_t:sock_file write;
+EOF
+# checkmodule -M -m -o zabbix_home.mod zabbix_home.te
+# semodule_package -o zabbix_home.pp -m zabbix_home.mod
+# semodule -i zabbix_home.pp
+# restorecon -R /var/lib/zabbix
+```'),
+('10648',NULL,'PostgreSQL by Zabbix agent 2 active','3','-1','2','','','PostgreSQL by Zabbix agent 2 active','0',NULL,'This template is designed for the deployment of PostgreSQL monitoring by Zabbix via Zabbix agent 2 and uses a loadable plugin to run SQL queries.
+
+Setup:
+
+1. Deploy Zabbix agent 2 with the PostgreSQL plugin. Starting with Zabbix versions 6.0.10 / 6.2.4 / 6.4 PostgreSQL metrics are moved to a loadable plugin and require installation of a separate package or compilation of the plugin from sources (https://www.zabbix.com/documentation/8.0/manual/extensions/plugins/build).
+
+2. Create the PostgreSQL user for monitoring (`` at your discretion) and inherit permissions from the default role `pg_monitor`:
+CREATE USER zbx_monitor WITH PASSWORD '''' INHERIT;
+GRANT pg_monitor TO zbx_monitor;
+
+3. Edit the `pg_hba.conf` configuration file to allow connections for the user `zbx_monitor`. You can check the PostgreSQL documentation for examples (https://www.postgresql.org/docs/current/auth-pg-hba-conf.html).
+
+4. Set the connection string for the PostgreSQL instance in the `{$PG.CONNSTRING.AGENT2}` macro as URI, such as ``, or specify the named session - ``.
+
+Note: if you want to use SSL/TLS encryption to protect communications with the remote PostgreSQL instance, a named session must be used. In that case, the instance URI should be specified in the `Plugins.PostgreSQL.Sessions.*.Uri` parameter in the PostgreSQL plugin configuration files alongside all the encryption parameters (type, certificate/key filepaths if needed etc.).
+
+You can check the PostgreSQL plugin documentation (https://git.zabbix.com/projects/AP/repos/postgresql/browse?at=refs%2Fheads%2Frelease%2F8.0) for details about agent plugin parameters and named sessions.
+
+Also, it is assumed that you set up the PostgreSQL instance to work in the desired encryption mode. Check the PostgreSQL documentation (https://www.postgresql.org/docs/current/ssl-tcp.html) for details.
+
+Note that plugin TLS certificate validation relies on checking the Subject Alternative Names (SAN) instead of the Common Name (CN), check the cryptography package documentation (https://pkg.go.dev/crypto/x509) for details.
+
+For example, to enable required encryption in transport mode without identity checks you could create the file `/etc/zabbix/zabbix_agent2.d/postgresql_myconn.conf` with the following configuration for the named session `myconn` (replace `` with the address of the PostgreSQL instance):
+Plugins.PostgreSQL.Sessions.myconn.Uri=tcp://:5432
+Plugins.PostgreSQL.Sessions.myconn.TLSConnect=required
+
+Then set the `{$PG.CONNSTRING.AGENT2}` macro to `myconn` to use this named session.
+
+5. Set the password that you specified in step 2 in the macro `{$PG.PASSWORD}`.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/384190-%C2%A0discussion-thread-for-official-zabbix-template-db-postgresql
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','21cca24cec1d40cdb0c2999aa6ac3037','POSTGRESQL BY ZABBIX AGENT 2 ACTIVE','Zabbix','8.0-0',NULL,'0','1','## Overview
+
+This template is designed for the deployment of PostgreSQL monitoring by Zabbix via Zabbix agent 2 and uses a loadable plugin to run SQL queries.
+
+## Setup
+
+1. Create the PostgreSQL user for monitoring (`` at your discretion) and inherit permissions from the default role `pg_monitor`:
+
+```sql
+CREATE USER zbx_monitor WITH PASSWORD '''' INHERIT;
+GRANT pg_monitor TO zbx_monitor;
+```
+
+2. Edit the `pg_hba.conf` configuration file to allow connections for the user `zbx_monitor`. For example, you could add one of the following rows to allow local TCP connections from the same host:
+
+```bash
+# TYPE DATABASE USER ADDRESS METHOD
+ host all zbx_monitor localhost trust
+ host all zbx_monitor 127.0.0.1/32 md5
+ host all zbx_monitor ::1/128 scram-sha-256
+```
+
+For more information please read the PostgreSQL documentation `https://www.postgresql.org/docs/current/auth-pg-hba-conf.html`.
+
+3. Set the connection string for the PostgreSQL instance in the `PostgreSQL connection string` host wizard configuration field as URI, such as ``, or specify the named session - ``.
+
+**Note:** if you want to use SSL/TLS encryption to protect communications with the remote PostgreSQL instance, a named session must be used. In that case, the instance URI should be specified in the `Plugins.PostgreSQL.Sessions.*.Uri` parameter in the PostgreSQL plugin configuration files alongside all the encryption parameters (type, certificate/key filepaths if needed etc.).
+
+You can check the [`PostgreSQL plugin documentation`](https://git.zabbix.com/projects/AP/repos/postgresql/browse?at=refs%2Fheads%2Frelease%2F8.0) for details about agent plugin parameters and named sessions.
+
+Also, it is assumed that you set up the PostgreSQL instance to work in the desired encryption mode. Check the [`PostgreSQL documentation`](https://www.postgresql.org/docs/current/ssl-tcp.html) for details.
+
+**Note:** plugin TLS certificate validation relies on checking the Subject Alternative Names (SAN) instead of the Common Name (CN), check the cryptography package [`documentation`](https://pkg.go.dev/crypto/x509) for details.
+
+For example, to enable required encryption in transport mode without identity checks you could create the file `/etc/zabbix/zabbix_agent2.d/postgresql_myconn.conf` with the following configuration for the named session `myconn` (replace `` with the address of the PostgreSQL instance):
+
+```bash
+Plugins.PostgreSQL.Sessions.myconn.Uri=tcp://:5432
+Plugins.PostgreSQL.Sessions.myconn.TLSConnect=required
+```
+
+Then set the `PostgreSQL connection string` field to `myconn` to use this named session.
+
+4. Set the password that you specified in step 2 in the `PostgreSQL user password` field.'),
+('10649',NULL,'PostgreSQL by Zabbix agent active','3','-1','2','','','PostgreSQL by Zabbix agent active','0',NULL,'This template is designed for the deployment of PostgreSQL monitoring by Zabbix via Zabbix agent and uses user parameters to run SQL queries with the `psql` command-line tool.
+
+Note:
+- The template requires `pg_isready` and `psql` utilities to be installed on the same host with Zabbix agent.
+- The template requires files with SQL queries and user parameters that can be found in the Zabbix official repository:
+https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/templates/db/postgresql?at=refs%2Fheads%2Frelease%2F6.0
+
+Setup:
+
+1. Deploy Zabbix agent and create the PostgreSQL user for monitoring (`` at your discretion) with proper access rights to your PostgreSQL instance.
+
+For PostgreSQL version 10 and above:
+CREATE USER zbx_monitor WITH PASSWORD '''' INHERIT;
+GRANT pg_monitor TO zbx_monitor;
+
+For PostgreSQL version 9.6 and below:
+CREATE USER zbx_monitor WITH PASSWORD '''';
+GRANT SELECT ON pg_stat_database TO zbx_monitor;
+ALTER USER zbx_monitor WITH SUPERUSER;
+
+2. Copy the `postgresql/` directory to the `zabbix` user home directory - `/var/lib/zabbix/`. The `postgresql/` directory contains the files with SQL queries needed to obtain metrics from PostgreSQL instance.
+
+If the home directory of the `zabbix` user doesn''t exist, create it first:
+mkdir -m u=rwx,g=rwx,o= -p /var/lib/zabbix
+chown zabbix:zabbix /var/lib/zabbix
+
+3. Copy the `template_db_postgresql.conf` file, containing user parameters, to the Zabbix agent configuration directory `/etc/zabbix/zabbix_agentd.d/` and restart Zabbix agent service.
+
+If you want to use SSL/TLS encryption to protect communications with the remote PostgreSQL instance, you can modify the connection string in user parameters. For example, to enable required encryption in transport mode without identity checks you could append `?sslmode=required` to the end of the connection string for all keys that use `psql`:
+UserParameter=pgsql.bgwriter[*], psql -qtAX postgresql://"$3":"$4"@"$1":"$2"/"$5"?sslmode=required -f "/var/lib/zabbix/postgresql/pgsql.bgwriter.sql"
+
+Consult the PostgreSQL documentation about protection modes (https://www.postgresql.org/docs/current/libpq-ssl.html#LIBPQ-SSL-PROTECTION) and client connection parameters (https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNECT-SSLMODE).
+
+Also, it is assumed that you set up the PostgreSQL instance to work in the desired encryption mode. Check the PostgreSQL documentation (https://www.postgresql.org/docs/current/ssl-tcp.html) for details.
+
+4. Edit the `pg_hba.conf` configuration file to allow connections for the user `zbx_monitor`. You can check the PostgreSQL documentation for examples (https://www.postgresql.org/docs/current/auth-pg-hba-conf.html).
+
+5. Specify the host name or IP address in the `{$PG.HOST}` macro. Adjust the port number with `{$PG.PORT}` macro if needed.
+
+6. Set the password that you specified in step 1 in the macro `{$PG.PASSWORD}`.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/384190-%C2%A0discussion-thread-for-official-zabbix-template-db-postgresql
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','7005acc9123e4bc290805a3a16dab9cf','POSTGRESQL BY ZABBIX AGENT ACTIVE','Zabbix','8.0-0',NULL,'0','1','## Overview
+
+This template is designed for the deployment of PostgreSQL monitoring by Zabbix via Zabbix agent and uses user parameters to run SQL queries with the `psql` command-line tool.
+
+## Setup
+
+**Note:**
+- The template requires `pg_isready` and `psql` utilities to be installed on the same host with Zabbix agent.
+
+1. Create the PostgreSQL user for monitoring (`` at your discretion) with proper access rights to your PostgreSQL instance.
+
+For PostgreSQL version 10 and above:
+
+```sql
+CREATE USER zbx_monitor WITH PASSWORD '''' INHERIT;
+GRANT pg_monitor TO zbx_monitor;
+```
+
+For PostgreSQL version 9.6 and below:
+
+```sql
+CREATE USER zbx_monitor WITH PASSWORD '''';
+GRANT SELECT ON pg_stat_database TO zbx_monitor;
+
+-- To collect WAL metrics, the user must have a `superuser` role.
+ALTER USER zbx_monitor WITH SUPERUSER;
+```
+
+2. Copy the `postgresql/` directory to the `zabbix` user home directory - `/var/lib/zabbix/`. The `postgresql/` directory contains the files with SQL queries needed to obtain metrics from PostgreSQL instance.
+
+If the home directory of the `zabbix` user doesn''t exist, create it first:
+
+```bash
+mkdir -m u=rwx,g=rwx,o= -p /var/lib/zabbix
+chown zabbix:zabbix /var/lib/zabbix
+```
+
+3. Copy the `template_db_postgresql.conf` file, containing user parameters, to the Zabbix agent configuration directory `/etc/zabbix/zabbix_agentd.d/` and restart Zabbix agent service.
+
+**Note:** if you want to use SSL/TLS encryption to protect communications with the remote PostgreSQL instance, you can modify the connection string in user parameters. For example, to enable required encryption in transport mode without identity checks you could append `?sslmode=required` to the end of the connection string for all keys that use `psql`:
+
+```bash
+UserParameter=pgsql.bgwriter[*], psql -qtAX postgresql://"$3":"$4"@"$1":"$2"/"$5"?sslmode=required -f "/var/lib/zabbix/postgresql/pgsql.bgwriter.sql"
+```
+
+Consult the PostgreSQL documentation about [`protection modes`](https://www.postgresql.org/docs/current/libpq-ssl.html#LIBPQ-SSL-PROTECTION) and [`client connection parameters`](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNECT-SSLMODE).
+
+Also, it is assumed that you set up the PostgreSQL instance to work in the desired encryption mode. Check the [`PostgreSQL documentation`](https://www.postgresql.org/docs/current/ssl-tcp.html) for details.
+
+4. Edit the `pg_hba.conf` configuration file to allow connections for the user `zbx_monitor`. For example, you could add one of the following rows to allow local TCP connections from the same host:
+
+```bash
+# TYPE DATABASE USER ADDRESS METHOD
+ host all zbx_monitor localhost trust
+ host all zbx_monitor 127.0.0.1/32 md5
+ host all zbx_monitor ::1/128 scram-sha-256
+```
+
+For more information please read the PostgreSQL documentation `https://www.postgresql.org/docs/current/auth-pg-hba-conf.html`.
+
+5. Specify the host name or IP address in the `PostgreSQL host` host wizard configuration field. Adjust the port number in the `PostgreSQL port` field if needed.
+
+6. Set the password that you specified in step 1 in the `PostgreSQL user password` field.'),
+('10650',NULL,'Nvidia by Zabbix agent 2 active','3','-1','2','','','Nvidia by Zabbix agent 2 active','0',NULL,'This template is designed for Nvidia GPU monitoring and doesn''t require any external scripts.
+1. Setup and configure Zabbix agent 2 compiled with the Nvidia monitoring plugin.
+2. Create a host and attach the template to it.
+All Nvidia GPUs will be discovered. Set filters with macros if you want to override default filter parameters.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','7297d66e419543c6b83dd8cfe5eb4fb7','NVIDIA BY ZABBIX AGENT 2 ACTIVE','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed for Nvidia GPU monitoring and doesn''t require any external scripts.
+All Nvidia GPUs will be discovered. Set filters with host wizard configuration fields if you want to override default filter parameters.
+
+## Setup
+
+1. Set up and configure Zabbix agent 2 compiled with the Nvidia monitoring plugin.
+2. Create a host and attach the template to it.
+
+Test availability: `zabbix_get -s nvidia-host -k nvml.system.driver.version`'),
+('10651',NULL,'Nvidia by Zabbix agent 2','3','-1','2','','','Nvidia by Zabbix agent 2','0',NULL,'This template is designed for Nvidia GPU monitoring and doesn''t require any external scripts.
+1. Setup and configure Zabbix agent 2 compiled with the Nvidia monitoring plugin.
+2. Create a host with Zabbix agent interface and attach the template to it.
+All Nvidia GPUs will be discovered. Set filters with macros if you want to override default filter parameters.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','32a39c8aca9445df862e9f3e1369c19a','NVIDIA BY ZABBIX AGENT 2','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed for Nvidia GPU monitoring and doesn''t require any external scripts.
+All Nvidia GPUs will be discovered. Set filters with host wizard configuration fields if you want to override default filter parameters.
+
+## Setup
+
+1. Set up and configure Zabbix agent 2 compiled with the Nvidia monitoring plugin.
+2. Create a host with a Zabbix agent interface and attach the template to it.
+
+Test availability: `zabbix_get -s nvidia-host -k nvml.system.driver.version`'),
+('10652',NULL,'Azure SQL Managed Instance by HTTP','3','-1','2','','','Azure SQL Managed Instance by HTTP','0',NULL,'This template is designed to monitor Azure SQL Managed Instance by HTTP.
+It works without any external scripts and uses the script item.
+
+Setup:
+ 1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+ See https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli for more details.
+ 2. Link the template to a host.
+ 3. Configure the macros: {$AZURE.APP.ID}, {$AZURE.PASSWORD}, {$AZURE.TENANT.ID}, {$AZURE.SUBSCRIPTION.ID}, and {$AZURE.RESOURCE.ID}.
+
+You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/.
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','a93f57ccc68e442da79bf4a20fe46570','AZURE SQL MANAGED INSTANCE BY HTTP','Zabbix','8.0-2',NULL,'0','1','## Overview
+
+This template is designed to monitor Microsoft Azure SQL Managed Instance by HTTP.
+It works without any external scripts and uses the script item.
+
+## Setup
+
+1. Create an Azure service principal via the Azure command-line interface (Azure CLI) for your subscription.
+
+ `az ad sp create-for-rbac --name zabbix --role reader --scope /subscriptions/`
+
+> See [Azure documentation](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) for more details.
+
+2. Link the template to a host.
+3. Configure the host wizard configuration fields: `Azure App ID`, `Azure password`, `Azure tenant ID`, `Azure subscription ID`, and `Azure SQL managed instance ID`.'),
+('10654',NULL,'Juniper MX by SNMP','3','-1','2','','','Juniper MX by SNMP','0',NULL,'The template for monitoring Juniper MX Series by SNMP.
+
+MIBs used:
+SNMPv2-MIB
+EtherLike-MIB
+HOST-RESOURCES-MIB
+IF-MIB
+OSPF-MIB
+JUNIPER-ALARM-MIB
+JUNIPER-DOM-MIB
+JUNIPER-MIB
+BGP4-V2-MIB-JUNIPER
+OSPFV3-MIB-JUNIPER
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','fe7eb8b22ce84017b07bcab36e9032dc','JUNIPER MX BY SNMP','Zabbix','8.0-2',NULL,'0','1','The template for monitoring Juniper MX Series by SNMP.
+
+ MIBs used:
+ SNMPv2-MIB
+ EtherLike-MIB
+ HOST-RESOURCES-MIB
+ IF-MIB
+ OSPF-MIB
+ JUNIPER-ALARM-MIB
+ JUNIPER-DOM-MIB
+ JUNIPER-MIB
+ BGP4-V2-MIB-JUNIPER
+ OSPFV3-MIB-JUNIPER'),
+('10655',NULL,'Palo Alto PA-440 by HTTP','3','-1','2','','','Palo Alto PA-440 by HTTP','0',NULL,'This template is designed for the effortless deployment of Palo Alto PA-440 monitoring by Zabbix via XML API and doesn''t require any external scripts.
+
+Setup:
+
+Configure a user for monitoring. Note that in order to retrieve the device certificate information, superuser privileges are required. If you opt for a user with limited access (for security reasons), the device certificate expiration metrics will not be discovered.
+
+Superuser privileges user (full access to all data):
+1. Add a new administrator user. Go to "Device" > "Administrators" and click "Add".
+2. Enter the necessary details. Set the "Administrator Type" to "Dynamic" and select the built-in "Superuser" role. Commit the changes.
+
+Limited privileges user (no access to device certificate data):
+1. Create a new Admin Role. Go to "Device" > "Admin Role" and click "Add".
+2. Enter the necessary details. Adjust the list of permissions:
+- Restrict access to all sections in the "Web UI" tab
+- Allow access to the "Configuration" and "Operational Requests" sections in the "XML API" tab
+- Check that the access to CLI is set to "None" in the "Command Line" tab
+- Restrict access to all sections in the "REST API" tab
+3. Add a new administrator user. Go to "Device" > "Administrators" and click "Add".
+4. Enter the necessary details. Set the "Administrator Type" to "Role Based" and select the profile that was created in the previous steps. Commit the changes.
+
+Set the host macros:
+1. Set the firewall XML API endpoint URL in the "{$PAN.PA440.API.URL}" macro in the format "://[:port]/api" (port is optional).
+2. Set the name of the user that you created in the "{$PAN.PA440.USER}" macro.
+3. Set the password of the user that you created in the "{$PAN.PA440.PASSWORD}" macro.
+
+For more details about PAN-OS API, refer to the official documentation:
+https://docs.paloaltonetworks.com/pan-os/11-1/pan-os-panorama-api
+
+Generated by official Zabbix template tool "Templator"','1','1','','','','','0','0','edc752f178f94b9dbaee459ec7bacc66','PALO ALTO PA-440 BY HTTP','Zabbix','8.0-1',NULL,'0','1','## Overview
+
+This template is designed for the effortless deployment of Palo Alto PA-440 monitoring by Zabbix via XML API and doesn''t require any external scripts.
+
+For more details about PAN-OS API, refer to the [official documentation](https://docs.paloaltonetworks.com/pan-os/11-1/pan-os-panorama-api).
+
+## Setup
+
+Configure a user for monitoring. Note that in order to retrieve the device certificate information, superuser privileges are required. If you opt for a user with limited access (for security reasons), the device certificate expiration metrics will not be discovered.
+
+Superuser privileges user (full access to all data):
+1. Add a new administrator user. Go to `Device` > `Administrators` and click `Add`.
+2. Enter the necessary details. Set the `Administrator Type` to `Dynamic` and select the built-in `Superuser` role. Commit the changes.
+
+Limited privileges user (no access to device certificate data):
+1. Create a new Admin Role. Go to `Device` > `Admin Role` and click `Add`.
+2. Enter the necessary details. Adjust the list of permissions:
+- Restrict access to all sections in the `Web UI` tab
+- Allow access to the `Configuration` and `Operational Requests` sections in the `XML API` tab
+- Check that the access to CLI is set to `None` in the `Command Line` tab
+- Restrict access to all sections in the `REST API` tab
+3. Add a new administrator user. Go to `Device` > `Administrators` and click `Add`.
+4. Enter the necessary details. Set the `Administrator Type` to `Role Based` and select the profile that was created in the previous steps. Commit the changes.
+
+Set the host wizard configuration fields:
+1. Set the firewall XML API endpoint URL in the `URL` in the format `