diff options
author | Tikhon Uskov <tikhon.uskov@zabbix.com> | 2021-04-15 11:53:27 +0300 |
---|---|---|
committer | Tikhon Uskov <tikhon.uskov@zabbix.com> | 2021-04-15 11:53:27 +0300 |
commit | 0f46808033994d2a2587d573423499f15d41658a (patch) | |
tree | 683bc3d59ae9dc4e0ab61992075bffaefce7a581 /templates | |
parent | 78f46e063d6783943829c700d5ca8f726c1b2099 (diff) |
.........T [ZBXNEXT-6592] fixed after review
Diffstat (limited to 'templates')
-rw-r--r-- | templates/media/manageengine_servicedesk/README.md | 31 | ||||
-rw-r--r-- | templates/media/manageengine_servicedesk/media_manageengine_servicedesk.yaml | 142 |
2 files changed, 93 insertions, 80 deletions
diff --git a/templates/media/manageengine_servicedesk/README.md b/templates/media/manageengine_servicedesk/README.md index 4403eca67c8..ff8e6a9a7e6 100644 --- a/templates/media/manageengine_servicedesk/README.md +++ b/templates/media/manageengine_servicedesk/README.md @@ -3,16 +3,16 @@ This guide describes how to integrate Zabbix 5.4 installation with ManageEngine ServiceDesk (both on-premise and on-demand) using the Zabbix webhook feature. This guide provides instructions on setting up a media type, a user and an action in Zabbix.<br> Please note that recovery and update operations are supported only for trigger-based events. -### Setting up ManageEngine ServiceDesk +## Setting up ManageEngine ServiceDesk At first, create a user for API or use an existing one. -## Setting up the on-premise installation +### Setting up the on-premise installation 1\. Go to *Admin -> Technicians*.<br> 2\. Click the *Add New Technician* link, enter the Technician details and provide login permission.<br> 3\. Click *Generate link* under the API key details block. Select a time frame for the key to expire using the Calendar icon, or simply retain the same key perpetually.<br> 4\. Save TEHNICAN_KEY for use in Zabbix later.<br> -## Setting up the on-demand installation +### Setting up the on-demand installation 1\. Go to [Zoho Developer Console](https://api-console.zoho.com/).<br> 2\. Choose *Self Client* from the list of client types, and click *Create Now*.<br> 3\. Click OK in the pop up to enable a self client for your account.<br> @@ -21,18 +21,27 @@ At first, create a user for API or use an existing one. 6\. Select the *Time Duration* for which the grant token is valid. Please note that after this time, the grant token expires.<br> 7\. Enter a description and click *Generate*.<br> 8\. The generated code for the specified scope is displayed. Copy the grant code.<br> -9\. Make a POST request with the following URL.<br> -```https://accounts.zoho.com/oauth/v2/token?code=1000.f74e7b6fc16c95bbc1fa2f067962f84b.9768e796b6273774817032613ba6892a&grant_type=authorization_code&client_id=1000.15S25B602CISR5WO9RUZ8UT39O3RIH&client_secret=9ea302935eb150d9d6cbefd35b1eb8891332d815b8&redirect_uri=https://www.zoho.com```<br> +9\. Make a POST request with the URL params following parameters:<br> +- **code**: enter the Grant Token / Authorization Code generated from previous step. +- **grant_type**: enter the value as "authorization_code". +- **client_id**: specify client_id obtained in step 4. +- **client_secret**: specify client_secret obtained in step 4. +- **redirect_uri**: specify the Callback URL that you registered during the app registration. You can use any ULR for Self client mode, *https://www.zoho.com* for example. + +Example: +```curl -X POST https://accounts.zoho.com/oauth/v2/token?code=1000.f74e7b6fc16c95bbc1fa2f067962f84b.9768e796b6273774817032613ba6892a&grant_type=authorization_code&client_id=1000.15S25B602CISR5WO9RUZ8UT39O3RIH&client_secret=9ea302935eb150d9d6cbefd35b1eb8891332d815b8&redirect_uri=https://www.zoho.com```<br> Use your domain-specific Zoho accounts URL when you make the request.<br> +- For US: https://accounts.zoho.com +- For AU: https://accounts.zoho.com.au - For EU: https://accounts.zoho.eu -- For CN: https://accounts.zoho.com.cn - For IN: https://accounts.zoho.in +- For CN: https://accounts.zoho.com.cn 10\. If the request is successful, you will receive the following output:<br> ```{ “access_token”: “1000.2370ff1fd75e968ae780cd8d14841e82.03518d2d1dab9c6c4cf74ae82b89defa”, “refresh_token”: “1000.2afabf2f5a396325e88f715c6de34d12.edce6130ca3832a14e5f80d005a5324d”, “token_type”: “Bearer”, “expires_in”: 3600 }```<br> Save the *refresh_token* for using in Zabbix later. -### Setting up the webhook in Zabbix +## Setting up the webhook in Zabbix 1\. In the *Administration > Media types* section, import [media_manageengine_servicedesk.yaml](media_manageengine_servicedesk.yaml). 2\. Open the newly added **ManageEngine ServiceDesk** media type and replace all *<PLACEHOLDERS>* with your values.<br> @@ -40,11 +49,11 @@ The following parameters are required:<br> **sd_on_premise** - true or false. Pass *true* if you are using on-premise installation and *false* if not.<br> **sd_url** - the URL of your instance.<br> -The following parameters are required for on-premise servicedesk:<br> +The following parameters are required for on-premise ServiceDesk:<br> **sd_on_premise_auth_token** - the TEHNICAN_KEY generated earlier.<br> **field_ref:requester** - login of the account used for request creation.<br> -The following parameters are required for on-demand servicedesk:<br> +The following parameters are required for on-demand ServiceDesk:<br> **sd_url_auth** - your domain-specific Zoho accounts URL for refreshing access token.<br> **sd_on_demand_client_id**, **sd_on_demand_client_secret**, **sd_on_demand_refresh_token** - created earlier authentication details.<br> **field_ref:requester** - requester's displaying name. You can remove this parameter or use any name. *"Zabbix"*, for example. <br> @@ -55,10 +64,10 @@ Make sure this user has access to all hosts, for which you would like problem no ## Customize your requests You can add any data to ServiceDesk or user-defined fields.<br> -Please see the [Om-demand](https://www.manageengine.com/products/service-desk/sdpod-v3-api/SDPOD-V3-API.html#add-request) and [On-premise]( +Please see the [On-demand](https://www.manageengine.com/products/service-desk/sdpod-v3-api/SDPOD-V3-API.html#add-request) and [On-premise]( https://ui.servicedeskplus.com/APIDocs3/index.html#add-request) API specification for details about fields.<br> Most of fields should be filled as single-line string, other should be an object with *name* property. Zabbix can fill both, but not *"date"* fields.<br> -Fields shoud be in format **field_string:fieldname**, where:<br> +Fields should be in format **field_string:fieldname**, where:<br> **field** - can be *field* or *udf_field*. The prefix for payload generator.<br> **string** - should be *string* for single-line strings or any other for objects.<br> **:** - separator between prefix and field name.<br> diff --git a/templates/media/manageengine_servicedesk/media_manageengine_servicedesk.yaml b/templates/media/manageengine_servicedesk/media_manageengine_servicedesk.yaml index 6ce6b9528ef..4da48d6dc03 100644 --- a/templates/media/manageengine_servicedesk/media_manageengine_servicedesk.yaml +++ b/templates/media/manageengine_servicedesk/media_manageengine_servicedesk.yaml @@ -1,6 +1,6 @@ zabbix_export: version: '5.4' - date: '2021-04-12T06:46:03Z' + date: '2021-04-15T08:50:14Z' media_types: - name: 'ManageEngine ServiceDesk' @@ -110,15 +110,14 @@ zabbix_export: }, createLink: function (id, url) { - if (MEngine.params.on_premise.toLowerCase() === 'true') { - return url + (url.endsWith('/') ? '' : '/') + 'WorkOrder.do?woMode=viewWO&woID=' + id; - } - else { - return url + (url.endsWith('/') ? '' : '/') + 'app/itdesk/ui/requests/' + id + '/details'; - } + return url + (url.endsWith('/') ? '' : '/') + + ((MEngine.params.on_premise.toLowerCase() === 'true') + ? ('WorkOrder.do?woMode=viewWO&woID=' + id) + : ('app/itdesk/ui/requests/' + id + '/details') + ); }, - setToken: function () { + refreshAccessToken: function () { [ 'url_auth', 'on_demand_refresh_token', @@ -134,9 +133,9 @@ zabbix_export: var response, request = new HttpRequest(), url = MEngine.params.url_auth + - 'refresh_token=' + MEngine.params.on_demand_refresh_token + - '&grant_type=refresh_token&client_id=' + MEngine.params.on_demand_client_id + - '&client_secret=' + MEngine.params.on_demand_client_secret + + '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) { @@ -150,18 +149,26 @@ zabbix_export: Zabbix.log(4, '[ ManageEngine Webhook ] Received response with status code ' + request.getStatus() + '\n' + response); - if (request.getStatus() < 200 || request.getStatus() >= 300) { - throw 'Access token resresh failed with status code ' + request.getStatus() + + 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 = JSON.parse(response).access_token; + 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; @@ -181,15 +188,16 @@ zabbix_export: data = JSON.stringify(data); } - Zabbix.log(4, '[ ManageEngine Webhook ] Sending request: ' + url + '?input_data=' + encodeURIComponent(data)); + input = 'input_data=' + encodeURIComponent(data); + Zabbix.log(4, '[ ManageEngine Webhook ] Sending request: ' + url + '?' + input); switch (method) { case 'post': - response = request.post(url + '?input_data=' + encodeURIComponent(data)); + response = request.post(url, input); break; case 'put': - response = request.put(url + '?input_data=' + encodeURIComponent(data)); + response = request.put(url, input); break; default: @@ -204,8 +212,6 @@ zabbix_export: } catch (error) { Zabbix.log(4, '[ ManageEngine Webhook ] Failed to parse response received from ManageEngine'); - throw 'Failed to parse response received from ManageEngine.\nRequest status code ' + - request.getStatus() + '. Check debug log for more information.'; } if ((request.getStatus() < 200 || request.getStatus() >= 300) @@ -216,7 +222,9 @@ zabbix_export: 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].message) { + 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; } @@ -236,51 +244,49 @@ zabbix_export: var data = {}, result; - if (typeof fields === 'object' && Object.keys(fields).length) { - if (isNote) { - data.description = fields['field_string:description']; - 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)] = fields[field]; - } - else { - root[field.substring(field.indexOf(':') + 1)] = { - name: fields[field] - }; - } + if (isNote) { + data.description = fields['field_string:description']; + 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; } - catch (error) { - Zabbix.log(4, '[ ManageEngine Webhook ] Can\'t parse field "' + field + - '". The field ignored.'); + else if (prefix.startsWith('udf_')) { + root = data.udf_fields; + } + else { + root = data; + } + + if (prefix.endsWith('string')) { + root[field.substring(field.indexOf(':') + 1)] = fields[field]; + } + else { + root[field.substring(field.indexOf(':') + 1)] = { + name: fields[field] + }; } } - }); - result = {request: data}; - } + catch (error) { + Zabbix.log(4, '[ ManageEngine Webhook ] Can\'t parse field "' + field + + '". The field ignored.'); + } + } + }); + result = {request: data}; } return result; @@ -315,8 +321,7 @@ zabbix_export: fields[key] = params[key]; } - if (required_params.indexOf(key) !== -1 - && (typeof params[key] === 'undefined' || params[key].trim() === '')) { + if (required_params.indexOf(key) !== -1 && params[key].trim() === '') { throw 'Parameter "' + key + '" can\'t be empty.'; } }); @@ -347,7 +352,6 @@ zabbix_export: fields['field_object:priority'] = params['priority_' + severities[params.event_nseverity].name] || 'Normal'; - 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}')) { @@ -358,10 +362,9 @@ zabbix_export: MEngine.setProxy(params.HTTPProxy); if (MEngine.params.on_premise.toLowerCase() !== 'true') { - MEngine.setToken(); + MEngine.refreshAccessToken(); } - // Create issue for non trigger-based events. if (params.event_source !== '0' && params.event_recovery_value !== '0') { MEngine.request('post', 'requests', MEngine.createPaylaod(fields)); @@ -379,13 +382,14 @@ zabbix_export: } else { MEngine.request('post', 'requests/' + params.sd_request_id + '/notes', - MEngine.createPaylaod(fields, params.event_update_status === '1')); + MEngine.createPaylaod(fields, params.event_update_status === '1') + ); } return JSON.stringify(result); } catch (error) { - Zabbix.log(3, '[ MEngine Webhook ] ERROR: ' + error); + Zabbix.log(3, '[ ManageEngine Webhook ] ERROR: ' + error); throw 'Sending failed: ' + error; } process_tags: 'YES' |