@sonde/packs 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (359) hide show
  1. package/.turbo/turbo-build.log +6 -0
  2. package/.turbo/turbo-test.log +814 -0
  3. package/.turbo/turbo-typecheck.log +4 -0
  4. package/CHANGELOG.md +10 -0
  5. package/dist/index.d.ts +16 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +40 -2
  8. package/dist/index.js.map +1 -1
  9. package/dist/integrations/citrix.d.ts +13 -0
  10. package/dist/integrations/citrix.d.ts.map +1 -0
  11. package/dist/integrations/citrix.js +420 -0
  12. package/dist/integrations/citrix.js.map +1 -0
  13. package/dist/integrations/citrix.test.d.ts +2 -0
  14. package/dist/integrations/citrix.test.d.ts.map +1 -0
  15. package/dist/integrations/citrix.test.js +464 -0
  16. package/dist/integrations/citrix.test.js.map +1 -0
  17. package/dist/integrations/graph.d.ts +9 -0
  18. package/dist/integrations/graph.d.ts.map +1 -0
  19. package/dist/integrations/graph.js +290 -0
  20. package/dist/integrations/graph.js.map +1 -0
  21. package/dist/integrations/graph.test.d.ts +2 -0
  22. package/dist/integrations/graph.test.d.ts.map +1 -0
  23. package/dist/integrations/graph.test.js +356 -0
  24. package/dist/integrations/graph.test.js.map +1 -0
  25. package/dist/integrations/httpbin.d.ts +3 -0
  26. package/dist/integrations/httpbin.d.ts.map +1 -0
  27. package/dist/integrations/httpbin.js +70 -0
  28. package/dist/integrations/httpbin.js.map +1 -0
  29. package/dist/integrations/nutanix.d.ts +18 -0
  30. package/dist/integrations/nutanix.d.ts.map +1 -0
  31. package/dist/integrations/nutanix.js +1121 -0
  32. package/dist/integrations/nutanix.js.map +1 -0
  33. package/dist/integrations/nutanix.test.d.ts +2 -0
  34. package/dist/integrations/nutanix.test.d.ts.map +1 -0
  35. package/dist/integrations/nutanix.test.js +978 -0
  36. package/dist/integrations/nutanix.test.js.map +1 -0
  37. package/dist/integrations/proxmox.d.ts +12 -0
  38. package/dist/integrations/proxmox.d.ts.map +1 -0
  39. package/dist/integrations/proxmox.js +733 -0
  40. package/dist/integrations/proxmox.js.map +1 -0
  41. package/dist/integrations/proxmox.test.d.ts +2 -0
  42. package/dist/integrations/proxmox.test.d.ts.map +1 -0
  43. package/dist/integrations/proxmox.test.js +697 -0
  44. package/dist/integrations/proxmox.test.js.map +1 -0
  45. package/dist/integrations/servicenow.d.ts +3 -0
  46. package/dist/integrations/servicenow.d.ts.map +1 -0
  47. package/dist/integrations/servicenow.js +257 -0
  48. package/dist/integrations/servicenow.js.map +1 -0
  49. package/dist/integrations/servicenow.test.d.ts +2 -0
  50. package/dist/integrations/servicenow.test.d.ts.map +1 -0
  51. package/dist/integrations/servicenow.test.js +217 -0
  52. package/dist/integrations/servicenow.test.js.map +1 -0
  53. package/dist/integrations/splunk.d.ts +9 -0
  54. package/dist/integrations/splunk.d.ts.map +1 -0
  55. package/dist/integrations/splunk.js +242 -0
  56. package/dist/integrations/splunk.js.map +1 -0
  57. package/dist/integrations/splunk.test.d.ts +2 -0
  58. package/dist/integrations/splunk.test.d.ts.map +1 -0
  59. package/dist/integrations/splunk.test.js +323 -0
  60. package/dist/integrations/splunk.test.js.map +1 -0
  61. package/dist/mysql/index.d.ts +3 -0
  62. package/dist/mysql/index.d.ts.map +1 -0
  63. package/dist/mysql/index.js +13 -0
  64. package/dist/mysql/index.js.map +1 -0
  65. package/dist/mysql/manifest.d.ts +3 -0
  66. package/dist/mysql/manifest.d.ts.map +1 -0
  67. package/dist/mysql/manifest.js +69 -0
  68. package/dist/mysql/manifest.js.map +1 -0
  69. package/dist/mysql/probes/databases-list.d.ts +13 -0
  70. package/dist/mysql/probes/databases-list.d.ts.map +1 -0
  71. package/dist/mysql/probes/databases-list.js +31 -0
  72. package/dist/mysql/probes/databases-list.js.map +1 -0
  73. package/dist/mysql/probes/databases-list.test.d.ts +2 -0
  74. package/dist/mysql/probes/databases-list.test.d.ts.map +1 -0
  75. package/dist/mysql/probes/databases-list.test.js +54 -0
  76. package/dist/mysql/probes/databases-list.test.js.map +1 -0
  77. package/dist/mysql/probes/processlist.d.ts +18 -0
  78. package/dist/mysql/probes/processlist.d.ts.map +1 -0
  79. package/dist/mysql/probes/processlist.js +36 -0
  80. package/dist/mysql/probes/processlist.js.map +1 -0
  81. package/dist/mysql/probes/processlist.test.d.ts +2 -0
  82. package/dist/mysql/probes/processlist.test.d.ts.map +1 -0
  83. package/dist/mysql/probes/processlist.test.js +41 -0
  84. package/dist/mysql/probes/processlist.test.js.map +1 -0
  85. package/dist/mysql/probes/status.d.ts +14 -0
  86. package/dist/mysql/probes/status.d.ts.map +1 -0
  87. package/dist/mysql/probes/status.js +40 -0
  88. package/dist/mysql/probes/status.js.map +1 -0
  89. package/dist/mysql/probes/status.test.d.ts +2 -0
  90. package/dist/mysql/probes/status.test.d.ts.map +1 -0
  91. package/dist/mysql/probes/status.test.js +43 -0
  92. package/dist/mysql/probes/status.test.js.map +1 -0
  93. package/dist/nginx/index.d.ts +3 -0
  94. package/dist/nginx/index.d.ts.map +1 -0
  95. package/dist/nginx/index.js +13 -0
  96. package/dist/nginx/index.js.map +1 -0
  97. package/dist/nginx/manifest.d.ts +3 -0
  98. package/dist/nginx/manifest.d.ts.map +1 -0
  99. package/dist/nginx/manifest.js +68 -0
  100. package/dist/nginx/manifest.js.map +1 -0
  101. package/dist/nginx/probes/access-log-tail.d.ts +9 -0
  102. package/dist/nginx/probes/access-log-tail.d.ts.map +1 -0
  103. package/dist/nginx/probes/access-log-tail.js +14 -0
  104. package/dist/nginx/probes/access-log-tail.js.map +1 -0
  105. package/dist/nginx/probes/access-log-tail.test.d.ts +2 -0
  106. package/dist/nginx/probes/access-log-tail.test.d.ts.map +1 -0
  107. package/dist/nginx/probes/access-log-tail.test.js +40 -0
  108. package/dist/nginx/probes/access-log-tail.test.js.map +1 -0
  109. package/dist/nginx/probes/config-test.d.ts +8 -0
  110. package/dist/nginx/probes/config-test.d.ts.map +1 -0
  111. package/dist/nginx/probes/config-test.js +18 -0
  112. package/dist/nginx/probes/config-test.js.map +1 -0
  113. package/dist/nginx/probes/config-test.test.d.ts +2 -0
  114. package/dist/nginx/probes/config-test.test.d.ts.map +1 -0
  115. package/dist/nginx/probes/config-test.test.js +35 -0
  116. package/dist/nginx/probes/config-test.test.js.map +1 -0
  117. package/dist/nginx/probes/error-log-tail.d.ts +9 -0
  118. package/dist/nginx/probes/error-log-tail.d.ts.map +1 -0
  119. package/dist/nginx/probes/error-log-tail.js +14 -0
  120. package/dist/nginx/probes/error-log-tail.js.map +1 -0
  121. package/dist/nginx/probes/error-log-tail.test.d.ts +2 -0
  122. package/dist/nginx/probes/error-log-tail.test.d.ts.map +1 -0
  123. package/dist/nginx/probes/error-log-tail.test.js +34 -0
  124. package/dist/nginx/probes/error-log-tail.test.js.map +1 -0
  125. package/dist/postgres/index.d.ts +3 -0
  126. package/dist/postgres/index.d.ts.map +1 -0
  127. package/dist/postgres/index.js +13 -0
  128. package/dist/postgres/index.js.map +1 -0
  129. package/dist/postgres/manifest.d.ts +3 -0
  130. package/dist/postgres/manifest.d.ts.map +1 -0
  131. package/dist/postgres/manifest.js +90 -0
  132. package/dist/postgres/manifest.js.map +1 -0
  133. package/dist/postgres/probes/connections-active.d.ts +17 -0
  134. package/dist/postgres/probes/connections-active.d.ts.map +1 -0
  135. package/dist/postgres/probes/connections-active.js +37 -0
  136. package/dist/postgres/probes/connections-active.js.map +1 -0
  137. package/dist/postgres/probes/connections-active.test.d.ts +2 -0
  138. package/dist/postgres/probes/connections-active.test.d.ts.map +1 -0
  139. package/dist/postgres/probes/connections-active.test.js +36 -0
  140. package/dist/postgres/probes/connections-active.test.js.map +1 -0
  141. package/dist/postgres/probes/databases-list.d.ts +14 -0
  142. package/dist/postgres/probes/databases-list.d.ts.map +1 -0
  143. package/dist/postgres/probes/databases-list.js +34 -0
  144. package/dist/postgres/probes/databases-list.js.map +1 -0
  145. package/dist/postgres/probes/databases-list.test.d.ts +2 -0
  146. package/dist/postgres/probes/databases-list.test.d.ts.map +1 -0
  147. package/dist/postgres/probes/databases-list.test.js +49 -0
  148. package/dist/postgres/probes/databases-list.test.js.map +1 -0
  149. package/dist/postgres/probes/query-slow.d.ts +17 -0
  150. package/dist/postgres/probes/query-slow.d.ts.map +1 -0
  151. package/dist/postgres/probes/query-slow.js +37 -0
  152. package/dist/postgres/probes/query-slow.js.map +1 -0
  153. package/dist/postgres/probes/query-slow.test.d.ts +2 -0
  154. package/dist/postgres/probes/query-slow.test.d.ts.map +1 -0
  155. package/dist/postgres/probes/query-slow.test.js +30 -0
  156. package/dist/postgres/probes/query-slow.test.js.map +1 -0
  157. package/dist/proxmox/index.d.ts +3 -0
  158. package/dist/proxmox/index.d.ts.map +1 -0
  159. package/dist/proxmox/index.js +23 -0
  160. package/dist/proxmox/index.js.map +1 -0
  161. package/dist/proxmox/manifest.d.ts +3 -0
  162. package/dist/proxmox/manifest.d.ts.map +1 -0
  163. package/dist/proxmox/manifest.js +75 -0
  164. package/dist/proxmox/manifest.js.map +1 -0
  165. package/dist/proxmox/probes/ceph-status.d.ts +36 -0
  166. package/dist/proxmox/probes/ceph-status.d.ts.map +1 -0
  167. package/dist/proxmox/probes/ceph-status.js +71 -0
  168. package/dist/proxmox/probes/ceph-status.js.map +1 -0
  169. package/dist/proxmox/probes/ceph-status.test.d.ts +2 -0
  170. package/dist/proxmox/probes/ceph-status.test.d.ts.map +1 -0
  171. package/dist/proxmox/probes/ceph-status.test.js +115 -0
  172. package/dist/proxmox/probes/ceph-status.test.js.map +1 -0
  173. package/dist/proxmox/probes/cluster-config.d.ts +31 -0
  174. package/dist/proxmox/probes/cluster-config.d.ts.map +1 -0
  175. package/dist/proxmox/probes/cluster-config.js +72 -0
  176. package/dist/proxmox/probes/cluster-config.js.map +1 -0
  177. package/dist/proxmox/probes/cluster-config.test.d.ts +2 -0
  178. package/dist/proxmox/probes/cluster-config.test.d.ts.map +1 -0
  179. package/dist/proxmox/probes/cluster-config.test.js +107 -0
  180. package/dist/proxmox/probes/cluster-config.test.js.map +1 -0
  181. package/dist/proxmox/probes/ha-status.d.ts +18 -0
  182. package/dist/proxmox/probes/ha-status.d.ts.map +1 -0
  183. package/dist/proxmox/probes/ha-status.js +38 -0
  184. package/dist/proxmox/probes/ha-status.js.map +1 -0
  185. package/dist/proxmox/probes/ha-status.test.d.ts +2 -0
  186. package/dist/proxmox/probes/ha-status.test.d.ts.map +1 -0
  187. package/dist/proxmox/probes/ha-status.test.js +66 -0
  188. package/dist/proxmox/probes/ha-status.test.js.map +1 -0
  189. package/dist/proxmox/probes/lvm.d.ts +35 -0
  190. package/dist/proxmox/probes/lvm.d.ts.map +1 -0
  191. package/dist/proxmox/probes/lvm.js +75 -0
  192. package/dist/proxmox/probes/lvm.js.map +1 -0
  193. package/dist/proxmox/probes/lvm.test.d.ts +2 -0
  194. package/dist/proxmox/probes/lvm.test.d.ts.map +1 -0
  195. package/dist/proxmox/probes/lvm.test.js +128 -0
  196. package/dist/proxmox/probes/lvm.test.js.map +1 -0
  197. package/dist/proxmox/probes/lxc-config.d.ts +29 -0
  198. package/dist/proxmox/probes/lxc-config.d.ts.map +1 -0
  199. package/dist/proxmox/probes/lxc-config.js +67 -0
  200. package/dist/proxmox/probes/lxc-config.js.map +1 -0
  201. package/dist/proxmox/probes/lxc-config.test.d.ts +2 -0
  202. package/dist/proxmox/probes/lxc-config.test.d.ts.map +1 -0
  203. package/dist/proxmox/probes/lxc-config.test.js +77 -0
  204. package/dist/proxmox/probes/lxc-config.test.js.map +1 -0
  205. package/dist/proxmox/probes/lxc-list.d.ts +20 -0
  206. package/dist/proxmox/probes/lxc-list.d.ts.map +1 -0
  207. package/dist/proxmox/probes/lxc-list.js +49 -0
  208. package/dist/proxmox/probes/lxc-list.js.map +1 -0
  209. package/dist/proxmox/probes/lxc-list.test.d.ts +2 -0
  210. package/dist/proxmox/probes/lxc-list.test.d.ts.map +1 -0
  211. package/dist/proxmox/probes/lxc-list.test.js +51 -0
  212. package/dist/proxmox/probes/lxc-list.test.js.map +1 -0
  213. package/dist/proxmox/probes/vm-config.d.ts +21 -0
  214. package/dist/proxmox/probes/vm-config.d.ts.map +1 -0
  215. package/dist/proxmox/probes/vm-config.js +58 -0
  216. package/dist/proxmox/probes/vm-config.js.map +1 -0
  217. package/dist/proxmox/probes/vm-config.test.d.ts +2 -0
  218. package/dist/proxmox/probes/vm-config.test.d.ts.map +1 -0
  219. package/dist/proxmox/probes/vm-config.test.js +80 -0
  220. package/dist/proxmox/probes/vm-config.test.js.map +1 -0
  221. package/dist/proxmox/probes/vm-locks.d.ts +16 -0
  222. package/dist/proxmox/probes/vm-locks.d.ts.map +1 -0
  223. package/dist/proxmox/probes/vm-locks.js +35 -0
  224. package/dist/proxmox/probes/vm-locks.js.map +1 -0
  225. package/dist/proxmox/probes/vm-locks.test.d.ts +2 -0
  226. package/dist/proxmox/probes/vm-locks.test.d.ts.map +1 -0
  227. package/dist/proxmox/probes/vm-locks.test.js +54 -0
  228. package/dist/proxmox/probes/vm-locks.test.js.map +1 -0
  229. package/dist/redis/index.d.ts +3 -0
  230. package/dist/redis/index.d.ts.map +1 -0
  231. package/dist/redis/index.js +13 -0
  232. package/dist/redis/index.js.map +1 -0
  233. package/dist/redis/manifest.d.ts +3 -0
  234. package/dist/redis/manifest.d.ts.map +1 -0
  235. package/dist/redis/manifest.js +51 -0
  236. package/dist/redis/manifest.js.map +1 -0
  237. package/dist/redis/probes/info.d.ts +15 -0
  238. package/dist/redis/probes/info.d.ts.map +1 -0
  239. package/dist/redis/probes/info.js +32 -0
  240. package/dist/redis/probes/info.js.map +1 -0
  241. package/dist/redis/probes/info.test.d.ts +2 -0
  242. package/dist/redis/probes/info.test.d.ts.map +1 -0
  243. package/dist/redis/probes/info.test.js +64 -0
  244. package/dist/redis/probes/info.test.js.map +1 -0
  245. package/dist/redis/probes/keys-count.d.ts +13 -0
  246. package/dist/redis/probes/keys-count.d.ts.map +1 -0
  247. package/dist/redis/probes/keys-count.js +24 -0
  248. package/dist/redis/probes/keys-count.js.map +1 -0
  249. package/dist/redis/probes/keys-count.test.d.ts +2 -0
  250. package/dist/redis/probes/keys-count.test.d.ts.map +1 -0
  251. package/dist/redis/probes/keys-count.test.js +37 -0
  252. package/dist/redis/probes/keys-count.test.js.map +1 -0
  253. package/dist/redis/probes/memory-usage.d.ts +16 -0
  254. package/dist/redis/probes/memory-usage.d.ts.map +1 -0
  255. package/dist/redis/probes/memory-usage.js +31 -0
  256. package/dist/redis/probes/memory-usage.js.map +1 -0
  257. package/dist/redis/probes/memory-usage.test.d.ts +2 -0
  258. package/dist/redis/probes/memory-usage.test.d.ts.map +1 -0
  259. package/dist/redis/probes/memory-usage.test.js +48 -0
  260. package/dist/redis/probes/memory-usage.test.js.map +1 -0
  261. package/dist/runbooks/nutanix.d.ts +3 -0
  262. package/dist/runbooks/nutanix.d.ts.map +1 -0
  263. package/dist/runbooks/nutanix.js +619 -0
  264. package/dist/runbooks/nutanix.js.map +1 -0
  265. package/dist/runbooks/nutanix.test.d.ts +2 -0
  266. package/dist/runbooks/nutanix.test.d.ts.map +1 -0
  267. package/dist/runbooks/nutanix.test.js +971 -0
  268. package/dist/runbooks/nutanix.test.js.map +1 -0
  269. package/dist/runbooks/proxmox.d.ts +3 -0
  270. package/dist/runbooks/proxmox.d.ts.map +1 -0
  271. package/dist/runbooks/proxmox.js +451 -0
  272. package/dist/runbooks/proxmox.js.map +1 -0
  273. package/dist/runbooks/proxmox.test.d.ts +2 -0
  274. package/dist/runbooks/proxmox.test.d.ts.map +1 -0
  275. package/dist/runbooks/proxmox.test.js +700 -0
  276. package/dist/runbooks/proxmox.test.js.map +1 -0
  277. package/dist/signatures.d.ts +2 -0
  278. package/dist/signatures.d.ts.map +1 -0
  279. package/dist/signatures.js +2 -0
  280. package/dist/signatures.js.map +1 -0
  281. package/dist/types.d.ts +53 -0
  282. package/dist/types.d.ts.map +1 -1
  283. package/dist/validation.d.ts +6 -1
  284. package/dist/validation.d.ts.map +1 -1
  285. package/dist/validation.js +10 -1
  286. package/dist/validation.js.map +1 -1
  287. package/package.json +1 -1
  288. package/src/index.ts +60 -6
  289. package/src/integrations/citrix.test.ts +592 -0
  290. package/src/integrations/citrix.ts +557 -0
  291. package/src/integrations/graph.test.ts +478 -0
  292. package/src/integrations/graph.ts +413 -0
  293. package/src/integrations/httpbin.ts +72 -0
  294. package/src/integrations/nutanix.test.ts +1508 -0
  295. package/src/integrations/nutanix.ts +1460 -0
  296. package/src/integrations/proxmox.test.ts +1020 -0
  297. package/src/integrations/proxmox.ts +989 -0
  298. package/src/integrations/servicenow.test.ts +314 -0
  299. package/src/integrations/servicenow.ts +285 -0
  300. package/src/integrations/splunk.test.ts +440 -0
  301. package/src/integrations/splunk.ts +356 -0
  302. package/src/mysql/index.ts +14 -0
  303. package/src/mysql/manifest.ts +70 -0
  304. package/src/mysql/probes/databases-list.test.ts +62 -0
  305. package/src/mysql/probes/databases-list.ts +45 -0
  306. package/src/mysql/probes/processlist.test.ts +47 -0
  307. package/src/mysql/probes/processlist.ts +55 -0
  308. package/src/mysql/probes/status.test.ts +50 -0
  309. package/src/mysql/probes/status.ts +56 -0
  310. package/src/nginx/index.ts +14 -0
  311. package/src/nginx/manifest.ts +69 -0
  312. package/src/nginx/probes/access-log-tail.test.ts +51 -0
  313. package/src/nginx/probes/access-log-tail.ts +23 -0
  314. package/src/nginx/probes/config-test.test.ts +47 -0
  315. package/src/nginx/probes/config-test.ts +24 -0
  316. package/src/nginx/probes/error-log-tail.test.ts +44 -0
  317. package/src/nginx/probes/error-log-tail.ts +23 -0
  318. package/src/postgres/index.ts +14 -0
  319. package/src/postgres/manifest.ts +91 -0
  320. package/src/postgres/probes/connections-active.test.ts +42 -0
  321. package/src/postgres/probes/connections-active.ts +55 -0
  322. package/src/postgres/probes/databases-list.test.ts +57 -0
  323. package/src/postgres/probes/databases-list.ts +49 -0
  324. package/src/postgres/probes/query-slow.test.ts +37 -0
  325. package/src/postgres/probes/query-slow.ts +55 -0
  326. package/src/proxmox/index.ts +24 -0
  327. package/src/proxmox/manifest.ts +76 -0
  328. package/src/proxmox/probes/ceph-status.test.ts +126 -0
  329. package/src/proxmox/probes/ceph-status.ts +116 -0
  330. package/src/proxmox/probes/cluster-config.test.ts +118 -0
  331. package/src/proxmox/probes/cluster-config.ts +97 -0
  332. package/src/proxmox/probes/ha-status.test.ts +76 -0
  333. package/src/proxmox/probes/ha-status.ts +56 -0
  334. package/src/proxmox/probes/lvm.test.ts +140 -0
  335. package/src/proxmox/probes/lvm.ts +121 -0
  336. package/src/proxmox/probes/lxc-config.test.ts +89 -0
  337. package/src/proxmox/probes/lxc-config.ts +90 -0
  338. package/src/proxmox/probes/lxc-list.test.ts +60 -0
  339. package/src/proxmox/probes/lxc-list.ts +67 -0
  340. package/src/proxmox/probes/vm-config.test.ts +93 -0
  341. package/src/proxmox/probes/vm-config.ts +77 -0
  342. package/src/proxmox/probes/vm-locks.test.ts +63 -0
  343. package/src/proxmox/probes/vm-locks.ts +49 -0
  344. package/src/redis/index.ts +14 -0
  345. package/src/redis/manifest.ts +52 -0
  346. package/src/redis/probes/info.test.ts +73 -0
  347. package/src/redis/probes/info.ts +46 -0
  348. package/src/redis/probes/keys-count.test.ts +44 -0
  349. package/src/redis/probes/keys-count.ts +38 -0
  350. package/src/redis/probes/memory-usage.test.ts +54 -0
  351. package/src/redis/probes/memory-usage.ts +46 -0
  352. package/src/runbooks/nutanix.test.ts +1138 -0
  353. package/src/runbooks/nutanix.ts +941 -0
  354. package/src/runbooks/proxmox.test.ts +838 -0
  355. package/src/runbooks/proxmox.ts +626 -0
  356. package/src/signatures.ts +1 -0
  357. package/src/types.ts +62 -0
  358. package/src/validation.ts +21 -1
  359. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,413 @@
1
+ import type {
2
+ FetchFn,
3
+ IntegrationConfig,
4
+ IntegrationCredentials,
5
+ IntegrationPack,
6
+ IntegrationProbeHandler,
7
+ } from '@sonde/shared';
8
+
9
+ // --- Token cache ---
10
+
11
+ interface CachedToken {
12
+ accessToken: string;
13
+ expiresAt: number;
14
+ }
15
+
16
+ let tokenCache: CachedToken | null = null;
17
+
18
+ /** Acquire or reuse a Graph OAuth2 token via client_credentials grant */
19
+ export async function ensureGraphToken(
20
+ credentials: IntegrationCredentials,
21
+ fetchFn: FetchFn,
22
+ ): Promise<string> {
23
+ if (tokenCache && Date.now() < tokenCache.expiresAt - 30_000) {
24
+ return tokenCache.accessToken;
25
+ }
26
+
27
+ const tenantId = credentials.credentials.tenantId ?? '';
28
+ const clientId = credentials.credentials.clientId ?? '';
29
+ const clientSecret = credentials.credentials.clientSecret ?? '';
30
+ const tokenUrl = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`;
31
+
32
+ const body = new URLSearchParams({
33
+ grant_type: 'client_credentials',
34
+ scope: 'https://graph.microsoft.com/.default',
35
+ client_id: clientId,
36
+ client_secret: clientSecret,
37
+ });
38
+
39
+ const res = await fetchFn(tokenUrl, {
40
+ method: 'POST',
41
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
42
+ body: body.toString(),
43
+ });
44
+
45
+ if (!res.ok) {
46
+ throw new Error(`Graph token request failed: ${res.status} ${res.statusText}`);
47
+ }
48
+
49
+ const data = (await res.json()) as { access_token: string; expires_in: number };
50
+ tokenCache = {
51
+ accessToken: data.access_token,
52
+ expiresAt: Date.now() + data.expires_in * 1000,
53
+ };
54
+ return tokenCache.accessToken;
55
+ }
56
+
57
+ /** Clear the cached token (used for testing) */
58
+ export function clearTokenCache(): void {
59
+ tokenCache = null;
60
+ }
61
+
62
+ // --- Graph API helpers ---
63
+
64
+ interface GraphResponse {
65
+ value: unknown[];
66
+ '@odata.nextLink'?: string;
67
+ }
68
+
69
+ /** Fetch a Graph API endpoint with pagination */
70
+ export async function graphFetch(
71
+ path: string,
72
+ config: IntegrationConfig,
73
+ credentials: IntegrationCredentials,
74
+ fetchFn: FetchFn,
75
+ queryParams?: Record<string, string>,
76
+ maxPages = 5,
77
+ ): Promise<unknown[]> {
78
+ const token = await ensureGraphToken(credentials, fetchFn);
79
+ const baseUrl = `${config.endpoint.replace(/\/$/, '')}${path}`;
80
+ const url = new URL(baseUrl);
81
+ if (queryParams) {
82
+ for (const [key, value] of Object.entries(queryParams)) {
83
+ url.searchParams.set(key, value);
84
+ }
85
+ }
86
+
87
+ const headers: Record<string, string> = {
88
+ Authorization: `Bearer ${token}`,
89
+ Accept: 'application/json',
90
+ ...config.headers,
91
+ };
92
+
93
+ const results: unknown[] = [];
94
+ let nextUrl: string | undefined = url.toString();
95
+ let page = 0;
96
+
97
+ while (nextUrl && page < maxPages) {
98
+ const res = await fetchFn(nextUrl, { headers });
99
+ if (!res.ok) throw new Error(`Graph API returned ${res.status}: ${res.statusText}`);
100
+ const data = (await res.json()) as GraphResponse;
101
+ results.push(...(data.value ?? []));
102
+ nextUrl = data['@odata.nextLink'];
103
+ page++;
104
+ }
105
+
106
+ return results;
107
+ }
108
+
109
+ /** Fetch a Graph API endpoint with 403 handling for Intune endpoints */
110
+ async function graphFetchIntune(
111
+ path: string,
112
+ config: IntegrationConfig,
113
+ credentials: IntegrationCredentials,
114
+ fetchFn: FetchFn,
115
+ queryParams?: Record<string, string>,
116
+ maxPages = 5,
117
+ ): Promise<unknown[]> {
118
+ try {
119
+ return await graphFetch(path, config, credentials, fetchFn, queryParams, maxPages);
120
+ } catch (error) {
121
+ if (error instanceof Error && error.message.includes('403')) {
122
+ throw new Error(
123
+ 'Intune license or permissions required. Ensure the app registration has DeviceManagementManagedDevices.Read.All permission and an Intune license is active.',
124
+ );
125
+ }
126
+ throw error;
127
+ }
128
+ }
129
+
130
+ // --- Probe handlers ---
131
+
132
+ const userLookup: IntegrationProbeHandler = async (params, config, credentials, fetchFn) => {
133
+ const q = (params?.q as string) ?? '';
134
+ if (!q) throw new Error('q parameter is required (name, email, or UPN)');
135
+
136
+ const filter = `startsWith(displayName,'${q}') or mail eq '${q}' or userPrincipalName eq '${q}'`;
137
+ const select =
138
+ 'id,displayName,mail,userPrincipalName,jobTitle,department,officeLocation,accountEnabled';
139
+
140
+ const items = await graphFetch(
141
+ '/users',
142
+ config,
143
+ credentials,
144
+ fetchFn,
145
+ { $filter: filter, $select: select },
146
+ 1,
147
+ );
148
+
149
+ return { users: items, count: items.length };
150
+ };
151
+
152
+ const userGroups: IntegrationProbeHandler = async (params, config, credentials, fetchFn) => {
153
+ const userId = (params?.id as string) ?? '';
154
+ if (!userId) throw new Error('id parameter is required (user object ID or UPN)');
155
+
156
+ const items = (await graphFetch(`/users/${userId}/memberOf`, config, credentials, fetchFn, {
157
+ $select: 'id,displayName',
158
+ })) as Array<Record<string, unknown>>;
159
+
160
+ const groups = items.filter(
161
+ (item) => (item['@odata.type'] as string) === '#microsoft.graph.group',
162
+ );
163
+
164
+ return {
165
+ groups: groups.map((g) => ({ id: g.id, displayName: g.displayName })),
166
+ count: groups.length,
167
+ };
168
+ };
169
+
170
+ const signinRecent: IntegrationProbeHandler = async (params, config, credentials, fetchFn) => {
171
+ const user = (params?.user as string) ?? '';
172
+ if (!user) throw new Error('user parameter is required (UPN)');
173
+
174
+ const hours = (params?.hours as number) || 24;
175
+ const cutoff = new Date(Date.now() - hours * 60 * 60 * 1000).toISOString();
176
+
177
+ const filter = `userPrincipalName eq '${user}' and createdDateTime ge ${cutoff}`;
178
+ const select =
179
+ 'createdDateTime,appDisplayName,ipAddress,status,location,deviceDetail,riskLevelDuringSignIn';
180
+
181
+ const items = await graphFetch('/auditLogs/signIns', config, credentials, fetchFn, {
182
+ $filter: filter,
183
+ $select: select,
184
+ });
185
+
186
+ return { signIns: items, count: items.length, periodHours: hours };
187
+ };
188
+
189
+ const usersRisky: IntegrationProbeHandler = async (params, config, credentials, fetchFn) => {
190
+ const level = (params?.level as string) || 'high';
191
+ const filter = `riskLevel eq '${level}'`;
192
+ const select =
193
+ 'id,userDisplayName,userPrincipalName,riskLevel,riskState,riskDetail,riskLastUpdatedDateTime';
194
+
195
+ const items = await graphFetch('/identityProtection/riskyUsers', config, credentials, fetchFn, {
196
+ $filter: filter,
197
+ $select: select,
198
+ });
199
+
200
+ return { riskyUsers: items, count: items.length, riskLevel: level };
201
+ };
202
+
203
+ const intuneDevicesCompliance: IntegrationProbeHandler = async (
204
+ params,
205
+ config,
206
+ credentials,
207
+ fetchFn,
208
+ ) => {
209
+ const user = params?.user as string | undefined;
210
+ const select =
211
+ 'id,deviceName,operatingSystem,osVersion,complianceState,lastSyncDateTime,userPrincipalName,model,manufacturer';
212
+ const queryParams: Record<string, string> = { $select: select };
213
+
214
+ if (user) {
215
+ queryParams.$filter = `userPrincipalName eq '${user}'`;
216
+ }
217
+
218
+ const items = await graphFetchIntune(
219
+ '/deviceManagement/managedDevices',
220
+ config,
221
+ credentials,
222
+ fetchFn,
223
+ queryParams,
224
+ );
225
+
226
+ return { devices: items, count: items.length };
227
+ };
228
+
229
+ const intuneDevicesNoncompliant: IntegrationProbeHandler = async (
230
+ _params,
231
+ config,
232
+ credentials,
233
+ fetchFn,
234
+ ) => {
235
+ const select =
236
+ 'id,deviceName,operatingSystem,osVersion,complianceState,lastSyncDateTime,userPrincipalName,model,manufacturer';
237
+
238
+ const items = await graphFetchIntune(
239
+ '/deviceManagement/managedDevices',
240
+ config,
241
+ credentials,
242
+ fetchFn,
243
+ { $filter: "complianceState eq 'noncompliant'", $select: select },
244
+ );
245
+
246
+ return { devices: items, count: items.length };
247
+ };
248
+
249
+ const intuneAppsStatus: IntegrationProbeHandler = async (_params, config, credentials, fetchFn) => {
250
+ const apps = (await graphFetchIntune(
251
+ '/deviceAppManagement/mobileApps',
252
+ config,
253
+ credentials,
254
+ fetchFn,
255
+ { $select: 'id,displayName,publisher' },
256
+ )) as Array<Record<string, unknown>>;
257
+
258
+ const token = await ensureGraphToken(credentials, fetchFn);
259
+ const headers: Record<string, string> = {
260
+ Authorization: `Bearer ${token}`,
261
+ Accept: 'application/json',
262
+ ...config.headers,
263
+ };
264
+
265
+ const appsWithStatus = await Promise.all(
266
+ apps.map(async (app) => {
267
+ try {
268
+ const summaryUrl = `${config.endpoint.replace(/\/$/, '')}/deviceAppManagement/mobileApps/${app.id}/installSummary`;
269
+ const res = await fetchFn(summaryUrl, { headers });
270
+ if (res.ok) {
271
+ const summary = (await res.json()) as Record<string, unknown>;
272
+ return { ...app, installSummary: summary };
273
+ }
274
+ return { ...app, installSummary: null };
275
+ } catch {
276
+ return { ...app, installSummary: null };
277
+ }
278
+ }),
279
+ );
280
+
281
+ return { apps: appsWithStatus, count: appsWithStatus.length };
282
+ };
283
+
284
+ // --- Pack definition ---
285
+
286
+ export const graphPack: IntegrationPack = {
287
+ manifest: {
288
+ name: 'graph',
289
+ type: 'integration',
290
+ version: '0.1.0',
291
+ description:
292
+ 'Microsoft Graph — Entra ID users, sign-in logs, risky users, Intune device compliance',
293
+ requires: { groups: [], files: [], commands: [] },
294
+ probes: [
295
+ {
296
+ name: 'user.lookup',
297
+ description: 'Look up Entra ID users by name, email, or UPN',
298
+ capability: 'observe',
299
+ params: {
300
+ q: {
301
+ type: 'string',
302
+ description: 'Search query (display name prefix, email, or UPN)',
303
+ required: true,
304
+ },
305
+ },
306
+ timeout: 15000,
307
+ },
308
+ {
309
+ name: 'user.groups',
310
+ description: 'List group memberships for a user',
311
+ capability: 'observe',
312
+ params: {
313
+ id: {
314
+ type: 'string',
315
+ description: 'User object ID or UPN',
316
+ required: true,
317
+ },
318
+ },
319
+ timeout: 15000,
320
+ },
321
+ {
322
+ name: 'signin.recent',
323
+ description: 'Recent sign-in logs for a user',
324
+ capability: 'observe',
325
+ params: {
326
+ user: {
327
+ type: 'string',
328
+ description: 'User principal name (UPN)',
329
+ required: true,
330
+ },
331
+ hours: {
332
+ type: 'number',
333
+ description: 'Lookback period in hours (default: 24)',
334
+ required: false,
335
+ },
336
+ },
337
+ timeout: 30000,
338
+ },
339
+ {
340
+ name: 'users.risky',
341
+ description: 'Users flagged by Identity Protection at a given risk level',
342
+ capability: 'observe',
343
+ params: {
344
+ level: {
345
+ type: 'string',
346
+ description: "Risk level filter: 'low', 'medium', or 'high' (default: 'high')",
347
+ required: false,
348
+ },
349
+ },
350
+ timeout: 15000,
351
+ },
352
+ {
353
+ name: 'intune.devices.compliance',
354
+ description: 'Intune managed device compliance status',
355
+ capability: 'observe',
356
+ params: {
357
+ user: {
358
+ type: 'string',
359
+ description: 'Optional UPN filter — if omitted, returns all managed devices',
360
+ required: false,
361
+ },
362
+ },
363
+ timeout: 30000,
364
+ },
365
+ {
366
+ name: 'intune.devices.noncompliant',
367
+ description: 'Intune devices with noncompliant status',
368
+ capability: 'observe',
369
+ params: {},
370
+ timeout: 30000,
371
+ },
372
+ {
373
+ name: 'intune.apps.status',
374
+ description: 'Intune mobile app inventory with install summaries',
375
+ capability: 'observe',
376
+ params: {},
377
+ timeout: 30000,
378
+ },
379
+ ],
380
+ runbook: {
381
+ category: 'identity',
382
+ probes: ['user.lookup', 'users.risky', 'intune.devices.noncompliant'],
383
+ parallel: true,
384
+ },
385
+ },
386
+
387
+ handlers: {
388
+ 'user.lookup': userLookup,
389
+ 'user.groups': userGroups,
390
+ 'signin.recent': signinRecent,
391
+ 'users.risky': usersRisky,
392
+ 'intune.devices.compliance': intuneDevicesCompliance,
393
+ 'intune.devices.noncompliant': intuneDevicesNoncompliant,
394
+ 'intune.apps.status': intuneAppsStatus,
395
+ },
396
+
397
+ testConnection: async (config, credentials, fetchFn) => {
398
+ try {
399
+ const token = await ensureGraphToken(credentials, fetchFn);
400
+ const url = `${config.endpoint.replace(/\/$/, '')}/organization?$select=id&$top=1`;
401
+ const res = await fetchFn(url, {
402
+ headers: {
403
+ Authorization: `Bearer ${token}`,
404
+ Accept: 'application/json',
405
+ ...config.headers,
406
+ },
407
+ });
408
+ return res.ok;
409
+ } catch {
410
+ return false;
411
+ }
412
+ },
413
+ };
@@ -0,0 +1,72 @@
1
+ import type { IntegrationPack } from '@sonde/shared';
2
+
3
+ export const httpbinPack: IntegrationPack = {
4
+ manifest: {
5
+ name: 'httpbin',
6
+ type: 'integration',
7
+ version: '0.1.0',
8
+ description: 'httpbin.org integration for testing HTTP requests',
9
+ requires: { groups: [], files: [], commands: [] },
10
+ probes: [
11
+ {
12
+ name: 'ip',
13
+ description: 'Get the origin IP address',
14
+ capability: 'observe',
15
+ timeout: 5000,
16
+ },
17
+ {
18
+ name: 'headers',
19
+ description: 'Get the request headers as seen by the server',
20
+ capability: 'observe',
21
+ timeout: 5000,
22
+ },
23
+ {
24
+ name: 'status',
25
+ description: 'Return a response with the given HTTP status code',
26
+ capability: 'observe',
27
+ params: {
28
+ code: {
29
+ type: 'number',
30
+ description: 'HTTP status code to return',
31
+ required: true,
32
+ },
33
+ },
34
+ timeout: 5000,
35
+ },
36
+ ],
37
+ runbook: {
38
+ category: 'httpbin',
39
+ probes: ['ip', 'headers'],
40
+ parallel: true,
41
+ },
42
+ },
43
+
44
+ handlers: {
45
+ ip: async (_params, config, _credentials, fetchFn) => {
46
+ const res = await fetchFn(`${config.endpoint}/ip`);
47
+ if (!res.ok) throw new Error(`httpbin /ip returned ${res.status}`);
48
+ return await res.json();
49
+ },
50
+
51
+ headers: async (_params, config, _credentials, fetchFn) => {
52
+ const res = await fetchFn(`${config.endpoint}/headers`);
53
+ if (!res.ok) throw new Error(`httpbin /headers returned ${res.status}`);
54
+ return await res.json();
55
+ },
56
+
57
+ status: async (params, config, _credentials, fetchFn) => {
58
+ const code = params?.code ?? 200;
59
+ const res = await fetchFn(`${config.endpoint}/status/${code}`);
60
+ return { statusCode: res.status, ok: res.ok };
61
+ },
62
+ },
63
+
64
+ testConnection: async (config, _credentials, fetchFn) => {
65
+ try {
66
+ const res = await fetchFn(`${config.endpoint}/ip`);
67
+ return res.ok;
68
+ } catch {
69
+ return false;
70
+ }
71
+ },
72
+ };