@oneuptime/common 12.0.5 → 12.0.6

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 (528) hide show
  1. package/Models/DatabaseModels/AIRun.ts +33 -0
  2. package/Models/DatabaseModels/DataSource.ts +744 -0
  3. package/Models/DatabaseModels/Index.ts +3 -0
  4. package/Models/DatabaseModels/ProjectCallSMSConfig.ts +10 -2
  5. package/Models/DatabaseModels/User.ts +2 -0
  6. package/Models/DatabaseModels/UserOnCallLog.ts +2 -0
  7. package/Models/DatabaseModels/UserOnCallLogTimeline.ts +2 -0
  8. package/Models/DatabaseModels/UserSession.ts +2 -0
  9. package/Models/DatabaseModels/UserTotpAuth.ts +6 -4
  10. package/Models/DatabaseModels/UserWebAuthn.ts +5 -3
  11. package/Server/API/AIInsightAPI.ts +47 -4
  12. package/Server/API/AIInvestigationAPI.ts +25 -0
  13. package/Server/API/DashboardAPI.ts +176 -492
  14. package/Server/API/DataSourceAPI.ts +268 -0
  15. package/Server/API/StatusPageAPI.ts +11 -1
  16. package/Server/API/UserAPI.ts +119 -0
  17. package/Server/Infrastructure/ClickhouseConfig.ts +59 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1786303472848-AddDataSourceTable.ts +39 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/1786600000000-AddInvestigationAnalysisTldr.ts +24 -0
  20. package/Server/Infrastructure/Postgres/SchemaMigrations/1786700000000-DropProjectCallSMSConfigCredentialUniques.ts +76 -0
  21. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  22. package/Server/Infrastructure/Queue.ts +26 -0
  23. package/Server/Infrastructure/QueueWorker.ts +17 -0
  24. package/Server/Middleware/TelemetryIngest.ts +8 -3
  25. package/Server/Services/AIInsightService.ts +132 -12
  26. package/Server/Services/AIRunService.ts +34 -0
  27. package/Server/Services/AIService.ts +17 -2
  28. package/Server/Services/AlertService.ts +38 -32
  29. package/Server/Services/AnalyticsDatabaseService.ts +8 -4
  30. package/Server/Services/DataSourceService.ts +200 -0
  31. package/Server/Services/HostService.ts +92 -0
  32. package/Server/Services/IncidentService.ts +45 -0
  33. package/Server/Services/Index.ts +2 -0
  34. package/Server/Services/MonitorService.ts +49 -0
  35. package/Server/Services/MonitorStatusService.ts +166 -0
  36. package/Server/Services/OpenTelemetryIngestService.ts +255 -184
  37. package/Server/Services/RumSessionPinService.ts +7 -21
  38. package/Server/Services/StatusPageSubscriberService.ts +13 -0
  39. package/Server/Services/UserService.ts +280 -9
  40. package/Server/Static/Vendor/README.md +62 -0
  41. package/Server/Static/Vendor/fonts/InterVariable.woff2 +0 -0
  42. package/Server/Static/Vendor/highlight/highlight.min.js +1244 -0
  43. package/Server/Static/Vendor/highlight/languages/apache.min.js +15 -0
  44. package/Server/Static/Vendor/highlight/languages/bash.min.js +21 -0
  45. package/Server/Static/Vendor/highlight/languages/c.min.js +41 -0
  46. package/Server/Static/Vendor/highlight/languages/cpp.min.js +47 -0
  47. package/Server/Static/Vendor/highlight/languages/csharp.min.js +49 -0
  48. package/Server/Static/Vendor/highlight/languages/css.min.js +31 -0
  49. package/Server/Static/Vendor/highlight/languages/diff.min.js +9 -0
  50. package/Server/Static/Vendor/highlight/languages/dns.min.js +11 -0
  51. package/Server/Static/Vendor/highlight/languages/dockerfile.min.js +8 -0
  52. package/Server/Static/Vendor/highlight/languages/go.min.js +20 -0
  53. package/Server/Static/Vendor/highlight/languages/graphql.min.js +12 -0
  54. package/Server/Static/Vendor/highlight/languages/http.min.js +14 -0
  55. package/Server/Static/Vendor/highlight/languages/ini.min.js +15 -0
  56. package/Server/Static/Vendor/highlight/languages/java.min.js +38 -0
  57. package/Server/Static/Vendor/highlight/languages/javascript.min.js +81 -0
  58. package/Server/Static/Vendor/highlight/languages/json.min.js +8 -0
  59. package/Server/Static/Vendor/highlight/languages/kotlin.min.js +46 -0
  60. package/Server/Static/Vendor/highlight/languages/lua.min.js +15 -0
  61. package/Server/Static/Vendor/highlight/languages/makefile.min.js +14 -0
  62. package/Server/Static/Vendor/highlight/languages/nginx.min.js +21 -0
  63. package/Server/Static/Vendor/highlight/languages/perl.min.js +41 -0
  64. package/Server/Static/Vendor/highlight/languages/php.min.js +59 -0
  65. package/Server/Static/Vendor/highlight/languages/powershell.min.js +39 -0
  66. package/Server/Static/Vendor/highlight/languages/python.min.js +42 -0
  67. package/Server/Static/Vendor/highlight/languages/r.min.js +26 -0
  68. package/Server/Static/Vendor/highlight/languages/ruby.min.js +54 -0
  69. package/Server/Static/Vendor/highlight/languages/rust.min.js +27 -0
  70. package/Server/Static/Vendor/highlight/languages/scala.min.js +28 -0
  71. package/Server/Static/Vendor/highlight/languages/sql.min.js +21 -0
  72. package/Server/Static/Vendor/highlight/languages/swift.min.js +68 -0
  73. package/Server/Static/Vendor/highlight/languages/typescript.min.js +99 -0
  74. package/Server/Static/Vendor/highlight/languages/xml.min.js +29 -0
  75. package/Server/Static/Vendor/highlight/languages/yaml.min.js +28 -0
  76. package/Server/Static/Vendor/highlight/styles/github-dark.min.css +10 -0
  77. package/Server/Static/Vendor/highlight/styles/vs2015.min.css +1 -0
  78. package/Server/Static/Vendor/tailwind/tailwind-3.4.5.js +21028 -0
  79. package/Server/Types/Database/Permissions/BasePermission.ts +7 -0
  80. package/Server/Types/Database/Permissions/DeletePermission.ts +2 -0
  81. package/Server/Types/Database/Permissions/ReadPermission.ts +3 -0
  82. package/Server/Types/Database/Permissions/TenantPermission.ts +101 -16
  83. package/Server/Utils/AI/CodeFix/FixRunBudget.ts +2 -2
  84. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +90 -11
  85. package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +1 -0
  86. package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +1 -0
  87. package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionIdentity.ts +125 -0
  88. package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +25 -15
  89. package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +256 -57
  90. package/Server/Utils/AI/SRE/Insights/InsightStore.ts +76 -18
  91. package/Server/Utils/AI/SRE/InvestigationTldr.ts +352 -0
  92. package/Server/Utils/AnalyticsDatabase/InsertDedupContext.ts +7 -2
  93. package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +1793 -0
  94. package/Server/Utils/Dashboard/PublicDashboardViewConfig.ts +65 -0
  95. package/Server/Utils/DataSource/ConnectorRegistry.ts +53 -0
  96. package/Server/Utils/DataSource/Connectors/ClickHouseConnector.ts +338 -0
  97. package/Server/Utils/DataSource/Connectors/ElasticsearchConnector.ts +717 -0
  98. package/Server/Utils/DataSource/Connectors/LokiConnector.ts +606 -0
  99. package/Server/Utils/DataSource/Connectors/MySqlConnector.ts +307 -0
  100. package/Server/Utils/DataSource/Connectors/PostgresConnector.ts +260 -0
  101. package/Server/Utils/DataSource/Connectors/PrometheusConnector.ts +555 -0
  102. package/Server/Utils/DataSource/Connectors/RestApiConnector.ts +597 -0
  103. package/Server/Utils/DataSource/Connectors/SqlServerConnector.ts +318 -0
  104. package/Server/Utils/DataSource/EgressGuard.ts +446 -0
  105. package/Server/Utils/DataSource/HttpFetch.ts +221 -0
  106. package/Server/Utils/DataSource/SqlQueryGuard.ts +383 -0
  107. package/Server/Utils/DataSource/SqlResultShaper.ts +372 -0
  108. package/Server/Utils/DataSource/Types.ts +93 -0
  109. package/Server/Utils/Database/PostgresErrorTranslator.ts +172 -17
  110. package/Server/Utils/InProcessMemo.ts +141 -0
  111. package/Server/Utils/InstanceHealth/TelemetryIngestion.ts +628 -0
  112. package/Server/Utils/Monitor/MonitorMetricUtil.ts +58 -0
  113. package/Server/Utils/Monitor/MonitorResource.ts +14 -0
  114. package/Server/Utils/Response.ts +12 -1
  115. package/Server/Utils/SSRFProtection.ts +237 -0
  116. package/Server/Utils/StartServer.ts +8 -0
  117. package/Server/Utils/StatusPageSubscriberWebhook.ts +30 -0
  118. package/Server/Utils/Telemetry/CaptureSpan.ts +30 -18
  119. package/Server/Utils/Telemetry/IngestionTimestamp.ts +75 -0
  120. package/Server/Utils/Telemetry/ResourceHeartbeat.ts +99 -7
  121. package/Server/Utils/Telemetry/Telemetry.ts +112 -1
  122. package/Server/Utils/Telemetry.ts +104 -3
  123. package/Server/Utils/VendorAssets.ts +165 -0
  124. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +28 -5
  125. package/Server/Utils/Workspace/Slack/Slack.ts +5 -0
  126. package/Server/Views/Partials/Head.ejs +21 -7
  127. package/Tests/App/AdminDashboard/AdminProjectsIdFilter.test.tsx +207 -0
  128. package/Tests/App/AdminDashboard/AdminUsersIdFilter.test.tsx +216 -0
  129. package/Tests/App/Dashboard/AIInsightViewActions.test.tsx +422 -0
  130. package/Tests/App/Dashboard/AddWidgetModal.test.tsx +10 -3
  131. package/Tests/App/Dashboard/AlertsSideMenu.test.tsx +387 -0
  132. package/Tests/App/Dashboard/ChatActivityFeed.test.tsx +199 -0
  133. package/Tests/App/Dashboard/DataSourceChartSyntheticConfig.test.tsx +736 -0
  134. package/Tests/App/Dashboard/DataSourceQueryEditor.test.tsx +868 -0
  135. package/Tests/App/Dashboard/DataSourceWidgetCatalog.test.ts +440 -0
  136. package/Tests/App/Dashboard/DataSourceWidgetFetching.test.tsx +2109 -0
  137. package/Tests/App/Dashboard/DataSourceWidgetViews.test.tsx +726 -0
  138. package/Tests/App/Dashboard/IncidentsSideMenu.test.tsx +447 -0
  139. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +514 -3
  140. package/Tests/App/Dashboard/ProductMenuBreadcrumbs.test.tsx +391 -0
  141. package/Tests/App/Dashboard/ScheduledMaintenanceSideMenu.test.tsx +326 -0
  142. package/Tests/App/Dashboard/SideMenuHarness.tsx +187 -0
  143. package/Tests/App/Dashboard/WidgetCatalog.test.ts +6 -1
  144. package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +1858 -0
  145. package/Tests/Models/DatabaseModels/DataSourceModelSecrets.test.ts +70 -0
  146. package/Tests/Server/API/AIInvestigationAPI.test.ts +187 -0
  147. package/Tests/Server/API/DashboardPublicDataSourceStrip.test.ts +686 -0
  148. package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +585 -823
  149. package/Tests/Server/API/DataSourceAPIRoutes.test.ts +486 -0
  150. package/Tests/Server/API/StatusPageSubscriberOwnership.test.ts +291 -0
  151. package/Tests/Server/API/UserAuthenticationAPI.test.ts +641 -0
  152. package/Tests/Server/Infrastructure/ClickhouseKeepAliveOptions.test.ts +441 -0
  153. package/Tests/Server/Middleware/TelemetryIngestTokenLog.test.ts +140 -0
  154. package/Tests/Server/Services/AIInsightService.test.ts +266 -11
  155. package/Tests/Server/Services/AIRunAnalysisTldrPersistence.test.ts +160 -0
  156. package/Tests/Server/Services/AIServiceDailyBudget.test.ts +4 -0
  157. package/Tests/Server/Services/AlertMetricResourceAttributes.test.ts +352 -0
  158. package/Tests/Server/Services/DataSourceServiceSettings.test.ts +244 -0
  159. package/Tests/Server/Services/HostServiceFindOrCreateMemo.test.ts +397 -0
  160. package/Tests/Server/Services/HostServiceUpdateLastSeen.test.ts +41 -2
  161. package/Tests/Server/Services/IncidentMetricResourceAttributes.test.ts +408 -0
  162. package/Tests/Server/Services/MonitorStatusServiceDeleteReferenceCleanup.test.ts +351 -0
  163. package/Tests/Server/Services/MonitorStatusServiceValidation.test.ts +171 -0
  164. package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +398 -0
  165. package/Tests/Server/Services/OpenTelemetryServiceResolutionCache.test.ts +19 -0
  166. package/Tests/Server/Services/ProjectCallSMSConfigCredentialUniqueness.test.ts +305 -0
  167. package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +36 -1
  168. package/Tests/Server/Services/RumSessionPinUniqueViolationRecovery.test.ts +163 -0
  169. package/Tests/Server/Services/UserAuthenticationService.test.ts +973 -0
  170. package/Tests/Server/Types/Database/ObjectIdColumnQuery.test.ts +262 -0
  171. package/Tests/Server/Types/Database/Permissions/TenantPermission.test.ts +358 -0
  172. package/Tests/Server/Utils/AI/FixRunBudget.test.ts +2 -2
  173. package/Tests/Server/Utils/AI/Insights/ExceptionSpikeDetector.test.ts +6 -1
  174. package/Tests/Server/Utils/AI/Insights/InsightStore.test.ts +121 -4
  175. package/Tests/Server/Utils/AI/Insights/NewExceptionDetector.test.ts +361 -10
  176. package/Tests/Server/Utils/AI/InvestigationSettlement.test.ts +292 -0
  177. package/Tests/Server/Utils/AI/InvestigationTldr.test.ts +623 -0
  178. package/Tests/Server/Utils/AI/InvestigationTldrWiring.test.ts +98 -0
  179. package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +857 -0
  180. package/Tests/Server/Utils/Dashboard/PublicDashboardViewConfig.test.ts +480 -0
  181. package/Tests/Server/Utils/DataSource/ClickHouseConnector.test.ts +759 -0
  182. package/Tests/Server/Utils/DataSource/ConnectorRegistry.test.ts +37 -0
  183. package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +645 -0
  184. package/Tests/Server/Utils/DataSource/ElasticsearchConnector.test.ts +1206 -0
  185. package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +616 -0
  186. package/Tests/Server/Utils/DataSource/LokiConnector.test.ts +970 -0
  187. package/Tests/Server/Utils/DataSource/MySqlConnector.test.ts +935 -0
  188. package/Tests/Server/Utils/DataSource/PostgresConnector.test.ts +854 -0
  189. package/Tests/Server/Utils/DataSource/PrometheusConnector.test.ts +881 -0
  190. package/Tests/Server/Utils/DataSource/RestApiConnector.test.ts +1020 -0
  191. package/Tests/Server/Utils/DataSource/SqlQueryGuard.test.ts +425 -0
  192. package/Tests/Server/Utils/DataSource/SqlResultShaper.test.ts +555 -0
  193. package/Tests/Server/Utils/DataSource/SqlServerConnector.test.ts +934 -0
  194. package/Tests/Server/Utils/Database/PostgresErrorTranslator.test.ts +228 -7
  195. package/Tests/Server/Utils/InProcessMemo.test.ts +292 -0
  196. package/Tests/Server/Utils/InstanceHealth/TelemetryIngestion.test.ts +960 -0
  197. package/Tests/Server/Utils/MicrosoftTeamsWebhookUrlValidation.test.ts +103 -0
  198. package/Tests/Server/Utils/Monitor/MonitorMetricResourceAttributes.test.ts +336 -0
  199. package/Tests/Server/Utils/OfflineAssetHygiene.test.ts +521 -0
  200. package/Tests/Server/Utils/ResponseRenderAnalytics.test.ts +143 -0
  201. package/Tests/Server/Utils/SSRFProtection.test.ts +193 -0
  202. package/Tests/Server/Utils/StatusPageSubscriberWebhook.test.ts +101 -0
  203. package/Tests/Server/Utils/TailwindBuildCopy.test.ts +225 -0
  204. package/Tests/Server/Utils/Telemetry/ResourceHeartbeatL1Memo.test.ts +355 -0
  205. package/Tests/Server/Utils/Telemetry/TelemetryFanInWriter.test.ts +128 -0
  206. package/Tests/Server/Utils/Telemetry/TelemetryUtilAttributeKeys.test.ts +381 -0
  207. package/Tests/Server/Utils/Telemetry.test.ts +87 -0
  208. package/Tests/Server/Utils/VendorAssetIntegrity.test.ts +343 -0
  209. package/Tests/Server/Utils/VendorAssets.test.ts +671 -0
  210. package/Tests/Server/Views/OfflineRender.test.ts +297 -0
  211. package/Tests/Types/Dashboard/DataSourceComponentTypes.test.ts +618 -0
  212. package/Tests/Types/DateClickhouseFormat.test.ts +192 -0
  213. package/Tests/Types/Password.test.ts +363 -0
  214. package/Tests/UI/Components/ConfirmModal.test.tsx +7 -0
  215. package/Tests/UI/Components/ErrorBoundary.test.tsx +53 -0
  216. package/Tests/UI/Components/Modal.test.tsx +281 -1
  217. package/Tests/UI/Components/ObjectIdFilterPipeline.test.tsx +396 -0
  218. package/Tests/UI/Components/StatusPage/ResourceGroupNavigator.test.tsx +1147 -0
  219. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +116 -1
  220. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +2 -0
  221. package/Tests/Utils/Analytics.test.ts +23 -0
  222. package/Tests/Utils/Dashboard/Components/DashboardDataSourceComponents.test.ts +640 -0
  223. package/Tests/Utils/DataSource/DataSourceQueryText.test.ts +138 -0
  224. package/Tests/Utils/DataSource/DataSourceValueReducer.test.ts +526 -0
  225. package/Tests/Utils/Metrics/MetricResourceAttributeUtil.test.ts +691 -0
  226. package/Tests/Utils/StatusPage/GroupHierarchyView.test.ts +1452 -0
  227. package/Tests/Utils/StatusPage/ResourceExplorer.test.ts +931 -0
  228. package/Tests/Utils/Telemetry/CaptureSpanExportGating.test.ts +288 -0
  229. package/Tests/Utils/Telemetry/IngestionTimestamp.test.ts +170 -0
  230. package/Types/AI/AIInsightEvidence.ts +6 -0
  231. package/Types/Analytics/RevenueEvent.ts +31 -0
  232. package/Types/Dashboard/DashboardComponentType.ts +31 -0
  233. package/Types/Dashboard/DashboardComponents/DashboardDataSourceChartComponent.ts +27 -0
  234. package/Types/Dashboard/DashboardComponents/DashboardDataSourceGaugeComponent.ts +32 -0
  235. package/Types/Dashboard/DashboardComponents/DashboardDataSourceTableComponent.ts +30 -0
  236. package/Types/Dashboard/DashboardComponents/DashboardDataSourceValueComponent.ts +55 -0
  237. package/Types/DataSource/DataSourceLimits.ts +62 -0
  238. package/Types/DataSource/DataSourceQueryConfig.ts +41 -0
  239. package/Types/DataSource/DataSourceTableResult.ts +38 -0
  240. package/Types/DataSource/DataSourceType.ts +213 -0
  241. package/Types/Date.ts +43 -3
  242. package/Types/Password.ts +64 -0
  243. package/Types/Permission.ts +46 -0
  244. package/Types/UserAuthenticationStatus.ts +34 -0
  245. package/UI/Components/Button/Button.tsx +1 -1
  246. package/UI/Components/ErrorBoundary.tsx +459 -108
  247. package/UI/Components/Icon/Icon.tsx +10 -9
  248. package/UI/Components/Modal/ConfirmModal.tsx +6 -1
  249. package/UI/Components/Modal/Modal.tsx +267 -35
  250. package/UI/Components/Modal/ModalFooter.tsx +6 -1
  251. package/UI/Components/MoreMenu/MoreMenu.tsx +19 -4
  252. package/UI/Components/MoreMenu/MoreMenuItem.tsx +6 -1
  253. package/UI/Components/StatusPage/ResourceGrid.tsx +314 -0
  254. package/UI/Components/StatusPage/ResourceGroupNavigator.tsx +808 -0
  255. package/UI/Components/StatusPage/ResourceList.tsx +570 -0
  256. package/UI/Styles/Theme.css +18 -0
  257. package/UI/Utils/API/RequestOptions.ts +7 -0
  258. package/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.ts +1 -0
  259. package/UI/Utils/ModelAPI/ModelAPI.ts +1 -0
  260. package/UI/Utils/TestDataSource.ts +61 -0
  261. package/UI/esbuild-config.js +45 -0
  262. package/Utils/Analytics.ts +15 -0
  263. package/Utils/Dashboard/Components/DashboardDataSourceChartComponent.ts +88 -0
  264. package/Utils/Dashboard/Components/DashboardDataSourceGaugeComponent.ts +123 -0
  265. package/Utils/Dashboard/Components/DashboardDataSourceShared.ts +16 -0
  266. package/Utils/Dashboard/Components/DashboardDataSourceTableComponent.ts +72 -0
  267. package/Utils/Dashboard/Components/DashboardDataSourceValueComponent.ts +126 -0
  268. package/Utils/Dashboard/Components/Index.ts +28 -0
  269. package/Utils/DataSource/DataSourceQueryText.ts +94 -0
  270. package/Utils/DataSource/DataSourceValueReducer.ts +156 -0
  271. package/Utils/Metrics/MetricResourceAttributeUtil.ts +380 -0
  272. package/Utils/NetworkDiscovery/ScanTargetUtil.ts +8 -6
  273. package/Utils/StatusPage/GroupHierarchyView.ts +931 -0
  274. package/Utils/StatusPage/ResourceExplorer.ts +853 -0
  275. package/build/dist/Models/DatabaseModels/AIRun.js +34 -0
  276. package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
  277. package/build/dist/Models/DatabaseModels/DataSource.js +774 -0
  278. package/build/dist/Models/DatabaseModels/DataSource.js.map +1 -0
  279. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  280. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  281. package/build/dist/Models/DatabaseModels/ProjectCallSMSConfig.js +14 -4
  282. package/build/dist/Models/DatabaseModels/ProjectCallSMSConfig.js.map +1 -1
  283. package/build/dist/Models/DatabaseModels/User.js +2 -0
  284. package/build/dist/Models/DatabaseModels/User.js.map +1 -1
  285. package/build/dist/Models/DatabaseModels/UserOnCallLog.js +2 -0
  286. package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
  287. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +2 -0
  288. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
  289. package/build/dist/Models/DatabaseModels/UserSession.js +2 -0
  290. package/build/dist/Models/DatabaseModels/UserSession.js.map +1 -1
  291. package/build/dist/Models/DatabaseModels/UserTotpAuth.js +6 -4
  292. package/build/dist/Models/DatabaseModels/UserTotpAuth.js.map +1 -1
  293. package/build/dist/Models/DatabaseModels/UserWebAuthn.js +5 -3
  294. package/build/dist/Models/DatabaseModels/UserWebAuthn.js.map +1 -1
  295. package/build/dist/Server/API/AIInsightAPI.js +34 -4
  296. package/build/dist/Server/API/AIInsightAPI.js.map +1 -1
  297. package/build/dist/Server/API/AIInvestigationAPI.js +23 -0
  298. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  299. package/build/dist/Server/API/DashboardAPI.js +119 -433
  300. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  301. package/build/dist/Server/API/DataSourceAPI.js +173 -0
  302. package/build/dist/Server/API/DataSourceAPI.js.map +1 -0
  303. package/build/dist/Server/API/StatusPageAPI.js +11 -1
  304. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  305. package/build/dist/Server/API/UserAPI.js +94 -2
  306. package/build/dist/Server/API/UserAPI.js.map +1 -1
  307. package/build/dist/Server/Infrastructure/ClickhouseConfig.js +49 -0
  308. package/build/dist/Server/Infrastructure/ClickhouseConfig.js.map +1 -1
  309. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786303472848-AddDataSourceTable.js +20 -0
  310. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786303472848-AddDataSourceTable.js.map +1 -0
  311. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786600000000-AddInvestigationAnalysisTldr.js +19 -0
  312. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786600000000-AddInvestigationAnalysisTldr.js.map +1 -0
  313. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786700000000-DropProjectCallSMSConfigCredentialUniques.js +64 -0
  314. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786700000000-DropProjectCallSMSConfigCredentialUniques.js.map +1 -0
  315. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  316. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  317. package/build/dist/Server/Infrastructure/Queue.js +27 -0
  318. package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
  319. package/build/dist/Server/Infrastructure/QueueWorker.js +13 -0
  320. package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
  321. package/build/dist/Server/Middleware/TelemetryIngest.js +8 -3
  322. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  323. package/build/dist/Server/Services/AIInsightService.js +110 -10
  324. package/build/dist/Server/Services/AIInsightService.js.map +1 -1
  325. package/build/dist/Server/Services/AIRunService.js +34 -0
  326. package/build/dist/Server/Services/AIRunService.js.map +1 -1
  327. package/build/dist/Server/Services/AIService.js +16 -2
  328. package/build/dist/Server/Services/AIService.js.map +1 -1
  329. package/build/dist/Server/Services/AlertService.js +28 -35
  330. package/build/dist/Server/Services/AlertService.js.map +1 -1
  331. package/build/dist/Server/Services/AnalyticsDatabaseService.js +8 -4
  332. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  333. package/build/dist/Server/Services/DataSourceService.js +159 -0
  334. package/build/dist/Server/Services/DataSourceService.js.map +1 -0
  335. package/build/dist/Server/Services/HostService.js +74 -0
  336. package/build/dist/Server/Services/HostService.js.map +1 -1
  337. package/build/dist/Server/Services/IncidentService.js +35 -24
  338. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  339. package/build/dist/Server/Services/Index.js +2 -0
  340. package/build/dist/Server/Services/Index.js.map +1 -1
  341. package/build/dist/Server/Services/MonitorService.js +45 -0
  342. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  343. package/build/dist/Server/Services/MonitorStatusService.js +129 -0
  344. package/build/dist/Server/Services/MonitorStatusService.js.map +1 -1
  345. package/build/dist/Server/Services/OpenTelemetryIngestService.js +222 -159
  346. package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
  347. package/build/dist/Server/Services/RumSessionPinService.js +7 -15
  348. package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
  349. package/build/dist/Server/Services/StatusPageSubscriberService.js +10 -0
  350. package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
  351. package/build/dist/Server/Services/UserService.js +241 -10
  352. package/build/dist/Server/Services/UserService.js.map +1 -1
  353. package/build/dist/Server/Types/Database/Permissions/BasePermission.js +6 -0
  354. package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
  355. package/build/dist/Server/Types/Database/Permissions/DeletePermission.js +1 -0
  356. package/build/dist/Server/Types/Database/Permissions/DeletePermission.js.map +1 -1
  357. package/build/dist/Server/Types/Database/Permissions/ReadPermission.js +2 -0
  358. package/build/dist/Server/Types/Database/Permissions/ReadPermission.js.map +1 -1
  359. package/build/dist/Server/Types/Database/Permissions/TenantPermission.js +68 -12
  360. package/build/dist/Server/Types/Database/Permissions/TenantPermission.js.map +1 -1
  361. package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +2 -2
  362. package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -1
  363. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +68 -8
  364. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  365. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +1 -0
  366. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
  367. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +1 -0
  368. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
  369. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionIdentity.js +97 -0
  370. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionIdentity.js.map +1 -0
  371. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +17 -15
  372. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -1
  373. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +178 -54
  374. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -1
  375. package/build/dist/Server/Utils/AI/SRE/Insights/InsightStore.js +65 -16
  376. package/build/dist/Server/Utils/AI/SRE/Insights/InsightStore.js.map +1 -1
  377. package/build/dist/Server/Utils/AI/SRE/InvestigationTldr.js +303 -0
  378. package/build/dist/Server/Utils/AI/SRE/InvestigationTldr.js.map +1 -0
  379. package/build/dist/Server/Utils/AnalyticsDatabase/InsertDedupContext.js.map +1 -1
  380. package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +1261 -0
  381. package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -0
  382. package/build/dist/Server/Utils/Dashboard/PublicDashboardViewConfig.js +47 -0
  383. package/build/dist/Server/Utils/Dashboard/PublicDashboardViewConfig.js.map +1 -0
  384. package/build/dist/Server/Utils/DataSource/ConnectorRegistry.js +42 -0
  385. package/build/dist/Server/Utils/DataSource/ConnectorRegistry.js.map +1 -0
  386. package/build/dist/Server/Utils/DataSource/Connectors/ClickHouseConnector.js +187 -0
  387. package/build/dist/Server/Utils/DataSource/Connectors/ClickHouseConnector.js.map +1 -0
  388. package/build/dist/Server/Utils/DataSource/Connectors/ElasticsearchConnector.js +493 -0
  389. package/build/dist/Server/Utils/DataSource/Connectors/ElasticsearchConnector.js.map +1 -0
  390. package/build/dist/Server/Utils/DataSource/Connectors/LokiConnector.js +399 -0
  391. package/build/dist/Server/Utils/DataSource/Connectors/LokiConnector.js.map +1 -0
  392. package/build/dist/Server/Utils/DataSource/Connectors/MySqlConnector.js +195 -0
  393. package/build/dist/Server/Utils/DataSource/Connectors/MySqlConnector.js.map +1 -0
  394. package/build/dist/Server/Utils/DataSource/Connectors/PostgresConnector.js +149 -0
  395. package/build/dist/Server/Utils/DataSource/Connectors/PostgresConnector.js.map +1 -0
  396. package/build/dist/Server/Utils/DataSource/Connectors/PrometheusConnector.js +362 -0
  397. package/build/dist/Server/Utils/DataSource/Connectors/PrometheusConnector.js.map +1 -0
  398. package/build/dist/Server/Utils/DataSource/Connectors/RestApiConnector.js +342 -0
  399. package/build/dist/Server/Utils/DataSource/Connectors/RestApiConnector.js.map +1 -0
  400. package/build/dist/Server/Utils/DataSource/Connectors/SqlServerConnector.js +186 -0
  401. package/build/dist/Server/Utils/DataSource/Connectors/SqlServerConnector.js.map +1 -0
  402. package/build/dist/Server/Utils/DataSource/EgressGuard.js +305 -0
  403. package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -0
  404. package/build/dist/Server/Utils/DataSource/HttpFetch.js +134 -0
  405. package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -0
  406. package/build/dist/Server/Utils/DataSource/SqlQueryGuard.js +331 -0
  407. package/build/dist/Server/Utils/DataSource/SqlQueryGuard.js.map +1 -0
  408. package/build/dist/Server/Utils/DataSource/SqlResultShaper.js +280 -0
  409. package/build/dist/Server/Utils/DataSource/SqlResultShaper.js.map +1 -0
  410. package/build/dist/Server/Utils/DataSource/Types.js +2 -0
  411. package/build/dist/Server/Utils/DataSource/Types.js.map +1 -0
  412. package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js +103 -9
  413. package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js.map +1 -1
  414. package/build/dist/Server/Utils/InProcessMemo.js +113 -0
  415. package/build/dist/Server/Utils/InProcessMemo.js.map +1 -0
  416. package/build/dist/Server/Utils/InstanceHealth/TelemetryIngestion.js +406 -0
  417. package/build/dist/Server/Utils/InstanceHealth/TelemetryIngestion.js.map +1 -0
  418. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +34 -0
  419. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
  420. package/build/dist/Server/Utils/Monitor/MonitorResource.js +14 -0
  421. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  422. package/build/dist/Server/Utils/Response.js +9 -1
  423. package/build/dist/Server/Utils/Response.js.map +1 -1
  424. package/build/dist/Server/Utils/SSRFProtection.js +192 -0
  425. package/build/dist/Server/Utils/SSRFProtection.js.map +1 -0
  426. package/build/dist/Server/Utils/StartServer.js +7 -0
  427. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  428. package/build/dist/Server/Utils/StatusPageSubscriberWebhook.js +24 -0
  429. package/build/dist/Server/Utils/StatusPageSubscriberWebhook.js.map +1 -1
  430. package/build/dist/Server/Utils/Telemetry/CaptureSpan.js +25 -11
  431. package/build/dist/Server/Utils/Telemetry/CaptureSpan.js.map +1 -1
  432. package/build/dist/Server/Utils/Telemetry/IngestionTimestamp.js +32 -0
  433. package/build/dist/Server/Utils/Telemetry/IngestionTimestamp.js.map +1 -0
  434. package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js +92 -5
  435. package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js.map +1 -1
  436. package/build/dist/Server/Utils/Telemetry/Telemetry.js +92 -6
  437. package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
  438. package/build/dist/Server/Utils/Telemetry.js +93 -6
  439. package/build/dist/Server/Utils/Telemetry.js.map +1 -1
  440. package/build/dist/Server/Utils/VendorAssets.js +121 -0
  441. package/build/dist/Server/Utils/VendorAssets.js.map +1 -0
  442. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +25 -4
  443. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  444. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +5 -0
  445. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  446. package/build/dist/Types/Analytics/RevenueEvent.js +26 -0
  447. package/build/dist/Types/Analytics/RevenueEvent.js.map +1 -0
  448. package/build/dist/Types/Dashboard/DashboardComponentType.js +27 -0
  449. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  450. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceChartComponent.js +2 -0
  451. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceChartComponent.js.map +1 -0
  452. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceGaugeComponent.js +2 -0
  453. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceGaugeComponent.js.map +1 -0
  454. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceTableComponent.js +2 -0
  455. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceTableComponent.js.map +1 -0
  456. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceValueComponent.js +16 -0
  457. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceValueComponent.js.map +1 -0
  458. package/build/dist/Types/DataSource/DataSourceLimits.js +47 -0
  459. package/build/dist/Types/DataSource/DataSourceLimits.js.map +1 -0
  460. package/build/dist/Types/DataSource/DataSourceQueryConfig.js +10 -0
  461. package/build/dist/Types/DataSource/DataSourceQueryConfig.js.map +1 -0
  462. package/build/dist/Types/DataSource/DataSourceTableResult.js +14 -0
  463. package/build/dist/Types/DataSource/DataSourceTableResult.js.map +1 -0
  464. package/build/dist/Types/DataSource/DataSourceType.js +183 -0
  465. package/build/dist/Types/DataSource/DataSourceType.js.map +1 -0
  466. package/build/dist/Types/Date.js +38 -3
  467. package/build/dist/Types/Date.js.map +1 -1
  468. package/build/dist/Types/Password.js +56 -0
  469. package/build/dist/Types/Password.js.map +1 -0
  470. package/build/dist/Types/Permission.js +42 -0
  471. package/build/dist/Types/Permission.js.map +1 -1
  472. package/build/dist/Types/UserAuthenticationStatus.js +2 -0
  473. package/build/dist/Types/UserAuthenticationStatus.js.map +1 -0
  474. package/build/dist/UI/Components/ErrorBoundary.js +388 -72
  475. package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
  476. package/build/dist/UI/Components/Icon/Icon.js +10 -4
  477. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  478. package/build/dist/UI/Components/Modal/ConfirmModal.js +1 -1
  479. package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
  480. package/build/dist/UI/Components/Modal/Modal.js +178 -19
  481. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  482. package/build/dist/UI/Components/Modal/ModalFooter.js +3 -1
  483. package/build/dist/UI/Components/Modal/ModalFooter.js.map +1 -1
  484. package/build/dist/UI/Components/MoreMenu/MoreMenu.js +9 -6
  485. package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
  486. package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +7 -1
  487. package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -1
  488. package/build/dist/UI/Components/StatusPage/ResourceGrid.js +119 -0
  489. package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -0
  490. package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js +354 -0
  491. package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js.map +1 -0
  492. package/build/dist/UI/Components/StatusPage/ResourceList.js +203 -0
  493. package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -0
  494. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js +1 -6
  495. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js.map +1 -1
  496. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +3 -8
  497. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  498. package/build/dist/UI/Utils/TestDataSource.js +39 -0
  499. package/build/dist/UI/Utils/TestDataSource.js.map +1 -0
  500. package/build/dist/Utils/Analytics.js +4 -0
  501. package/build/dist/Utils/Analytics.js.map +1 -1
  502. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceChartComponent.js +79 -0
  503. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceChartComponent.js.map +1 -0
  504. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceGaugeComponent.js +111 -0
  505. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceGaugeComponent.js.map +1 -0
  506. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceShared.js +15 -0
  507. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceShared.js.map +1 -0
  508. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceTableComponent.js +62 -0
  509. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceTableComponent.js.map +1 -0
  510. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceValueComponent.js +112 -0
  511. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceValueComponent.js.map +1 -0
  512. package/build/dist/Utils/Dashboard/Components/Index.js +16 -0
  513. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  514. package/build/dist/Utils/DataSource/DataSourceQueryText.js +64 -0
  515. package/build/dist/Utils/DataSource/DataSourceQueryText.js.map +1 -0
  516. package/build/dist/Utils/DataSource/DataSourceValueReducer.js +124 -0
  517. package/build/dist/Utils/DataSource/DataSourceValueReducer.js.map +1 -0
  518. package/build/dist/Utils/Metrics/MetricResourceAttributeUtil.js +281 -0
  519. package/build/dist/Utils/Metrics/MetricResourceAttributeUtil.js.map +1 -0
  520. package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js +8 -6
  521. package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js.map +1 -1
  522. package/build/dist/Utils/StatusPage/GroupHierarchyView.js +560 -0
  523. package/build/dist/Utils/StatusPage/GroupHierarchyView.js.map +1 -0
  524. package/build/dist/Utils/StatusPage/ResourceExplorer.js +519 -0
  525. package/build/dist/Utils/StatusPage/ResourceExplorer.js.map +1 -0
  526. package/jest.config.json +1 -0
  527. package/package.json +5 -1
  528. package/tsconfig.json +12 -10
@@ -0,0 +1,446 @@
1
+ import dns from "dns";
2
+ import net from "net";
3
+ import BadDataException from "../../../Types/Exception/BadDataException";
4
+ import { IsBillingEnabled } from "../../EnvironmentConfig";
5
+
6
+ /*
7
+ * SSRF egress guard for external Data Source connections.
8
+ *
9
+ * Data Sources let project members point OneUptime at arbitrary
10
+ * hosts — which would otherwise turn the API server into an authenticated
11
+ * request proxy into whatever network it runs in (cloud metadata endpoints,
12
+ * internal services, sibling tenants' infrastructure). Every connector must
13
+ * validate its target through this guard before opening a socket.
14
+ *
15
+ * Policy:
16
+ * - ALWAYS blocked, in every deployment: loopback, link-local (cloud
17
+ * metadata lives at 169.254.169.254), unspecified, multicast, broadcast
18
+ * and reserved ranges. Nothing a data source legitimately targets lives
19
+ * there, and the app server's own loopback is exactly what an attacker
20
+ * wants.
21
+ * - PRIVATE ranges (RFC1918, CGNAT, ULA, benchmark/documentation nets):
22
+ * blocked when billing is enabled (multi-tenant SaaS), allowed for
23
+ * self-hosted installs — a self-hosted OneUptime's databases usually ARE
24
+ * on 10.x/192.168.x. Self-hosted operators can force SaaS behavior with
25
+ * DATA_SOURCE_BLOCK_PRIVATE_ADDRESSES=true.
26
+ *
27
+ * Validation happens on RESOLVED ADDRESSES, not hostnames, so decimal
28
+ * (2130706433), octal (0177.0.0.1) and DNS-based tricks all get caught at
29
+ * the same choke point: whatever getaddrinfo would connect to is what gets
30
+ * checked. HTTP connectors additionally PIN the validated addresses into
31
+ * the socket lookup so the checked address is the connected address (no
32
+ * DNS-rebind window); SQL drivers connect by hostname immediately after
33
+ * validation, accepting a small residual rebind window in exchange for
34
+ * intact TLS hostname verification.
35
+ */
36
+
37
+ export interface ResolvedAddress {
38
+ address: string;
39
+ family: number; // 4 | 6
40
+ }
41
+
42
+ export type EgressResolveFunction = (
43
+ hostname: string,
44
+ ) => Promise<Array<ResolvedAddress>>;
45
+
46
+ export interface EgressGuardOptions {
47
+ /*
48
+ * Test seam / policy override. Undefined ⇒ derive from billing flag and
49
+ * the DATA_SOURCE_BLOCK_PRIVATE_ADDRESSES env var.
50
+ */
51
+ blockPrivateAddresses?: boolean | undefined;
52
+ // Test seam for DNS. Undefined ⇒ dns.promises.lookup with a timeout.
53
+ resolveFunction?: EgressResolveFunction | undefined;
54
+ }
55
+
56
+ export interface AddressVerdict {
57
+ blocked: boolean;
58
+ reason?: string | undefined;
59
+ }
60
+
61
+ const DNS_LOOKUP_TIMEOUT_IN_MS: number = 5000;
62
+
63
+ interface Ipv4Range {
64
+ base: number;
65
+ maskBits: number;
66
+ reason: string;
67
+ }
68
+
69
+ type RangeSpec = [string, number, string];
70
+
71
+ const ALWAYS_BLOCKED_IPV4_RANGE_SPECS: Array<RangeSpec> = [
72
+ ["127.0.0.0", 8, "loopback address"],
73
+ ["169.254.0.0", 16, "link-local address (cloud metadata range)"],
74
+ ["0.0.0.0", 8, "unspecified address"],
75
+ ["224.0.0.0", 4, "multicast address"],
76
+ ["240.0.0.0", 4, "reserved address"],
77
+ ];
78
+
79
+ const PRIVATE_IPV4_RANGE_SPECS: Array<RangeSpec> = [
80
+ ["10.0.0.0", 8, "private network address"],
81
+ ["172.16.0.0", 12, "private network address"],
82
+ ["192.168.0.0", 16, "private network address"],
83
+ ["100.64.0.0", 10, "carrier-grade NAT address"],
84
+ ["192.0.0.0", 24, "IETF protocol assignment address"],
85
+ ["198.18.0.0", 15, "benchmarking address"],
86
+ ["192.0.2.0", 24, "documentation address"],
87
+ ["198.51.100.0", 24, "documentation address"],
88
+ ["203.0.113.0", 24, "documentation address"],
89
+ ];
90
+
91
+ export default class DataSourceEgressGuard {
92
+ public static shouldBlockPrivateAddresses(): boolean {
93
+ if (process.env["DATA_SOURCE_BLOCK_PRIVATE_ADDRESSES"] === "true") {
94
+ return true;
95
+ }
96
+ return IsBillingEnabled;
97
+ }
98
+
99
+ private static ipv4ToInt(ip: string): number {
100
+ const parts: Array<string> = ip.split(".");
101
+ let value: number = 0;
102
+ for (const part of parts) {
103
+ value = value * 256 + parseInt(part, 10);
104
+ }
105
+ // >>> 0 keeps the value an unsigned 32-bit int.
106
+ return value >>> 0;
107
+ }
108
+
109
+ private static buildRanges(specs: Array<RangeSpec>): Array<Ipv4Range> {
110
+ return specs.map((spec: RangeSpec) => {
111
+ return {
112
+ base: this.ipv4ToInt(spec[0]),
113
+ maskBits: spec[1],
114
+ reason: spec[2],
115
+ };
116
+ });
117
+ }
118
+
119
+ private static isInRange(ipAsInt: number, range: Ipv4Range): boolean {
120
+ /*
121
+ * maskBits 0 would shift by 32 (undefined behavior in JS bitwise ops);
122
+ * no range here uses it, but guard anyway.
123
+ */
124
+ if (range.maskBits <= 0) {
125
+ return true;
126
+ }
127
+ const mask: number = (0xffffffff << (32 - range.maskBits)) >>> 0;
128
+ return (ipAsInt & mask) >>> 0 === (range.base & mask) >>> 0;
129
+ }
130
+
131
+ private static checkIpv4(
132
+ ip: string,
133
+ blockPrivateAddresses: boolean,
134
+ ): AddressVerdict {
135
+ const ipAsInt: number = this.ipv4ToInt(ip);
136
+
137
+ if (ip === "255.255.255.255") {
138
+ return { blocked: true, reason: "broadcast address" };
139
+ }
140
+
141
+ for (const range of this.buildRanges(ALWAYS_BLOCKED_IPV4_RANGE_SPECS)) {
142
+ if (this.isInRange(ipAsInt, range)) {
143
+ return { blocked: true, reason: range.reason };
144
+ }
145
+ }
146
+
147
+ if (blockPrivateAddresses) {
148
+ for (const range of this.buildRanges(PRIVATE_IPV4_RANGE_SPECS)) {
149
+ if (this.isInRange(ipAsInt, range)) {
150
+ return { blocked: true, reason: range.reason };
151
+ }
152
+ }
153
+ }
154
+
155
+ return { blocked: false };
156
+ }
157
+
158
+ /*
159
+ * Expand an IPv6 address to its full 8-group lowercase form so prefix
160
+ * checks are string-safe ("fe80::1" -> "fe80:0000:...:0001"). Zone ids
161
+ * (%eth0) are stripped first.
162
+ */
163
+ private static expandIpv6(ip: string): string | null {
164
+ let address: string = ip.toLowerCase();
165
+ const zoneIndex: number = address.indexOf("%");
166
+ if (zoneIndex !== -1) {
167
+ address = address.substring(0, zoneIndex);
168
+ }
169
+
170
+ /*
171
+ * Convert a trailing embedded IPv4 (::ffff:127.0.0.1) into two hex
172
+ * groups so the group math below is uniform.
173
+ */
174
+ const lastColon: number = address.lastIndexOf(":");
175
+ const tail: string = address.substring(lastColon + 1);
176
+ if (tail.includes(".")) {
177
+ if (net.isIPv4(tail) === false) {
178
+ return null;
179
+ }
180
+ const octets: Array<number> = tail.split(".").map((part: string) => {
181
+ return parseInt(part, 10);
182
+ });
183
+ const groupA: string = ((octets[0]! << 8) | octets[1]!).toString(16);
184
+ const groupB: string = ((octets[2]! << 8) | octets[3]!).toString(16);
185
+ address = `${address.substring(0, lastColon)}:${groupA}:${groupB}`;
186
+ }
187
+
188
+ const doubleColonParts: Array<string> = address.split("::");
189
+ if (doubleColonParts.length > 2) {
190
+ return null;
191
+ }
192
+
193
+ let groups: Array<string>;
194
+ if (doubleColonParts.length === 2) {
195
+ const head: Array<string> = doubleColonParts[0]
196
+ ? doubleColonParts[0].split(":")
197
+ : [];
198
+ const tailGroups: Array<string> = doubleColonParts[1]
199
+ ? doubleColonParts[1].split(":")
200
+ : [];
201
+ const missing: number = 8 - head.length - tailGroups.length;
202
+ if (missing < 0) {
203
+ return null;
204
+ }
205
+ groups = [...head, ...Array(missing).fill("0"), ...tailGroups];
206
+ } else {
207
+ groups = address.split(":");
208
+ }
209
+
210
+ if (groups.length !== 8) {
211
+ return null;
212
+ }
213
+
214
+ return groups
215
+ .map((group: string) => {
216
+ return group.padStart(4, "0");
217
+ })
218
+ .join(":");
219
+ }
220
+
221
+ private static checkIpv6(
222
+ ip: string,
223
+ blockPrivateAddresses: boolean,
224
+ ): AddressVerdict {
225
+ const expanded: string | null = this.expandIpv6(ip);
226
+ if (!expanded) {
227
+ return { blocked: true, reason: "unparseable IPv6 address" };
228
+ }
229
+
230
+ /*
231
+ * IPv4-mapped (::ffff:a.b.c.d) and NAT64 (64:ff9b::/96) addresses
232
+ * reach IPv4 targets — extract the embedded IPv4 and apply the IPv4
233
+ * policy so mapping can't be used to smuggle a blocked v4 address.
234
+ */
235
+ const embeddedV4Prefixes: Array<string> = [
236
+ "0000:0000:0000:0000:0000:ffff:",
237
+ "0064:ff9b:0000:0000:0000:0000:",
238
+ ];
239
+ for (const prefix of embeddedV4Prefixes) {
240
+ if (expanded.startsWith(prefix)) {
241
+ const hexGroups: Array<string> = expanded
242
+ .substring(prefix.length)
243
+ .split(":");
244
+ const high: number = parseInt(hexGroups[0]!, 16);
245
+ const low: number = parseInt(hexGroups[1]!, 16);
246
+ const embedded: string = [
247
+ (high >> 8) & 0xff,
248
+ high & 0xff,
249
+ (low >> 8) & 0xff,
250
+ low & 0xff,
251
+ ].join(".");
252
+ return this.checkIpv4(embedded, blockPrivateAddresses);
253
+ }
254
+ }
255
+
256
+ const allZero: boolean = expanded === "0000:".repeat(7) + "0000";
257
+ if (allZero) {
258
+ return { blocked: true, reason: "unspecified address" };
259
+ }
260
+ if (expanded === "0000:".repeat(7) + "0001") {
261
+ return { blocked: true, reason: "loopback address" };
262
+ }
263
+
264
+ const firstGroup: number = parseInt(expanded.substring(0, 4), 16);
265
+ // fe80::/10 link-local.
266
+ if ((firstGroup & 0xffc0) === 0xfe80) {
267
+ return { blocked: true, reason: "link-local address" };
268
+ }
269
+ // ff00::/8 multicast.
270
+ if ((firstGroup & 0xff00) === 0xff00) {
271
+ return { blocked: true, reason: "multicast address" };
272
+ }
273
+
274
+ if (blockPrivateAddresses) {
275
+ // fc00::/7 unique-local.
276
+ if ((firstGroup & 0xfe00) === 0xfc00) {
277
+ return { blocked: true, reason: "private network address" };
278
+ }
279
+ // 2001:db8::/32 documentation.
280
+ if (expanded.startsWith("2001:0db8:")) {
281
+ return { blocked: true, reason: "documentation address" };
282
+ }
283
+ }
284
+
285
+ return { blocked: false };
286
+ }
287
+
288
+ /*
289
+ * Verdict for a single literal IP address under the given (or derived)
290
+ * policy. Exposed for tests and for connectors that receive addresses
291
+ * from somewhere other than the standard resolve path.
292
+ */
293
+ public static checkAddress(
294
+ address: string,
295
+ options?: EgressGuardOptions,
296
+ ): AddressVerdict {
297
+ const blockPrivateAddresses: boolean =
298
+ options?.blockPrivateAddresses ?? this.shouldBlockPrivateAddresses();
299
+
300
+ const family: number = net.isIP(address);
301
+ if (family === 4) {
302
+ return this.checkIpv4(address, blockPrivateAddresses);
303
+ }
304
+ if (family === 6) {
305
+ return this.checkIpv6(address, blockPrivateAddresses);
306
+ }
307
+ return { blocked: true, reason: "not a valid IP address" };
308
+ }
309
+
310
+ private static async defaultResolve(
311
+ hostname: string,
312
+ ): Promise<Array<ResolvedAddress>> {
313
+ /*
314
+ * dns.lookup (getaddrinfo) rather than dns.resolve so /etc/hosts and
315
+ * container DNS behave exactly as the eventual socket connect would —
316
+ * we must validate what would actually be dialed.
317
+ */
318
+ const lookupPromise: Promise<Array<ResolvedAddress>> = dns.promises
319
+ .lookup(hostname, { all: true })
320
+ .then((results: Array<{ address: string; family: number }>) => {
321
+ return results.map((result: { address: string; family: number }) => {
322
+ return { address: result.address, family: result.family };
323
+ });
324
+ });
325
+
326
+ let timeoutHandle: ReturnType<typeof setTimeout> | undefined = undefined;
327
+ const timeoutPromise: Promise<never> = new Promise(
328
+ (_resolve: (value: never) => void, reject: (error: Error) => void) => {
329
+ timeoutHandle = setTimeout(() => {
330
+ reject(new BadDataException(`DNS lookup timed out for ${hostname}`));
331
+ }, DNS_LOOKUP_TIMEOUT_IN_MS);
332
+ },
333
+ );
334
+
335
+ try {
336
+ return await Promise.race([lookupPromise, timeoutPromise]);
337
+ } finally {
338
+ if (timeoutHandle) {
339
+ clearTimeout(timeoutHandle);
340
+ }
341
+ }
342
+ }
343
+
344
+ /*
345
+ * Resolve a hostname (or accept a literal IP) and assert every address it
346
+ * can reach is allowed. Returns the validated addresses so HTTP callers
347
+ * can pin them into the socket lookup. Throws BadDataException when any
348
+ * address is blocked — ALL must pass, otherwise a multi-record DNS answer
349
+ * could mix one public decoy with a private target.
350
+ */
351
+ public static async assertHostnameAllowed(
352
+ hostname: string,
353
+ options?: EgressGuardOptions,
354
+ ): Promise<Array<ResolvedAddress>> {
355
+ if (!hostname) {
356
+ throw new BadDataException("Data source host is required.");
357
+ }
358
+
359
+ // Literal [::1] style hosts arrive with brackets from URL parsing.
360
+ const bareHostname: string = hostname.replace(/^\[|\]$/g, "");
361
+
362
+ if (net.isIP(bareHostname) !== 0) {
363
+ const verdict: AddressVerdict = this.checkAddress(bareHostname, options);
364
+ if (verdict.blocked) {
365
+ throw new BadDataException(
366
+ `Data source host ${bareHostname} is not allowed: ${verdict.reason}.`,
367
+ );
368
+ }
369
+ return [{ address: bareHostname, family: net.isIP(bareHostname) }];
370
+ }
371
+
372
+ const resolveFunction: EgressResolveFunction =
373
+ options?.resolveFunction ||
374
+ ((host: string) => {
375
+ return this.defaultResolve(host);
376
+ });
377
+
378
+ let addresses: Array<ResolvedAddress> = [];
379
+ try {
380
+ addresses = await resolveFunction(bareHostname);
381
+ } catch (error) {
382
+ throw new BadDataException(
383
+ `Could not resolve data source host ${bareHostname}: ${
384
+ error instanceof Error ? error.message : String(error)
385
+ }`,
386
+ );
387
+ }
388
+
389
+ if (addresses.length === 0) {
390
+ throw new BadDataException(
391
+ `Could not resolve data source host ${bareHostname}.`,
392
+ );
393
+ }
394
+
395
+ for (const resolved of addresses) {
396
+ const verdict: AddressVerdict = this.checkAddress(
397
+ resolved.address,
398
+ options,
399
+ );
400
+ if (verdict.blocked) {
401
+ throw new BadDataException(
402
+ `Data source host ${bareHostname} resolves to ${resolved.address}, which is not allowed: ${verdict.reason}.`,
403
+ );
404
+ }
405
+ }
406
+
407
+ return addresses;
408
+ }
409
+
410
+ /*
411
+ * Validate a full HTTP(S) URL: scheme must be http/https and the host
412
+ * must pass address validation. Returns the parsed URL plus the pinned
413
+ * addresses for the HTTP client.
414
+ */
415
+ public static async assertUrlAllowed(
416
+ urlString: string,
417
+ options?: EgressGuardOptions,
418
+ ): Promise<{ url: URL; addresses: Array<ResolvedAddress> }> {
419
+ if (!urlString) {
420
+ throw new BadDataException("Data source URL is required.");
421
+ }
422
+
423
+ let url: URL;
424
+ try {
425
+ url = new URL(urlString);
426
+ } catch {
427
+ throw new BadDataException(`Invalid data source URL: ${urlString}`);
428
+ }
429
+
430
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
431
+ throw new BadDataException(
432
+ `Data source URL must use http or https (got ${url.protocol.replace(
433
+ ":",
434
+ "",
435
+ )}).`,
436
+ );
437
+ }
438
+
439
+ const addresses: Array<ResolvedAddress> = await this.assertHostnameAllowed(
440
+ url.hostname,
441
+ options,
442
+ );
443
+
444
+ return { url, addresses };
445
+ }
446
+ }
@@ -0,0 +1,221 @@
1
+ import http from "http";
2
+ import https from "https";
3
+ import axios, { AxiosRequestConfig, AxiosResponse } from "axios";
4
+ import API from "../../../Utils/API";
5
+ import Dictionary from "../../../Types/Dictionary";
6
+ import BadDataException from "../../../Types/Exception/BadDataException";
7
+ import {
8
+ DATA_SOURCE_MAX_RESPONSE_SIZE_IN_BYTES,
9
+ DATA_SOURCE_QUERY_TIMEOUT_IN_MS,
10
+ } from "../../../Types/DataSource/DataSourceLimits";
11
+ import DataSourceEgressGuard, {
12
+ EgressGuardOptions,
13
+ ResolvedAddress,
14
+ } from "./EgressGuard";
15
+ import { DataSourceConnectionSettings } from "./Types";
16
+
17
+ /*
18
+ * SSRF-hardened HTTP client for HTTP-based Data Source connectors
19
+ * (Prometheus, Loki, Elasticsearch, REST API).
20
+ *
21
+ * Every request:
22
+ * - validates the URL through DataSourceEgressGuard and PINS the resolved,
23
+ * validated addresses into the socket lookup — the address that was
24
+ * checked is the address that gets dialed, closing the DNS-rebind
25
+ * window while TLS still verifies against the original hostname;
26
+ * - refuses redirects (maxRedirects: 0) — a 3xx from the target could
27
+ * otherwise bounce the request to an unvalidated host;
28
+ * - caps response size and wall-clock time.
29
+ *
30
+ * Uses axios directly (not Common/Utils/API.fetch) because the shared
31
+ * wrapper does not expose maxContentLength, and the response-size cap is a
32
+ * hard requirement here.
33
+ */
34
+
35
+ export interface DataSourceHttpRequest {
36
+ method: "GET" | "POST";
37
+ url: string;
38
+ headers?: Dictionary<string> | undefined;
39
+ /*
40
+ * POST body. Strings are sent as-is; objects are JSON-encoded unless
41
+ * formUrlEncoded is set (Prometheus' query endpoints take form bodies).
42
+ */
43
+ body?: string | Dictionary<string> | undefined;
44
+ formUrlEncoded?: boolean | undefined;
45
+ timeoutInMs?: number | undefined;
46
+ // Test seam — forwarded to the egress guard.
47
+ egressOptions?: EgressGuardOptions | undefined;
48
+ }
49
+
50
+ export interface DataSourceHttpResponse {
51
+ statusCode: number;
52
+ bodyText: string;
53
+ // Parsed JSON body, or undefined when the body is not valid JSON.
54
+ bodyJson: unknown;
55
+ }
56
+
57
+ type LookupCallback = (
58
+ error: NodeJS.ErrnoException | null,
59
+ address: string | Array<{ address: string; family: number }>,
60
+ family?: number,
61
+ ) => void;
62
+
63
+ export default class DataSourceHttpFetch {
64
+ /*
65
+ * Standard auth headers for a data source: Bearer token wins, else HTTP
66
+ * basic from username/password; custom headers are applied last so an
67
+ * explicit Authorization header in customHeaders takes precedence.
68
+ */
69
+ public static buildAuthHeaders(
70
+ settings: DataSourceConnectionSettings,
71
+ ): Dictionary<string> {
72
+ const headers: Dictionary<string> = {};
73
+
74
+ if (settings.apiToken) {
75
+ headers["Authorization"] = `Bearer ${settings.apiToken}`;
76
+ } else if (settings.username || settings.password) {
77
+ const encoded: string = Buffer.from(
78
+ `${settings.username || ""}:${settings.password || ""}`,
79
+ ).toString("base64");
80
+ headers["Authorization"] = `Basic ${encoded}`;
81
+ }
82
+
83
+ if (settings.customHeaders) {
84
+ for (const key of Object.keys(settings.customHeaders)) {
85
+ headers[key] = settings.customHeaders[key] as string;
86
+ }
87
+ }
88
+
89
+ return headers;
90
+ }
91
+
92
+ public static async fetch(
93
+ request: DataSourceHttpRequest,
94
+ ): Promise<DataSourceHttpResponse> {
95
+ const { url, addresses } = await DataSourceEgressGuard.assertUrlAllowed(
96
+ request.url,
97
+ request.egressOptions,
98
+ );
99
+
100
+ /*
101
+ * Pin the validated addresses: whatever getaddrinfo said at validation
102
+ * time is what the socket dials, even if DNS answers differently a
103
+ * millisecond later.
104
+ */
105
+ const pinnedLookup: (
106
+ hostname: string,
107
+ options: { all?: boolean },
108
+ callback: LookupCallback,
109
+ ) => void = (
110
+ _hostname: string,
111
+ options: { all?: boolean },
112
+ callback: LookupCallback,
113
+ ): void => {
114
+ const first: ResolvedAddress = addresses[0]!;
115
+ if (options && options.all) {
116
+ callback(
117
+ null,
118
+ addresses.map((resolved: ResolvedAddress) => {
119
+ return { address: resolved.address, family: resolved.family };
120
+ }),
121
+ );
122
+ return;
123
+ }
124
+ callback(null, first.address, first.family);
125
+ };
126
+
127
+ const httpAgent: http.Agent = new http.Agent({
128
+ lookup: pinnedLookup as never,
129
+ });
130
+ const httpsAgent: https.Agent = new https.Agent({
131
+ lookup: pinnedLookup as never,
132
+ });
133
+
134
+ const headers: Dictionary<string> = { ...(request.headers || {}) };
135
+
136
+ let data: string | URLSearchParams | undefined = undefined;
137
+ if (request.method === "POST" && request.body !== undefined) {
138
+ if (typeof request.body === "string") {
139
+ data = request.body;
140
+ if (!headers["Content-Type"]) {
141
+ headers["Content-Type"] = "application/json";
142
+ }
143
+ } else if (request.formUrlEncoded) {
144
+ data = new URLSearchParams(request.body);
145
+ headers["Content-Type"] = "application/x-www-form-urlencoded";
146
+ } else {
147
+ data = JSON.stringify(request.body);
148
+ headers["Content-Type"] = "application/json";
149
+ }
150
+ }
151
+
152
+ const axiosOptions: AxiosRequestConfig = {
153
+ method: request.method,
154
+ url: url.toString(),
155
+ headers: headers,
156
+ data: data,
157
+ timeout: request.timeoutInMs || DATA_SOURCE_QUERY_TIMEOUT_IN_MS,
158
+ maxRedirects: 0,
159
+ maxContentLength: DATA_SOURCE_MAX_RESPONSE_SIZE_IN_BYTES,
160
+ maxBodyLength: DATA_SOURCE_MAX_RESPONSE_SIZE_IN_BYTES,
161
+ /*
162
+ * Keep the raw body so connectors can produce useful errors for
163
+ * non-JSON responses; status handling is ours, not axios'.
164
+ */
165
+ responseType: "text",
166
+ transformResponse: [
167
+ (body: string): string => {
168
+ return body;
169
+ },
170
+ ],
171
+ validateStatus: (status: number): boolean => {
172
+ // 3xx must throw — redirects are refused by policy, not followed.
173
+ return status < 300;
174
+ },
175
+ httpAgent: httpAgent,
176
+ httpsAgent: httpsAgent,
177
+ };
178
+
179
+ try {
180
+ const response: AxiosResponse<string> = await axios(axiosOptions);
181
+ const bodyText: string = response.data || "";
182
+
183
+ let bodyJson: unknown = undefined;
184
+ try {
185
+ bodyJson = JSON.parse(bodyText);
186
+ } catch {
187
+ bodyJson = undefined;
188
+ }
189
+
190
+ return {
191
+ statusCode: response.status,
192
+ bodyText: bodyText,
193
+ bodyJson: bodyJson,
194
+ };
195
+ } catch (error) {
196
+ if (axios.isAxiosError(error) && error.response) {
197
+ /*
198
+ * The server answered with an error status. Surface status + a
199
+ * trimmed body excerpt — Prometheus/Elasticsearch put the real
200
+ * reason ("parse error at char 5") in the body.
201
+ */
202
+ const responseBody: string =
203
+ typeof error.response.data === "string"
204
+ ? error.response.data
205
+ : JSON.stringify(error.response.data ?? "");
206
+ throw new BadDataException(
207
+ `Data source responded with HTTP ${error.response.status}: ${responseBody.substring(0, 500)}`,
208
+ );
209
+ }
210
+
211
+ throw new BadDataException(
212
+ `Could not reach data source: ${API.getFriendlyErrorMessage(
213
+ error as Error,
214
+ )}`,
215
+ );
216
+ } finally {
217
+ httpAgent.destroy();
218
+ httpsAgent.destroy();
219
+ }
220
+ }
221
+ }