-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSet_Better_Map_Widget_Connections.json
More file actions
76 lines (76 loc) · 10.3 KB
/
Copy pathSet_Better_Map_Widget_Connections.json
File metadata and controls
76 lines (76 loc) · 10.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
{
"searchKeywords": "",
"name": "Set Better Map Widget Connections",
"description": "Looks for properties on instances and parses them up to resource-level properties with all the necessary information to plot them on the Better Map Widget.",
"appliesTo": "(hasCategory(\"snmpTCPUDP\") || hasCategory(\"snmp\") || hasCategory(\"pingcheckdevice\") || hasCategory(\"webcheckdevice\")) && lmaccess.id && lmaccess.key",
"type": 5,
"technicalNotes": "Requires the user to set an instance level property called 'custom_map_connection' on instances with information in the following format: `{Connection Title} > {Display name or hostname of connecting resource}`",
"version": 1764611102,
"registryMetadata": {
"currentUuid": "8AxW498NRdyhfrQysAzPnQ",
"originalUuid": "fG79BHiWQ5aFn09qcHj6fw",
"locatorId": "",
"authorCompanyUuid": "2dfa8856-1b93-11e5-9235-90b11c05f31e",
"registryVersion": "1.0.0",
"checksum": "84e6adac9a01aeb641a636a5095f26f5",
"namespace": "",
"registryId": "",
"isChangedFromOrigin": false,
"status": ""
},
"script": {
"type": "groovy",
"content": "/*******************************************************************************\n * © 2007-2025 - LogicMonitor, Inc. All rights reserved.\n ******************************************************************************/\n\nimport groovy.json.JsonSlurper\nimport com.santaba.agent.util.Settings\nimport com.santaba.agent.live.LiveHostSet\nimport org.apache.commons.codec.binary.Hex\nimport javax.crypto.Mac\nimport javax.crypto.spec.SecretKeySpec\nimport java.security.MessageDigest\n\n// To run in debug mode, set this global variable to true...\ndebug = false\n\nString apiId = hostProps.get(\"lmaccess.id\") ?: hostProps.get(\"logicmonitor.access.id\")\nString apiKey = hostProps.get(\"lmaccess.key\") ?: hostProps.get(\"logicmonitor.access.key\")\ndef portalName = hostProps.get(\"lmaccount\") ?: Settings.getSetting(Settings.AGENT_COMPANY)\nString deviceID = hostProps.get(\"system.deviceId\")\nMap proxyInfo = getProxyInfo()\n// Name of the instance-level property where the user should specify connections to plot...\nString connectionProp = \"custom_map_connection\"\n\nconnectionData = \"\"\n\n// Get a list of relevant datasources to search...\napiGetManyV2(portalName, apiId, apiKey, \"/device/devices/\" + deviceID + \"/devicedatasources\", proxyInfo, [fields:'dataSourceName,id,instanceNumber',filter:'dataSourceName:SNMP_Network_Interfaces|*VPN*|Web_Check_Individual|Ping_Check_Individual']).each { ds->\n\t\n\t// Loop through the results...\n\tds.items.each { thisDS-> \n\t\t\n\t\t// Get a list of the datasource's instances that have the appropriate property set...\n\t\tapiGetManyV2(portalName, apiId, apiKey, \"/device/devices/${deviceID}/devicedatasources/${thisDS.id}/instances\", proxyInfo, [fields:'dataSourceName,id,instanceNumber,customProperties',filter:'customProperties.name:' + connectionProp]).each { instances->\n\t\n\t\t\t// Loop through the instances...\n\t\t\tinstances.items.each { instance-> \n\t\t\t\t// Loop through the instance's properties...\n\t\t\t\tinstance.customProperties.each { thisProp->\n\t\t\t\t\t// Look for our property of interest...\n\t\t\t\t\tif (thisProp.name == connectionProp) {\n\t\t\t\t\t\t// Parse the map connection info property (example: \"Corporate WAN > 12345\")...\n\t\t\t\t\t\tdef connectionInfo = thisProp.value.split(\">\")\n\t\t\t\t\t\tif (connectionInfo.size() == 2) {\n\t\t\t\t\t\t\tdef connectionName = connectionInfo[0].trim()\n\t\t\t\t\t\t\tdef connectionDest = connectionInfo[1].trim()\n\t\t\t\t\t\t\tdef connectionID = connectionDest\n\t\t\t\t\t\t\tLMDebugPrint(\"connectionDest: ${connectionDest}\")\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (connectionDest != \"\") {\n\t\t\t\t\t\t\t\t// Lookup the connected resource's device ID...\n\t\t\t\t\t\t\t\tapiGetManyV2(portalName, apiId, apiKey, \"/device/devices\", proxyInfo, [fields:'name,id,displayName',filter:'displayName:' + connectionDest + '||name:' + connectionDest]).each { resource->\n\t\t\t\t\t\t\t\t\tif (resource.items.size() > 0) {\n\t\t\t\t\t\t\t\t\t\tconnectionID = resource.items[0].id\n\t\t\t\t\t\t\t\t\t\t// Output format: Connection title, Datasource ID, Instance ID, Destination device ID\n\t\t\t\t\t\t\t\t\t\tconnectionData = \"${connectionName},${thisDS.id},${instance.id},${connectionID};${connectionData}\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\tLMDebugPrint(\"No resource found for ${connectionDest}\")\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (connectionData != \"\") {\n\t\t\t\tprintln \"custom_map_connection_data=${connectionData.replaceAll(/;$/, '')}\"\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nreturn 0\n\n/* Paginated GET method. Returns a list of objects. */\nList apiGetManyV2(portalName, apiId, apiKey, endPoint, proxyInfo, Map args=[:]) {\n\n\tdef pageSize = args.get('size', 1000) // Default the page size to 1000 if not specified.\n\tList items = []\n\n\targs['size'] = pageSize\n\n\tdef pageCount = 0\n\twhile (true) {\n\t\tpageCount += 1\n\n\t\t// Updated the args\n\t\targs['size'] = pageSize\n\t\targs['offset'] = items.size()\n\n\t\tdef response = apiGetV2(portalName, apiId, apiKey, endPoint, proxyInfo, args)\n\t\tif (response.get(\"errmsg\", \"OK\") != \"OK\") {\n\t\t\tthrow new Exception(\"Santaba returned errormsg: ${response?.errmsg}\")\n\t\t}\n\t\titems.addAll(response.data)\n\n\t\t// If we recieved less than we asked for it means we are done\n\t\tif (response.data.size() < pageSize) break\n\t}\n\treturn items\n}\n\n\n/* Simple GET, returns a parsed json payload. No processing. */\ndef apiGetV2(portalName, apiId, apiKey, endPoint, proxyInfo, Map args=[:]) {\n\tdef request = rawGetV2(portalName, apiId, apiKey, endPoint, proxyInfo, args)\n\tif (request.getResponseCode() == 200) {\n\t\tdef payload = new JsonSlurper().parseText(request.content.text)\n\t\t\n\t\treturn payload\n\t}\n\telse {\n\t\tthrow new Exception(\"Server return HTTP code ${request.getResponseCode()}\")\n\t}\n}\n\n\n/* Raw GET method. */\ndef rawGetV2(portalName, apiId, apiKey, endPoint, proxyInfo, Map args=[:]) {\n\tdef auth = generateAuth(apiId, apiKey, endPoint)\n\tdef headers = [\"Authorization\": auth, \"Content-Type\": \"application/json\", \"External-User\":\"true\"]\n\tdef url = \"https://${portalName}.logicmonitor.com/santaba/rest${endPoint}\"\n\n\tif (args) {\n\t\tdef encodedArgs = []\n\t\targs.each{ k,v ->\n\t\t\tencodedArgs << \"${k}=${java.net.URLEncoder.encode(v.toString(), \"UTF-8\")}\"\n\t\t}\n\t\turl += \"?${encodedArgs.join('&')}\"\n\t}\n\n\tdef request\n\tif (proxyInfo.enabled) {\n\t\trequest = url.toURL().openConnection(proxyInfo.proxy)\n\t}\n\telse {\n\t\trequest = url.toURL().openConnection()\n\t}\n\trequest.setRequestMethod(\"GET\")\n\trequest.setDoOutput(true)\n\theaders.each{ k,v ->\n\t\trequest.addRequestProperty(k, v)\n\t}\n\n\treturn request\n}\n\n\n/* Generate auth for API calls. */\nstatic String generateAuth(id, key, path) {\n\tLong epoch_time = System.currentTimeMillis()\n\tMac hmac = Mac.getInstance(\"HmacSHA256\")\n\thmac.init(new SecretKeySpec(key.getBytes(), \"HmacSHA256\"))\n\tdef signature = Hex.encodeHexString(hmac.doFinal(\"GET${epoch_time}${path}\".getBytes())).bytes.encodeBase64()\n\n\treturn \"LMv1 ${id}:${signature}:${epoch_time}\"\n}\n\n\n/* Helper method to remind the collector this device is not dead */\ndef keepAlive(hostProps) {\n\t// Update the liveHost set so tell the collector we are happy.\n\thostId = hostProps.get(\"system.deviceId\").toInteger()\n\tdef liveHostSet = LiveHostSet.getInstance()\n\tliveHostSet.flag(hostId)\n}\n\n\n/**\n* Get collector proxy settings\n* @return Map with proxy settings, empty map if proxy not set.\n*/\nMap getProxyInfo() {\n\t// Each property must be evaluated for null to determine whether to use collected value or fallback value\n\t// Elvis operator does not play nice with booleans\n\t// default to true in absence of property to use collectorProxy as determinant\n\tBoolean deviceProxy = hostProps.get(\"proxy.enable\")?.toBoolean()\n\tdeviceProxy = (deviceProxy != null) ? deviceProxy : true \n\t// if settings are not present, value should be false\n\tBoolean collectorProxy = Settings.getSetting(\"proxy.enable\")?.toBoolean()\n\tcollectorProxy = (collectorProxy != null) ? collectorProxy : false \n\n\tMap proxyInfo = [:]\n\t\n\tif (deviceProxy && collectorProxy) {\n\t\tproxyInfo = [\n\t\t\tenabled : true,\n\t\t\thost : hostProps.get(\"proxy.host\") ?: Settings.getSetting(\"proxy.host\"),\n\t\t\tport : hostProps.get(\"proxy.port\") ?: Settings.getSetting(\"proxy.port\") ?: 3128,\n\t\t\tuser : Settings.getSetting(\"proxy.user\"),\n\t\t\tpass : Settings.getSetting(\"proxy.pass\")\n\t\t]\n\t\n\t\tproxyInfo[\"proxy\"] = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyInfo.host, proxyInfo.port.toInteger()))\n\t}\n\n\treturn proxyInfo\n}\n\n/**\n * Helper function to print out debug messages for troubleshooting purposes.\n */\ndef LMDebugPrint(message) {\n\tif (debug) {\n\t\tprintln(\"DEBUG: ${message.toString()}\")\n\t}\n}"
},
"group": "",
"headers": {
"cache-control": "no-cache, no-store",
"content-disposition": "attachment; filename=\"Set_Better_Map_Widget_Connections.json\"",
"content-encoding": "gzip",
"content-type": "application/json",
"date": "Mon, 01 Dec 2025 17:45:05 GMT",
"server": "LM",
"strict-transport-security": "max-age=31536000; includeSubDomains",
"vary": "accept-encoding",
"x-content-type-options": "nosniff",
"x-server-version": "229-9",
"x-xss-protection": "0"
},
"config": {
"transitional": {
"silentJSONParsing": true,
"forcedJSONParsing": true,
"clarifyTimeoutError": false
},
"adapter": [
"xhr",
"http",
"fetch"
],
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": -1,
"env": {},
"headers": {
"Accept": "application/json, text/javascript, */*; q=0.01",
"Content-Type": "application/json",
"X-version": "4",
"X-CSRF-Token": "6EB1D919974E140563B022CB19E8DE92"
},
"baseURL": "/santaba/rest",
"paramsSerializer": {},
"params": {},
"method": "post",
"url": "/exchange/toolbox/exchangePropertySources/443/file",
"data": "{}",
"allowAbsoluteUrls": true
}
}