@oneuptime/common 12.0.25 → 12.0.26
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.
- package/Models/AnalyticsModels/Index.ts +2 -0
- package/Models/AnalyticsModels/ThreatIntelIndicator.ts +413 -0
- package/Models/DatabaseModels/AlertSeverity.ts +4 -1
- package/Models/DatabaseModels/CephClusterFeed.ts +625 -0
- package/Models/DatabaseModels/CloudResourceFeed.ts +625 -0
- package/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.ts +13 -0
- package/Models/DatabaseModels/DetectionRule.ts +9 -3
- package/Models/DatabaseModels/DockerHostFeed.ts +625 -0
- package/Models/DatabaseModels/DockerSwarmClusterFeed.ts +628 -0
- package/Models/DatabaseModels/GoogleSecOpsConnection.ts +9 -3
- package/Models/DatabaseModels/HostFeed.ts +625 -0
- package/Models/DatabaseModels/IncidentSeverity.ts +4 -1
- package/Models/DatabaseModels/Index.ts +22 -0
- package/Models/DatabaseModels/KubernetesClusterFeed.ts +628 -0
- package/Models/DatabaseModels/Monitor.ts +87 -0
- package/Models/DatabaseModels/NetworkDevice.ts +96 -5
- package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +92 -6
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +301 -31
- package/Models/DatabaseModels/NetworkSite.ts +120 -0
- package/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.ts +1 -0
- package/Models/DatabaseModels/PodmanHostFeed.ts +625 -0
- package/Models/DatabaseModels/ProxmoxClusterFeed.ts +626 -0
- package/Models/DatabaseModels/ScheduledMaintenance.ts +67 -0
- package/Models/DatabaseModels/ServiceFeed.ts +625 -0
- package/Models/DatabaseModels/TelemetrySourceMap.ts +474 -0
- package/Models/DatabaseModels/ThreatIntelFeed.ts +758 -0
- package/Models/DatabaseModels/UserOnCallLog.ts +1 -0
- package/Models/DatabaseModels/UserTotpAuth.ts +1 -0
- package/Models/DatabaseModels/UserWebAuthn.ts +1 -0
- package/Server/API/AlertAPI.ts +23 -1
- package/Server/API/BaseAPI.ts +14 -3
- package/Server/API/IncidentAPI.ts +41 -1
- package/Server/API/IncidentEpisodeAPI.ts +23 -1
- package/Server/API/MicrosoftTeamsAPI.ts +31 -2
- package/Server/API/ScheduledMaintenanceAPI.ts +23 -1
- package/Server/API/SlackAPI.ts +48 -0
- package/Server/API/TelemetryAPI.ts +167 -42
- package/Server/API/UserOnCallLogTimelineAPI.ts +75 -61
- package/Server/API/UserTotpAuthAPI.ts +67 -1
- package/Server/API/UserWebAuthnAPI.ts +44 -1
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787923136162-MigrationName.ts +57 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789600000000-AddAutoProvisionedNetworkDeviceMonitors.ts +49 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789700000000-AddNetworkScaleIndexes.ts +129 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789800000000-WidenSecurityEventLastErrorColumns.ts +54 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789900000000-AddNetworkSiteRollupPolicyAndMaintenance.ts +64 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790000000000-AddTelemetrySourceMap.ts +64 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790000000001-AddSnmpConfigsToNetworkDeviceDiscoveryScan.ts +72 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790003445000-AddSnmpEnabledToNetworkDeviceDiscoveryScan.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790100000000-AddResourceActivityFeeds.ts +489 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +18 -0
- package/Server/Middleware/IdentityRateLimit.ts +53 -3
- package/Server/Services/AIService.ts +181 -41
- package/Server/Services/CephClusterFeedService.ts +99 -0
- package/Server/Services/CephClusterLabelRuleEngineService.ts +29 -0
- package/Server/Services/CephClusterOwnerRuleEngineService.ts +23 -0
- package/Server/Services/CephClusterOwnerTeamService.ts +129 -0
- package/Server/Services/CephClusterOwnerUserService.ts +123 -0
- package/Server/Services/CephClusterService.ts +223 -2
- package/Server/Services/CloudResourceFeedService.ts +99 -0
- package/Server/Services/CloudResourceLabelRuleEngineService.ts +30 -0
- package/Server/Services/CloudResourceOwnerRuleEngineService.ts +33 -0
- package/Server/Services/CloudResourceOwnerTeamService.ts +129 -0
- package/Server/Services/CloudResourceOwnerUserService.ts +123 -0
- package/Server/Services/CloudResourceService.ts +227 -2
- package/Server/Services/DatabaseService.ts +265 -0
- package/Server/Services/DockerHostFeedService.ts +99 -0
- package/Server/Services/DockerHostLabelRuleEngineService.ts +29 -0
- package/Server/Services/DockerHostOwnerRuleEngineService.ts +23 -0
- package/Server/Services/DockerHostOwnerTeamService.ts +129 -0
- package/Server/Services/DockerHostOwnerUserService.ts +123 -0
- package/Server/Services/DockerHostService.ts +227 -2
- package/Server/Services/DockerSwarmClusterFeedService.ts +102 -0
- package/Server/Services/DockerSwarmClusterLabelRuleEngineService.ts +30 -0
- package/Server/Services/DockerSwarmClusterOwnerRuleEngineService.ts +24 -0
- package/Server/Services/DockerSwarmClusterOwnerTeamService.ts +133 -0
- package/Server/Services/DockerSwarmClusterOwnerUserService.ts +127 -0
- package/Server/Services/DockerSwarmClusterService.ts +229 -2
- package/Server/Services/EnterpriseLicenseService.ts +15 -7
- package/Server/Services/ExceptionAggregationService.ts +12 -2
- package/Server/Services/HostFeedService.ts +99 -0
- package/Server/Services/HostLabelRuleEngineService.ts +29 -0
- package/Server/Services/HostOwnerRuleEngineService.ts +23 -0
- package/Server/Services/HostOwnerTeamService.ts +129 -0
- package/Server/Services/HostOwnerUserService.ts +123 -0
- package/Server/Services/HostService.ts +215 -2
- package/Server/Services/IncidentService.ts +11 -0
- package/Server/Services/Index.ts +24 -0
- package/Server/Services/KubernetesClusterFeedService.ts +99 -0
- package/Server/Services/KubernetesClusterLabelRuleEngineService.ts +30 -0
- package/Server/Services/KubernetesClusterOwnerRuleEngineService.ts +24 -0
- package/Server/Services/KubernetesClusterOwnerTeamService.ts +133 -0
- package/Server/Services/KubernetesClusterOwnerUserService.ts +127 -0
- package/Server/Services/KubernetesClusterService.ts +231 -2
- package/Server/Services/LogAggregationService.ts +23 -280
- package/Server/Services/MetricAggregationService.ts +98 -1
- package/Server/Services/MonitorService.ts +177 -13
- package/Server/Services/MonitorTemplateService.ts +111 -0
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +777 -86
- package/Server/Services/NetworkDeviceAutoImportRuleService.ts +199 -16
- package/Server/Services/NetworkDeviceDiscoveryScanService.ts +1055 -14
- package/Server/Services/NetworkDeviceService.ts +750 -4
- package/Server/Services/NetworkInterfaceService.ts +415 -0
- package/Server/Services/NetworkSiteService.ts +485 -52
- package/Server/Services/PodmanHostFeedService.ts +99 -0
- package/Server/Services/PodmanHostLabelRuleEngineService.ts +29 -0
- package/Server/Services/PodmanHostOwnerRuleEngineService.ts +23 -0
- package/Server/Services/PodmanHostOwnerTeamService.ts +129 -0
- package/Server/Services/PodmanHostOwnerUserService.ts +123 -0
- package/Server/Services/PodmanHostService.ts +227 -2
- package/Server/Services/ProjectService.ts +16 -10
- package/Server/Services/ProxmoxClusterFeedService.ts +99 -0
- package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +30 -0
- package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +24 -0
- package/Server/Services/ProxmoxClusterOwnerTeamService.ts +131 -0
- package/Server/Services/ProxmoxClusterOwnerUserService.ts +124 -0
- package/Server/Services/ProxmoxClusterService.ts +225 -2
- package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +61 -0
- package/Server/Services/ServiceFeedService.ts +99 -0
- package/Server/Services/ServiceLabelRuleEngineService.ts +29 -0
- package/Server/Services/ServiceOwnerRuleEngineService.ts +26 -0
- package/Server/Services/ServiceOwnerTeamService.ts +129 -0
- package/Server/Services/ServiceOwnerUserService.ts +123 -0
- package/Server/Services/ServiceService.ts +227 -3
- package/Server/Services/StatusPageSubscriberService.ts +7 -0
- package/Server/Services/TelemetryAttributeService.ts +13 -3
- package/Server/Services/TelemetrySourceMapService.ts +307 -0
- package/Server/Services/ThreatIntelFeedService.ts +222 -0
- package/Server/Services/ThreatIntelIndicatorService.ts +428 -0
- package/Server/Services/TraceAggregationService.ts +101 -11
- package/Server/Services/UserService.ts +13 -6
- package/Server/Services/UserTwoFactorBackupCodeService.ts +127 -0
- package/Server/Services/UserWebhookService.ts +11 -2
- package/Server/Static/Brand/README.md +38 -0
- package/Server/Static/Brand/favicons/apple-touch-icon.png +0 -0
- package/Server/Static/Brand/favicons/favicon-16x16.png +0 -0
- package/Server/Static/Brand/favicons/favicon-32x32.png +0 -0
- package/Server/Static/Brand/favicons/favicon.ico +0 -0
- package/Server/Static/Brand/favicons/safari-pinned-tab.svg +31 -0
- package/Server/Static/Brand/hou-wb.svg +1 -0
- package/Server/Static/Brand/oneuptime-logo.svg +1 -0
- package/Server/Static/Brand/ou-wb.svg +1 -0
- package/Server/Static/Vendor/README.md +4 -0
- package/Server/Types/AnalyticsDatabase/ModelPermission.ts +13 -3
- package/Server/Types/Database/AggregateBy.ts +83 -0
- package/Server/Types/Database/AggregateResultUtil.ts +126 -0
- package/Server/Types/Database/JSONColumnQuery.ts +18 -0
- package/Server/Types/Database/QueryHelper.ts +40 -0
- package/Server/Types/Database/QueryUtil.ts +26 -0
- package/Server/Types/Workflow/Components/API/Utils.ts +10 -1
- package/Server/Types/Workflow/Components/JavaScript.ts +8 -0
- package/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.ts +9 -0
- package/Server/Utils/AI/SRE/InvestigationGrader.ts +18 -0
- package/Server/Utils/AnalyticsDatabase/AttributeFilterStatement.ts +422 -0
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +176 -0
- package/Server/Utils/DataSource/HttpFetch.ts +18 -0
- package/Server/Utils/Database/RelationIdUtil.ts +42 -0
- package/Server/Utils/Marketing/MarketingEventUtil.ts +38 -9
- package/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.ts +34 -3
- package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +9 -1
- package/Server/Utils/Monitor/Criteria/SyntheticMonitor.ts +28 -10
- package/Server/Utils/Monitor/MonitorAlert.ts +541 -332
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +330 -64
- package/Server/Utils/Monitor/MonitorIncident.ts +640 -434
- package/Server/Utils/Monitor/MonitorResource.ts +226 -49
- package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +46 -3
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +23 -102
- package/Server/Utils/Monitor/PerEntityCriteriaFanOut.ts +329 -0
- package/Server/Utils/NetworkDevice/DeviceHealthAggregation.ts +427 -0
- package/Server/Utils/NetworkSite/NetworkSiteMaintenanceSuppression.ts +310 -0
- package/Server/Utils/OnCallNotificationContext.ts +686 -0
- package/Server/Utils/PrivateNetworkWebhookConfig.ts +549 -0
- package/Server/Utils/ResourceFeed/ResourceFeedUtil.ts +139 -0
- package/Server/Utils/Response.ts +11 -1
- package/Server/Utils/SSRFProtection.ts +230 -60
- package/Server/Utils/SecurityEvent/ConnectorErrorMessage.ts +106 -0
- package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +84 -284
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +47 -20
- package/Server/Utils/SecurityEvent/SecurityEventAlerting.ts +318 -0
- package/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClient.ts +199 -0
- package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelEnricher.ts +252 -0
- package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.ts +739 -0
- package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.ts +533 -0
- package/Server/Utils/StartServer.ts +83 -56
- package/Server/Utils/StatusPageSubscriberWebhook.ts +3 -0
- package/Server/Utils/Telemetry/SourceMapResolver.ts +480 -0
- package/Server/Utils/TwoFactorBackupCodeNotification.ts +106 -0
- package/Server/Utils/VM/VMAPI.ts +3 -0
- package/Server/Utils/VM/VMRunner.ts +27 -1
- package/Server/Utils/VendorAssets.ts +42 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +136 -6
- package/Server/Views/AcknowledgeUserOnCallNotification.ejs +11 -9
- package/Server/Views/Partials/Head.ejs +9 -9
- package/Server/Views/Partials/OnCallNotificationDetails.ejs +48 -0
- package/Server/Views/ViewMessage.ejs +11 -9
- package/Tests/App/Accounts/LoginTwoFactorRecovery.test.tsx +972 -0
- package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +401 -0
- package/Tests/App/Dashboard/DiscoveryScanEditForm.test.tsx +707 -0
- package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +1908 -18
- package/Tests/App/Dashboard/ResourceFeed.test.tsx +230 -0
- package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +216 -0
- package/Tests/App/Dashboard/TopologyAddToMonitoring.test.tsx +192 -0
- package/Tests/App/Dashboard/WorkspaceNotificationRuleConditions.test.tsx +439 -0
- package/Tests/Models/DatabaseModels/DateColumnDeserialization.test.ts +182 -0
- package/Tests/Models/DatabaseModels/RelationColumnModelTypeCoverage.test.ts +82 -0
- package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +398 -0
- package/Tests/Models/DiscoveryScanNameColumn.test.ts +151 -16
- package/Tests/Models/DiscoveryScanSnmpEnabledColumn.test.ts +593 -0
- package/Tests/Models/NetworkDeviceCreateContract.test.ts +102 -0
- package/Tests/Server/API/AIGenerationProjectAIToggle.test.ts +607 -0
- package/Tests/Server/API/AIGenerationRequestBudget.test.ts +355 -0
- package/Tests/Server/API/AIKillSwitchBackstop.test.ts +602 -0
- package/Tests/Server/API/BaseAPIUpdateDateColumns.test.ts +154 -0
- package/Tests/Server/API/MicrosoftTeamsBotTestEndpoint.test.ts +335 -0
- package/Tests/Server/API/UserOnCallLogTimelineAcknowledgePage.test.ts +611 -0
- package/Tests/Server/API/UserTotpAuthAPI.test.ts +498 -4
- package/Tests/Server/API/UserWebAuthnBackupCodeMinting.test.ts +682 -0
- package/Tests/Server/Infrastructure/ExampleDockerfiles.test.ts +595 -0
- package/Tests/Server/Services/AIServiceDailyBudget.test.ts +9 -0
- package/Tests/Server/Services/AIServiceProjectAccess.test.ts +6 -0
- package/Tests/Server/Services/AutoImportScanCredentialSelect.test.ts +18 -0
- package/Tests/Server/Services/DatabaseServiceAggregateBy.test.ts +590 -0
- package/Tests/Server/Services/DatabaseServiceUpdateWriteRouting.test.ts +12 -0
- package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +162 -26
- package/Tests/Server/Services/EnterpriseLicenseServiceCreate.test.ts +292 -0
- package/Tests/Server/Services/FeedRetentionConsistency.test.ts +119 -12
- package/Tests/Server/Services/LogAggregationAttributeOperators.test.ts +109 -0
- package/Tests/Server/Services/MetricAggregationAttributeOperators.test.ts +170 -0
- package/Tests/Server/Services/MonitorTemplateServiceNetworkDeviceSync.test.ts +383 -0
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +997 -3
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleService.test.ts +830 -0
- package/Tests/Server/Services/NetworkDeviceAutoMonitorLifecycle.test.ts +528 -0
- package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +3141 -1
- package/Tests/Server/Services/NetworkDeviceRegisteredHostnames.test.ts +1023 -0
- package/Tests/Server/Services/NetworkDeviceSiteAssignmentRuleSkip.test.ts +728 -0
- package/Tests/Server/Services/NetworkInterfaceServiceUpsert.test.ts +795 -0
- package/Tests/Server/Services/NetworkSiteRollupPolicyAndMaintenance.test.ts +903 -0
- package/Tests/Server/Services/NetworkSiteService.test.ts +165 -24
- package/Tests/Server/Services/ProjectServiceChangePlan.test.ts +5 -3
- package/Tests/Server/Services/ProjectServiceCreateSubscriptionStarted.test.ts +5 -2
- package/Tests/Server/Services/ResourceCreationFeedWrites.test.ts +304 -0
- package/Tests/Server/Services/ResourceFeedServices.test.ts +269 -0
- package/Tests/Server/Services/ResourceOwnerFeedWrites.test.ts +245 -0
- package/Tests/Server/Services/SecurityEventLastErrorColumnWidth.test.ts +792 -0
- package/Tests/Server/Services/TelemetrySourceMapService.test.ts +483 -0
- package/Tests/Server/Services/ThreatIntelFeedService.test.ts +351 -0
- package/Tests/Server/Services/ThreatIntelIndicatorService.test.ts +366 -0
- package/Tests/Server/Services/TraceAggregationAttributeOperators.test.ts +507 -0
- package/Tests/Server/Services/UserTwoFactorBackupCodeGenerateIfNone.test.ts +705 -0
- package/Tests/Server/Services/WorkspaceNotificationRuleOnCallDutyPolicy.test.ts +306 -0
- package/Tests/Server/Types/Database/AggregateResultUtil.test.ts +386 -0
- package/Tests/Server/Types/Database/Permissions/SelectRejectionMessageContract.test.ts +424 -0
- package/Tests/Server/Types/Database/QueryHelperWildcard.test.ts +142 -0
- package/Tests/Server/Types/Workflow/Components/ApiComponentPrivateNetwork.test.ts +163 -0
- package/Tests/Server/Types/Workflow/Components/JavaScriptPrivateNetwork.test.ts +124 -0
- package/Tests/Server/Utils/AI/CodeFixAgentCompletion.test.ts +5 -0
- package/Tests/Server/Utils/AI/InvestigationGrader.test.ts +39 -1
- package/Tests/Server/Utils/AnalyticsDatabase/AttributeFilterStatement.test.ts +338 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorWildcard.test.ts +383 -0
- package/Tests/Server/Utils/Marketing/EmittedMarketingEvent.ts +23 -0
- package/Tests/Server/Utils/Marketing/MarketingEventUtil.test.ts +51 -0
- package/Tests/Server/Utils/Monitor/Criteria/SyntheticMonitorCriteria.test.ts +259 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPerSeriesFanout.test.ts +557 -0
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +12 -2
- package/Tests/Server/Utils/Monitor/NetworkDeviceWalkLogWritePath.test.ts +404 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +8 -2
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +125 -98
- package/Tests/Server/Utils/Monitor/PerEntityCriteriaFanOut.test.ts +444 -0
- package/Tests/Server/Utils/Monitor/PerSeriesSecondEntityAlerting.test.ts +1112 -0
- package/Tests/Server/Utils/NetworkDevice/DeviceHealthAggregation.test.ts +717 -0
- package/Tests/Server/Utils/NetworkDevice/RulePatternValidator.test.ts +78 -0
- package/Tests/Server/Utils/NetworkSite/NetworkSiteMaintenanceSuppression.test.ts +363 -0
- package/Tests/Server/Utils/OfflineAssetHygiene.test.ts +35 -0
- package/Tests/Server/Utils/OnCallNotificationContext.test.ts +908 -0
- package/Tests/Server/Utils/PrivateNetworkWebhookConfig.test.ts +423 -0
- package/Tests/Server/Utils/ResourceFeed/ResourceFeedUtil.test.ts +191 -0
- package/Tests/Server/Utils/SSRFProtectionPrivateNetwork.test.ts +597 -0
- package/Tests/Server/Utils/SecurityEvent/ConnectorErrorMessage.test.ts +819 -0
- package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +381 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +417 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +819 -0
- package/Tests/Server/Utils/SecurityEvent/SecurityEventAlerting.test.ts +246 -0
- package/Tests/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClient.test.ts +282 -0
- package/Tests/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelEnricher.test.ts +312 -0
- package/Tests/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.test.ts +854 -0
- package/Tests/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.test.ts +437 -0
- package/Tests/Server/Utils/StartServerErrorStatus.test.ts +225 -0
- package/Tests/Server/Utils/StatusPage/MonitorRulePatternValidator.test.ts +62 -0
- package/Tests/Server/Utils/StatusPageSubscriberWebhookPrivateNetwork.test.ts +119 -0
- package/Tests/Server/Utils/Telemetry/SourceMapResolver.test.ts +542 -0
- package/Tests/Server/Utils/TwoFactorBackupCodeNotification.test.ts +272 -0
- package/Tests/Server/Utils/VM/VMRunnerPrivateNetworkWiring.test.ts +111 -0
- package/Tests/Server/Utils/VendorAssets.test.ts +117 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +101 -4
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsInstallStateDiagnostics.test.ts +922 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsRosterDiagnosticMessages.test.ts +642 -0
- package/Tests/Server/Views/OnCallAcknowledgePage.test.ts +430 -0
- package/Tests/Types/API/URLQueryString.test.ts +472 -0
- package/Tests/Types/BaseDatabase/Wildcard.test.ts +163 -0
- package/Tests/Types/BaseDatabase/WildcardPattern.test.ts +149 -0
- package/Tests/Types/Database/DateColumnValue.test.ts +265 -0
- package/Tests/Types/DateToIsoStringOrNull.test.ts +67 -0
- package/Tests/Types/Log/LogQueryToFilter.test.ts +218 -43
- package/Tests/Types/Monitor/KubernetesTemplateGroupByKeys.test.ts +225 -0
- package/Tests/Types/Monitor/TemplateGroupByKeys.test.ts +296 -0
- package/Tests/Types/NetworkAutomation/RuleRunResult.test.ts +102 -0
- package/Tests/Types/NetworkAutomation/RuleRunResultDescribe.test.ts +145 -0
- package/Tests/Types/NetworkSite/SiteHealthRollupPolicy.test.ts +58 -0
- package/Tests/Types/SerializableObjectDictionaryImportCycle.test.ts +15 -0
- package/Tests/Types/Telemetry/TelemetrySearchQuery.test.ts +620 -0
- package/Tests/Types/WhatsApp/WhatsAppTemplates.test.ts +110 -0
- package/Tests/Types/Workspace/NotificationRuleConditionUtil.test.ts +76 -6
- package/Tests/Types/Workspace/NotificationRules/NotificationRuleCondition.test.ts +16 -4
- package/Tests/Types/Workspace/NotificationRules/OnCallDutyPolicyConditions.test.ts +669 -0
- package/Tests/UI/Components/DictionaryFilterOperatorWildcard.test.ts +175 -0
- package/Tests/UI/Components/IconOpticalSize.test.tsx +377 -0
- package/Tests/UI/MicrosoftTeams/MicrosoftTeamsChatsCardInstallGuidance.test.tsx +332 -0
- package/Tests/UI/MicrosoftTeams/MicrosoftTeamsInstallGuidanceContent.test.tsx +643 -0
- package/Tests/Utils/Monitor/InterfaceInventoryUtil.test.ts +824 -0
- package/Tests/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.test.ts +626 -0
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +718 -0
- package/Tests/Utils/NetworkDevice/DeviceHealthStateUtil.test.ts +59 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +287 -2
- package/Tests/Utils/NetworkDiscovery/DiscoveryImportEligibility.test.ts +73 -0
- package/Tests/Utils/NetworkDiscovery/PingMonitorBuilder.test.ts +317 -0
- package/Tests/Utils/NetworkDiscovery/RescanIntervalUtil.test.ts +262 -0
- package/Tests/Utils/NetworkDiscovery/ScanModeUtil.test.ts +474 -0
- package/Tests/Utils/NetworkDiscovery/SnmpScanConfigUtil.test.ts +2442 -0
- package/Tests/Utils/NetworkSite/SiteMaintenanceUtil.test.ts +188 -0
- package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +522 -0
- package/Tests/Utils/NetworkSite/SiteUptimeUtil.test.ts +694 -0
- package/Tests/Utils/SecurityEvent/ThreatIntel/StixPatternParser.test.ts +281 -0
- package/Tests/Utils/Telemetry/CrossSignalScope.test.ts +87 -67
- package/Types/API/URL.ts +45 -10
- package/Types/AnalyticsDatabase/AnalyticsTableName.ts +8 -0
- package/Types/BaseDatabase/NotWildcard.ts +86 -0
- package/Types/BaseDatabase/Wildcard.ts +89 -0
- package/Types/BaseDatabase/WildcardPattern.ts +176 -0
- package/Types/Database/DateColumnValue.ts +184 -0
- package/Types/Database/TableColumn.ts +40 -5
- package/Types/Date.ts +37 -0
- package/Types/Email/EmailTemplateType.ts +1 -0
- package/Types/JSON.ts +8 -0
- package/Types/Log/LogQueryToFilter.ts +167 -129
- package/Types/Monitor/DockerAlertTemplates.ts +43 -12
- package/Types/Monitor/HostAlertTemplates.ts +31 -3
- package/Types/Monitor/KubernetesAlertTemplates.ts +98 -0
- package/Types/Monitor/MonitorStep.ts +49 -0
- package/Types/Monitor/PodmanAlertTemplates.ts +39 -12
- package/Types/Monitor/SnmpMonitor/CdpNeighbor.ts +14 -0
- package/Types/Monitor/SnmpMonitor/LldpNeighbor.ts +11 -0
- package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +11 -4
- package/Types/NetworkAutomation/RuleRunResult.ts +191 -2
- package/Types/NetworkSite/SiteHealthRollupPolicy.ts +96 -0
- package/Types/Permission.ts +411 -0
- package/Types/Probe/ProbeApiIngestResponse.ts +42 -0
- package/Types/SecurityEvent/ThreatIntelConstants.ts +118 -0
- package/Types/SerializableObjectDictionary.ts +8 -0
- package/Types/Telemetry/SourceMap.ts +56 -0
- package/Types/Telemetry/TelemetrySearchQuery.ts +949 -0
- package/Types/Workspace/NotificationRules/NotificationRuleCondition.ts +12 -1
- package/UI/Components/Dictionary/DictionaryFilterOperator.ts +83 -0
- package/UI/Components/Icon/Icon.tsx +28 -1
- package/UI/Components/LogsViewer/components/LogSearchBar.tsx +26 -4
- package/UI/Components/LogsViewer/components/LogSearchHelp.tsx +34 -16
- package/UI/Components/TelemetryViewer/components/TelemetrySearchBar.tsx +15 -2
- package/Utils/Metrics/MetricExplorerUrl.ts +77 -15
- package/Utils/Monitor/InterfaceInventoryUtil.ts +251 -0
- package/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.ts +333 -0
- package/Utils/Monitor/NetworkTopologyUtil.ts +249 -28
- package/Utils/NetworkDevice/DeviceHealthStateUtil.ts +14 -6
- package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +2 -0
- package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +49 -18
- package/Utils/NetworkDiscovery/PingMonitorBuilder.ts +215 -0
- package/Utils/NetworkDiscovery/RescanIntervalUtil.ts +148 -0
- package/Utils/NetworkDiscovery/ScanModeUtil.ts +105 -0
- package/Utils/NetworkDiscovery/SnmpScanConfigUtil.ts +827 -0
- package/Utils/NetworkSite/SiteMaintenanceUtil.ts +110 -0
- package/Utils/NetworkSite/SiteStatusRollupUtil.ts +350 -19
- package/Utils/NetworkSite/SiteUptimeUtil.ts +422 -21
- package/Utils/SecurityEvent/ThreatIntel/StixPatternParser.ts +383 -0
- package/Utils/Telemetry/CrossSignalScope.ts +37 -39
- package/build/dist/Models/AnalyticsModels/Index.js +2 -0
- package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/ThreatIntelIndicator.js +325 -0
- package/build/dist/Models/AnalyticsModels/ThreatIntelIndicator.js.map +1 -0
- package/build/dist/Models/DatabaseModels/AlertSeverity.js +4 -1
- package/build/dist/Models/DatabaseModels/AlertSeverity.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CephClusterFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/CephClusterFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/CloudResourceFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/CloudResourceFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js +11 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DetectionRule.js +9 -3
- package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerHostFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/DockerHostFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DockerSwarmClusterFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/DockerSwarmClusterFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js +9 -3
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js.map +1 -1
- package/build/dist/Models/DatabaseModels/HostFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/HostFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/IncidentSeverity.js +4 -1
- package/build/dist/Models/DatabaseModels/IncidentSeverity.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +22 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesClusterFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/KubernetesClusterFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Monitor.js +81 -0
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +103 -7
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +91 -6
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +276 -31
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSite.js +124 -1
- package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js +1 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/PodmanHostFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/PodmanHostFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ProxmoxClusterFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/ProxmoxClusterFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +66 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/ServiceFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/TelemetrySourceMap.js +496 -0
- package/build/dist/Models/DatabaseModels/TelemetrySourceMap.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js +800 -0
- package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/UserOnCallLog.js +1 -0
- package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserTotpAuth.js +1 -0
- package/build/dist/Models/DatabaseModels/UserTotpAuth.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWebAuthn.js +1 -0
- package/build/dist/Models/DatabaseModels/UserWebAuthn.js.map +1 -1
- package/build/dist/Server/API/AlertAPI.js +18 -1
- package/build/dist/Server/API/AlertAPI.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +8 -1
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/IncidentAPI.js +35 -1
- package/build/dist/Server/API/IncidentAPI.js.map +1 -1
- package/build/dist/Server/API/IncidentEpisodeAPI.js +18 -1
- package/build/dist/Server/API/IncidentEpisodeAPI.js.map +1 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js +30 -2
- package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js +18 -1
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -1
- package/build/dist/Server/API/SlackAPI.js +45 -0
- package/build/dist/Server/API/SlackAPI.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js +100 -35
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/API/UserOnCallLogTimelineAPI.js +64 -59
- package/build/dist/Server/API/UserOnCallLogTimelineAPI.js.map +1 -1
- package/build/dist/Server/API/UserTotpAuthAPI.js +65 -1
- package/build/dist/Server/API/UserTotpAuthAPI.js.map +1 -1
- package/build/dist/Server/API/UserWebAuthnAPI.js +42 -1
- package/build/dist/Server/API/UserWebAuthnAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787923136162-MigrationName.js +26 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787923136162-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789600000000-AddAutoProvisionedNetworkDeviceMonitors.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789600000000-AddAutoProvisionedNetworkDeviceMonitors.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789700000000-AddNetworkScaleIndexes.js +88 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789700000000-AddNetworkScaleIndexes.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789800000000-WidenSecurityEventLastErrorColumns.js +39 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789800000000-WidenSecurityEventLastErrorColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789900000000-AddNetworkSiteRollupPolicyAndMaintenance.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789900000000-AddNetworkSiteRollupPolicyAndMaintenance.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790000000000-AddTelemetrySourceMap.js +32 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790000000000-AddTelemetrySourceMap.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790000000001-AddSnmpConfigsToNetworkDeviceDiscoveryScan.js +61 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790000000001-AddSnmpConfigsToNetworkDeviceDiscoveryScan.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790003445000-AddSnmpEnabledToNetworkDeviceDiscoveryScan.js +23 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790003445000-AddSnmpEnabledToNetworkDeviceDiscoveryScan.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790100000000-AddResourceActivityFeeds.js +179 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790100000000-AddResourceActivityFeeds.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/IdentityRateLimit.js +40 -3
- package/build/dist/Server/Middleware/IdentityRateLimit.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +177 -30
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterFeedService.js +89 -0
- package/build/dist/Server/Services/CephClusterFeedService.js.map +1 -0
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +27 -3
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +21 -0
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterOwnerTeamService.js +120 -0
- package/build/dist/Server/Services/CephClusterOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterOwnerUserService.js +113 -0
- package/build/dist/Server/Services/CephClusterOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterService.js +175 -1
- package/build/dist/Server/Services/CephClusterService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceFeedService.js +89 -0
- package/build/dist/Server/Services/CloudResourceFeedService.js.map +1 -0
- package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js +27 -3
- package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js +28 -3
- package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceOwnerTeamService.js +120 -0
- package/build/dist/Server/Services/CloudResourceOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceOwnerUserService.js +113 -0
- package/build/dist/Server/Services/CloudResourceOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceService.js +177 -1
- package/build/dist/Server/Services/CloudResourceService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +201 -0
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostFeedService.js +89 -0
- package/build/dist/Server/Services/DockerHostFeedService.js.map +1 -0
- package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js +27 -3
- package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js +21 -0
- package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostOwnerTeamService.js +120 -0
- package/build/dist/Server/Services/DockerHostOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostOwnerUserService.js +113 -0
- package/build/dist/Server/Services/DockerHostOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostService.js +177 -1
- package/build/dist/Server/Services/DockerHostService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterFeedService.js +90 -0
- package/build/dist/Server/Services/DockerSwarmClusterFeedService.js.map +1 -0
- package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js +27 -3
- package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js +21 -0
- package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterOwnerTeamService.js +120 -0
- package/build/dist/Server/Services/DockerSwarmClusterOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterOwnerUserService.js +113 -0
- package/build/dist/Server/Services/DockerSwarmClusterOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterService.js +175 -1
- package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
- package/build/dist/Server/Services/EnterpriseLicenseService.js +40 -30
- package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
- package/build/dist/Server/Services/ExceptionAggregationService.js +8 -2
- package/build/dist/Server/Services/ExceptionAggregationService.js.map +1 -1
- package/build/dist/Server/Services/HostFeedService.js +89 -0
- package/build/dist/Server/Services/HostFeedService.js.map +1 -0
- package/build/dist/Server/Services/HostLabelRuleEngineService.js +27 -3
- package/build/dist/Server/Services/HostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/HostOwnerRuleEngineService.js +21 -0
- package/build/dist/Server/Services/HostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/HostOwnerTeamService.js +120 -0
- package/build/dist/Server/Services/HostOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/HostOwnerUserService.js +113 -0
- package/build/dist/Server/Services/HostOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/HostService.js +175 -1
- package/build/dist/Server/Services/HostService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +10 -0
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +24 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterFeedService.js +89 -0
- package/build/dist/Server/Services/KubernetesClusterFeedService.js.map +1 -0
- package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js +27 -3
- package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js +21 -0
- package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterOwnerTeamService.js +120 -0
- package/build/dist/Server/Services/KubernetesClusterOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterOwnerUserService.js +113 -0
- package/build/dist/Server/Services/KubernetesClusterOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterService.js +177 -1
- package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +19 -196
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MetricAggregationService.js +59 -0
- package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +115 -13
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +86 -0
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +561 -67
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +130 -16
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +850 -8
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +594 -5
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkInterfaceService.js +306 -0
- package/build/dist/Server/Services/NetworkInterfaceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteService.js +408 -47
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostFeedService.js +89 -0
- package/build/dist/Server/Services/PodmanHostFeedService.js.map +1 -0
- package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js +27 -3
- package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js +21 -0
- package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostOwnerTeamService.js +120 -0
- package/build/dist/Server/Services/PodmanHostOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostOwnerUserService.js +113 -0
- package/build/dist/Server/Services/PodmanHostOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostService.js +177 -1
- package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +40 -30
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterFeedService.js +89 -0
- package/build/dist/Server/Services/ProxmoxClusterFeedService.js.map +1 -0
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +27 -3
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +21 -0
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterOwnerTeamService.js +120 -0
- package/build/dist/Server/Services/ProxmoxClusterOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterOwnerUserService.js +113 -0
- package/build/dist/Server/Services/ProxmoxClusterOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterService.js +175 -1
- package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +56 -0
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceFeedService.js +89 -0
- package/build/dist/Server/Services/ServiceFeedService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLabelRuleEngineService.js +27 -3
- package/build/dist/Server/Services/ServiceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js +24 -0
- package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceOwnerTeamService.js +120 -0
- package/build/dist/Server/Services/ServiceOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/ServiceOwnerUserService.js +113 -0
- package/build/dist/Server/Services/ServiceOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/ServiceService.js +173 -2
- package/build/dist/Server/Services/ServiceService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberService.js +7 -0
- package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryAttributeService.js +9 -3
- package/build/dist/Server/Services/TelemetryAttributeService.js.map +1 -1
- package/build/dist/Server/Services/TelemetrySourceMapService.js +265 -0
- package/build/dist/Server/Services/TelemetrySourceMapService.js.map +1 -0
- package/build/dist/Server/Services/ThreatIntelFeedService.js +157 -0
- package/build/dist/Server/Services/ThreatIntelFeedService.js.map +1 -0
- package/build/dist/Server/Services/ThreatIntelIndicatorService.js +276 -0
- package/build/dist/Server/Services/ThreatIntelIndicatorService.js.map +1 -0
- package/build/dist/Server/Services/TraceAggregationService.js +62 -6
- package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +22 -13
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Services/UserTwoFactorBackupCodeService.js +120 -0
- package/build/dist/Server/Services/UserTwoFactorBackupCodeService.js.map +1 -1
- package/build/dist/Server/Services/UserWebhookService.js +11 -2
- package/build/dist/Server/Services/UserWebhookService.js.map +1 -1
- package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js +12 -1
- package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/AggregateBy.js +2 -0
- package/build/dist/Server/Types/Database/AggregateBy.js.map +1 -0
- package/build/dist/Server/Types/Database/AggregateResultUtil.js +90 -0
- package/build/dist/Server/Types/Database/AggregateResultUtil.js.map +1 -0
- package/build/dist/Server/Types/Database/JSONColumnQuery.js +14 -0
- package/build/dist/Server/Types/Database/JSONColumnQuery.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +42 -0
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryUtil.js +18 -0
- package/build/dist/Server/Types/Database/QueryUtil.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Utils.js +10 -1
- package/build/dist/Server/Types/Workflow/Components/API/Utils.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/JavaScript.js +8 -0
- package/build/dist/Server/Types/Workflow/Components/JavaScript.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js +8 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +15 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/AttributeFilterStatement.js +266 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/AttributeFilterStatement.js.map +1 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +134 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/DataSource/HttpFetch.js +8 -0
- package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
- package/build/dist/Server/Utils/Database/RelationIdUtil.js +31 -0
- package/build/dist/Server/Utils/Database/RelationIdUtil.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js +26 -8
- package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js +42 -17
- package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +9 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SyntheticMonitor.js +15 -2
- package/build/dist/Server/Utils/Monitor/Criteria/SyntheticMonitor.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +386 -271
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +278 -64
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +469 -350
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +183 -44
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +46 -3
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +18 -91
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/PerEntityCriteriaFanOut.js +194 -0
- package/build/dist/Server/Utils/Monitor/PerEntityCriteriaFanOut.js.map +1 -0
- package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js +332 -0
- package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js.map +1 -0
- package/build/dist/Server/Utils/NetworkSite/NetworkSiteMaintenanceSuppression.js +279 -0
- package/build/dist/Server/Utils/NetworkSite/NetworkSiteMaintenanceSuppression.js.map +1 -0
- package/build/dist/Server/Utils/OnCallNotificationContext.js +415 -0
- package/build/dist/Server/Utils/OnCallNotificationContext.js.map +1 -0
- package/build/dist/Server/Utils/PrivateNetworkWebhookConfig.js +424 -0
- package/build/dist/Server/Utils/PrivateNetworkWebhookConfig.js.map +1 -0
- package/build/dist/Server/Utils/ResourceFeed/ResourceFeedUtil.js +108 -0
- package/build/dist/Server/Utils/ResourceFeed/ResourceFeedUtil.js.map +1 -0
- package/build/dist/Server/Utils/Response.js +12 -1
- package/build/dist/Server/Utils/Response.js.map +1 -1
- package/build/dist/Server/Utils/SSRFProtection.js +160 -58
- package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js +89 -0
- package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +75 -234
- package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +41 -16
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/SecurityEventAlerting.js +217 -0
- package/build/dist/Server/Utils/SecurityEvent/SecurityEventAlerting.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClient.js +103 -0
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelEnricher.js +168 -0
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelEnricher.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js +527 -0
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js +376 -0
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js.map +1 -0
- package/build/dist/Server/Utils/StartServer.js +70 -44
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/StatusPageSubscriberWebhook.js +3 -0
- package/build/dist/Server/Utils/StatusPageSubscriberWebhook.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/SourceMapResolver.js +327 -0
- package/build/dist/Server/Utils/Telemetry/SourceMapResolver.js.map +1 -0
- package/build/dist/Server/Utils/TwoFactorBackupCodeNotification.js +84 -0
- package/build/dist/Server/Utils/TwoFactorBackupCodeNotification.js.map +1 -0
- package/build/dist/Server/Utils/VM/VMAPI.js.map +1 -1
- package/build/dist/Server/Utils/VM/VMRunner.js +10 -1
- package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
- package/build/dist/Server/Utils/VendorAssets.js +29 -0
- package/build/dist/Server/Utils/VendorAssets.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +121 -6
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/API/URL.js +40 -10
- package/build/dist/Types/API/URL.js.map +1 -1
- package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js +8 -0
- package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js.map +1 -1
- package/build/dist/Types/BaseDatabase/NotWildcard.js +72 -0
- package/build/dist/Types/BaseDatabase/NotWildcard.js.map +1 -0
- package/build/dist/Types/BaseDatabase/Wildcard.js +75 -0
- package/build/dist/Types/BaseDatabase/Wildcard.js.map +1 -0
- package/build/dist/Types/BaseDatabase/WildcardPattern.js +137 -0
- package/build/dist/Types/BaseDatabase/WildcardPattern.js.map +1 -0
- package/build/dist/Types/Database/DateColumnValue.js +125 -0
- package/build/dist/Types/Database/DateColumnValue.js.map +1 -0
- package/build/dist/Types/Database/TableColumn.js +18 -2
- package/build/dist/Types/Database/TableColumn.js.map +1 -1
- package/build/dist/Types/Date.js +31 -0
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/JSON.js +2 -0
- package/build/dist/Types/JSON.js.map +1 -1
- package/build/dist/Types/Log/LogQueryToFilter.js +111 -108
- package/build/dist/Types/Log/LogQueryToFilter.js.map +1 -1
- package/build/dist/Types/Monitor/DockerAlertTemplates.js +40 -16
- package/build/dist/Types/Monitor/DockerAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/HostAlertTemplates.js +29 -7
- package/build/dist/Types/Monitor/HostAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +98 -4
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +40 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/PodmanAlertTemplates.js +36 -16
- package/build/dist/Types/Monitor/PodmanAlertTemplates.js.map +1 -1
- package/build/dist/Types/NetworkAutomation/RuleRunResult.js +90 -0
- package/build/dist/Types/NetworkAutomation/RuleRunResult.js.map +1 -1
- package/build/dist/Types/NetworkSite/SiteHealthRollupPolicy.js +84 -0
- package/build/dist/Types/NetworkSite/SiteHealthRollupPolicy.js.map +1 -0
- package/build/dist/Types/Permission.js +354 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js +100 -0
- package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js.map +1 -0
- package/build/dist/Types/SerializableObjectDictionary.js +8 -0
- package/build/dist/Types/SerializableObjectDictionary.js.map +1 -1
- package/build/dist/Types/Telemetry/SourceMap.js +9 -0
- package/build/dist/Types/Telemetry/SourceMap.js.map +1 -0
- package/build/dist/Types/Telemetry/TelemetrySearchQuery.js +661 -0
- package/build/dist/Types/Telemetry/TelemetrySearchQuery.js.map +1 -0
- package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js +12 -1
- package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js.map +1 -1
- package/build/dist/UI/Components/Dictionary/DictionaryFilterOperator.js +67 -0
- package/build/dist/UI/Components/Dictionary/DictionaryFilterOperator.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +28 -1
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogSearchBar.js +25 -4
- package/build/dist/UI/Components/LogsViewer/components/LogSearchBar.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogSearchHelp.js +36 -16
- package/build/dist/UI/Components/LogsViewer/components/LogSearchHelp.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js +14 -2
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js.map +1 -1
- package/build/dist/Utils/Metrics/MetricExplorerUrl.js +54 -9
- package/build/dist/Utils/Metrics/MetricExplorerUrl.js.map +1 -1
- package/build/dist/Utils/Monitor/InterfaceInventoryUtil.js +128 -0
- package/build/dist/Utils/Monitor/InterfaceInventoryUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js +190 -0
- package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +206 -28
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js +14 -7
- package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +34 -18
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js +163 -0
- package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/RescanIntervalUtil.js +99 -0
- package/build/dist/Utils/NetworkDiscovery/RescanIntervalUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/ScanModeUtil.js +85 -0
- package/build/dist/Utils/NetworkDiscovery/ScanModeUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/SnmpScanConfigUtil.js +560 -0
- package/build/dist/Utils/NetworkDiscovery/SnmpScanConfigUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/SiteMaintenanceUtil.js +56 -0
- package/build/dist/Utils/NetworkSite/SiteMaintenanceUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +185 -10
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -1
- package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js +248 -21
- package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js.map +1 -1
- package/build/dist/Utils/SecurityEvent/ThreatIntel/StixPatternParser.js +255 -0
- package/build/dist/Utils/SecurityEvent/ThreatIntel/StixPatternParser.js.map +1 -0
- package/build/dist/Utils/Telemetry/CrossSignalScope.js +27 -30
- package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -1
- package/package.json +2 -1
- package/Tests/Types/Log/LogQueryParser.test.ts +0 -186
- package/Types/Log/LogQueryParser.ts +0 -252
- package/build/dist/Types/Log/LogQueryParser.js +0 -200
- package/build/dist/Types/Log/LogQueryParser.js.map +0 -1
|
@@ -5,8 +5,170 @@ import CreateBy from "../Types/Database/CreateBy";
|
|
|
5
5
|
import UpdateBy from "../Types/Database/UpdateBy";
|
|
6
6
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
7
7
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
8
|
+
import ObjectID from "../../Types/ObjectID";
|
|
9
|
+
import OneUptimeDate from "../../Types/Date";
|
|
10
|
+
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
11
|
+
import QueryDeepPartialEntity from "../../Types/Database/PartialEntity";
|
|
12
|
+
import ProbeService from "./ProbeService";
|
|
13
|
+
import Probe from "../../Models/DatabaseModels/Probe";
|
|
14
|
+
import RelationIdUtil from "../Utils/Database/RelationIdUtil";
|
|
8
15
|
import ScanTargetUtil from "../../Utils/NetworkDiscovery/ScanTargetUtil";
|
|
9
16
|
import ScanNameUtil from "../../Utils/NetworkDiscovery/ScanNameUtil";
|
|
17
|
+
import SnmpScanConfigUtil, {
|
|
18
|
+
DiscoveryScanSnmpConfig,
|
|
19
|
+
SnmpScanConfigSource,
|
|
20
|
+
} from "../../Utils/NetworkDiscovery/SnmpScanConfigUtil";
|
|
21
|
+
import { getNextScanAt } from "../../Utils/NetworkDiscovery/RescanIntervalUtil";
|
|
22
|
+
import ScanModeUtil from "../../Utils/NetworkDiscovery/ScanModeUtil";
|
|
23
|
+
|
|
24
|
+
/*
|
|
25
|
+
* The two spellings a many-to-one reference reaches a hook under: the
|
|
26
|
+
* dashboard posts the relation object, server callers write the FK column.
|
|
27
|
+
* See RelationIdUtil.
|
|
28
|
+
*/
|
|
29
|
+
const PROBE_RELATION_KEYS: Array<string> = ["probeId", "probe"];
|
|
30
|
+
|
|
31
|
+
/*
|
|
32
|
+
* The columns that decide what the probe sweeps, and what it sweeps with.
|
|
33
|
+
* Changing any of them means the results already on the row describe a sweep
|
|
34
|
+
* that no longer exists — which is what onUpdateSuccess below acts on.
|
|
35
|
+
*
|
|
36
|
+
* `probe` is folded into `probeId` by RelationIdUtil rather than listed here,
|
|
37
|
+
* because the same reference arrives under either name.
|
|
38
|
+
*/
|
|
39
|
+
const SWEEP_COLUMNS: Array<string> = [
|
|
40
|
+
"cidr",
|
|
41
|
+
"probeId",
|
|
42
|
+
/*
|
|
43
|
+
* The method as well as the credentials: turning SNMP off (or back on)
|
|
44
|
+
* changes what the sweep asks of every address, so the hosts already on the
|
|
45
|
+
* row answered a different question (issue #3445).
|
|
46
|
+
*/
|
|
47
|
+
"isSnmpEnabled",
|
|
48
|
+
/*
|
|
49
|
+
* The ordered credential list. Listed FIRST among the credential columns
|
|
50
|
+
* because it is the one the form actually posts now; the flattened columns
|
|
51
|
+
* below it are mirrored from its first entry (see applySnmpConfigs) and
|
|
52
|
+
* remain here so a scan edited through the API with only those fields still
|
|
53
|
+
* retires its run (issue #3458).
|
|
54
|
+
*/
|
|
55
|
+
"snmpConfigs",
|
|
56
|
+
"snmpVersion",
|
|
57
|
+
"snmpCommunityString",
|
|
58
|
+
"snmpPort",
|
|
59
|
+
"snmpV3SecurityLevel",
|
|
60
|
+
"snmpV3Username",
|
|
61
|
+
"snmpV3AuthProtocol",
|
|
62
|
+
"snmpV3AuthKey",
|
|
63
|
+
"snmpV3PrivProtocol",
|
|
64
|
+
"snmpV3PrivKey",
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
/*
|
|
68
|
+
* The numeric columns a form can hand back as an empty string.
|
|
69
|
+
*
|
|
70
|
+
* A Number field posts its value as text (Common/UI/Components/Forms/Fields/
|
|
71
|
+
* FormField.tsx sets it straight from the input), so an operator who clears
|
|
72
|
+
* the box sends "" — and "" into an integer column is a Postgres error, i.e. a
|
|
73
|
+
* 500 where the operator simply meant "leave this unset". Clearing a box was
|
|
74
|
+
* hard to do before these fields were editable, because a create form starts
|
|
75
|
+
* them empty; an edit form starts them filled.
|
|
76
|
+
*/
|
|
77
|
+
const NULLABLE_NUMBER_COLUMNS: Array<string> = [
|
|
78
|
+
"snmpPort",
|
|
79
|
+
"rescanIntervalInMinutes",
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
/*
|
|
83
|
+
* The columns that decide WHEN the scan runs again, and nothing else. They
|
|
84
|
+
* never retire a result — they only re-derive nextScanAt.
|
|
85
|
+
*/
|
|
86
|
+
/*
|
|
87
|
+
* The single credential set a scan carried before `snmpConfigs` existed. Still
|
|
88
|
+
* written — mirrored from the list's first entry — so a probe that predates
|
|
89
|
+
* the list keeps sweeping with real credentials; see applySnmpConfigs.
|
|
90
|
+
*/
|
|
91
|
+
const LEGACY_SNMP_COLUMNS: Array<string> = [
|
|
92
|
+
"snmpVersion",
|
|
93
|
+
"snmpCommunityString",
|
|
94
|
+
"snmpPort",
|
|
95
|
+
"snmpV3SecurityLevel",
|
|
96
|
+
"snmpV3Username",
|
|
97
|
+
"snmpV3AuthProtocol",
|
|
98
|
+
"snmpV3AuthKey",
|
|
99
|
+
"snmpV3PrivProtocol",
|
|
100
|
+
"snmpV3PrivKey",
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
const SCHEDULE_COLUMNS: Array<string> = [
|
|
104
|
+
"isRecurring",
|
|
105
|
+
"rescanIntervalInMinutes",
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
/*
|
|
109
|
+
* Everything a finished run left on the row. Written together, as one
|
|
110
|
+
* statement, to put the scan back in the state a brand-new one is created in:
|
|
111
|
+
* queued, with nothing to show yet.
|
|
112
|
+
*
|
|
113
|
+
* This is the same reset the requeue worker performs on a recurring scan that
|
|
114
|
+
* is due (Workers/Jobs/NetworkDeviceDiscovery/RequeueRecurringScans.ts) with
|
|
115
|
+
* one deliberate difference: the results ARE cleared here. The worker keeps
|
|
116
|
+
* them because a recurring scan re-runs the SAME sweep, so last run's
|
|
117
|
+
* inventory is still the best answer available until the next one lands. A
|
|
118
|
+
* scan whose target or credentials just changed has no such excuse — its
|
|
119
|
+
* hosts came from somewhere the scan no longer points at.
|
|
120
|
+
*/
|
|
121
|
+
const RETIRE_RUN_PAYLOAD: Record<string, unknown> = {
|
|
122
|
+
status: "Pending",
|
|
123
|
+
/*
|
|
124
|
+
* Not cleared but replaced, because the row has some explaining to do: the
|
|
125
|
+
* operator saved a settings change and the scan's results vanished. The
|
|
126
|
+
* scans list renders this sentence in the results cell of a scan that has
|
|
127
|
+
* not reported (Dashboard Components/NetworkDevice/DiscoveryScanOutcome),
|
|
128
|
+
* which is exactly where the missing results used to be. The claim endpoint
|
|
129
|
+
* clears it the moment a probe picks the scan up.
|
|
130
|
+
*/
|
|
131
|
+
statusMessage:
|
|
132
|
+
"Settings changed, so this scan is queued to run again. The hosts the previous run found have been cleared - they described settings this scan no longer has.",
|
|
133
|
+
startedAt: null,
|
|
134
|
+
completedAt: null,
|
|
135
|
+
nextScanAt: null,
|
|
136
|
+
discoveredDevices: null,
|
|
137
|
+
scannedHostCount: null,
|
|
138
|
+
respondedHostCount: null,
|
|
139
|
+
autoImportProcessedAt: null,
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
/*
|
|
143
|
+
* The one thing onUpdateSuccess cannot work out for itself, because answering
|
|
144
|
+
* it needs the values the update has already overwritten: did this save
|
|
145
|
+
* actually change what the probe sweeps?
|
|
146
|
+
*
|
|
147
|
+
* Everything else it needs — the schedule, the run state — it re-reads from
|
|
148
|
+
* the row afterwards rather than predicting from the payload. Predicting would
|
|
149
|
+
* mean trusting the request's types (a number field posted as "60", a toggle
|
|
150
|
+
* posted as "false"), and a schedule mis-read as "no cadence" silently
|
|
151
|
+
* unschedules a recurring scan.
|
|
152
|
+
*/
|
|
153
|
+
interface ScanUpdatePlan {
|
|
154
|
+
isSweepChanged: boolean;
|
|
155
|
+
/*
|
|
156
|
+
* Whether this row's credential LIST has to be rebuilt from its flattened
|
|
157
|
+
* columns once the update has landed — the answer to a save written through
|
|
158
|
+
* the old single-credential API (see reconcileLegacySnmpUpdate).
|
|
159
|
+
*
|
|
160
|
+
* Deferred to onUpdateSuccess rather than done in the payload because the
|
|
161
|
+
* rebuilt list is a function of the ROW, and one update payload is shared by
|
|
162
|
+
* every row the query matches. onUpdateSuccess already writes per row, by id.
|
|
163
|
+
*/
|
|
164
|
+
isLegacySnmpWritten: boolean;
|
|
165
|
+
/*
|
|
166
|
+
* Whether the save asked about the schedule at all. Only a save that did
|
|
167
|
+
* gets its next run re-derived — so an edit that leaves the recurrence boxes
|
|
168
|
+
* alone cannot move a scan the stale-scan reaper had made due immediately.
|
|
169
|
+
*/
|
|
170
|
+
isScheduleWritten: boolean;
|
|
171
|
+
}
|
|
10
172
|
|
|
11
173
|
export class Service extends DatabaseService<Model> {
|
|
12
174
|
public constructor() {
|
|
@@ -53,25 +215,128 @@ export class Service extends DatabaseService<Model> {
|
|
|
53
215
|
(createBy.data as unknown as Record<string, unknown>)["name"] =
|
|
54
216
|
ScanNameUtil.normalize(createBy.data.name) ?? undefined;
|
|
55
217
|
|
|
218
|
+
this.nullEmptyNumbers(
|
|
219
|
+
createBy.data as unknown as Record<string, unknown>,
|
|
220
|
+
Object.keys(createBy.data || {}),
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
const createData: Record<string, unknown> =
|
|
224
|
+
createBy.data as unknown as Record<string, unknown>;
|
|
225
|
+
|
|
226
|
+
/*
|
|
227
|
+
* The keys the CLIENT actually supplied, not the keys the object has.
|
|
228
|
+
*
|
|
229
|
+
* `createBy.data` is a model INSTANCE, and every column on it is declared
|
|
230
|
+
* as a class field with `= undefined` — so `Object.keys()` returns all 37
|
|
231
|
+
* column names on a brand-new scan no matter what was posted. Handing that
|
|
232
|
+
* to applySnmpConfigs made its "the payload wins where it speaks for
|
|
233
|
+
* itself" guard fire for all nine flattened columns, every time, and the
|
|
234
|
+
* mirror it protects became a permanent no-op on this path: a scan created
|
|
235
|
+
* through the wizard (which posts `snmpConfigs` and nothing else) stored
|
|
236
|
+
* its credentials in the list while its flattened columns kept the bare
|
|
237
|
+
* Postgres defaults, and every probe a version behind swept it with
|
|
238
|
+
* v2c/"public"/161 and reported the confident zero the mirror exists to
|
|
239
|
+
* prevent.
|
|
240
|
+
*
|
|
241
|
+
* A column the client really did send carries a DEFINED value — including
|
|
242
|
+
* an explicit null, which is a caller clearing it — so testing for
|
|
243
|
+
* definedness is exactly the distinction the guard wanted in the first
|
|
244
|
+
* place. The update path never had this problem: BaseAPI builds a plain
|
|
245
|
+
* partial there, holding only the posted keys.
|
|
246
|
+
*/
|
|
247
|
+
const suppliedCreateKeys: Array<string> = Object.keys(
|
|
248
|
+
createData || {},
|
|
249
|
+
).filter((key: string): boolean => {
|
|
250
|
+
return createData[key] !== undefined;
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
/*
|
|
254
|
+
* Only for a scan that will actually send SNMP. An ICMP-only scan has its
|
|
255
|
+
* whole SNMP set nulled at the end of this hook, so validating a credential
|
|
256
|
+
* list it is about to discard would refuse the create over a value nothing
|
|
257
|
+
* will ever read — and the wizard posts the field whether or not the step
|
|
258
|
+
* was visible.
|
|
259
|
+
*/
|
|
260
|
+
const isSnmpEnabledOnCreate: boolean = ScanModeUtil.isSnmpEnabled(
|
|
261
|
+
createBy.data,
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
if (isSnmpEnabledOnCreate) {
|
|
265
|
+
this.applySnmpConfigs(createData, suppliedCreateKeys);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/*
|
|
269
|
+
* Every scan leaves this hook WITH a credential list, even one created
|
|
270
|
+
* through the flattened columns alone (an API caller, an integration
|
|
271
|
+
* written before this column existed).
|
|
272
|
+
*
|
|
273
|
+
* The invariant is what the Edit dialog depends on. That form's only SNMP
|
|
274
|
+
* control is the list editor, so it selects `snmpConfigs` and nothing else
|
|
275
|
+
* — a scan whose list were NULL would open with an empty card, and saving
|
|
276
|
+
* it would replace the credentials the operator could not see. The reader
|
|
277
|
+
* (SnmpScanConfigUtil.resolve) still falls back to the flattened columns,
|
|
278
|
+
* because rows written out of band exist; this just means the product
|
|
279
|
+
* never creates one.
|
|
280
|
+
*/
|
|
281
|
+
if (
|
|
282
|
+
isSnmpEnabledOnCreate &&
|
|
283
|
+
!SnmpScanConfigUtil.readStoredList(createData["snmpConfigs"])
|
|
284
|
+
) {
|
|
285
|
+
createData["snmpConfigs"] = SnmpScanConfigUtil.normalizeForStorage(
|
|
286
|
+
SnmpScanConfigUtil.resolve(
|
|
287
|
+
createData as unknown as SnmpScanConfigSource,
|
|
288
|
+
),
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
await this.validateProbeIsUsable({
|
|
293
|
+
data: createBy.data as unknown as Record<string, unknown>,
|
|
294
|
+
dataKeys: Object.keys(createBy.data || {}),
|
|
295
|
+
projectId: createBy.data.projectId || createBy.props.tenantId,
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
/*
|
|
299
|
+
* A scan that will not send SNMP stores no SNMP settings. Enforced here
|
|
300
|
+
* rather than in the form alone, so it holds for a direct API call too —
|
|
301
|
+
* the same reason the scan target is validated on this hook rather than
|
|
302
|
+
* only in the wizard.
|
|
303
|
+
*
|
|
304
|
+
* Read through ScanModeUtil so an ABSENT flag reads as an SNMP scan, which
|
|
305
|
+
* is what every scan created before this column existed was, and what
|
|
306
|
+
* every API client that has never heard of the column means.
|
|
307
|
+
*
|
|
308
|
+
* LAST, after nullEmptyNumbers: that pass turns an empty snmpPort box into
|
|
309
|
+
* null, and this one nulls the whole SNMP set anyway, so running it after
|
|
310
|
+
* means there is exactly one answer for what an ICMP-only row holds.
|
|
311
|
+
*/
|
|
312
|
+
if (ScanModeUtil.isIcmpOnly(createBy.data)) {
|
|
313
|
+
this.clearSnmpConfig(createBy.data);
|
|
314
|
+
}
|
|
315
|
+
|
|
56
316
|
return { createBy, carryForward: null };
|
|
57
317
|
}
|
|
58
318
|
|
|
59
319
|
/*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
320
|
+
* Everything that has to be true of an update before it is allowed to land,
|
|
321
|
+
* plus the reading of the row that onUpdateSuccess needs and can no longer
|
|
322
|
+
* take once the write has happened.
|
|
323
|
+
*
|
|
324
|
+
* Two classes of writer arrive here. The form, editing a scan's settings —
|
|
325
|
+
* which is what this hook mostly exists for now (OneUptime issue #3444) —
|
|
326
|
+
* and the server's own root writers: the probe-ingest endpoints, the
|
|
327
|
+
* recurring-scan worker, migrations. The root writers carry only run-state
|
|
328
|
+
* columns and take the cheap exit below without paying for a read.
|
|
64
329
|
*/
|
|
65
330
|
@CaptureSpan()
|
|
66
331
|
protected override async onBeforeUpdate(
|
|
67
332
|
updateBy: UpdateBy<Model>,
|
|
68
333
|
): Promise<OnUpdate<Model>> {
|
|
69
|
-
const
|
|
334
|
+
const data: Record<string, unknown> = (updateBy.data ||
|
|
335
|
+
{}) as unknown as Record<string, unknown>;
|
|
336
|
+
const dataKeys: Array<string> = Object.keys(data);
|
|
70
337
|
|
|
71
338
|
if (dataKeys.includes("cidr")) {
|
|
72
|
-
this.validateScanTarget(
|
|
73
|
-
(updateBy.data as Record<string, unknown>)["cidr"],
|
|
74
|
-
);
|
|
339
|
+
this.validateScanTarget(data["cidr"]);
|
|
75
340
|
}
|
|
76
341
|
|
|
77
342
|
/*
|
|
@@ -86,16 +351,792 @@ export class Service extends DatabaseService<Model> {
|
|
|
86
351
|
* would try to write.
|
|
87
352
|
*/
|
|
88
353
|
if (dataKeys.includes("name")) {
|
|
89
|
-
const data: Record<string, unknown> = updateBy.data as Record<
|
|
90
|
-
string,
|
|
91
|
-
unknown
|
|
92
|
-
>;
|
|
93
|
-
|
|
94
354
|
this.validateScanName(data["name"]);
|
|
95
355
|
data["name"] = ScanNameUtil.normalize(data["name"]);
|
|
96
356
|
}
|
|
97
357
|
|
|
98
|
-
|
|
358
|
+
this.nullEmptyNumbers(data, dataKeys);
|
|
359
|
+
|
|
360
|
+
/*
|
|
361
|
+
* Turning the method off clears the credentials in the same statement, so
|
|
362
|
+
* the row can never say "sends no SNMP" while carrying a community string
|
|
363
|
+
* or a v3 passphrase (issue #3445). The edit form posts every declared
|
|
364
|
+
* field regardless of visibility, so the SNMP boxes the operator just hid
|
|
365
|
+
* are still in this payload.
|
|
366
|
+
*
|
|
367
|
+
* Gated on the key being WRITTEN, not merely on the stored value being
|
|
368
|
+
* false: a rename, or the probe-ingest endpoints writing run state, must
|
|
369
|
+
* not reach in and null a column they never mentioned. `data` is mutated
|
|
370
|
+
* in place because onUpdateSuccess is handed back the same updateBy object.
|
|
371
|
+
*/
|
|
372
|
+
const isTurningSnmpOff: boolean =
|
|
373
|
+
dataKeys.includes("isSnmpEnabled") && ScanModeUtil.isIcmpOnly(data);
|
|
374
|
+
|
|
375
|
+
if (isTurningSnmpOff) {
|
|
376
|
+
this.clearSnmpConfig(data);
|
|
377
|
+
} else {
|
|
378
|
+
/*
|
|
379
|
+
* Runs BEFORE isSweepWritten is computed, because it can ADD the
|
|
380
|
+
* flattened SNMP columns to the payload — and those are sweep columns. A
|
|
381
|
+
* mirror written after that flag was read would be invisible to the
|
|
382
|
+
* reconciliation and could hand the probe one credential while the row
|
|
383
|
+
* advertised another.
|
|
384
|
+
*
|
|
385
|
+
* Skipped entirely when the save is turning SNMP OFF, and that is not
|
|
386
|
+
* merely an optimisation: this pass VALIDATES the credential list, and
|
|
387
|
+
* the form posts every declared field whether or not it was visible. An
|
|
388
|
+
* operator who unticked Check SNMP would otherwise be refused their save
|
|
389
|
+
* over a half-finished credential set they had just told the product to
|
|
390
|
+
* stop using. clearSnmpConfig nulls the list along with the flattened
|
|
391
|
+
* columns, so there is nothing left to validate.
|
|
392
|
+
*/
|
|
393
|
+
this.applySnmpConfigs(data, dataKeys);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const dataKeysAfterMirror: Array<string> = Object.keys(data);
|
|
397
|
+
|
|
398
|
+
const isSweepWritten: boolean =
|
|
399
|
+
RelationIdUtil.isWritten(dataKeysAfterMirror, PROBE_RELATION_KEYS) ||
|
|
400
|
+
SWEEP_COLUMNS.some((column: string) => {
|
|
401
|
+
return dataKeysAfterMirror.includes(column);
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
const isScheduleWritten: boolean = SCHEDULE_COLUMNS.some(
|
|
405
|
+
(column: string) => {
|
|
406
|
+
return dataKeysAfterMirror.includes(column);
|
|
407
|
+
},
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
/*
|
|
411
|
+
* THE CHEAP EXIT, and it is load-bearing rather than an optimisation.
|
|
412
|
+
*
|
|
413
|
+
* Every server-side writer of this model touches run state only — the
|
|
414
|
+
* claim writes status/startedAt/statusMessage, the result ingest writes
|
|
415
|
+
* the results, the requeue worker and the stale-scan reaper write status
|
|
416
|
+
* and timestamps, the unclaimed-diagnosis pass writes statusMessage. None
|
|
417
|
+
* of them carries a sweep or schedule column, so none of them reads a row
|
|
418
|
+
* here, and none can trip the reconciliation below into retiring the very
|
|
419
|
+
* result it is in the middle of storing.
|
|
420
|
+
*
|
|
421
|
+
* `updateBy` is also handed back as the SAME object, which is what
|
|
422
|
+
* Common/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts
|
|
423
|
+
* pins: the claim's hook-free write is only safe while this hook is a
|
|
424
|
+
* pass-through for the claim's payload.
|
|
425
|
+
*/
|
|
426
|
+
if (!isSweepWritten && !isScheduleWritten) {
|
|
427
|
+
return { updateBy, carryForward: null };
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/*
|
|
431
|
+
* Scoped by hand, because this hook runs BEFORE
|
|
432
|
+
* ModelPermission.checkUpdateQueryPermissions and BaseAPI hands the
|
|
433
|
+
* service a bare `{_id}` query — so reading with the caller's own query as
|
|
434
|
+
* root, unscoped, would answer "does this id exist, and what are its
|
|
435
|
+
* credentials" for every project on the instance. Same shape as
|
|
436
|
+
* MonitorService.onBeforeUpdate.
|
|
437
|
+
*/
|
|
438
|
+
const scans: Array<Model> = await this.findBy({
|
|
439
|
+
query:
|
|
440
|
+
!updateBy.props.isRoot && updateBy.props.tenantId
|
|
441
|
+
? { ...updateBy.query, projectId: updateBy.props.tenantId }
|
|
442
|
+
: updateBy.query,
|
|
443
|
+
select: {
|
|
444
|
+
_id: true,
|
|
445
|
+
projectId: true,
|
|
446
|
+
cidr: true,
|
|
447
|
+
probeId: true,
|
|
448
|
+
snmpConfigs: true,
|
|
449
|
+
snmpVersion: true,
|
|
450
|
+
snmpCommunityString: true,
|
|
451
|
+
snmpPort: true,
|
|
452
|
+
snmpV3SecurityLevel: true,
|
|
453
|
+
snmpV3Username: true,
|
|
454
|
+
snmpV3AuthProtocol: true,
|
|
455
|
+
snmpV3AuthKey: true,
|
|
456
|
+
snmpV3PrivProtocol: true,
|
|
457
|
+
snmpV3PrivKey: true,
|
|
458
|
+
},
|
|
459
|
+
limit: LIMIT_MAX,
|
|
460
|
+
skip: 0,
|
|
461
|
+
props: {
|
|
462
|
+
isRoot: true,
|
|
463
|
+
ignoreHooks: true,
|
|
464
|
+
},
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
const plans: Record<string, ScanUpdatePlan> = {};
|
|
468
|
+
|
|
469
|
+
for (const scan of scans) {
|
|
470
|
+
const scanId: string | undefined = scan._id?.toString();
|
|
471
|
+
|
|
472
|
+
if (!scanId) {
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/*
|
|
477
|
+
* Checked per matched scan, because the answer depends on which project
|
|
478
|
+
* the scan belongs to — and read from the row rather than from the
|
|
479
|
+
* caller's tenant, so a root writer is held to the same rule.
|
|
480
|
+
*/
|
|
481
|
+
await this.validateProbeIsUsable({
|
|
482
|
+
data: data,
|
|
483
|
+
dataKeys: dataKeysAfterMirror,
|
|
484
|
+
projectId: scan.projectId,
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
const isLegacySnmpWritten: boolean = this.reconcileLegacySnmpUpdate({
|
|
488
|
+
data: data,
|
|
489
|
+
dataKeys: dataKeysAfterMirror,
|
|
490
|
+
scan: scan,
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
plans[scanId] = {
|
|
494
|
+
isSweepChanged: isSweepWritten
|
|
495
|
+
? this.hasSweepChanged(scan, data, dataKeysAfterMirror)
|
|
496
|
+
: false,
|
|
497
|
+
isScheduleWritten: isScheduleWritten,
|
|
498
|
+
isLegacySnmpWritten: isLegacySnmpWritten,
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
return { updateBy, carryForward: plans };
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/*
|
|
506
|
+
* Put the row back into a state that describes itself honestly.
|
|
507
|
+
*
|
|
508
|
+
* Two things can be wrong the moment a settings edit lands, and neither can
|
|
509
|
+
* be fixed in the update itself: the columns that would fix them
|
|
510
|
+
* (status, nextScanAt, the result columns) grant no update permission to
|
|
511
|
+
* anybody, and ModelPermission checks the payload AFTER onBeforeUpdate has
|
|
512
|
+
* run — so a payload carrying them would be refused for the very user doing
|
|
513
|
+
* the editing. They are written here instead, as root, through the same
|
|
514
|
+
* hook-free single-statement path the probe's claim uses.
|
|
515
|
+
*
|
|
516
|
+
* 1. A changed target, probe or credential leaves the row advertising
|
|
517
|
+
* hosts from a sweep that is no longer the sweep this scan describes:
|
|
518
|
+
* "12 of 254 hosts" beside a range it never visited, a Review Results
|
|
519
|
+
* dialog offering them for import under the new credentials, and an
|
|
520
|
+
* auto-import worker willing to create devices from them. The run is
|
|
521
|
+
* retired and the scan re-queued, so the probe simply sweeps again.
|
|
522
|
+
*
|
|
523
|
+
* 2. nextScanAt is derived state that only the result-ingest endpoint used
|
|
524
|
+
* to write. Turning recurrence ON for a scan that had already finished
|
|
525
|
+
* therefore scheduled nothing at all — the column stayed NULL, and the
|
|
526
|
+
* requeue worker's `nextScanAt <= now` is never true of NULL — so the
|
|
527
|
+
* list said "Every 60 min" over a scan that would never run again.
|
|
528
|
+
* Shortening the interval had the same shape of bug: the new cadence
|
|
529
|
+
* only took effect one full old cadence later.
|
|
530
|
+
*
|
|
531
|
+
* A known and deliberate gap: this is a second statement, so between the two
|
|
532
|
+
* writes the row briefly holds the new settings with the old run state. Two
|
|
533
|
+
* things can go wrong inside that window, both of them one database round
|
|
534
|
+
* trip wide. A probe result landing there is stamped onto the new settings;
|
|
535
|
+
* closing that needs the probe to echo a run identity back, which is a probe
|
|
536
|
+
* protocol change. And if this write itself fails while the settings write
|
|
537
|
+
* succeeded, the row keeps the new settings with the old results until the
|
|
538
|
+
* next edit that actually changes something — the operator sees the error,
|
|
539
|
+
* but re-saving the same values will not repair it, because by then nothing
|
|
540
|
+
* has changed.
|
|
541
|
+
*
|
|
542
|
+
* Doing it FIRST instead, in onBeforeUpdate, would be worse rather than
|
|
543
|
+
* better: that hook runs before the row-level gate as well, so a caller
|
|
544
|
+
* whose update is about to be refused would have retired the scan on the way
|
|
545
|
+
* through.
|
|
546
|
+
*/
|
|
547
|
+
@CaptureSpan()
|
|
548
|
+
protected override async onUpdateSuccess(
|
|
549
|
+
onUpdate: OnUpdate<Model>,
|
|
550
|
+
updatedItemIds: Array<ObjectID>,
|
|
551
|
+
): Promise<OnUpdate<Model>> {
|
|
552
|
+
const plans: Record<string, ScanUpdatePlan> | null =
|
|
553
|
+
(onUpdate.carryForward as Record<string, ScanUpdatePlan> | null) || null;
|
|
554
|
+
|
|
555
|
+
if (!plans) {
|
|
556
|
+
return onUpdate;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
const now: Date = OneUptimeDate.getCurrentDate();
|
|
560
|
+
|
|
561
|
+
for (const itemId of updatedItemIds) {
|
|
562
|
+
const plan: ScanUpdatePlan | undefined = plans[itemId.toString()];
|
|
563
|
+
|
|
564
|
+
if (!plan) {
|
|
565
|
+
continue;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/*
|
|
569
|
+
* Nothing to do at all: the save named a setting but changed none of
|
|
570
|
+
* them, and never mentioned the schedule.
|
|
571
|
+
*/
|
|
572
|
+
if (
|
|
573
|
+
!plan.isSweepChanged &&
|
|
574
|
+
!plan.isScheduleWritten &&
|
|
575
|
+
!plan.isLegacySnmpWritten
|
|
576
|
+
) {
|
|
577
|
+
continue;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/*
|
|
581
|
+
* The row as it stands now that the update has landed. Read rather than
|
|
582
|
+
* predicted from the payload: the schedule columns are what the next run
|
|
583
|
+
* is derived from, and reading them back means the derivation sees the
|
|
584
|
+
* values the DATABASE holds — properly typed — instead of whatever
|
|
585
|
+
* shape the request happened to send them in.
|
|
586
|
+
*/
|
|
587
|
+
const scan: Model | null = await this.findOneById({
|
|
588
|
+
id: itemId,
|
|
589
|
+
select: {
|
|
590
|
+
status: true,
|
|
591
|
+
isRecurring: true,
|
|
592
|
+
rescanIntervalInMinutes: true,
|
|
593
|
+
completedAt: true,
|
|
594
|
+
nextScanAt: true,
|
|
595
|
+
/*
|
|
596
|
+
* For the legacy-write rebuild below. Read back rather than taken
|
|
597
|
+
* from the payload, so the list is built from the values the
|
|
598
|
+
* database actually holds — the payload may have named only some of
|
|
599
|
+
* them, and the rest are whatever the row already had.
|
|
600
|
+
*/
|
|
601
|
+
isSnmpEnabled: true,
|
|
602
|
+
snmpVersion: true,
|
|
603
|
+
snmpCommunityString: true,
|
|
604
|
+
snmpPort: true,
|
|
605
|
+
snmpV3SecurityLevel: true,
|
|
606
|
+
snmpV3Username: true,
|
|
607
|
+
snmpV3AuthProtocol: true,
|
|
608
|
+
snmpV3AuthKey: true,
|
|
609
|
+
snmpV3PrivProtocol: true,
|
|
610
|
+
snmpV3PrivKey: true,
|
|
611
|
+
},
|
|
612
|
+
props: {
|
|
613
|
+
isRoot: true,
|
|
614
|
+
ignoreHooks: true,
|
|
615
|
+
},
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
// Hard-deleted between the write and this read. Nothing to reconcile.
|
|
619
|
+
if (!scan) {
|
|
620
|
+
continue;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
const reconcile: Record<string, unknown> = plan.isSweepChanged
|
|
624
|
+
? { ...RETIRE_RUN_PAYLOAD }
|
|
625
|
+
: {};
|
|
626
|
+
|
|
627
|
+
/*
|
|
628
|
+
* The save came through the old single-credential API, so put the list
|
|
629
|
+
* back in step with the flattened columns it just wrote.
|
|
630
|
+
*
|
|
631
|
+
* Rebuilt from the ROW, which is why it happens here: one update payload
|
|
632
|
+
* is shared by every row the query matched, and the values to rebuild
|
|
633
|
+
* from are per row. resolve() over a row with no list synthesizes exactly
|
|
634
|
+
* one config from those columns, which is the whole of a
|
|
635
|
+
* single-credential scan — reconcileLegacySnmpUpdate has already refused
|
|
636
|
+
* the case where the row has more.
|
|
637
|
+
*
|
|
638
|
+
* An ICMP-only scan is skipped: it stores no SNMP settings at all, and
|
|
639
|
+
* materializing a list of the nulls it holds would be a credential set
|
|
640
|
+
* that says nothing, on a scan that sends nothing.
|
|
641
|
+
*/
|
|
642
|
+
if (plan.isLegacySnmpWritten && ScanModeUtil.isSnmpEnabled(scan)) {
|
|
643
|
+
reconcile["snmpConfigs"] = SnmpScanConfigUtil.normalizeForStorage(
|
|
644
|
+
SnmpScanConfigUtil.resolve(scan as unknown as SnmpScanConfigSource),
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/*
|
|
649
|
+
* Only a save that changed the sweep or asked about the schedule gets
|
|
650
|
+
* its next run re-derived — and the gate has to be stated here rather
|
|
651
|
+
* than left to the early `continue` above.
|
|
652
|
+
*
|
|
653
|
+
* It used to be left to it: that exit returned unless the sweep had
|
|
654
|
+
* changed or the schedule was written, so nothing else could reach this.
|
|
655
|
+
* Adding the credential-list rebuild to that condition opened a third
|
|
656
|
+
* way in, and a save through the flattened columns alone — which asks
|
|
657
|
+
* about neither — began re-deriving the column. On a recurring scan the
|
|
658
|
+
* stale-scan reaper had made due immediately (nextScanAt pulled back to
|
|
659
|
+
* completedAt so the requeue worker picks it up now), that pushed the
|
|
660
|
+
* recovery a full cadence into the future for a save that changed
|
|
661
|
+
* nothing about when the scan should run.
|
|
662
|
+
*
|
|
663
|
+
* For a retired run the state to derive from is the queued one written
|
|
664
|
+
* just above, not the finished one the row still shows.
|
|
665
|
+
*/
|
|
666
|
+
if (plan.isSweepChanged || plan.isScheduleWritten) {
|
|
667
|
+
const nextScanAt: Date | null = getNextScanAt(
|
|
668
|
+
{
|
|
669
|
+
isRecurring: scan.isRecurring,
|
|
670
|
+
rescanIntervalInMinutes: scan.rescanIntervalInMinutes,
|
|
671
|
+
status: plan.isSweepChanged ? "Pending" : scan.status,
|
|
672
|
+
completedAt: plan.isSweepChanged ? null : scan.completedAt,
|
|
673
|
+
},
|
|
674
|
+
now,
|
|
675
|
+
);
|
|
676
|
+
|
|
677
|
+
if (!this.isSameMoment(nextScanAt, scan.nextScanAt)) {
|
|
678
|
+
reconcile["nextScanAt"] = nextScanAt;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
if (Object.keys(reconcile).length === 0) {
|
|
683
|
+
continue;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
await this.updateColumnsByIdWithoutHooks({
|
|
687
|
+
id: itemId,
|
|
688
|
+
// Cast: the model's JSON column makes DeepPartial recursion blow up.
|
|
689
|
+
data: reconcile as unknown as QueryDeepPartialEntity<Model>,
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
return onUpdate;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/*
|
|
697
|
+
* Whether this update actually changes what the probe would sweep.
|
|
698
|
+
*
|
|
699
|
+
* VALUE comparison, never key presence: ModelForm posts every field it
|
|
700
|
+
* declares on every save, dirty or not, so an operator who opened Edit and
|
|
701
|
+
* pressed Save without typing sends the whole sweep back verbatim. Keyed on
|
|
702
|
+
* presence, that would retire a good result set on every no-op save.
|
|
703
|
+
*/
|
|
704
|
+
private hasSweepChanged(
|
|
705
|
+
scan: Model,
|
|
706
|
+
data: Record<string, unknown>,
|
|
707
|
+
dataKeys: Array<string>,
|
|
708
|
+
): boolean {
|
|
709
|
+
if (RelationIdUtil.isWritten(dataKeys, PROBE_RELATION_KEYS)) {
|
|
710
|
+
const probeId: ObjectID | null = RelationIdUtil.read(
|
|
711
|
+
data,
|
|
712
|
+
PROBE_RELATION_KEYS,
|
|
713
|
+
);
|
|
714
|
+
|
|
715
|
+
if (probeId?.toString() !== scan.probeId?.toString()) {
|
|
716
|
+
return true;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
for (const column of SWEEP_COLUMNS) {
|
|
721
|
+
if (column === "probeId" || !dataKeys.includes(column)) {
|
|
722
|
+
continue;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
if (
|
|
726
|
+
this.normalizeSweepValue(data[column]) !==
|
|
727
|
+
this.normalizeSweepValue(
|
|
728
|
+
(scan as unknown as Record<string, unknown>)[column],
|
|
729
|
+
)
|
|
730
|
+
) {
|
|
731
|
+
return true;
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
return false;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
/*
|
|
739
|
+
* The probe a scan is pointed at has to be one this project may actually use
|
|
740
|
+
* — its own, or a global one.
|
|
741
|
+
*
|
|
742
|
+
* The scan is dispatched by probe id alone: the claim endpoint hands a
|
|
743
|
+
* Pending scan to whichever probe authenticates as that id, with no project
|
|
744
|
+
* check of its own, and the results are written back onto this row. So a
|
|
745
|
+
* scan pointing at ANOTHER project's probe is a scan that makes that
|
|
746
|
+
* project's probe sweep its own network and report the hosts it finds into
|
|
747
|
+
* this one. The ids are not guessable and the probe list is tenant-scoped,
|
|
748
|
+
* so this is a lock rather than a repair — but it is the lock that has to
|
|
749
|
+
* exist now that the column can be re-pointed after creation, and it is
|
|
750
|
+
* applied on create for the same reason.
|
|
751
|
+
*
|
|
752
|
+
* A probe with no project is a global probe and is available to everyone.
|
|
753
|
+
*/
|
|
754
|
+
private async validateProbeIsUsable(input: {
|
|
755
|
+
data: Record<string, unknown>;
|
|
756
|
+
dataKeys: Array<string>;
|
|
757
|
+
projectId: ObjectID | undefined;
|
|
758
|
+
}): Promise<void> {
|
|
759
|
+
if (!RelationIdUtil.isWritten(input.dataKeys, PROBE_RELATION_KEYS)) {
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
/*
|
|
764
|
+
* readConsistent, not read: a payload that points the FK column and the
|
|
765
|
+
* relation object at two different probes must be refused rather than
|
|
766
|
+
* validated against whichever one TypeORM happens to persist.
|
|
767
|
+
*/
|
|
768
|
+
const probeId: ObjectID | null = RelationIdUtil.readConsistent(
|
|
769
|
+
input.data,
|
|
770
|
+
PROBE_RELATION_KEYS,
|
|
771
|
+
"Probe",
|
|
772
|
+
);
|
|
773
|
+
|
|
774
|
+
/*
|
|
775
|
+
* probeId is NOT NULL, so a payload that names the probe and resolves to
|
|
776
|
+
* nothing is an operator clearing the box. Without this it reaches
|
|
777
|
+
* Postgres as a constraint violation — a 500 where the truthful answer is
|
|
778
|
+
* a 400 with a sentence in it.
|
|
779
|
+
*/
|
|
780
|
+
if (!probeId) {
|
|
781
|
+
throw new BadDataException(
|
|
782
|
+
"A discovery scan needs a probe to run it. Pick the probe that can reach this address range.",
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// Nothing to compare against; the write itself is still tenant-checked.
|
|
787
|
+
if (!input.projectId) {
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
const probe: Probe | null = await ProbeService.findOneById({
|
|
792
|
+
id: probeId,
|
|
793
|
+
select: {
|
|
794
|
+
_id: true,
|
|
795
|
+
projectId: true,
|
|
796
|
+
},
|
|
797
|
+
props: {
|
|
798
|
+
isRoot: true,
|
|
799
|
+
},
|
|
800
|
+
});
|
|
801
|
+
|
|
802
|
+
if (!probe) {
|
|
803
|
+
throw new BadDataException(
|
|
804
|
+
"That probe could not be found. Pick a probe that can reach this address range.",
|
|
805
|
+
);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
if (
|
|
809
|
+
probe.projectId &&
|
|
810
|
+
probe.projectId.toString() !== input.projectId.toString()
|
|
811
|
+
) {
|
|
812
|
+
throw new BadDataException(
|
|
813
|
+
"That probe belongs to another project. Pick one of this project's probes, or a global probe.",
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/*
|
|
819
|
+
* An emptied number box means "unset", not "the empty string".
|
|
820
|
+
*
|
|
821
|
+
* Written in place, like the name normalization above, so the value the rest
|
|
822
|
+
* of the pipeline sees is the value that will be stored.
|
|
823
|
+
*/
|
|
824
|
+
private nullEmptyNumbers(
|
|
825
|
+
data: Record<string, unknown>,
|
|
826
|
+
dataKeys: Array<string>,
|
|
827
|
+
): void {
|
|
828
|
+
for (const column of NULLABLE_NUMBER_COLUMNS) {
|
|
829
|
+
if (!dataKeys.includes(column)) {
|
|
830
|
+
continue;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
const value: unknown = data[column];
|
|
834
|
+
|
|
835
|
+
if (typeof value === "string" && value.trim() === "") {
|
|
836
|
+
data[column] = null;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/*
|
|
842
|
+
* A sweep column's value as a comparable string.
|
|
843
|
+
*
|
|
844
|
+
* An empty box and an unset column are the SAME setting and must compare
|
|
845
|
+
* equal, or a V3 scan — whose community string is NULL in the database and
|
|
846
|
+
* "" in the form — would read as changed on the first save and retire its
|
|
847
|
+
* own results. Numbers are compared as numbers so the port arriving as the
|
|
848
|
+
* string "161" from a form field does not read as a change either.
|
|
849
|
+
*/
|
|
850
|
+
private normalizeSweepValue(value: unknown): string {
|
|
851
|
+
if (value === undefined || value === null || value === "") {
|
|
852
|
+
return "";
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
if (typeof value === "number") {
|
|
856
|
+
return String(value);
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
if (typeof value === "string") {
|
|
860
|
+
return value.trim();
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/*
|
|
864
|
+
* The credential LIST, and the reason the fall-through below cannot be
|
|
865
|
+
* left to speak for it: `String([{ ... }])` is "[object Object]" for every
|
|
866
|
+
* possible list, so two completely different sets of credentials would
|
|
867
|
+
* compare equal and a save that swapped them would leave the row
|
|
868
|
+
* advertising hosts found with the old ones.
|
|
869
|
+
*
|
|
870
|
+
* Compared through the same normalizer the probe and the importer read the
|
|
871
|
+
* column with, so the comparison is of the credentials that will actually
|
|
872
|
+
* be USED — an empty box against an unset field, "161" against 161, "V3"
|
|
873
|
+
* against "3" — rather than of the shape the form happened to post. That
|
|
874
|
+
* is what stops a no-op Save (ModelForm posts every field, dirty or not)
|
|
875
|
+
* from retiring a good result set on every visit to the Edit dialog.
|
|
876
|
+
*
|
|
877
|
+
* An empty array normalizes to "" — the same answer as an unset column —
|
|
878
|
+
* because both mean "this scan has no list of its own". A list is refused
|
|
879
|
+
* as empty at validation time anyway; this only decides whether the two
|
|
880
|
+
* shapes read as a CHANGE.
|
|
881
|
+
*/
|
|
882
|
+
if (Array.isArray(value)) {
|
|
883
|
+
/*
|
|
884
|
+
* Compared on what the PROBE would do differently, which is neither the
|
|
885
|
+
* whole stored object nor a naive stringify of it. Two fields are
|
|
886
|
+
* deliberately excluded, and each one caused a real bug:
|
|
887
|
+
*
|
|
888
|
+
* - `name` is the operator's label. It reaches a log line and the
|
|
889
|
+
* scan's status message and nothing else — never the wire. Including
|
|
890
|
+
* it meant renaming a credential card retired the run and deleted
|
|
891
|
+
* every host the scan had found, for a change that alters nothing
|
|
892
|
+
* about the sweep.
|
|
893
|
+
* - `id` is server-minted bookkeeping. applySnmpConfigs runs BEFORE
|
|
894
|
+
* this comparison and mints a fresh ObjectID for any entry that
|
|
895
|
+
* arrived without one, so a client that does not echo ids back — an
|
|
896
|
+
* API caller, a reconciler re-applying the same desired state — sent
|
|
897
|
+
* a byte-identical body twice and had the second read as a credential
|
|
898
|
+
* change. A scan under such a reconciler could never hold a result
|
|
899
|
+
* set at all.
|
|
900
|
+
*
|
|
901
|
+
* What survives is exactly the session parameters: version, community,
|
|
902
|
+
* port and the v3 block, in the operator's order. A REORDER still reads
|
|
903
|
+
* as a change, because order decides which credential each host is tried
|
|
904
|
+
* with first.
|
|
905
|
+
*
|
|
906
|
+
* Through resolve(), NOT normalizeForStorage(): the latter mints ids, and
|
|
907
|
+
* a comparison has to be a pure function of its input.
|
|
908
|
+
*/
|
|
909
|
+
const configs: Array<DiscoveryScanSnmpConfig> =
|
|
910
|
+
SnmpScanConfigUtil.resolve({
|
|
911
|
+
snmpConfigs: value as Array<DiscoveryScanSnmpConfig>,
|
|
912
|
+
});
|
|
913
|
+
|
|
914
|
+
const sweepShape: Array<Record<string, unknown>> = configs.map(
|
|
915
|
+
(config: DiscoveryScanSnmpConfig): Record<string, unknown> => {
|
|
916
|
+
const sweepFields: Record<string, unknown> = {
|
|
917
|
+
...config,
|
|
918
|
+
} as unknown as Record<string, unknown>;
|
|
919
|
+
|
|
920
|
+
delete sweepFields["id"];
|
|
921
|
+
delete sweepFields["name"];
|
|
922
|
+
|
|
923
|
+
return sweepFields;
|
|
924
|
+
},
|
|
925
|
+
);
|
|
926
|
+
|
|
927
|
+
return value.length === 0 ? "" : JSON.stringify(sweepShape);
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
return String(value);
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
/*
|
|
934
|
+
* An update written through the FLATTENED columns alone, on a scan that has
|
|
935
|
+
* a credential list.
|
|
936
|
+
*
|
|
937
|
+
* The list shadows those columns — SnmpScanConfigUtil.resolve reads it and
|
|
938
|
+
* ignores them — so such a write would land in the database and change
|
|
939
|
+
* nothing about the sweep, which is the worst of both outcomes: the caller
|
|
940
|
+
* is told it succeeded and the scan keeps the credentials it had.
|
|
941
|
+
*
|
|
942
|
+
* There are exactly two honest answers, and which one applies depends only
|
|
943
|
+
* on how many configs the row holds:
|
|
944
|
+
*
|
|
945
|
+
* - ONE (or none): the scan is single-credential, so the flattened columns
|
|
946
|
+
* can describe it completely. This returns true and onUpdateSuccess
|
|
947
|
+
* REBUILDS the list from the row's own flattened columns once the write
|
|
948
|
+
* has landed — the behaviour this API had before the list existed, with
|
|
949
|
+
* the list kept in step rather than discarded.
|
|
950
|
+
* - MORE THAN ONE: there is no flattened column set that could express the
|
|
951
|
+
* scan, and picking one config to overwrite would silently discard the
|
|
952
|
+
* others. Refused, naming the field to use instead.
|
|
953
|
+
*
|
|
954
|
+
* It does NOT null the column, which is what it used to do. A NULL list is
|
|
955
|
+
* readable — SnmpScanConfigUtil.resolve falls back to the flattened columns
|
|
956
|
+
* — but it is not EDITABLE: the Edit dialog's only SNMP control is the list
|
|
957
|
+
* editor, so it selects `snmpConfigs` alone, and a NULL there opened a blank
|
|
958
|
+
* card over a scan that had real credentials. Saving that card then mirrored
|
|
959
|
+
* its emptiness back over all nine columns and wiped them. The invariant
|
|
960
|
+
* "every scan the product has touched has a list" is what makes that
|
|
961
|
+
* unreachable, and this is the third place that maintains it, after the
|
|
962
|
+
* backfill migration and onBeforeCreate.
|
|
963
|
+
*/
|
|
964
|
+
private reconcileLegacySnmpUpdate(input: {
|
|
965
|
+
data: Record<string, unknown>;
|
|
966
|
+
dataKeys: Array<string>;
|
|
967
|
+
scan: Model;
|
|
968
|
+
}): boolean {
|
|
969
|
+
if (input.dataKeys.includes("snmpConfigs")) {
|
|
970
|
+
return false;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
const isLegacyColumnWritten: boolean = LEGACY_SNMP_COLUMNS.some(
|
|
974
|
+
(column: string) => {
|
|
975
|
+
return input.dataKeys.includes(column);
|
|
976
|
+
},
|
|
977
|
+
);
|
|
978
|
+
|
|
979
|
+
if (!isLegacyColumnWritten) {
|
|
980
|
+
return false;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
const stored: Array<DiscoveryScanSnmpConfig> | null =
|
|
984
|
+
SnmpScanConfigUtil.readStoredList(input.scan.snmpConfigs);
|
|
985
|
+
|
|
986
|
+
if (stored && stored.length > 1) {
|
|
987
|
+
throw new BadDataException(
|
|
988
|
+
`This scan tries ${stored.length} SNMP configs, which the single snmp* fields cannot describe. ` +
|
|
989
|
+
`Send the whole "snmpConfigs" list instead.`,
|
|
990
|
+
);
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
return true;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
/*
|
|
997
|
+
* The scan's ordered SNMP credential list: validated, normalized, and
|
|
998
|
+
* mirrored into the flattened columns.
|
|
999
|
+
*
|
|
1000
|
+
* Called from BOTH write hooks, and a no-op for a payload that does not
|
|
1001
|
+
* mention `snmpConfigs` — which is every server-side writer of this model
|
|
1002
|
+
* (the probe claim, the result ingest, the requeue worker) and every API
|
|
1003
|
+
* caller still using the flattened columns alone.
|
|
1004
|
+
*
|
|
1005
|
+
* THE MIRROR IS THE POINT. A probe is deployed separately from the server
|
|
1006
|
+
* and is routinely a version behind, and a probe that has never heard of
|
|
1007
|
+
* `snmpConfigs` reads the flattened columns and nothing else. Without this,
|
|
1008
|
+
* saving a multi-config scan would leave those columns holding whatever the
|
|
1009
|
+
* scan was created with — or, for a scan created after this feature, the
|
|
1010
|
+
* bare column defaults — and every older probe in the fleet would sweep with
|
|
1011
|
+
* "public"/v2c and report a confident zero. Mirroring the FIRST config keeps
|
|
1012
|
+
* such a probe doing exactly what it would have done under the old
|
|
1013
|
+
* single-config UI.
|
|
1014
|
+
*/
|
|
1015
|
+
private applySnmpConfigs(
|
|
1016
|
+
data: Record<string, unknown>,
|
|
1017
|
+
dataKeys: Array<string>,
|
|
1018
|
+
): void {
|
|
1019
|
+
if (!dataKeys.includes("snmpConfigs")) {
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
const raw: unknown = data["snmpConfigs"];
|
|
1024
|
+
|
|
1025
|
+
/*
|
|
1026
|
+
* An absent list is not the same as a bad one. The edit form always posts
|
|
1027
|
+
* the key, so a null/empty value here is an API caller clearing the column
|
|
1028
|
+
* — which puts the scan back on its flattened columns, exactly where a
|
|
1029
|
+
* scan created before this feature already is. Nothing is mirrored in that
|
|
1030
|
+
* case: there is no first config to mirror from, and overwriting the
|
|
1031
|
+
* flattened columns with defaults would erase the credentials that clearing
|
|
1032
|
+
* the list just fell back to.
|
|
1033
|
+
*/
|
|
1034
|
+
if (raw === undefined || raw === null || raw === "") {
|
|
1035
|
+
data["snmpConfigs"] = null;
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
const validationError: string | null =
|
|
1040
|
+
SnmpScanConfigUtil.getValidationError(raw);
|
|
1041
|
+
|
|
1042
|
+
if (validationError) {
|
|
1043
|
+
throw new BadDataException(validationError);
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
const configs: Array<DiscoveryScanSnmpConfig> | null =
|
|
1047
|
+
SnmpScanConfigUtil.normalizeForStorage(raw);
|
|
1048
|
+
|
|
1049
|
+
data["snmpConfigs"] = configs;
|
|
1050
|
+
|
|
1051
|
+
if (!configs || configs.length === 0) {
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
const mirrored: Record<string, string | number | null> =
|
|
1056
|
+
SnmpScanConfigUtil.getMirroredLegacyColumns(configs);
|
|
1057
|
+
|
|
1058
|
+
for (const column of Object.keys(mirrored)) {
|
|
1059
|
+
/*
|
|
1060
|
+
* The payload wins where it speaks for itself. An API caller that sends
|
|
1061
|
+
* BOTH the list and a flattened column meant the flattened one, and
|
|
1062
|
+
* silently overwriting it would make the two disagree in a way only the
|
|
1063
|
+
* database could reveal.
|
|
1064
|
+
*/
|
|
1065
|
+
if (dataKeys.includes(column)) {
|
|
1066
|
+
continue;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
data[column] = mirrored[column] ?? null;
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
/*
|
|
1074
|
+
* Two nullable timestamps, compared by the instant they name. The stored
|
|
1075
|
+
* value comes back from Postgres and the derived one is built here, so a
|
|
1076
|
+
* strict equality between the two objects is never true even when the moment
|
|
1077
|
+
* is identical, and every no-op save would write the column again.
|
|
1078
|
+
*/
|
|
1079
|
+
private isSameMoment(
|
|
1080
|
+
left: Date | null | undefined,
|
|
1081
|
+
right: Date | null | undefined,
|
|
1082
|
+
): boolean {
|
|
1083
|
+
if (!left || !right) {
|
|
1084
|
+
return !left && !right;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
return (
|
|
1088
|
+
OneUptimeDate.fromString(left).getTime() ===
|
|
1089
|
+
OneUptimeDate.fromString(right).getTime()
|
|
1090
|
+
);
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
/*
|
|
1094
|
+
* The columns an ICMP-only scan must not carry (OneUptime issue #3445).
|
|
1095
|
+
*
|
|
1096
|
+
* Hiding the fields in the form is not enough on its own, for two separate
|
|
1097
|
+
* reasons. ModelForm builds the request body out of every DECLARED field
|
|
1098
|
+
* without checking whether it was visible, so a v3 passphrase typed before
|
|
1099
|
+
* the operator changed their mind is still posted — and TypeORM OMITS an
|
|
1100
|
+
* undefined property from the INSERT, at which point Postgres fills in the
|
|
1101
|
+
* column defaults, which for this table are 'V2c' and 161. Either way the
|
|
1102
|
+
* stored row claims to be an SNMP v2c scan on port 161 while its own method
|
|
1103
|
+
* column says it sends no SNMP at all.
|
|
1104
|
+
*
|
|
1105
|
+
* An explicit null is the only value that beats a column default, which is
|
|
1106
|
+
* why these are nulled rather than deleted.
|
|
1107
|
+
*/
|
|
1108
|
+
private static readonly SNMP_CONFIG_COLUMNS: Array<string> = [
|
|
1109
|
+
/*
|
|
1110
|
+
* The credential LIST belongs here as much as the flattened columns do,
|
|
1111
|
+
* and more urgently: it is where the community strings and v3 passphrases
|
|
1112
|
+
* of a multi-credential scan actually live (issue #3458). Clearing the
|
|
1113
|
+
* nine below while leaving this behind would store an ICMP-only scan whose
|
|
1114
|
+
* own method column says it sends no SNMP, carrying every credential the
|
|
1115
|
+
* operator had typed.
|
|
1116
|
+
*/
|
|
1117
|
+
"snmpConfigs",
|
|
1118
|
+
"snmpVersion",
|
|
1119
|
+
"snmpCommunityString",
|
|
1120
|
+
"snmpPort",
|
|
1121
|
+
"snmpV3SecurityLevel",
|
|
1122
|
+
"snmpV3Username",
|
|
1123
|
+
"snmpV3AuthProtocol",
|
|
1124
|
+
"snmpV3AuthKey",
|
|
1125
|
+
"snmpV3PrivProtocol",
|
|
1126
|
+
"snmpV3PrivKey",
|
|
1127
|
+
];
|
|
1128
|
+
|
|
1129
|
+
/*
|
|
1130
|
+
* Written through a cast for the same reason the name normalize above is:
|
|
1131
|
+
* the properties are typed `string | number | undefined` and
|
|
1132
|
+
* exactOptionalPropertyTypes forbids assigning null to them directly.
|
|
1133
|
+
*/
|
|
1134
|
+
private clearSnmpConfig(data: unknown): void {
|
|
1135
|
+
const record: Record<string, unknown> = data as Record<string, unknown>;
|
|
1136
|
+
|
|
1137
|
+
for (const column of Service.SNMP_CONFIG_COLUMNS) {
|
|
1138
|
+
record[column] = null;
|
|
1139
|
+
}
|
|
99
1140
|
}
|
|
100
1141
|
|
|
101
1142
|
/*
|