@oneuptime/common 13.0.4 → 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/Monitor/MonitorCriteriaEvaluatorPerSeriesFanout.test.ts +55 -2
- 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/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 +348 -2
- package/Tests/Server/Utils/Telemetry/ServiceDependencyDiscovery.test.ts +525 -0
- package/Tests/Server/Utils/Telemetry/TraceContextPropagation.test.ts +420 -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/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/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/Permission.ts +2 -2
- 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/Permission.js +2 -2
- package/build/dist/Types/Permission.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,689 @@
|
|
|
1
|
+
import APIException from "../../../../../Types/Exception/ApiException";
|
|
2
|
+
import { JSONObject, JSONValue } from "../../../../../Types/JSON";
|
|
3
|
+
import Dictionary from "../../../../../Types/Dictionary";
|
|
4
|
+
import { DataSourceHttpResponse } from "../../../DataSource/HttpFetch";
|
|
5
|
+
import { redactLogString, redactLogValue } from "../../../LogRedaction";
|
|
6
|
+
import { ConnectorTransport } from "../Types";
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* Minimal CrowdStrike Falcon API client for the alerts connector.
|
|
10
|
+
*
|
|
11
|
+
* Contract, verified against the public reference at
|
|
12
|
+
* https://developer.crowdstrike.com/api-reference/collections/oauth2/ and
|
|
13
|
+
* https://developer.crowdstrike.com/api-reference/collections/alerts/
|
|
14
|
+
* (the falconpy.io Service-Collections pages redirect there):
|
|
15
|
+
*
|
|
16
|
+
* - Auth: POST {base}/oauth2/token with form fields client_id and
|
|
17
|
+
* client_secret ("The API client ID/secret to authenticate your API
|
|
18
|
+
* requests"). Success is HTTP 201 ("Successfully issued token") with
|
|
19
|
+
* access_token, token_type and expires_in. The token is cached for its
|
|
20
|
+
* expires_in minus a safety margin.
|
|
21
|
+
* - GetQueriesAlertsV2: GET {base}/alerts/queries/alerts/v2 with query
|
|
22
|
+
* parameters filter (FQL), sort, limit ("default: 100; max: 10000") and
|
|
23
|
+
* offset ("Use with the offset parameter to manage pagination"), scope
|
|
24
|
+
* "Alerts: READ". Answers { resources: [composite_id...], meta: {
|
|
25
|
+
* pagination: { limit, offset, total } } }. The query index refuses
|
|
26
|
+
* limit + offset beyond 10,000 ("limit + offset must be less than
|
|
27
|
+
* 10000" — CrowdStrike/falconpy discussions #536, #1146 and #1153).
|
|
28
|
+
* - PostEntitiesAlertsV2: POST {base}/alerts/entities/alerts/v2 with
|
|
29
|
+
* body { composite_ids: [...] } ("CompositeIDs represent the slice of
|
|
30
|
+
* Alert CompositeIDs that would be looked up"), scope "Alerts: READ",
|
|
31
|
+
* answers { resources: [alert...] }. falconpy documents 1000 ids per
|
|
32
|
+
* request as the maximum (github.com/CrowdStrike/falconpy/wiki/Alerts).
|
|
33
|
+
* - The Alerts reference lists created_timestamp among the "filter
|
|
34
|
+
* fields that supports range comparisons (>, <, >=, <=)" and advises
|
|
35
|
+
* to "sort only on the fields that do not change over time (Examples:
|
|
36
|
+
* created_timestamp, composite_id)" for consistent pagination.
|
|
37
|
+
* - A 429 carries X-RateLimit-RetryAfter (with X-RateLimit-Limit and
|
|
38
|
+
* X-RateLimit-Remaining) per the Falcon API rate limiting guidance;
|
|
39
|
+
* it is named in the error so the operator knows what Falcon asked.
|
|
40
|
+
*
|
|
41
|
+
* Every request goes through the injected ConnectorTransport, which is the
|
|
42
|
+
* SSRF-guarded DataSourceHttpFetch in production and a fixture in tests.
|
|
43
|
+
* That transport THROWS on non-2xx statuses ("Data source responded with
|
|
44
|
+
* HTTP <status>: <body>") rather than returning them, so this client
|
|
45
|
+
* normalizes both shapes back into a status + body before deciding what
|
|
46
|
+
* to report.
|
|
47
|
+
*
|
|
48
|
+
* Error messages name the failing step in their prefix and are the
|
|
49
|
+
* contract the integration doc's troubleshooting section is written
|
|
50
|
+
* against; bodies are redacted before they enter a message and the
|
|
51
|
+
* configured secret and any issued token are scrubbed on top of that.
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
export type CrowdStrikeFalconCloud = "us-1" | "us-2" | "eu-1" | "us-gov-1";
|
|
55
|
+
|
|
56
|
+
/*
|
|
57
|
+
* API hostnames per Falcon cloud. A mismatched cloud answers 403, which
|
|
58
|
+
* reads like a permissions problem, so the connector names the cloud in
|
|
59
|
+
* that remediation.
|
|
60
|
+
*/
|
|
61
|
+
export const CROWDSTRIKE_FALCON_CLOUD_BASE_URLS: Record<
|
|
62
|
+
CrowdStrikeFalconCloud,
|
|
63
|
+
string
|
|
64
|
+
> = {
|
|
65
|
+
"us-1": "https://api.crowdstrike.com",
|
|
66
|
+
"us-2": "https://api.us-2.crowdstrike.com",
|
|
67
|
+
"eu-1": "https://api.eu-1.crowdstrike.com",
|
|
68
|
+
"us-gov-1": "https://api.laggar.gcw.crowdstrike.com",
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export function getCrowdStrikeFalconBaseUrl(cloud: string): string | null {
|
|
72
|
+
const key: string = (cloud || "").trim().toLowerCase();
|
|
73
|
+
|
|
74
|
+
if (
|
|
75
|
+
Object.prototype.hasOwnProperty.call(
|
|
76
|
+
CROWDSTRIKE_FALCON_CLOUD_BASE_URLS,
|
|
77
|
+
key,
|
|
78
|
+
)
|
|
79
|
+
) {
|
|
80
|
+
return CROWDSTRIKE_FALCON_CLOUD_BASE_URLS[key as CrowdStrikeFalconCloud];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export const CROWDSTRIKE_FALCON_CLOUDS: Array<CrowdStrikeFalconCloud> = [
|
|
87
|
+
"us-1",
|
|
88
|
+
"us-2",
|
|
89
|
+
"eu-1",
|
|
90
|
+
"us-gov-1",
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
/*
|
|
94
|
+
* The largest page the alerts query allows. Also used as the entity batch
|
|
95
|
+
* size so one ids page maps to one entity request.
|
|
96
|
+
*/
|
|
97
|
+
export const CROWDSTRIKE_ALERTS_QUERY_MAX_LIMIT: number = 10000;
|
|
98
|
+
export const CROWDSTRIKE_ALERTS_PAGE_SIZE: number = 1000;
|
|
99
|
+
export const CROWDSTRIKE_ALERTS_ENTITY_BATCH_SIZE: number = 1000;
|
|
100
|
+
/*
|
|
101
|
+
* limit + offset must not exceed this on the alerts query index. A window
|
|
102
|
+
* with more alerts than this cannot be read completely by offset paging.
|
|
103
|
+
*/
|
|
104
|
+
export const CROWDSTRIKE_ALERTS_OFFSET_CEILING: number = 10000;
|
|
105
|
+
export const CROWDSTRIKE_ALERTS_DEFAULT_SORT: string = "created_timestamp.asc";
|
|
106
|
+
|
|
107
|
+
/*
|
|
108
|
+
* Falcon tokens last 30 minutes; refresh a minute early so a token that
|
|
109
|
+
* expires mid-page does not turn into a spurious 401.
|
|
110
|
+
*/
|
|
111
|
+
const TOKEN_EXPIRY_SLACK_IN_SECONDS: number = 60;
|
|
112
|
+
const DEFAULT_TOKEN_LIFETIME_IN_SECONDS: number = 1799;
|
|
113
|
+
|
|
114
|
+
/*
|
|
115
|
+
* Error bodies are echoed for diagnosis but bounded: a WAF or gateway can
|
|
116
|
+
* answer with a multi-megabyte HTML page.
|
|
117
|
+
*/
|
|
118
|
+
const MAX_ERROR_BODY_LENGTH: number = 2000;
|
|
119
|
+
const TRUNCATION_MARKER: string = "... (truncated)";
|
|
120
|
+
|
|
121
|
+
const RATE_LIMIT_RETRY_AFTER_HEADER: string = "x-ratelimit-retryafter";
|
|
122
|
+
|
|
123
|
+
/*
|
|
124
|
+
* What DataSourceHttpFetch throws for a non-2xx status. The status and the
|
|
125
|
+
* body are recovered from it so the caller sees one shape either way.
|
|
126
|
+
*/
|
|
127
|
+
const TRANSPORT_STATUS_ERROR_PATTERN: RegExp =
|
|
128
|
+
/Data source responded with HTTP (\d{3})(?::\s?([\s\S]*))?$/;
|
|
129
|
+
|
|
130
|
+
const HTTP_STATUS_IN_MESSAGE_PATTERN: RegExp = /\(HTTP (\d{3})\)/;
|
|
131
|
+
|
|
132
|
+
export type CrowdStrikeFalconRequestStep =
|
|
133
|
+
| "token request"
|
|
134
|
+
| "alerts query"
|
|
135
|
+
| "alerts fetch";
|
|
136
|
+
|
|
137
|
+
export interface CrowdStrikeFalconClientOptions {
|
|
138
|
+
cloud: string;
|
|
139
|
+
clientId: string;
|
|
140
|
+
clientSecret: string;
|
|
141
|
+
transport: ConnectorTransport;
|
|
142
|
+
requestTimeoutInMs: number;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface CrowdStrikeAlertIdsPage {
|
|
146
|
+
compositeIds: Array<string>;
|
|
147
|
+
// meta.pagination.total, or null when Falcon did not report it.
|
|
148
|
+
total: number | null;
|
|
149
|
+
offset: number;
|
|
150
|
+
limit: number;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export interface CrowdStrikeAlertCount {
|
|
154
|
+
/*
|
|
155
|
+
* meta.pagination.total for the filter when Falcon reported it, else the
|
|
156
|
+
* number of ids the one-record probe page held (0 or 1).
|
|
157
|
+
*/
|
|
158
|
+
count: number;
|
|
159
|
+
// False when Falcon omitted the total and count is only the probe page.
|
|
160
|
+
exact: boolean;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
interface NormalizedResponse {
|
|
164
|
+
statusCode: number;
|
|
165
|
+
bodyText: string;
|
|
166
|
+
bodyJson: unknown;
|
|
167
|
+
headers: Dictionary<string>;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export default class CrowdStrikeFalconClient {
|
|
171
|
+
private baseUrl: string;
|
|
172
|
+
private clientId: string;
|
|
173
|
+
private clientSecret: string;
|
|
174
|
+
private transport: ConnectorTransport;
|
|
175
|
+
private requestTimeoutInMs: number;
|
|
176
|
+
|
|
177
|
+
private cachedAccessToken: string | null = null;
|
|
178
|
+
private cachedAccessTokenExpiresAtInMs: number = 0;
|
|
179
|
+
private requestCount: number = 0;
|
|
180
|
+
|
|
181
|
+
public constructor(options: CrowdStrikeFalconClientOptions) {
|
|
182
|
+
const baseUrl: string | null = getCrowdStrikeFalconBaseUrl(options.cloud);
|
|
183
|
+
|
|
184
|
+
if (!baseUrl) {
|
|
185
|
+
throw new APIException(
|
|
186
|
+
`CrowdStrike Falcon cloud "${redactLogString(String(options.cloud || ""))}" is not one of ${CROWDSTRIKE_FALCON_CLOUDS.join(", ")}.`,
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
this.baseUrl = baseUrl;
|
|
191
|
+
this.clientId = options.clientId;
|
|
192
|
+
this.clientSecret = options.clientSecret;
|
|
193
|
+
this.transport = options.transport;
|
|
194
|
+
this.requestTimeoutInMs = options.requestTimeoutInMs;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
public getBaseUrl(): string {
|
|
198
|
+
return this.baseUrl;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Outbound requests issued so far, token requests included.
|
|
202
|
+
public getRequestCount(): number {
|
|
203
|
+
return this.requestCount;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/*
|
|
207
|
+
* FQL for "created in [start, end)". Quoted RFC3339 timestamps and `+`
|
|
208
|
+
* as the conjunction, per Falcon Query Language. The filter is passed
|
|
209
|
+
* through URLSearchParams, which percent-encodes the `+` so Falcon does
|
|
210
|
+
* not read it as a space.
|
|
211
|
+
*/
|
|
212
|
+
public static buildCreatedTimestampFilter(start: Date, end: Date): string {
|
|
213
|
+
return `created_timestamp:>='${start.toISOString()}'+created_timestamp:<'${end.toISOString()}'`;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
public static parseHttpStatusFromMessage(message: string): number | null {
|
|
217
|
+
const match: RegExpMatchArray | null = (message || "").match(
|
|
218
|
+
HTTP_STATUS_IN_MESSAGE_PATTERN,
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
if (!match || !match[1]) {
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return Number(match[1]);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
public async getAccessToken(): Promise<string> {
|
|
229
|
+
if (
|
|
230
|
+
this.cachedAccessToken &&
|
|
231
|
+
Date.now() < this.cachedAccessTokenExpiresAtInMs
|
|
232
|
+
) {
|
|
233
|
+
return this.cachedAccessToken;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const response: NormalizedResponse = await this.send("token request", {
|
|
237
|
+
method: "POST",
|
|
238
|
+
url: `${this.baseUrl}/oauth2/token`,
|
|
239
|
+
headers: { Accept: "application/json" },
|
|
240
|
+
body: { client_id: this.clientId, client_secret: this.clientSecret },
|
|
241
|
+
formUrlEncoded: true,
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// Falcon answers the token request with 201, not 200.
|
|
245
|
+
if (response.statusCode < 200 || response.statusCode >= 300) {
|
|
246
|
+
throw new APIException(
|
|
247
|
+
`CrowdStrike Falcon token request failed (HTTP ${response.statusCode}): ${this.describeErrorBody(response)}`,
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (!this.isJsonObject(response.bodyJson)) {
|
|
252
|
+
throw new APIException(
|
|
253
|
+
"CrowdStrike Falcon token request returned a non-JSON body.",
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const accessToken: unknown = response.bodyJson["access_token"];
|
|
258
|
+
|
|
259
|
+
if (typeof accessToken !== "string" || !accessToken) {
|
|
260
|
+
throw new APIException(
|
|
261
|
+
"CrowdStrike Falcon token request returned no access_token.",
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const expiresIn: unknown = response.bodyJson["expires_in"];
|
|
266
|
+
const lifetimeInSeconds: number =
|
|
267
|
+
typeof expiresIn === "number" &&
|
|
268
|
+
Number.isFinite(expiresIn) &&
|
|
269
|
+
expiresIn > 0
|
|
270
|
+
? expiresIn
|
|
271
|
+
: DEFAULT_TOKEN_LIFETIME_IN_SECONDS;
|
|
272
|
+
|
|
273
|
+
this.cachedAccessToken = accessToken;
|
|
274
|
+
this.cachedAccessTokenExpiresAtInMs =
|
|
275
|
+
Date.now() +
|
|
276
|
+
Math.max(1, lifetimeInSeconds - TOKEN_EXPIRY_SLACK_IN_SECONDS) * 1000;
|
|
277
|
+
|
|
278
|
+
return accessToken;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/*
|
|
282
|
+
* GET /alerts/queries/alerts/v2 — one page of composite ids matching the
|
|
283
|
+
* filter, sorted by creation time ascending so offset paging is stable.
|
|
284
|
+
*/
|
|
285
|
+
public async queryAlertIds(data: {
|
|
286
|
+
filter: string;
|
|
287
|
+
limit: number;
|
|
288
|
+
offset: number;
|
|
289
|
+
sort?: string | undefined;
|
|
290
|
+
}): Promise<CrowdStrikeAlertIdsPage> {
|
|
291
|
+
if (data.limit < 1 || data.limit > CROWDSTRIKE_ALERTS_QUERY_MAX_LIMIT) {
|
|
292
|
+
throw new APIException(
|
|
293
|
+
`CrowdStrike Falcon alerts query limit must be between 1 and ${CROWDSTRIKE_ALERTS_QUERY_MAX_LIMIT}.`,
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (data.offset < 0) {
|
|
298
|
+
throw new APIException(
|
|
299
|
+
"CrowdStrike Falcon alerts query offset must not be negative.",
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const params: URLSearchParams = new URLSearchParams();
|
|
304
|
+
params.set("filter", data.filter);
|
|
305
|
+
params.set("sort", data.sort || CROWDSTRIKE_ALERTS_DEFAULT_SORT);
|
|
306
|
+
params.set("limit", String(data.limit));
|
|
307
|
+
params.set("offset", String(data.offset));
|
|
308
|
+
|
|
309
|
+
const response: NormalizedResponse = await this.sendAuthenticated(
|
|
310
|
+
"alerts query",
|
|
311
|
+
{
|
|
312
|
+
method: "GET",
|
|
313
|
+
url: `${this.baseUrl}/alerts/queries/alerts/v2?${params.toString()}`,
|
|
314
|
+
},
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
if (response.statusCode < 200 || response.statusCode >= 300) {
|
|
318
|
+
throw new APIException(
|
|
319
|
+
`CrowdStrike Falcon alerts query failed (HTTP ${response.statusCode}): ${this.describeErrorBody(response)}`,
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (!this.isJsonObject(response.bodyJson)) {
|
|
324
|
+
throw new APIException(
|
|
325
|
+
"CrowdStrike Falcon alerts query returned a non-JSON body.",
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const resources: unknown = response.bodyJson["resources"];
|
|
330
|
+
|
|
331
|
+
/*
|
|
332
|
+
* `resources` may be null on an empty result in some Falcon responses;
|
|
333
|
+
* anything that is neither null nor an array is not this endpoint.
|
|
334
|
+
*/
|
|
335
|
+
if (
|
|
336
|
+
resources !== null &&
|
|
337
|
+
resources !== undefined &&
|
|
338
|
+
!Array.isArray(resources)
|
|
339
|
+
) {
|
|
340
|
+
throw new APIException(
|
|
341
|
+
`CrowdStrike Falcon alerts query returned an unrecognized response shape: ${this.summarizeBody(response.bodyJson)}`,
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const compositeIds: Array<string> = (
|
|
346
|
+
Array.isArray(resources) ? resources : []
|
|
347
|
+
)
|
|
348
|
+
.filter((item: unknown): boolean => {
|
|
349
|
+
return typeof item === "string" && item.length > 0;
|
|
350
|
+
})
|
|
351
|
+
.map((item: unknown): string => {
|
|
352
|
+
return String(item);
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
const pagination: JSONObject | null = this.readPagination(
|
|
356
|
+
response.bodyJson,
|
|
357
|
+
);
|
|
358
|
+
|
|
359
|
+
return {
|
|
360
|
+
compositeIds,
|
|
361
|
+
total: this.readCount(pagination, "total"),
|
|
362
|
+
offset: this.readCount(pagination, "offset") ?? data.offset,
|
|
363
|
+
limit: this.readCount(pagination, "limit") ?? data.limit,
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/*
|
|
368
|
+
* How many alerts Falcon created in [start, end): one request with
|
|
369
|
+
* limit=1, reading meta.pagination.total. Bounded by construction — the
|
|
370
|
+
* count is Falcon's, not a page walk — which is what the availability
|
|
371
|
+
* check needs for a 7-day window on a busy tenant.
|
|
372
|
+
*/
|
|
373
|
+
public async countAlertsCreatedBetween(data: {
|
|
374
|
+
startTime: Date;
|
|
375
|
+
endTime: Date;
|
|
376
|
+
}): Promise<CrowdStrikeAlertCount> {
|
|
377
|
+
const page: CrowdStrikeAlertIdsPage = await this.queryAlertIds({
|
|
378
|
+
filter: CrowdStrikeFalconClient.buildCreatedTimestampFilter(
|
|
379
|
+
data.startTime,
|
|
380
|
+
data.endTime,
|
|
381
|
+
),
|
|
382
|
+
limit: 1,
|
|
383
|
+
offset: 0,
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
if (page.total !== null) {
|
|
387
|
+
return { count: page.total, exact: true };
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return { count: page.compositeIds.length, exact: false };
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/*
|
|
394
|
+
* POST /alerts/entities/alerts/v2 — full alert entities for up to one
|
|
395
|
+
* batch of composite ids. Batching is the caller's job so it can count
|
|
396
|
+
* requests against its budget.
|
|
397
|
+
*/
|
|
398
|
+
public async getAlerts(
|
|
399
|
+
compositeIds: Array<string>,
|
|
400
|
+
): Promise<Array<JSONObject>> {
|
|
401
|
+
if (!compositeIds.length) {
|
|
402
|
+
return [];
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (compositeIds.length > CROWDSTRIKE_ALERTS_ENTITY_BATCH_SIZE) {
|
|
406
|
+
throw new APIException(
|
|
407
|
+
`CrowdStrike Falcon alerts fetch accepts at most ${CROWDSTRIKE_ALERTS_ENTITY_BATCH_SIZE} composite ids per request.`,
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const response: NormalizedResponse = await this.sendAuthenticated(
|
|
412
|
+
"alerts fetch",
|
|
413
|
+
{
|
|
414
|
+
method: "POST",
|
|
415
|
+
url: `${this.baseUrl}/alerts/entities/alerts/v2`,
|
|
416
|
+
body: JSON.stringify({ composite_ids: compositeIds }),
|
|
417
|
+
},
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
if (response.statusCode < 200 || response.statusCode >= 300) {
|
|
421
|
+
throw new APIException(
|
|
422
|
+
`CrowdStrike Falcon alerts fetch failed (HTTP ${response.statusCode}): ${this.describeErrorBody(response)}`,
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
if (!this.isJsonObject(response.bodyJson)) {
|
|
427
|
+
throw new APIException(
|
|
428
|
+
"CrowdStrike Falcon alerts fetch returned a non-JSON body.",
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
const resources: unknown = response.bodyJson["resources"];
|
|
433
|
+
|
|
434
|
+
if (
|
|
435
|
+
resources !== null &&
|
|
436
|
+
resources !== undefined &&
|
|
437
|
+
!Array.isArray(resources)
|
|
438
|
+
) {
|
|
439
|
+
throw new APIException(
|
|
440
|
+
`CrowdStrike Falcon alerts fetch returned an unrecognized response shape: ${this.summarizeBody(response.bodyJson)}`,
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return (Array.isArray(resources) ? resources : []).filter(
|
|
445
|
+
(item: unknown): item is JSONObject => {
|
|
446
|
+
return this.isJsonObject(item);
|
|
447
|
+
},
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/*
|
|
452
|
+
* Authenticated call with one retry on 401 when the token came from the
|
|
453
|
+
* cache: a token revoked mid-run (client secret rotated in Falcon) should
|
|
454
|
+
* cost one extra request, not a failed poll.
|
|
455
|
+
*/
|
|
456
|
+
private async sendAuthenticated(
|
|
457
|
+
step: CrowdStrikeFalconRequestStep,
|
|
458
|
+
request: {
|
|
459
|
+
method: "GET" | "POST";
|
|
460
|
+
url: string;
|
|
461
|
+
body?: string | undefined;
|
|
462
|
+
},
|
|
463
|
+
): Promise<NormalizedResponse> {
|
|
464
|
+
const hadCachedToken: boolean = Boolean(this.cachedAccessToken);
|
|
465
|
+
const token: string = await this.getAccessToken();
|
|
466
|
+
|
|
467
|
+
const response: NormalizedResponse = await this.send(step, {
|
|
468
|
+
method: request.method,
|
|
469
|
+
url: request.url,
|
|
470
|
+
headers: {
|
|
471
|
+
Authorization: `Bearer ${token}`,
|
|
472
|
+
Accept: "application/json",
|
|
473
|
+
...(request.body !== undefined
|
|
474
|
+
? { "Content-Type": "application/json" }
|
|
475
|
+
: {}),
|
|
476
|
+
},
|
|
477
|
+
body: request.body,
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
if (response.statusCode !== 401 || !hadCachedToken) {
|
|
481
|
+
return response;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
this.cachedAccessToken = null;
|
|
485
|
+
this.cachedAccessTokenExpiresAtInMs = 0;
|
|
486
|
+
const freshToken: string = await this.getAccessToken();
|
|
487
|
+
|
|
488
|
+
return this.send(step, {
|
|
489
|
+
method: request.method,
|
|
490
|
+
url: request.url,
|
|
491
|
+
headers: {
|
|
492
|
+
Authorization: `Bearer ${freshToken}`,
|
|
493
|
+
Accept: "application/json",
|
|
494
|
+
...(request.body !== undefined
|
|
495
|
+
? { "Content-Type": "application/json" }
|
|
496
|
+
: {}),
|
|
497
|
+
},
|
|
498
|
+
body: request.body,
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/*
|
|
503
|
+
* The one place a request leaves this class. Applies the timeout, counts
|
|
504
|
+
* the request, and folds the transport's thrown non-2xx errors back into
|
|
505
|
+
* a response so every caller sees status + body.
|
|
506
|
+
*/
|
|
507
|
+
private async send(
|
|
508
|
+
step: CrowdStrikeFalconRequestStep,
|
|
509
|
+
request: {
|
|
510
|
+
method: "GET" | "POST";
|
|
511
|
+
url: string;
|
|
512
|
+
headers?: Dictionary<string> | undefined;
|
|
513
|
+
body?: string | Dictionary<string> | undefined;
|
|
514
|
+
formUrlEncoded?: boolean | undefined;
|
|
515
|
+
},
|
|
516
|
+
): Promise<NormalizedResponse> {
|
|
517
|
+
this.requestCount++;
|
|
518
|
+
|
|
519
|
+
let response: DataSourceHttpResponse;
|
|
520
|
+
|
|
521
|
+
try {
|
|
522
|
+
response = await this.transport({
|
|
523
|
+
method: request.method,
|
|
524
|
+
url: request.url,
|
|
525
|
+
headers: request.headers,
|
|
526
|
+
body: request.body,
|
|
527
|
+
formUrlEncoded: request.formUrlEncoded,
|
|
528
|
+
timeoutInMs: this.requestTimeoutInMs,
|
|
529
|
+
});
|
|
530
|
+
} catch (error) {
|
|
531
|
+
const message: string =
|
|
532
|
+
error instanceof Error ? error.message : String(error);
|
|
533
|
+
const match: RegExpMatchArray | null = message.match(
|
|
534
|
+
TRANSPORT_STATUS_ERROR_PATTERN,
|
|
535
|
+
);
|
|
536
|
+
|
|
537
|
+
if (match && match[1]) {
|
|
538
|
+
const bodyText: string = match[2] || "";
|
|
539
|
+
return {
|
|
540
|
+
statusCode: Number(match[1]),
|
|
541
|
+
bodyText,
|
|
542
|
+
bodyJson: this.tryParseJson(bodyText),
|
|
543
|
+
headers: {},
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/*
|
|
548
|
+
* Timeouts, DNS failures, egress-guard refusals: nothing came back,
|
|
549
|
+
* so no status is claimed. The transport's own wording ("timeout of
|
|
550
|
+
* 20000ms exceeded") is kept, redacted.
|
|
551
|
+
*/
|
|
552
|
+
throw new APIException(
|
|
553
|
+
`CrowdStrike Falcon ${step} could not be completed: ${this.scrubSecrets(redactLogString(message))}`,
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
const headers: Dictionary<string> = {};
|
|
558
|
+
|
|
559
|
+
for (const key of Object.keys(response.headers || {})) {
|
|
560
|
+
headers[key.toLowerCase()] = String(
|
|
561
|
+
(response.headers as Dictionary<string>)[key],
|
|
562
|
+
);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
return {
|
|
566
|
+
statusCode: response.statusCode,
|
|
567
|
+
bodyText: response.bodyText || "",
|
|
568
|
+
bodyJson:
|
|
569
|
+
response.bodyJson !== undefined
|
|
570
|
+
? response.bodyJson
|
|
571
|
+
: this.tryParseJson(response.bodyText || ""),
|
|
572
|
+
headers,
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/*
|
|
577
|
+
* The echoed error body: JSON is redacted structurally (so a
|
|
578
|
+
* `client_secret` member is replaced whatever its value), text is
|
|
579
|
+
* redacted textually, both are bounded, and a 429 names the
|
|
580
|
+
* X-RateLimit-RetryAfter header so the operator knows what Falcon asked.
|
|
581
|
+
*/
|
|
582
|
+
private describeErrorBody(response: NormalizedResponse): string {
|
|
583
|
+
let body: string;
|
|
584
|
+
|
|
585
|
+
if (response.bodyJson !== undefined) {
|
|
586
|
+
body = JSON.stringify(redactLogValue(response.bodyJson as JSONValue));
|
|
587
|
+
} else {
|
|
588
|
+
body = redactLogString(response.bodyText || "");
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
body = this.scrubSecrets(body || "(empty body)");
|
|
592
|
+
|
|
593
|
+
if (body.length > MAX_ERROR_BODY_LENGTH) {
|
|
594
|
+
body = `${body.slice(0, MAX_ERROR_BODY_LENGTH - TRUNCATION_MARKER.length)}${TRUNCATION_MARKER}`;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
if (response.statusCode === 429) {
|
|
598
|
+
const retryAfter: string | undefined =
|
|
599
|
+
response.headers[RATE_LIMIT_RETRY_AFTER_HEADER];
|
|
600
|
+
|
|
601
|
+
return retryAfter
|
|
602
|
+
? `${body}; Falcon rate limited the request, X-RateLimit-RetryAfter: ${redactLogString(retryAfter)}`
|
|
603
|
+
: `${body}; Falcon rate limited the request and the X-RateLimit-RetryAfter header was not available`;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
return body;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
private summarizeBody(bodyJson: unknown): string {
|
|
610
|
+
let summary: string = "";
|
|
611
|
+
|
|
612
|
+
try {
|
|
613
|
+
summary = JSON.stringify(redactLogValue(bodyJson as JSONValue)) || "";
|
|
614
|
+
} catch {
|
|
615
|
+
summary = "(unserializable body)";
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
summary = this.scrubSecrets(summary);
|
|
619
|
+
|
|
620
|
+
if (summary.length > MAX_ERROR_BODY_LENGTH) {
|
|
621
|
+
summary = `${summary.slice(0, MAX_ERROR_BODY_LENGTH - TRUNCATION_MARKER.length)}${TRUNCATION_MARKER}`;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
return summary;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/*
|
|
628
|
+
* Belt and braces behind the generic redactor: the values this client
|
|
629
|
+
* KNOWS are secrets are removed by literal match wherever they appear.
|
|
630
|
+
*/
|
|
631
|
+
private scrubSecrets(text: string): string {
|
|
632
|
+
let scrubbed: string = text;
|
|
633
|
+
|
|
634
|
+
for (const secret of [this.clientSecret, this.cachedAccessToken]) {
|
|
635
|
+
if (secret && secret.length >= 4) {
|
|
636
|
+
scrubbed = scrubbed.split(secret).join("[REDACTED]");
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
return scrubbed;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
private readPagination(bodyJson: JSONObject): JSONObject | null {
|
|
644
|
+
const meta: unknown = bodyJson["meta"];
|
|
645
|
+
|
|
646
|
+
if (!this.isJsonObject(meta)) {
|
|
647
|
+
return null;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
const pagination: unknown = meta["pagination"];
|
|
651
|
+
|
|
652
|
+
return this.isJsonObject(pagination) ? pagination : null;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
private readCount(pagination: JSONObject | null, key: string): number | null {
|
|
656
|
+
if (!pagination) {
|
|
657
|
+
return null;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
const value: unknown = pagination[key];
|
|
661
|
+
|
|
662
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
663
|
+
return value;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
667
|
+
const parsed: number = Number(value);
|
|
668
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : null;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
return null;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
private tryParseJson(text: string): unknown {
|
|
675
|
+
if (!text) {
|
|
676
|
+
return undefined;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
try {
|
|
680
|
+
return JSON.parse(text);
|
|
681
|
+
} catch {
|
|
682
|
+
return undefined;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
private isJsonObject(value: unknown): value is JSONObject {
|
|
687
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
688
|
+
}
|
|
689
|
+
}
|