@oneuptime/common 13.0.3 → 13.0.5
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/DatabaseModels/Index.ts +4 -0
- package/Models/DatabaseModels/RumApplication.ts +1 -1
- package/Models/DatabaseModels/SecurityEventConnection.ts +457 -0
- package/Models/DatabaseModels/SecurityEventConnectionRun.ts +263 -0
- package/Models/DatabaseModels/TelemetryIngestionKey.ts +2 -2
- package/Server/API/AIInvestigationAPI.ts +484 -24
- package/Server/API/GoogleSecOpsConnectionAPI.ts +249 -8
- package/Server/API/SecurityEventConnectionAPI.ts +250 -0
- package/Server/API/TelemetryAPI.ts +402 -265
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792700000000-AddSecurityEventConnections.ts +99 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Middleware/TelemetryIngest.ts +101 -6
- package/Server/Services/ExceptionAggregationService.ts +7 -16
- package/Server/Services/GoogleSecOpsConnectionService.ts +15 -0
- package/Server/Services/Index.ts +4 -0
- package/Server/Services/InventoryItemService.ts +28 -0
- package/Server/Services/LogAggregationService.ts +17 -23
- package/Server/Services/MetricAggregationService.ts +4 -14
- package/Server/Services/SecurityEventConnectionRunService.ts +10 -0
- package/Server/Services/SecurityEventConnectionService.ts +538 -0
- package/Server/Services/TraceAggregationService.ts +77 -28
- package/Server/Types/AnalyticsDatabase/ModelPermission.ts +9 -0
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +13 -1
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +15 -1
- package/Server/Utils/AI/SRE/InvestigationEvidence.ts +658 -0
- package/Server/Utils/AI/SRE/InvestigationReferences.ts +324 -0
- package/Server/Utils/AI/Toolbox/Index.ts +38 -0
- package/Server/Utils/AI/Toolbox/TimelineTools.ts +9 -2
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +80 -0
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +5 -3
- package/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubClient.ts +1108 -0
- package/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.ts +732 -0
- package/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.ts +495 -0
- package/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.ts +689 -0
- package/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.ts +767 -0
- package/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.ts +571 -0
- package/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.ts +827 -0
- package/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.ts +610 -0
- package/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.ts +549 -0
- package/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.ts +830 -0
- package/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.ts +684 -0
- package/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.ts +487 -0
- package/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.ts +778 -0
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.ts +1002 -0
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.ts +556 -0
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.ts +275 -0
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.ts +53 -0
- package/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.ts +709 -0
- package/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.ts +596 -0
- package/Server/Utils/SecurityEvent/Connectors/Types.ts +191 -0
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.ts +353 -65
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.ts +777 -0
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +747 -148
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.ts +48 -2
- package/Server/Utils/SecurityEvent/SecurityEventDedupe.ts +81 -0
- package/Server/Utils/SessionReplay/SessionReplayReadService.ts +741 -40
- package/Server/Utils/StartServer.ts +10 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +8 -0
- package/Server/Utils/Telemetry/KubernetesResourceAttributes.ts +108 -0
- package/Server/Utils/Telemetry/ResourceEntityFilter.ts +174 -93
- package/Server/Utils/Telemetry/ResourceFacetPlanner.ts +251 -0
- package/Server/Utils/Telemetry/ResourceFacetResolver.ts +248 -413
- package/Server/Utils/Telemetry/ServiceDependencyDiscovery.ts +668 -0
- package/Server/Utils/Telemetry/TraceContextPropagation.ts +348 -0
- package/Server/Utils/Telemetry.ts +18 -0
- package/Tests/App/Dashboard/AIInvestigationHeaderStatus.test.tsx +413 -0
- package/Tests/App/Dashboard/AIRootCauseFeedItem.test.tsx +285 -0
- package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +242 -0
- package/Tests/App/Dashboard/AlertEpisodeViewFields.test.tsx +601 -15
- package/Tests/App/Dashboard/ChangeAlertStateAIHeader.test.tsx +835 -0
- package/Tests/App/Dashboard/CloudResourceTelemetryScope.test.ts +41 -0
- package/Tests/App/Dashboard/ConnectionTestModal.test.tsx +604 -0
- package/Tests/App/Dashboard/ConnectorTestReportView.test.tsx +738 -0
- package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +153 -6
- package/Tests/App/Dashboard/EntityDetailPanel.test.tsx +165 -0
- package/Tests/App/Dashboard/EpisodeChangeState.test.tsx +1069 -0
- package/Tests/App/Dashboard/EpisodeMembersCard.test.tsx +772 -0
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +2354 -0
- package/Tests/App/Dashboard/EventOverviewSkeleton.test.tsx +210 -0
- package/Tests/App/Dashboard/EventStatBar.test.tsx +392 -0
- package/Tests/App/Dashboard/EventStatusPanel.test.tsx +247 -0
- package/Tests/App/Dashboard/ExceptionAIAssistance.test.tsx +606 -0
- package/Tests/App/Dashboard/ExceptionBreadcrumbTimeline.test.tsx +273 -0
- package/Tests/App/Dashboard/ExceptionDetailSideMenu.test.tsx +176 -0
- package/Tests/App/Dashboard/ExceptionOverviewCards.test.tsx +366 -0
- package/Tests/App/Dashboard/ExceptionSignalPages.test.tsx +371 -0
- package/Tests/App/Dashboard/ExceptionStackFrameViewer.test.tsx +440 -0
- package/Tests/App/Dashboard/ExceptionSummary.test.tsx +381 -0
- package/Tests/App/Dashboard/ExceptionTriage.test.tsx +306 -0
- package/Tests/App/Dashboard/ExceptionsResourceFacets.test.tsx +604 -0
- package/Tests/App/Dashboard/ExceptionsViewerEntityChips.test.tsx +706 -0
- package/Tests/App/Dashboard/FeedOrdering.test.ts +32 -0
- package/Tests/App/Dashboard/GoogleSecOpsConnectionForm.test.tsx +838 -0
- package/Tests/App/Dashboard/GoogleSecOpsConnectionsErrors.test.tsx +18 -0
- package/Tests/App/Dashboard/GoogleSecOpsDiagnostics.test.tsx +297 -20
- package/Tests/App/Dashboard/IncidentEpisodeViewFields.test.tsx +618 -13
- package/Tests/App/Dashboard/InfrastructureExplorer.test.tsx +254 -207
- package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +303 -135
- package/Tests/App/Dashboard/InvestigationEvidenceList.test.tsx +1251 -0
- package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +303 -0
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +876 -8
- package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +35 -0
- package/Tests/App/Dashboard/InvestigationReferenceLink.test.tsx +177 -0
- package/Tests/App/Dashboard/InvestigationReportView.test.tsx +1295 -0
- package/Tests/App/Dashboard/KubernetesImageReferenceView.test.tsx +114 -0
- package/Tests/App/Dashboard/KubernetesLogsTabChips.test.tsx +285 -0
- package/Tests/App/Dashboard/LogsEntityChipNames.test.tsx +316 -0
- package/Tests/App/Dashboard/LogsResourceFacetChips.test.tsx +361 -0
- package/Tests/App/Dashboard/ProfileTableEntityNames.test.tsx +432 -0
- package/Tests/App/Dashboard/ProfileViewEntityName.test.tsx +250 -0
- package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +10 -0
- package/Tests/App/Dashboard/ResourceLogsTabsBareLayout.test.tsx +700 -0
- package/Tests/App/Dashboard/ResourcePageEntityNameProps.test.tsx +803 -0
- package/Tests/App/Dashboard/RumSessionReplaySideMenu.test.tsx +11 -1
- package/Tests/App/Dashboard/ScheduledMaintenanceChangeState.test.tsx +1026 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceFeedRefresh.test.tsx +436 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +1195 -0
- package/Tests/App/Dashboard/SecurityEventConnectionFormModal.test.tsx +1022 -0
- package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +905 -0
- package/Tests/App/Dashboard/SecurityEventsSideMenu.test.tsx +247 -0
- package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +375 -274
- package/Tests/App/Dashboard/SessionReplayAuditTable.test.tsx +410 -0
- package/Tests/App/Dashboard/TelemetryResourceRetentionSettings.test.tsx +774 -0
- package/Tests/App/Dashboard/TopErrorsPanelResourceNames.test.tsx +316 -0
- package/Tests/App/Dashboard/TopologyDataLoading.test.tsx +30 -0
- package/Tests/App/Dashboard/TopologyPageNavigation.test.tsx +88 -24
- package/Tests/App/Dashboard/TraceExplorer.test.tsx +1590 -0
- package/Tests/App/Dashboard/TraceWaterfall.test.tsx +488 -0
- package/Tests/App/Dashboard/TracesAnalyticsSeriesLabels.test.tsx +367 -0
- package/Tests/App/Dashboard/TracesEntityNames.test.tsx +585 -0
- package/Tests/App/Dashboard/TracesResourceFacets.test.tsx +613 -0
- package/Tests/App/Dashboard/UseServiceNames.test.tsx +359 -0
- package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +7 -0
- package/Tests/Models/InventoryItemNaming.test.ts +132 -16
- package/Tests/Models/SecurityDomainAccessControl.test.ts +61 -17
- package/Tests/Server/API/AIInvestigationAPI.test.ts +611 -2
- package/Tests/Server/API/AIInvestigationEvidenceAPI.test.ts +1098 -0
- package/Tests/Server/API/GoogleSecOpsConnectionAPI.test.ts +409 -0
- package/Tests/Server/API/SecurityEventConnectionAPI.test.ts +856 -0
- package/Tests/Server/API/SessionReplayAPI.test.ts +528 -1
- package/Tests/Server/API/TelemetryFacetsAPI.test.ts +810 -0
- package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +240 -0
- package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +229 -0
- package/Tests/Server/Services/InventoryItemDisplayName.test.ts +66 -0
- package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +28 -1
- package/Tests/Server/Services/SecurityEventConnectionService.test.ts +1233 -0
- package/Tests/Server/Services/TelemetryIngestionKeyValidation.test.ts +53 -0
- package/Tests/Server/Services/TelemetryResourceFacetCounting.test.ts +218 -0
- package/Tests/Server/Services/TelemetryResourceFacetFilters.test.ts +155 -1
- package/Tests/Server/Services/TraceAggregationExceptionScope.test.ts +142 -0
- package/Tests/Server/Services/TraceAnalyticsResourceDisplayNames.test.ts +85 -24
- package/Tests/Server/Types/Database/Permissions/SecurityRoleAccess.test.ts +33 -0
- package/Tests/Server/Utils/AI/InvestigationEvidence.test.ts +1395 -0
- package/Tests/Server/Utils/AI/InvestigationReferences.test.ts +616 -0
- package/Tests/Server/Utils/AI/TimelineTools.test.ts +119 -0
- package/Tests/Server/Utils/AI/Toolbox/AIToolbox.test.ts +151 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +65 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorExceptionScope.test.ts +224 -0
- package/Tests/Server/Utils/LoggerCore.test.ts +597 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPerSeriesFanout.test.ts +55 -2
- package/Tests/Server/Utils/Monitor/MonitorTemplateUtil.test.ts +1109 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubClient.test.ts +1240 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.test.ts +1853 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.test.ts +1129 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.test.ts +1066 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.test.ts +1568 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.test.ts +930 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.test.ts +1409 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.test.ts +763 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.test.ts +1296 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.test.ts +1102 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.test.ts +1174 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.test.ts +1032 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.test.ts +1558 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.test.ts +3041 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.test.ts +1168 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.test.ts +906 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.test.ts +1068 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.test.ts +1004 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.test.ts +784 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.test.ts +113 -1
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsClient.test.ts +5 -1
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsDiagnostics.test.ts +93 -13
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsHttpIntegration.test.ts +23 -1
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +25 -3
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +22 -8
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerHardening.test.ts +82 -16
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsSearchDetections.test.ts +730 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsThreePassPoller.test.ts +1577 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayOriginAllowlist.test.ts +41 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +1453 -18
- package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +711 -0
- package/Tests/Server/Utils/Telemetry/KubernetesResourceAttributes.test.ts +162 -0
- package/Tests/Server/Utils/Telemetry/ResourceEntityFilter.test.ts +460 -13
- package/Tests/Server/Utils/Telemetry/ResourceFacetPlanner.test.ts +678 -0
- package/Tests/Server/Utils/Telemetry/ResourceFacetResolver.test.ts +868 -0
- package/Tests/Server/Utils/Telemetry/ServiceDependencyDiscovery.test.ts +525 -0
- package/Tests/Server/Utils/Telemetry/TraceContextPropagation.test.ts +420 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilCorePaths.test.ts +1014 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilExhaustiveRotation.test.ts +9 -6
- package/Tests/Types/Rules/RuleCriteriaFieldRegistry.test.ts +276 -0
- package/Tests/Types/Rum/SessionReplayApiContracts.test.ts +73 -0
- package/Tests/Types/Rum/SessionReplayTransportContracts.test.ts +95 -0
- package/Tests/Types/SecurityEvent/Connectors/ConnectorDiagnostics.test.ts +82 -0
- package/Tests/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.test.ts +314 -0
- package/Tests/Types/Telemetry/ExceptionSpanScope.test.ts +89 -0
- package/Tests/Types/Telemetry/LlmConventions.test.ts +495 -0
- package/Tests/Types/Telemetry/ResourceEntityFacet.test.ts +96 -0
- package/Tests/Types/Telemetry/ResourceFacetCatalog.test.ts +304 -0
- package/Tests/UI/Components/ActiveFilterChipsLockedFilters.test.tsx +357 -0
- package/Tests/UI/Components/Card.test.tsx +312 -1
- package/Tests/UI/Components/CardModelDetailHeaderLayout.test.tsx +253 -0
- package/Tests/UI/Components/CardModelDetailRefresher.test.tsx +342 -0
- package/Tests/UI/Components/Checkbox.test.tsx +79 -0
- package/Tests/UI/Components/CopyTextButton.test.tsx +142 -0
- package/Tests/UI/Components/DetailCompactStyle.test.tsx +621 -0
- package/Tests/UI/Components/ErrorBoundary.test.tsx +60 -0
- package/Tests/UI/Components/FacetSections.test.tsx +581 -0
- package/Tests/UI/Components/FacetSidebarControls.test.tsx +812 -0
- package/Tests/UI/Components/FacetVisibility.test.ts +429 -0
- package/Tests/UI/Components/LockedFilterActions.test.tsx +396 -0
- package/Tests/UI/Components/LockedFilterChip.test.tsx +651 -0
- package/Tests/UI/Components/LogsEntityNames.test.ts +1769 -0
- package/Tests/UI/Components/LogsEntityNamesComponents.test.tsx +696 -0
- package/Tests/UI/Components/LogsFacetSidebarHiddenFacets.test.tsx +600 -0
- package/Tests/UI/Components/LogsViewerEntityNames.test.tsx +713 -0
- package/Tests/UI/Components/MarkdownInlineReferences.test.tsx +2079 -0
- package/Tests/UI/Components/MemberRoleAssignment.test.tsx +446 -0
- package/Tests/UI/Components/ModelDetailRefetch.test.tsx +397 -0
- package/Tests/UI/Components/ModelListRefetch.test.tsx +233 -0
- package/Tests/UI/Components/ModelPageModelChange.test.tsx +409 -0
- package/Tests/UI/Components/PaginationIntegration.test.tsx +25 -0
- package/Tests/UI/Components/ResourceFacetConfigs.test.ts +172 -0
- package/Tests/UI/Components/SavedViewsSidebarIntegration.test.tsx +32 -14
- package/Tests/UI/Components/TableSortAndMobileColumns.test.tsx +44 -1
- package/Tests/UI/Components/TelemetryActiveFilterChipsLockedFilters.test.tsx +304 -0
- package/Tests/UI/Components/TelemetryFacetSidebarHiddenFacets.test.tsx +718 -0
- package/Tests/UI/Monitor/EvaluationLogList.test.tsx +303 -0
- package/Tests/UI/Monitor/MonitorSummarySnapshotRender.test.tsx +55 -1
- package/Tests/UI/Rum/FidelityNotices.test.ts +22 -0
- package/Tests/UI/Rum/RecordingHealthCard.test.tsx +120 -136
- package/Tests/UI/Rum/RecordingHealthDashboard.test.tsx +988 -0
- package/Tests/UI/Rum/ReplayCard.test.tsx +32 -0
- package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +709 -12
- package/Tests/UI/Rum/ReplayHeader.test.tsx +50 -1
- package/Tests/UI/Rum/ReplayPinControl.test.tsx +67 -10
- package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +41 -12
- package/Tests/UI/Rum/ReplayStage.test.tsx +663 -1
- package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +173 -0
- package/Tests/UI/Rum/ReplayUi.test.tsx +189 -2
- package/Tests/UI/Rum/ReplayUserSessionsMenu.test.tsx +91 -0
- package/Tests/UI/Rum/SessionReplayEmptyState.test.tsx +1 -1
- package/Tests/UI/Rum/SessionReplaySettingsPolicyLoading.test.tsx +585 -0
- package/Tests/UI/Rum/SessionReplayTable.test.tsx +844 -51
- package/Tests/UI/Rum/SessionReplayUsersTable.test.tsx +29 -1
- package/Tests/UI/Telemetry/TelemetryDetailPanel.test.tsx +288 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +31 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +6 -0
- package/Tests/UI/Utils/Clipboard.test.ts +154 -0
- package/Tests/UI/Utils/Navigation.test.ts +24 -0
- package/Tests/UI/Utils/Telemetry/TelemetryEntityNames.test.ts +2205 -0
- package/Tests/UI/Utils/Telemetry/UseTelemetryEntityNames.test.tsx +844 -0
- package/Tests/Utils/AI/InvestigationReport.test.ts +2430 -0
- package/Tests/Utils/APIOutgoingRequestTracer.test.ts +137 -0
- package/Tests/Utils/Rum/SessionReplayHealth.test.ts +884 -0
- package/Tests/Utils/Rum/SessionReplayHealthDiagnosis.test.ts +40 -0
- package/Tests/Utils/Rum/SessionReplayRecordingEnded.test.ts +619 -0
- package/Tests/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.test.ts +631 -0
- package/Tests/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.test.ts +479 -0
- package/Tests/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.test.ts +507 -0
- package/Tests/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.test.ts +686 -0
- package/Tests/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.test.ts +474 -0
- package/Tests/Utils/SecurityEvent/Connectors/OktaNormalizer.test.ts +736 -0
- package/Tests/Utils/SecurityEvent/Connectors/SplunkNormalizer.test.ts +407 -0
- package/Tests/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.test.ts +129 -0
- package/Tests/Utils/Telemetry/CrossSignalScope.test.ts +57 -1
- package/Tests/Utils/Telemetry/EntityRelationship.test.ts +36 -0
- package/Tests/Utils/Telemetry/LockedFilterSearch.test.ts +600 -0
- package/Tests/Utils/Telemetry/NetworkHost.test.ts +48 -0
- package/Tests/Utils/Telemetry/OriginAllowList.test.ts +154 -0
- package/Tests/Utils/Traces/CriticalPath.test.ts +25 -0
- package/Types/AI/AIChatTypes.ts +8 -0
- package/Types/AI/InvestigationEvidence.ts +96 -0
- package/Types/Monitor/MonitorEvaluationSummary.ts +5 -0
- package/Types/OnCallDutyPolicy/Layer.ts +12 -0
- package/Types/Permission.ts +2 -2
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +12 -0
- package/Types/Rum/SessionReplay.ts +109 -0
- package/Types/Rum/SessionReplayApi.ts +31 -0
- package/Types/SecurityEvent/Connectors/ConnectorDiagnostics.ts +111 -0
- package/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.ts +87 -0
- package/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.ts +492 -0
- package/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.ts +41 -0
- package/Types/SecurityEvent/GoogleSecOpsDiagnostics.ts +56 -1
- package/Types/SecurityEvent/GoogleSecOpsRegion.ts +34 -0
- package/Types/Telemetry/EntityType.ts +14 -0
- package/Types/Telemetry/ExceptionSpanScope.ts +83 -0
- package/Types/Telemetry/LockedFilterDetail.ts +46 -0
- package/Types/Telemetry/ResourceEntityFacet.ts +17 -10
- package/Types/Telemetry/ResourceFacetCatalog.ts +171 -0
- package/UI/Components/Card/Card.tsx +118 -83
- package/UI/Components/Checkbox/Checkbox.tsx +8 -5
- package/UI/Components/CopyTextButton/CopyTextButton.tsx +7 -1
- package/UI/Components/CustomFields/CustomFieldsDetail.tsx +4 -1
- package/UI/Components/Detail/Detail.tsx +137 -22
- package/UI/Components/ErrorBoundary.tsx +38 -0
- package/UI/Components/LogsViewer/LogsEntityNames.ts +912 -0
- package/UI/Components/LogsViewer/LogsViewer.tsx +156 -77
- package/UI/Components/LogsViewer/components/ActiveFilterChips.tsx +28 -11
- package/UI/Components/LogsViewer/components/FacetSection.tsx +66 -79
- package/UI/Components/LogsViewer/components/FacetValueRow.tsx +17 -2
- package/UI/Components/LogsViewer/components/LogDetailsPanel.tsx +45 -5
- package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +100 -19
- package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +156 -39
- package/UI/Components/LogsViewer/components/LogsTable.tsx +30 -8
- package/UI/Components/LogsViewer/types.ts +6 -0
- package/UI/Components/Markdown.tsx/InlineReferences.tsx +628 -0
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +385 -312
- package/UI/Components/MemberRoleAssignment/MemberRoleAssignment.tsx +50 -22
- package/UI/Components/ModelDetail/CardModelDetail.tsx +15 -0
- package/UI/Components/ModelDetail/ModelDetail.tsx +64 -19
- package/UI/Components/ModelList/ModelList.tsx +33 -8
- package/UI/Components/Page/ModelPage.tsx +119 -54
- package/UI/Components/Table/Table.tsx +8 -0
- package/UI/Components/Table/TableRow.tsx +13 -5
- package/UI/Components/TelemetryViewer/FacetVisibility.ts +229 -0
- package/UI/Components/TelemetryViewer/ResourceFacetConfigs.ts +46 -0
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +11 -0
- package/UI/Components/TelemetryViewer/components/FacetSearchInput.tsx +79 -0
- package/UI/Components/TelemetryViewer/components/FacetSectionHeader.tsx +69 -0
- package/UI/Components/TelemetryViewer/components/FacetShowMoreButton.tsx +36 -0
- package/UI/Components/TelemetryViewer/components/HiddenFacetsFooter.tsx +88 -0
- package/UI/Components/TelemetryViewer/components/LockedFilterActions.tsx +205 -0
- package/UI/Components/TelemetryViewer/components/LockedFilterChip.tsx +496 -0
- package/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.tsx +30 -10
- package/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.tsx +203 -10
- package/UI/Components/TelemetryViewer/components/TelemetryFacetSection.tsx +60 -73
- package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +94 -7
- package/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.tsx +17 -2
- package/UI/Components/TelemetryViewer/types.ts +19 -0
- package/UI/Components/TelemetryViewer/useFacetSearchExemptions.ts +158 -0
- package/UI/Components/TelemetryViewer/useFacetSectionSearch.ts +102 -0
- package/UI/Utils/Clipboard.ts +68 -2
- package/UI/Utils/Navigation.ts +17 -2
- package/UI/Utils/Telemetry/TelemetryEntityNames.ts +620 -0
- package/UI/Utils/Telemetry/UseTelemetryEntityNames.ts +151 -0
- package/Utils/AI/InvestigationReport.ts +1789 -0
- package/Utils/API.ts +90 -1
- package/Utils/Rum/SessionReplayHealth.ts +11 -0
- package/Utils/Rum/SessionReplayRecordingEnded.ts +134 -0
- package/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.ts +427 -0
- package/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.ts +197 -0
- package/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.ts +464 -0
- package/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.ts +567 -0
- package/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.ts +299 -0
- package/Utils/SecurityEvent/Connectors/OktaNormalizer.ts +467 -0
- package/Utils/SecurityEvent/Connectors/SplunkNormalizer.ts +439 -0
- package/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.ts +124 -12
- package/Utils/Telemetry/CrossSignalScope.ts +22 -8
- package/Utils/Telemetry/EntityRelationship.ts +8 -0
- package/Utils/Telemetry/LockedFilterSearch.ts +412 -0
- package/Utils/Telemetry/NetworkHost.ts +43 -0
- package/Utils/Telemetry/OriginAllowList.ts +139 -4
- package/Utils/Traces/CriticalPath.ts +10 -4
- package/build/dist/Models/DatabaseModels/Index.js +4 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RumApplication.js +1 -1
- package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
- package/build/dist/Models/DatabaseModels/SecurityEventConnection.js +490 -0
- package/build/dist/Models/DatabaseModels/SecurityEventConnection.js.map +1 -0
- package/build/dist/Models/DatabaseModels/SecurityEventConnectionRun.js +287 -0
- package/build/dist/Models/DatabaseModels/SecurityEventConnectionRun.js.map +1 -0
- package/build/dist/Models/DatabaseModels/TelemetryIngestionKey.js +2 -2
- package/build/dist/Models/DatabaseModels/TelemetryIngestionKey.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +336 -27
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js +182 -7
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js.map +1 -1
- package/build/dist/Server/API/SecurityEventConnectionAPI.js +171 -0
- package/build/dist/Server/API/SecurityEventConnectionAPI.js.map +1 -0
- package/build/dist/Server/API/TelemetryAPI.js +248 -170
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792700000000-AddSecurityEventConnections.js +40 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792700000000-AddSecurityEventConnections.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +57 -4
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/ExceptionAggregationService.js +7 -16
- package/build/dist/Server/Services/ExceptionAggregationService.js.map +1 -1
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js +8 -0
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +4 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/InventoryItemService.js +22 -0
- package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +8 -17
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MetricAggregationService.js +4 -14
- package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
- package/build/dist/Server/Services/SecurityEventConnectionRunService.js +9 -0
- package/build/dist/Server/Services/SecurityEventConnectionRunService.js.map +1 -0
- package/build/dist/Server/Services/SecurityEventConnectionService.js +356 -0
- package/build/dist/Server/Services/SecurityEventConnectionService.js.map +1 -0
- package/build/dist/Server/Services/TraceAggregationService.js +51 -25
- package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
- package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js +9 -0
- package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +3 -0
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +14 -7
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationEvidence.js +468 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationEvidence.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationReferences.js +230 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationReferences.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/Index.js +32 -0
- package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js +6 -2
- package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +59 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +5 -3
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubClient.js +752 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.js +493 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.js +352 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.js +405 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.js +466 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.js +344 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.js +511 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.js +406 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.js +336 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.js +474 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.js +417 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.js +314 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.js +494 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.js +719 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.js +404 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.js +209 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.js +40 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.js +494 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.js +379 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Types.js +27 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Types.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js +234 -61
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.js +537 -0
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +572 -115
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js +35 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/SecurityEventDedupe.js +52 -0
- package/build/dist/Server/Utils/SecurityEvent/SecurityEventDedupe.js.map +1 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +521 -32
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +10 -0
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +8 -0
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/KubernetesResourceAttributes.js +80 -0
- package/build/dist/Server/Utils/Telemetry/KubernetesResourceAttributes.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +122 -67
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceFacetPlanner.js +146 -0
- package/build/dist/Server/Utils/Telemetry/ResourceFacetPlanner.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js +174 -248
- package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js +492 -0
- package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TraceContextPropagation.js +259 -0
- package/build/dist/Server/Utils/Telemetry/TraceContextPropagation.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry.js +11 -5
- package/build/dist/Server/Utils/Telemetry.js.map +1 -1
- package/build/dist/Types/AI/InvestigationEvidence.js +2 -0
- package/build/dist/Types/AI/InvestigationEvidence.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/Layer.js +11 -0
- package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
- package/build/dist/Types/Permission.js +2 -2
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +9 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplay.js +95 -0
- package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -1
- package/build/dist/Types/SecurityEvent/Connectors/ConnectorDiagnostics.js +18 -0
- package/build/dist/Types/SecurityEvent/Connectors/ConnectorDiagnostics.js.map +1 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.js +2 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.js.map +1 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js +374 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js.map +1 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.js +35 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.js.map +1 -0
- package/build/dist/Types/SecurityEvent/GoogleSecOpsRegion.js +35 -0
- package/build/dist/Types/SecurityEvent/GoogleSecOpsRegion.js.map +1 -0
- package/build/dist/Types/Telemetry/EntityType.js +14 -0
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/Telemetry/ExceptionSpanScope.js +59 -0
- package/build/dist/Types/Telemetry/ExceptionSpanScope.js.map +1 -0
- package/build/dist/Types/Telemetry/LockedFilterDetail.js +16 -0
- package/build/dist/Types/Telemetry/LockedFilterDetail.js.map +1 -0
- package/build/dist/Types/Telemetry/ResourceEntityFacet.js +16 -10
- package/build/dist/Types/Telemetry/ResourceEntityFacet.js.map +1 -1
- package/build/dist/Types/Telemetry/ResourceFacetCatalog.js +119 -0
- package/build/dist/Types/Telemetry/ResourceFacetCatalog.js.map +1 -0
- package/build/dist/UI/Components/Card/Card.js +34 -17
- package/build/dist/UI/Components/Card/Card.js.map +1 -1
- package/build/dist/UI/Components/Checkbox/Checkbox.js +6 -4
- package/build/dist/UI/Components/Checkbox/Checkbox.js.map +1 -1
- package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js +5 -1
- package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js.map +1 -1
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +1 -1
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
- package/build/dist/UI/Components/Detail/Detail.js +63 -13
- package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
- package/build/dist/UI/Components/ErrorBoundary.js +34 -0
- package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsEntityNames.js +535 -0
- package/build/dist/UI/Components/LogsViewer/LogsEntityNames.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +117 -57
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js +5 -7
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/FacetSection.js +31 -44
- package/build/dist/UI/Components/LogsViewer/components/FacetSection.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js +17 -3
- package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js +19 -3
- package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +64 -18
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +100 -41
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsTable.js +13 -5
- package/build/dist/UI/Components/LogsViewer/components/LogsTable.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/types.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/InlineReferences.js +403 -0
- package/build/dist/UI/Components/Markdown.tsx/InlineReferences.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +197 -179
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js +30 -21
- package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +12 -0
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/ModelDetail.js +46 -12
- package/build/dist/UI/Components/ModelDetail/ModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelList/ModelList.js +26 -7
- package/build/dist/UI/Components/ModelList/ModelList.js.map +1 -1
- package/build/dist/UI/Components/Page/ModelPage.js +62 -34
- package/build/dist/UI/Components/Page/ModelPage.js.map +1 -1
- package/build/dist/UI/Components/Table/Table.js +3 -1
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +8 -1
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js +111 -0
- package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/ResourceFacetConfigs.js +22 -0
- package/build/dist/UI/Components/TelemetryViewer/ResourceFacetConfigs.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/FacetSearchInput.js +36 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetSearchInput.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetSectionHeader.js +21 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetSectionHeader.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetShowMoreButton.js +14 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetShowMoreButton.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/HiddenFacetsFooter.js +27 -0
- package/build/dist/UI/Components/TelemetryViewer/components/HiddenFacetsFooter.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterActions.js +88 -0
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterActions.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js +228 -0
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.js +6 -6
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.js +111 -12
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSection.js +27 -40
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSection.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +70 -10
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js +17 -3
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/types.js +0 -4
- package/build/dist/UI/Components/TelemetryViewer/types.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/useFacetSearchExemptions.js +70 -0
- package/build/dist/UI/Components/TelemetryViewer/useFacetSearchExemptions.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/useFacetSectionSearch.js +52 -0
- package/build/dist/UI/Components/TelemetryViewer/useFacetSectionSearch.js.map +1 -0
- package/build/dist/UI/Utils/Clipboard.js +59 -2
- package/build/dist/UI/Utils/Clipboard.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js +11 -2
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js +471 -0
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js.map +1 -0
- package/build/dist/UI/Utils/Telemetry/UseTelemetryEntityNames.js +113 -0
- package/build/dist/UI/Utils/Telemetry/UseTelemetryEntityNames.js.map +1 -0
- package/build/dist/Utils/AI/InvestigationReport.js +1241 -0
- package/build/dist/Utils/AI/InvestigationReport.js.map +1 -0
- package/build/dist/Utils/API.js +25 -0
- package/build/dist/Utils/API.js.map +1 -1
- package/build/dist/Utils/Rum/SessionReplayHealth.js +10 -0
- package/build/dist/Utils/Rum/SessionReplayHealth.js.map +1 -1
- package/build/dist/Utils/Rum/SessionReplayRecordingEnded.js +54 -0
- package/build/dist/Utils/Rum/SessionReplayRecordingEnded.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.js +311 -0
- package/build/dist/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.js +150 -0
- package/build/dist/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.js +328 -0
- package/build/dist/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.js +405 -0
- package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.js +212 -0
- package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/OktaNormalizer.js +351 -0
- package/build/dist/Utils/SecurityEvent/Connectors/OktaNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/SplunkNormalizer.js +348 -0
- package/build/dist/Utils/SecurityEvent/Connectors/SplunkNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js +103 -10
- package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js.map +1 -1
- package/build/dist/Utils/Telemetry/CrossSignalScope.js +16 -5
- package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -1
- package/build/dist/Utils/Telemetry/EntityRelationship.js +7 -0
- package/build/dist/Utils/Telemetry/EntityRelationship.js.map +1 -1
- package/build/dist/Utils/Telemetry/LockedFilterSearch.js +277 -0
- package/build/dist/Utils/Telemetry/LockedFilterSearch.js.map +1 -0
- package/build/dist/Utils/Telemetry/NetworkHost.js +39 -0
- package/build/dist/Utils/Telemetry/NetworkHost.js.map +1 -0
- package/build/dist/Utils/Telemetry/OriginAllowList.js +105 -4
- package/build/dist/Utils/Telemetry/OriginAllowList.js.map +1 -1
- package/build/dist/Utils/Traces/CriticalPath.js +9 -4
- package/build/dist/Utils/Traces/CriticalPath.js.map +1 -1
- package/package.json +1 -1
- package/Tests/UI/Rum/RecordingHealthStrip.test.tsx +0 -600
- package/UI/Components/GanttChart/Bar/BarLabel.tsx +0 -17
- package/UI/Components/GanttChart/Bar/Index.tsx +0 -149
- package/UI/Components/GanttChart/ChartContainer.tsx +0 -50
- package/UI/Components/GanttChart/Index.tsx +0 -90
- package/UI/Components/GanttChart/Row/Index.tsx +0 -22
- package/UI/Components/GanttChart/Row/Row.tsx +0 -231
- package/UI/Components/GanttChart/Row/RowLabel.tsx +0 -30
- package/UI/Components/GanttChart/Rows.tsx +0 -59
- package/UI/Components/GanttChart/Timeline/Index.tsx +0 -46
- package/UI/Components/GanttChart/Timeline/TimelineInterval.tsx +0 -33
- package/UI/Components/GanttChart/Timeline/TimelineIntervalMarks.tsx +0 -43
- package/build/dist/UI/Components/GanttChart/Bar/BarLabel.js +0 -8
- package/build/dist/UI/Components/GanttChart/Bar/BarLabel.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Bar/Index.js +0 -77
- package/build/dist/UI/Components/GanttChart/Bar/Index.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/ChartContainer.js +0 -33
- package/build/dist/UI/Components/GanttChart/ChartContainer.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Index.js +0 -39
- package/build/dist/UI/Components/GanttChart/Index.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Row/Index.js +0 -7
- package/build/dist/UI/Components/GanttChart/Row/Index.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Row/Row.js +0 -106
- package/build/dist/UI/Components/GanttChart/Row/Row.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Row/RowLabel.js +0 -10
- package/build/dist/UI/Components/GanttChart/Row/RowLabel.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Rows.js +0 -19
- package/build/dist/UI/Components/GanttChart/Rows.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Timeline/Index.js +0 -16
- package/build/dist/UI/Components/GanttChart/Timeline/Index.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Timeline/TimelineInterval.js +0 -13
- package/build/dist/UI/Components/GanttChart/Timeline/TimelineInterval.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Timeline/TimelineIntervalMarks.js +0 -13
- package/build/dist/UI/Components/GanttChart/Timeline/TimelineIntervalMarks.js.map +0 -1
|
@@ -0,0 +1,830 @@
|
|
|
1
|
+
import APIException from "../../../../../Types/Exception/ApiException";
|
|
2
|
+
import BadDataException from "../../../../../Types/Exception/BadDataException";
|
|
3
|
+
import { JSONObject, JSONValue } from "../../../../../Types/JSON";
|
|
4
|
+
import {
|
|
5
|
+
DataSourceHttpRequest,
|
|
6
|
+
DataSourceHttpResponse,
|
|
7
|
+
} from "../../../DataSource/HttpFetch";
|
|
8
|
+
import { redactLogString, redactLogValue } from "../../../LogRedaction";
|
|
9
|
+
import { ConnectorTransport } from "../Types";
|
|
10
|
+
|
|
11
|
+
/*
|
|
12
|
+
* Microsoft Sentinel HTTP client: Microsoft Entra client-credentials token
|
|
13
|
+
* plus the Azure Resource Manager (ARM) incidents list.
|
|
14
|
+
*
|
|
15
|
+
* Contracts this file relies on, verified against Microsoft's reference:
|
|
16
|
+
* - Token: POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
|
|
17
|
+
* with a form body grant_type=client_credentials, client_id,
|
|
18
|
+
* client_secret, scope=<resource>/.default; success carries
|
|
19
|
+
* access_token + expires_in, failure carries error + error_description.
|
|
20
|
+
* https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-client-creds-grant-flow
|
|
21
|
+
* - Incidents: GET {arm}/subscriptions/{sub}/resourceGroups/{rg}/providers/
|
|
22
|
+
* Microsoft.OperationalInsights/workspaces/{ws}/providers/
|
|
23
|
+
* Microsoft.SecurityInsights/incidents?api-version=2024-03-01 with
|
|
24
|
+
* optional $filter, $orderby, $top (max 1000) and $skipToken; the
|
|
25
|
+
* response is { value: Incident[], nextLink?: string } where nextLink
|
|
26
|
+
* is the absolute URL of the next page (it carries the skip token).
|
|
27
|
+
* https://learn.microsoft.com/en-us/rest/api/securityinsights/incidents/list?view=rest-securityinsights-2024-03-01
|
|
28
|
+
* - Azure Government hosts: login.microsoftonline.us for Entra and
|
|
29
|
+
* management.usgovcloudapi.net for ARM.
|
|
30
|
+
* https://learn.microsoft.com/en-us/azure/azure-government/compare-azure-government-global-azure
|
|
31
|
+
*
|
|
32
|
+
* Every request goes through the injected ConnectorTransport (the
|
|
33
|
+
* SSRF-guarded DataSourceHttpFetch in production), carries the caller's
|
|
34
|
+
* timeout, and is additionally raced against a local deadline so a
|
|
35
|
+
* transport that never settles cannot pin a poll. Every error is an
|
|
36
|
+
* APIException whose prefix names the step ("token request" or
|
|
37
|
+
* "incidents list") and whose body excerpt has been through redaction, so
|
|
38
|
+
* the message can be stored on the connection row and shown in the UI.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
export type MicrosoftSentinelCloud = "public" | "usgov";
|
|
42
|
+
|
|
43
|
+
export interface MicrosoftSentinelCloudEndpoints {
|
|
44
|
+
// Base of the Entra token endpoint, e.g. https://login.microsoftonline.com
|
|
45
|
+
loginBaseUrl: string;
|
|
46
|
+
// Base of Azure Resource Manager, e.g. https://management.azure.com
|
|
47
|
+
managementBaseUrl: string;
|
|
48
|
+
// Where a person opens the incident; used in remediation text only.
|
|
49
|
+
portalHost: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const MICROSOFT_SENTINEL_CLOUD_ENDPOINTS: Record<
|
|
53
|
+
MicrosoftSentinelCloud,
|
|
54
|
+
MicrosoftSentinelCloudEndpoints
|
|
55
|
+
> = {
|
|
56
|
+
public: {
|
|
57
|
+
loginBaseUrl: "https://login.microsoftonline.com",
|
|
58
|
+
managementBaseUrl: "https://management.azure.com",
|
|
59
|
+
portalHost: "portal.azure.com",
|
|
60
|
+
},
|
|
61
|
+
usgov: {
|
|
62
|
+
loginBaseUrl: "https://login.microsoftonline.us",
|
|
63
|
+
managementBaseUrl: "https://management.usgovcloudapi.net",
|
|
64
|
+
portalHost: "portal.azure.us",
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const MICROSOFT_SENTINEL_API_VERSION: string = "2024-03-01";
|
|
69
|
+
|
|
70
|
+
/*
|
|
71
|
+
* Page size for polling. The API allows up to 1000, but each incident is a
|
|
72
|
+
* few kilobytes and the transport caps response size; 50 keeps a page
|
|
73
|
+
* comfortably inside that cap while a 20-request budget still covers a
|
|
74
|
+
* thousand incidents per poll.
|
|
75
|
+
*/
|
|
76
|
+
export const MICROSOFT_SENTINEL_DEFAULT_PAGE_SIZE: number = 50;
|
|
77
|
+
export const MICROSOFT_SENTINEL_MAX_PAGE_SIZE: number = 1000;
|
|
78
|
+
|
|
79
|
+
export const MICROSOFT_SENTINEL_DEFAULT_REQUEST_TIMEOUT_IN_MS: number =
|
|
80
|
+
60 * 1000;
|
|
81
|
+
|
|
82
|
+
// Refresh a cached token this long before Entra says it expires.
|
|
83
|
+
const TOKEN_EXPIRY_SKEW_IN_MS: number = 60 * 1000;
|
|
84
|
+
|
|
85
|
+
const TOKEN_STEP: string = "token request";
|
|
86
|
+
const INCIDENTS_STEP: string = "incidents list";
|
|
87
|
+
|
|
88
|
+
const GUID_REGEX: RegExp =
|
|
89
|
+
/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
90
|
+
|
|
91
|
+
/*
|
|
92
|
+
* Entra accepts the tenant as a GUID or as a verified domain name
|
|
93
|
+
* (contoso.onmicrosoft.com). Anything with a slash, a space or a query
|
|
94
|
+
* character is refused because the value is interpolated into a URL path.
|
|
95
|
+
*/
|
|
96
|
+
const TENANT_DOMAIN_REGEX: RegExp =
|
|
97
|
+
/^[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?(?:\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)+$/;
|
|
98
|
+
|
|
99
|
+
/*
|
|
100
|
+
* Azure resource group names: 1-90 characters of letters, digits,
|
|
101
|
+
* underscores, hyphens, periods and parentheses, not ending in a period.
|
|
102
|
+
* https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-name-rules
|
|
103
|
+
*/
|
|
104
|
+
const RESOURCE_GROUP_REGEX: RegExp = /^[-\w._()]{1,90}$/;
|
|
105
|
+
|
|
106
|
+
/*
|
|
107
|
+
* Workspace name pattern from the incidents API's URI parameter table:
|
|
108
|
+
* ^[A-Za-z0-9][A-Za-z0-9-]+[A-Za-z0-9]$, 1-90 characters.
|
|
109
|
+
*/
|
|
110
|
+
const WORKSPACE_NAME_REGEX: RegExp = /^[A-Za-z0-9][A-Za-z0-9-]+[A-Za-z0-9]$/;
|
|
111
|
+
|
|
112
|
+
// The shape DataSourceHttpFetch throws for a non-2xx answer.
|
|
113
|
+
const TRANSPORT_HTTP_ERROR_REGEX: RegExp =
|
|
114
|
+
/^Data source responded with HTTP (\d{3}):\s*([\s\S]*)$/;
|
|
115
|
+
|
|
116
|
+
export interface MicrosoftSentinelClientOptions {
|
|
117
|
+
tenantId: string;
|
|
118
|
+
clientId: string;
|
|
119
|
+
clientSecret: string;
|
|
120
|
+
subscriptionId: string;
|
|
121
|
+
resourceGroup: string;
|
|
122
|
+
workspaceName: string;
|
|
123
|
+
cloud: MicrosoftSentinelCloud;
|
|
124
|
+
transport: ConnectorTransport;
|
|
125
|
+
requestTimeoutInMs?: number | undefined;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface MicrosoftSentinelIncidentsPage {
|
|
129
|
+
incidents: Array<JSONObject>;
|
|
130
|
+
// Absolute URL of the next page, or null when this was the last page.
|
|
131
|
+
nextLink: string | null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface MicrosoftSentinelIncidentCount {
|
|
135
|
+
// Incidents on the first page (bounded by the page size asked for).
|
|
136
|
+
count: number;
|
|
137
|
+
// True when the API offered a further page, i.e. the real count is larger.
|
|
138
|
+
hasMore: boolean;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
interface CachedToken {
|
|
142
|
+
accessToken: string;
|
|
143
|
+
expiresAtMs: number;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
interface AcquiredToken {
|
|
147
|
+
accessToken: string;
|
|
148
|
+
// True when the token came from the cache rather than a fresh request.
|
|
149
|
+
fromCache: boolean;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export default class MicrosoftSentinelClient {
|
|
153
|
+
private options: MicrosoftSentinelClientOptions;
|
|
154
|
+
private endpoints: MicrosoftSentinelCloudEndpoints;
|
|
155
|
+
private requestTimeoutInMs: number;
|
|
156
|
+
private cachedToken: CachedToken | null = null;
|
|
157
|
+
private requestCount: number = 0;
|
|
158
|
+
|
|
159
|
+
public constructor(options: MicrosoftSentinelClientOptions) {
|
|
160
|
+
MicrosoftSentinelClient.validateTenantId(options.tenantId);
|
|
161
|
+
MicrosoftSentinelClient.validateGuid(
|
|
162
|
+
options.clientId,
|
|
163
|
+
"Application (client) ID",
|
|
164
|
+
);
|
|
165
|
+
MicrosoftSentinelClient.validateGuid(
|
|
166
|
+
options.subscriptionId,
|
|
167
|
+
"Subscription ID",
|
|
168
|
+
);
|
|
169
|
+
MicrosoftSentinelClient.validateResourceGroup(options.resourceGroup);
|
|
170
|
+
MicrosoftSentinelClient.validateWorkspaceName(options.workspaceName);
|
|
171
|
+
|
|
172
|
+
if (!options.clientSecret) {
|
|
173
|
+
throw new BadDataException("Client secret is required.");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
this.options = options;
|
|
177
|
+
this.endpoints = MicrosoftSentinelClient.resolveCloud(options.cloud);
|
|
178
|
+
this.requestTimeoutInMs =
|
|
179
|
+
options.requestTimeoutInMs && options.requestTimeoutInMs > 0
|
|
180
|
+
? options.requestTimeoutInMs
|
|
181
|
+
: MICROSOFT_SENTINEL_DEFAULT_REQUEST_TIMEOUT_IN_MS;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Every outbound request this instance made, token requests included.
|
|
185
|
+
public getRequestCount(): number {
|
|
186
|
+
return this.requestCount;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/*
|
|
190
|
+
* ---------------------------------------------------------------------
|
|
191
|
+
* Validation (shared with the connector's validateSettings)
|
|
192
|
+
* ---------------------------------------------------------------------
|
|
193
|
+
*/
|
|
194
|
+
|
|
195
|
+
public static isCloud(value: string): value is MicrosoftSentinelCloud {
|
|
196
|
+
return value === "public" || value === "usgov";
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
public static resolveCloud(
|
|
200
|
+
cloud: string | undefined,
|
|
201
|
+
): MicrosoftSentinelCloudEndpoints {
|
|
202
|
+
const normalized: string = (cloud || "public").trim().toLowerCase();
|
|
203
|
+
|
|
204
|
+
if (!MicrosoftSentinelClient.isCloud(normalized)) {
|
|
205
|
+
throw new BadDataException(
|
|
206
|
+
`Cloud must be "public" or "usgov"; received "${normalized}".`,
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return MICROSOFT_SENTINEL_CLOUD_ENDPOINTS[normalized];
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
public static validateGuid(value: string, label: string): void {
|
|
214
|
+
if (!value || !GUID_REGEX.test(value.trim())) {
|
|
215
|
+
throw new BadDataException(
|
|
216
|
+
`${label} must be a GUID such as 00000000-0000-0000-0000-000000000000.`,
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
public static validateTenantId(value: string): void {
|
|
222
|
+
const trimmed: string = (value || "").trim();
|
|
223
|
+
|
|
224
|
+
if (
|
|
225
|
+
!trimmed ||
|
|
226
|
+
(!GUID_REGEX.test(trimmed) && !TENANT_DOMAIN_REGEX.test(trimmed))
|
|
227
|
+
) {
|
|
228
|
+
throw new BadDataException(
|
|
229
|
+
"Directory (tenant) ID must be the tenant GUID or a verified tenant domain such as contoso.onmicrosoft.com.",
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
public static validateResourceGroup(value: string): void {
|
|
235
|
+
const trimmed: string = (value || "").trim();
|
|
236
|
+
|
|
237
|
+
if (
|
|
238
|
+
!trimmed ||
|
|
239
|
+
!RESOURCE_GROUP_REGEX.test(trimmed) ||
|
|
240
|
+
trimmed.endsWith(".")
|
|
241
|
+
) {
|
|
242
|
+
throw new BadDataException(
|
|
243
|
+
"Resource group must be 1-90 characters of letters, digits, underscores, hyphens, periods or parentheses and must not end with a period.",
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
public static validateWorkspaceName(value: string): void {
|
|
249
|
+
const trimmed: string = (value || "").trim();
|
|
250
|
+
|
|
251
|
+
if (
|
|
252
|
+
!trimmed ||
|
|
253
|
+
trimmed.length > 90 ||
|
|
254
|
+
!WORKSPACE_NAME_REGEX.test(trimmed)
|
|
255
|
+
) {
|
|
256
|
+
throw new BadDataException(
|
|
257
|
+
"Workspace name must be 3-90 letters, digits or hyphens, starting and ending with a letter or digit.",
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/*
|
|
263
|
+
* ---------------------------------------------------------------------
|
|
264
|
+
* URLs
|
|
265
|
+
* ---------------------------------------------------------------------
|
|
266
|
+
*/
|
|
267
|
+
|
|
268
|
+
public getTokenUrl(): string {
|
|
269
|
+
return `${this.endpoints.loginBaseUrl}/${encodeURIComponent(
|
|
270
|
+
this.options.tenantId.trim(),
|
|
271
|
+
)}/oauth2/v2.0/token`;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/*
|
|
275
|
+
* The ARM resource for the token: the management host with the ".default"
|
|
276
|
+
* suffix, so the same client works in Azure Government where ARM is a
|
|
277
|
+
* different resource (https://management.usgovcloudapi.net/.default).
|
|
278
|
+
*/
|
|
279
|
+
public getTokenScope(): string {
|
|
280
|
+
return `${this.endpoints.managementBaseUrl}/.default`;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
public getIncidentsBaseUrl(): string {
|
|
284
|
+
return (
|
|
285
|
+
`${this.endpoints.managementBaseUrl}/subscriptions/${encodeURIComponent(
|
|
286
|
+
this.options.subscriptionId.trim(),
|
|
287
|
+
)}` +
|
|
288
|
+
`/resourceGroups/${encodeURIComponent(this.options.resourceGroup.trim())}` +
|
|
289
|
+
`/providers/Microsoft.OperationalInsights/workspaces/${encodeURIComponent(
|
|
290
|
+
this.options.workspaceName.trim(),
|
|
291
|
+
)}` +
|
|
292
|
+
`/providers/Microsoft.SecurityInsights/incidents`
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/*
|
|
297
|
+
* First-page URL for incidents CREATED in [startTime, endTime), oldest
|
|
298
|
+
* first. Creation time is the poll basis (see Connectors/Types.ts): a
|
|
299
|
+
* cursor over createdTimeUtc never skips an incident whose alerts
|
|
300
|
+
* describe activity from hours earlier.
|
|
301
|
+
*/
|
|
302
|
+
public buildIncidentsUrl(data: {
|
|
303
|
+
startTime: Date;
|
|
304
|
+
endTime: Date;
|
|
305
|
+
top: number;
|
|
306
|
+
}): string {
|
|
307
|
+
const top: number = MicrosoftSentinelClient.clampPageSize(data.top);
|
|
308
|
+
const url: URL = new URL(this.getIncidentsBaseUrl());
|
|
309
|
+
url.searchParams.set("api-version", MICROSOFT_SENTINEL_API_VERSION);
|
|
310
|
+
url.searchParams.set(
|
|
311
|
+
"$filter",
|
|
312
|
+
`(properties/createdTimeUtc ge ${data.startTime.toISOString()}) and (properties/createdTimeUtc lt ${data.endTime.toISOString()})`,
|
|
313
|
+
);
|
|
314
|
+
url.searchParams.set("$orderby", "properties/createdTimeUtc asc");
|
|
315
|
+
url.searchParams.set("$top", String(top));
|
|
316
|
+
|
|
317
|
+
return url.toString();
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
public static clampPageSize(value: number | undefined): number {
|
|
321
|
+
if (!value || !Number.isFinite(value)) {
|
|
322
|
+
return MICROSOFT_SENTINEL_DEFAULT_PAGE_SIZE;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return Math.min(
|
|
326
|
+
MICROSOFT_SENTINEL_MAX_PAGE_SIZE,
|
|
327
|
+
Math.max(1, Math.floor(value)),
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/*
|
|
332
|
+
* ---------------------------------------------------------------------
|
|
333
|
+
* Token
|
|
334
|
+
* ---------------------------------------------------------------------
|
|
335
|
+
*/
|
|
336
|
+
|
|
337
|
+
public async getAccessToken(): Promise<string> {
|
|
338
|
+
return (await this.acquireToken()).accessToken;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
private async acquireToken(): Promise<AcquiredToken> {
|
|
342
|
+
if (
|
|
343
|
+
this.cachedToken &&
|
|
344
|
+
this.cachedToken.expiresAtMs - TOKEN_EXPIRY_SKEW_IN_MS > Date.now()
|
|
345
|
+
) {
|
|
346
|
+
return { accessToken: this.cachedToken.accessToken, fromCache: true };
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const response: DataSourceHttpResponse = await this.send(
|
|
350
|
+
{
|
|
351
|
+
method: "POST",
|
|
352
|
+
url: this.getTokenUrl(),
|
|
353
|
+
headers: { Accept: "application/json" },
|
|
354
|
+
formUrlEncoded: true,
|
|
355
|
+
body: {
|
|
356
|
+
grant_type: "client_credentials",
|
|
357
|
+
client_id: this.options.clientId.trim(),
|
|
358
|
+
client_secret: this.options.clientSecret,
|
|
359
|
+
scope: this.getTokenScope(),
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
TOKEN_STEP,
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
const body: JSONObject = this.requireJsonObject(response, TOKEN_STEP);
|
|
366
|
+
const accessToken: unknown = body["access_token"];
|
|
367
|
+
|
|
368
|
+
if (typeof accessToken !== "string" || !accessToken) {
|
|
369
|
+
throw new APIException(
|
|
370
|
+
`Microsoft Sentinel ${TOKEN_STEP} returned no access_token: ${MicrosoftSentinelClient.describeBody(
|
|
371
|
+
response,
|
|
372
|
+
)}`,
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const expiresInRaw: unknown = body["expires_in"];
|
|
377
|
+
const expiresInSeconds: number =
|
|
378
|
+
typeof expiresInRaw === "number"
|
|
379
|
+
? expiresInRaw
|
|
380
|
+
: Number(expiresInRaw || 0);
|
|
381
|
+
|
|
382
|
+
this.cachedToken = {
|
|
383
|
+
accessToken,
|
|
384
|
+
expiresAtMs:
|
|
385
|
+
Date.now() +
|
|
386
|
+
(Number.isFinite(expiresInSeconds) && expiresInSeconds > 0
|
|
387
|
+
? expiresInSeconds * 1000
|
|
388
|
+
: 5 * 60 * 1000),
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
return { accessToken, fromCache: false };
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/*
|
|
395
|
+
* ---------------------------------------------------------------------
|
|
396
|
+
* Incidents
|
|
397
|
+
* ---------------------------------------------------------------------
|
|
398
|
+
*/
|
|
399
|
+
|
|
400
|
+
/*
|
|
401
|
+
* One page of incidents. Pass `nextLink` from the previous page to
|
|
402
|
+
* continue; the window parameters are ignored then because ARM encodes
|
|
403
|
+
* the whole query (filter, order, skip token) inside the link.
|
|
404
|
+
*/
|
|
405
|
+
public async listIncidents(data: {
|
|
406
|
+
startTime: Date;
|
|
407
|
+
endTime: Date;
|
|
408
|
+
top?: number | undefined;
|
|
409
|
+
nextLink?: string | null | undefined;
|
|
410
|
+
}): Promise<MicrosoftSentinelIncidentsPage> {
|
|
411
|
+
const url: string = data.nextLink
|
|
412
|
+
? this.assertNextLink(data.nextLink)
|
|
413
|
+
: this.buildIncidentsUrl({
|
|
414
|
+
startTime: data.startTime,
|
|
415
|
+
endTime: data.endTime,
|
|
416
|
+
top: data.top || MICROSOFT_SENTINEL_DEFAULT_PAGE_SIZE,
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
let token: AcquiredToken = await this.acquireToken();
|
|
420
|
+
let response: DataSourceHttpResponse = await this.sendRaw(
|
|
421
|
+
MicrosoftSentinelClient.incidentsRequest(url, token.accessToken),
|
|
422
|
+
INCIDENTS_STEP,
|
|
423
|
+
);
|
|
424
|
+
|
|
425
|
+
/*
|
|
426
|
+
* A cached token can be revoked (secret rotated, app registration
|
|
427
|
+
* removed) or expire between pages of one run. One retry with a
|
|
428
|
+
* freshly minted token separates "the token went stale" from "ARM does
|
|
429
|
+
* not accept tokens from this app" without ever looping: a fresh
|
|
430
|
+
* token that is refused fails below like any other 401.
|
|
431
|
+
*/
|
|
432
|
+
if (response.statusCode === 401 && token.fromCache) {
|
|
433
|
+
this.cachedToken = null;
|
|
434
|
+
token = await this.acquireToken();
|
|
435
|
+
response = await this.sendRaw(
|
|
436
|
+
MicrosoftSentinelClient.incidentsRequest(url, token.accessToken),
|
|
437
|
+
INCIDENTS_STEP,
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
this.assertOk(response, INCIDENTS_STEP);
|
|
442
|
+
|
|
443
|
+
const body: JSONObject = this.requireJsonObject(response, INCIDENTS_STEP);
|
|
444
|
+
const value: unknown = body["value"];
|
|
445
|
+
|
|
446
|
+
if (!Array.isArray(value)) {
|
|
447
|
+
throw new APIException(
|
|
448
|
+
`Microsoft Sentinel ${INCIDENTS_STEP} returned an unrecognized response shape: expected a "value" array, received keys ${MicrosoftSentinelClient.describeKeys(
|
|
449
|
+
body,
|
|
450
|
+
)}.`,
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
const incidents: Array<JSONObject> = (value as Array<JSONValue>).filter(
|
|
455
|
+
(item: JSONValue): boolean => {
|
|
456
|
+
return Boolean(
|
|
457
|
+
item && typeof item === "object" && !Array.isArray(item),
|
|
458
|
+
);
|
|
459
|
+
},
|
|
460
|
+
) as Array<JSONObject>;
|
|
461
|
+
|
|
462
|
+
const nextLinkRaw: unknown = body["nextLink"];
|
|
463
|
+
const nextLink: string | null =
|
|
464
|
+
typeof nextLinkRaw === "string" && nextLinkRaw.trim()
|
|
465
|
+
? nextLinkRaw.trim()
|
|
466
|
+
: null;
|
|
467
|
+
|
|
468
|
+
return { incidents, nextLink };
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/*
|
|
472
|
+
* Bounded availability count: one page of `top` incidents created in the
|
|
473
|
+
* window plus whether a further page exists. Never walks the pages — a
|
|
474
|
+
* count is for the test checklist, not for import.
|
|
475
|
+
*/
|
|
476
|
+
public async countIncidentsCreated(data: {
|
|
477
|
+
startTime: Date;
|
|
478
|
+
endTime: Date;
|
|
479
|
+
top?: number | undefined;
|
|
480
|
+
}): Promise<MicrosoftSentinelIncidentCount> {
|
|
481
|
+
const page: MicrosoftSentinelIncidentsPage = await this.listIncidents({
|
|
482
|
+
startTime: data.startTime,
|
|
483
|
+
endTime: data.endTime,
|
|
484
|
+
top: data.top || MICROSOFT_SENTINEL_DEFAULT_PAGE_SIZE,
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
return {
|
|
488
|
+
count: page.incidents.length,
|
|
489
|
+
hasMore: page.nextLink !== null,
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/*
|
|
494
|
+
* ---------------------------------------------------------------------
|
|
495
|
+
* Transport plumbing
|
|
496
|
+
* ---------------------------------------------------------------------
|
|
497
|
+
*/
|
|
498
|
+
|
|
499
|
+
private static incidentsRequest(
|
|
500
|
+
url: string,
|
|
501
|
+
accessToken: string,
|
|
502
|
+
): DataSourceHttpRequest {
|
|
503
|
+
return {
|
|
504
|
+
method: "GET",
|
|
505
|
+
url,
|
|
506
|
+
headers: {
|
|
507
|
+
Authorization: `Bearer ${accessToken}`,
|
|
508
|
+
Accept: "application/json",
|
|
509
|
+
},
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/*
|
|
514
|
+
* nextLink is server-supplied. It is followed only when it stays on the
|
|
515
|
+
* configured ARM host over https: a link elsewhere would let a
|
|
516
|
+
* compromised or misconfigured endpoint steer the bearer token to a
|
|
517
|
+
* host of its choosing. The egress guard would still vet the host, but
|
|
518
|
+
* the token must not leave ARM regardless.
|
|
519
|
+
*/
|
|
520
|
+
private assertNextLink(nextLink: string): string {
|
|
521
|
+
let parsed: URL;
|
|
522
|
+
|
|
523
|
+
try {
|
|
524
|
+
parsed = new URL(nextLink);
|
|
525
|
+
} catch {
|
|
526
|
+
throw new APIException(
|
|
527
|
+
`Microsoft Sentinel ${INCIDENTS_STEP} returned an unusable nextLink: ${redactLogString(
|
|
528
|
+
nextLink.substring(0, 200),
|
|
529
|
+
)}`,
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
const expected: URL = new URL(this.endpoints.managementBaseUrl);
|
|
534
|
+
|
|
535
|
+
if (parsed.protocol !== "https:" || parsed.host !== expected.host) {
|
|
536
|
+
throw new APIException(
|
|
537
|
+
`Microsoft Sentinel ${INCIDENTS_STEP} returned a nextLink on an unexpected host: ${redactLogString(
|
|
538
|
+
parsed.host,
|
|
539
|
+
)} (expected ${expected.host}).`,
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
return parsed.toString();
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// Send and require a 2xx answer.
|
|
547
|
+
private async send(
|
|
548
|
+
request: DataSourceHttpRequest,
|
|
549
|
+
stepLabel: string,
|
|
550
|
+
): Promise<DataSourceHttpResponse> {
|
|
551
|
+
const response: DataSourceHttpResponse = await this.sendRaw(
|
|
552
|
+
request,
|
|
553
|
+
stepLabel,
|
|
554
|
+
);
|
|
555
|
+
|
|
556
|
+
this.assertOk(response, stepLabel);
|
|
557
|
+
|
|
558
|
+
return response;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/*
|
|
562
|
+
* Send and return whatever status came back, so a caller can react to a
|
|
563
|
+
* 401 before the status is turned into an error. Transport failures
|
|
564
|
+
* that carry an HTTP status are folded into a response; everything else
|
|
565
|
+
* (connection refused, the transport's own timeout, the local deadline)
|
|
566
|
+
* throws with the step in the prefix.
|
|
567
|
+
*/
|
|
568
|
+
private async sendRaw(
|
|
569
|
+
request: DataSourceHttpRequest,
|
|
570
|
+
stepLabel: string,
|
|
571
|
+
): Promise<DataSourceHttpResponse> {
|
|
572
|
+
this.requestCount++;
|
|
573
|
+
|
|
574
|
+
const timeoutSeconds: number = Math.max(
|
|
575
|
+
1,
|
|
576
|
+
Math.round(this.requestTimeoutInMs / 1000),
|
|
577
|
+
);
|
|
578
|
+
let timer: ReturnType<typeof setTimeout> | undefined = undefined;
|
|
579
|
+
|
|
580
|
+
const deadline: Promise<never> = new Promise(
|
|
581
|
+
(
|
|
582
|
+
_resolve: (value: never | PromiseLike<never>) => void,
|
|
583
|
+
reject: (reason?: unknown) => void,
|
|
584
|
+
): void => {
|
|
585
|
+
timer = setTimeout((): void => {
|
|
586
|
+
reject(
|
|
587
|
+
new APIException(
|
|
588
|
+
`Microsoft Sentinel ${stepLabel} timed out after ${timeoutSeconds} seconds with no response.`,
|
|
589
|
+
),
|
|
590
|
+
);
|
|
591
|
+
}, this.requestTimeoutInMs);
|
|
592
|
+
},
|
|
593
|
+
);
|
|
594
|
+
|
|
595
|
+
try {
|
|
596
|
+
return await Promise.race([
|
|
597
|
+
this.options.transport({
|
|
598
|
+
...request,
|
|
599
|
+
timeoutInMs: this.requestTimeoutInMs,
|
|
600
|
+
}),
|
|
601
|
+
deadline,
|
|
602
|
+
]);
|
|
603
|
+
} catch (error) {
|
|
604
|
+
return this.recoverResponse(error, stepLabel);
|
|
605
|
+
} finally {
|
|
606
|
+
clearTimeout(timer);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
private assertOk(response: DataSourceHttpResponse, stepLabel: string): void {
|
|
611
|
+
if (response.statusCode >= 200 && response.statusCode < 300) {
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
throw new APIException(
|
|
616
|
+
`Microsoft Sentinel ${stepLabel} failed (HTTP ${response.statusCode}): ${MicrosoftSentinelClient.describeBody(
|
|
617
|
+
response,
|
|
618
|
+
)}${MicrosoftSentinelClient.hintForFailure(
|
|
619
|
+
stepLabel,
|
|
620
|
+
response.statusCode,
|
|
621
|
+
response.bodyJson,
|
|
622
|
+
)}`,
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/*
|
|
627
|
+
* The production transport does not return error statuses — it throws
|
|
628
|
+
* `Data source responded with HTTP <status>: <body>`. Recover the status
|
|
629
|
+
* so the operator sees the same "(HTTP 403)" prefix whichever transport
|
|
630
|
+
* is behind the client, and the docs' troubleshooting keys stay true.
|
|
631
|
+
*/
|
|
632
|
+
private recoverResponse(
|
|
633
|
+
error: unknown,
|
|
634
|
+
stepLabel: string,
|
|
635
|
+
): DataSourceHttpResponse {
|
|
636
|
+
if (error instanceof APIException) {
|
|
637
|
+
throw error;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
const message: string =
|
|
641
|
+
error instanceof Error ? error.message : String(error || "");
|
|
642
|
+
const match: RegExpMatchArray | null = message.match(
|
|
643
|
+
TRANSPORT_HTTP_ERROR_REGEX,
|
|
644
|
+
);
|
|
645
|
+
|
|
646
|
+
if (match) {
|
|
647
|
+
const bodyText: string = match[2] || "";
|
|
648
|
+
let bodyJson: unknown = undefined;
|
|
649
|
+
|
|
650
|
+
try {
|
|
651
|
+
bodyJson = JSON.parse(bodyText);
|
|
652
|
+
} catch {
|
|
653
|
+
bodyJson = undefined;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
return { statusCode: Number(match[1]), bodyText, bodyJson };
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
throw new APIException(
|
|
660
|
+
`Microsoft Sentinel ${stepLabel} failed: ${redactLogString(
|
|
661
|
+
message || "unknown transport error",
|
|
662
|
+
).substring(0, 500)}`,
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
private requireJsonObject(
|
|
667
|
+
response: DataSourceHttpResponse,
|
|
668
|
+
stepLabel: string,
|
|
669
|
+
): JSONObject {
|
|
670
|
+
const body: unknown = response.bodyJson;
|
|
671
|
+
|
|
672
|
+
if (body === undefined || body === null) {
|
|
673
|
+
throw new APIException(
|
|
674
|
+
`Microsoft Sentinel ${stepLabel} returned a non-JSON body: ${redactLogString(
|
|
675
|
+
(response.bodyText || "").substring(0, 200),
|
|
676
|
+
)}`,
|
|
677
|
+
);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
if (typeof body !== "object" || Array.isArray(body)) {
|
|
681
|
+
throw new APIException(
|
|
682
|
+
`Microsoft Sentinel ${stepLabel} returned an unrecognized response shape: expected a JSON object, received ${Array.isArray(body) ? "an array" : typeof body}.`,
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
return body as JSONObject;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
/*
|
|
690
|
+
* A body excerpt safe to store: structurally redacted when it parsed as
|
|
691
|
+
* JSON (so any `access_token`/`client_secret` key is masked whatever its
|
|
692
|
+
* value looks like), textually redacted otherwise, and clipped.
|
|
693
|
+
*/
|
|
694
|
+
private static describeBody(response: {
|
|
695
|
+
statusCode: number;
|
|
696
|
+
bodyText: string;
|
|
697
|
+
bodyJson: unknown;
|
|
698
|
+
}): string {
|
|
699
|
+
if (response.bodyJson !== undefined && response.bodyJson !== null) {
|
|
700
|
+
const redacted: unknown = redactLogValue(response.bodyJson);
|
|
701
|
+
let serialized: string = "";
|
|
702
|
+
|
|
703
|
+
try {
|
|
704
|
+
serialized = JSON.stringify(redacted);
|
|
705
|
+
} catch {
|
|
706
|
+
serialized = "[unserializable body]";
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
return serialized.substring(0, 500);
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
const text: string = (response.bodyText || "").trim();
|
|
713
|
+
|
|
714
|
+
return text
|
|
715
|
+
? redactLogString(text).substring(0, 500)
|
|
716
|
+
: "(empty response body)";
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
private static describeKeys(body: JSONObject): string {
|
|
720
|
+
const keys: Array<string> = Object.keys(body).slice(0, 10);
|
|
721
|
+
|
|
722
|
+
return keys.length ? keys.join(", ") : "(none)";
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/*
|
|
726
|
+
* What the status most likely means, in the operator's terms. Entra
|
|
727
|
+
* returns an `error` code with an AADSTS-prefixed description; ARM
|
|
728
|
+
* returns { error: { code, message } }. The hint never repeats the body.
|
|
729
|
+
*/
|
|
730
|
+
public static hintForFailure(
|
|
731
|
+
stepLabel: string,
|
|
732
|
+
status: number,
|
|
733
|
+
bodyJson: unknown,
|
|
734
|
+
): string {
|
|
735
|
+
const hint: string = MicrosoftSentinelClient.hintText(
|
|
736
|
+
stepLabel,
|
|
737
|
+
status,
|
|
738
|
+
bodyJson,
|
|
739
|
+
);
|
|
740
|
+
|
|
741
|
+
return hint ? ` — ${hint}` : "";
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
private static hintText(
|
|
745
|
+
stepLabel: string,
|
|
746
|
+
status: number,
|
|
747
|
+
bodyJson: unknown,
|
|
748
|
+
): string {
|
|
749
|
+
const body: JSONObject | null =
|
|
750
|
+
bodyJson && typeof bodyJson === "object" && !Array.isArray(bodyJson)
|
|
751
|
+
? (bodyJson as JSONObject)
|
|
752
|
+
: null;
|
|
753
|
+
|
|
754
|
+
if (stepLabel === TOKEN_STEP) {
|
|
755
|
+
const errorCode: string = body ? String(body["error"] || "") : "";
|
|
756
|
+
const description: string = body
|
|
757
|
+
? String(body["error_description"] || "")
|
|
758
|
+
: "";
|
|
759
|
+
|
|
760
|
+
/*
|
|
761
|
+
* AADSTS7000215 is "invalid client secret provided", AADSTS7000216 is
|
|
762
|
+
* "client secret is required" — both mean the secret, not the ids.
|
|
763
|
+
*/
|
|
764
|
+
if (
|
|
765
|
+
errorCode === "invalid_client" ||
|
|
766
|
+
description.includes("AADSTS7000215") ||
|
|
767
|
+
description.includes("AADSTS7000216")
|
|
768
|
+
) {
|
|
769
|
+
return "Microsoft Entra rejected the client secret. It is wrong, expired, or belongs to a different app registration; create a new secret under Certificates & secrets and update the connection.";
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
// AADSTS700016: application with identifier ... was not found in the directory.
|
|
773
|
+
if (
|
|
774
|
+
errorCode === "unauthorized_client" ||
|
|
775
|
+
description.includes("AADSTS700016")
|
|
776
|
+
) {
|
|
777
|
+
return "The Application (client) ID was not found in this tenant. Check the Directory (tenant) ID and Application (client) ID on the app registration's Overview page.";
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// AADSTS90002: tenant not found.
|
|
781
|
+
if (description.includes("AADSTS90002") || status === 404) {
|
|
782
|
+
return "The Directory (tenant) ID does not name an existing tenant. Copy it from the app registration's Overview page.";
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
if (status === 400 || status === 401) {
|
|
786
|
+
return "Microsoft Entra refused the client-credentials request. Check the Directory (tenant) ID, Application (client) ID and client secret.";
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
if (status === 429) {
|
|
790
|
+
return "Microsoft Entra is throttling token requests; the next poll retries.";
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
if (status >= 500) {
|
|
794
|
+
return "Microsoft Entra reported a server-side problem; the next poll retries.";
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
return "";
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
const armCode: string = body
|
|
801
|
+
? String(((body["error"] as JSONObject | undefined) || {})["code"] || "")
|
|
802
|
+
: "";
|
|
803
|
+
|
|
804
|
+
if (status === 401) {
|
|
805
|
+
return "Azure Resource Manager rejected the access token. The token was issued for the wrong cloud or the app registration was removed; confirm the Cloud setting matches where the workspace lives.";
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
if (status === 403 || armCode === "AuthorizationFailed") {
|
|
809
|
+
return "The app registration is not allowed to read incidents. Assign it the Microsoft Sentinel Reader role on the resource group that contains the workspace (Access control (IAM) > Add role assignment) and wait a few minutes for the assignment to propagate.";
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
if (status === 404) {
|
|
813
|
+
return "No workspace matched Subscription ID, Resource group and Workspace name, or Microsoft Sentinel is not enabled on it. Copy the values from the workspace's Overview page in the Azure portal.";
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
if (status === 429) {
|
|
817
|
+
return "Azure Resource Manager is throttling requests for this subscription; the next poll retries.";
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
if (status >= 500) {
|
|
821
|
+
return "Azure Resource Manager reported a server-side problem; the next poll retries.";
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
if (status === 400) {
|
|
825
|
+
return "Azure Resource Manager rejected the query. Report this message to OneUptime support; the incidents request is built by the connector, not from your settings.";
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
return "";
|
|
829
|
+
}
|
|
830
|
+
}
|