@oneuptime/common 14.0.9 → 14.0.11
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/AIConversation.ts +127 -1
- package/Models/DatabaseModels/AutoRemediationSuggestion.ts +60 -0
- package/Models/DatabaseModels/CephCluster.ts +225 -0
- package/Models/DatabaseModels/CloudResource.ts +12 -0
- package/Models/DatabaseModels/DatabaseServer.ts +225 -0
- package/Models/DatabaseModels/DockerHost.ts +225 -0
- package/Models/DatabaseModels/DockerSwarmCluster.ts +225 -0
- package/Models/DatabaseModels/GlobalConfig.ts +1 -1
- package/Models/DatabaseModels/GlobalOidc.ts +0 -4
- package/Models/DatabaseModels/GlobalOidcProject.ts +0 -4
- package/Models/DatabaseModels/GlobalSso.ts +0 -4
- package/Models/DatabaseModels/GlobalSsoProject.ts +0 -4
- package/Models/DatabaseModels/Host.ts +225 -0
- package/Models/DatabaseModels/IncidentForm.ts +594 -0
- package/Models/DatabaseModels/IncidentFormSubmission.ts +283 -0
- package/Models/DatabaseModels/IncidentTemplate.ts +59 -0
- package/Models/DatabaseModels/Index.ts +16 -0
- package/Models/DatabaseModels/IoTFleet.ts +12 -0
- package/Models/DatabaseModels/KubernetesCluster.ts +12 -0
- package/Models/DatabaseModels/MessageQueue.ts +1102 -0
- package/Models/DatabaseModels/MessageQueueLabelRule.ts +553 -0
- package/Models/DatabaseModels/MessageQueueOwnerRule.ts +633 -0
- package/Models/DatabaseModels/MessageQueueOwnerTeam.ts +491 -0
- package/Models/DatabaseModels/MessageQueueOwnerUser.ts +490 -0
- package/Models/DatabaseModels/PodmanHost.ts +225 -0
- package/Models/DatabaseModels/Project.ts +59 -0
- package/Models/DatabaseModels/ProjectOidc.ts +0 -4
- package/Models/DatabaseModels/ProjectSso.ts +0 -4
- package/Models/DatabaseModels/ProxmoxCluster.ts +225 -0
- package/Models/DatabaseModels/ResourceAiAgent.ts +419 -0
- package/Models/DatabaseModels/RumApplication.ts +12 -0
- package/Models/DatabaseModels/RunnerJob.ts +144 -0
- package/Models/DatabaseModels/ServerlessFunction.ts +12 -0
- package/Models/DatabaseModels/Service.ts +12 -0
- package/Models/DatabaseModels/StatusPageOidc.ts +0 -4
- package/Models/DatabaseModels/StatusPageSso.ts +0 -4
- package/Models/DatabaseModels/TeamComplianceSetting.ts +47 -2
- package/Models/DatabaseModels/VMwareVCenter.ts +225 -0
- package/Server/API/AIChatAPI.ts +13 -114
- package/Server/API/AIInvestigationAPI.ts +3 -3
- package/Server/API/AIInvestigationConversationAPI.ts +266 -0
- package/Server/API/AutoRemediationAPI.ts +392 -1
- package/Server/API/IncidentFormAPI.ts +376 -0
- package/Server/API/ProjectOIDC.ts +16 -25
- package/Server/API/ProjectSSO.ts +16 -24
- package/Server/API/ResourceAiAccessAPI.ts +1669 -0
- package/Server/API/StatusPageAPI.ts +42 -77
- package/Server/Enterprise/EnterpriseEdition.ts +93 -28
- package/Server/Enterprise/EnterpriseFeature.ts +25 -3
- package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +1 -1
- package/Server/Enterprise/EnterpriseServerModule.ts +4 -1
- package/Server/EnvironmentConfig.ts +1 -1
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.ts +423 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.ts +129 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.ts +52 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.ts +75 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.ts +477 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
- package/Server/Infrastructure/Semaphore.ts +22 -0
- package/Server/Middleware/IncidentFormRateLimit.ts +847 -0
- package/Server/Middleware/TelemetryIngest.ts +15 -5
- package/Server/Middleware/UserAuthorization.ts +16 -38
- package/Server/Services/AIService.ts +10 -13
- package/Server/Services/AnalyticsDatabaseService.ts +45 -1
- package/Server/Services/AutoRemediationRuleEngineService.ts +940 -112
- package/Server/Services/CephClusterService.ts +109 -1
- package/Server/Services/DatabaseServerService.ts +116 -1
- package/Server/Services/DockerHostService.ts +109 -1
- package/Server/Services/DockerSwarmClusterService.ts +113 -1
- package/Server/Services/HostService.ts +126 -4
- package/Server/Services/IncidentCustomFieldService.ts +112 -2
- package/Server/Services/IncidentEpisodeMemberService.ts +24 -4
- package/Server/Services/IncidentEpisodeService.ts +10 -1
- package/Server/Services/IncidentFormService.ts +1566 -0
- package/Server/Services/IncidentFormSubmissionService.ts +97 -0
- package/Server/Services/IncidentGroupingEngineService.ts +45 -8
- package/Server/Services/IncidentService.ts +123 -5
- package/Server/Services/IncidentTemplateService.ts +22 -0
- package/Server/Services/Index.ts +14 -0
- package/Server/Services/MessageQueueLabelRuleEngineService.ts +321 -0
- package/Server/Services/MessageQueueLabelRuleService.ts +14 -0
- package/Server/Services/MessageQueueOwnerRuleEngineService.ts +412 -0
- package/Server/Services/MessageQueueOwnerRuleService.ts +14 -0
- package/Server/Services/MessageQueueOwnerTeamService.ts +62 -0
- package/Server/Services/MessageQueueOwnerUserService.ts +62 -0
- package/Server/Services/MessageQueueService.ts +1463 -0
- package/Server/Services/MetricRecordingRuleService.ts +47 -0
- package/Server/Services/OpenTelemetryIngestService.ts +37 -4
- package/Server/Services/PodmanHostService.ts +109 -1
- package/Server/Services/ProjectService.ts +0 -59
- package/Server/Services/ProxmoxClusterService.ts +110 -1
- package/Server/Services/ResourceAiAccessService.ts +1439 -0
- package/Server/Services/ResourceAiAgentJobService.ts +202 -0
- package/Server/Services/ResourceAiAgentService.ts +2432 -0
- package/Server/Services/RunnerJobService.ts +611 -4
- package/Server/Services/StatusPagePrivateUserService.ts +1 -4
- package/Server/Services/StatusPageService.ts +1 -51
- package/Server/Services/TeamComplianceSettingService.ts +163 -42
- package/Server/Services/TelemetryUsageBillingService.ts +28 -0
- package/Server/Services/TraceRecordingRuleService.ts +33 -0
- package/Server/Services/UserNotificationRuleService.ts +8 -1
- package/Server/Services/VMwareVCenterService.ts +110 -1
- package/Server/Services/WorkspaceNotificationSummaryService.ts +12 -3
- package/Server/Types/Database/Permissions/CreatePermission.ts +17 -3
- package/Server/Types/Database/Permissions/EditionPermission.ts +140 -38
- package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +16 -0
- package/Server/Types/Database/Permissions/TablePermission.ts +3 -3
- package/Server/Types/Database/Permissions/UpdatePermission.ts +20 -6
- package/Server/Utils/AI/Chat/AgentContextCompactor.ts +200 -0
- package/Server/Utils/AI/Chat/ChatAgentRunner.ts +307 -48
- package/Server/Utils/AI/Chat/ChatRunCancellation.ts +156 -0
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +78 -18
- package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +1 -1
- package/Server/Utils/AI/Chat/ToolOutputPager.ts +322 -0
- package/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.ts +88 -30
- package/Server/Utils/AI/ClusterAccess/KubectlJobRunner.ts +13 -1
- package/Server/Utils/AI/CodeFix/CodeFixReadiness.ts +0 -32
- package/Server/Utils/AI/CodeFix/FixRunBudget.ts +27 -25
- package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +1442 -34
- package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +968 -34
- package/Server/Utils/AI/Remediation/RemediationPlanRunner.ts +25 -1
- package/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.ts +622 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAccessContext.ts +271 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.ts +45 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.ts +964 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.ts +333 -0
- package/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.ts +882 -0
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +125 -12
- package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +99 -15
- package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +99 -15
- package/Server/Utils/AI/SRE/InvestigationQueue.ts +16 -19
- package/Server/Utils/AI/SRE/InvestigationThread.ts +646 -0
- package/Server/Utils/AI/SRE/InvestigationThreadService.ts +715 -0
- package/Server/Utils/AI/Toolbox/Serializer.ts +10 -3
- package/Server/Utils/AutoRemediation/CommandPlanExecutor.ts +396 -13
- package/Server/Utils/AutoRemediation/RemediationVerifier.ts +35 -2
- package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +9 -1
- package/Server/Utils/EditionEnforcement.ts +19 -202
- package/Server/Utils/LLM/LLMService.ts +259 -63
- package/Server/Utils/RelaxedScimTeamLocksReport.ts +245 -0
- package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +25 -0
- package/Server/Utils/SameOriginRequest.ts +203 -0
- package/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.ts +920 -0
- package/Server/Utils/SessionReplay/SessionReplayUsage.ts +84 -6
- package/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.ts +2 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +4 -1
- package/Server/Utils/Telemetry/MessageQueueDiscovery.ts +1402 -0
- package/Server/Utils/Telemetry/ResourceEntityFilter.ts +4 -1
- package/Server/Utils/VendorAssets.ts +3 -3
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.ts +35 -15
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.ts +33 -15
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.ts +21 -1
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +301 -225
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +38 -16
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.ts +389 -175
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +376 -144
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.ts +163 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.ts +396 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.ts +418 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.ts +152 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.ts +251 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.ts +214 -0
- package/Tests/App/Accounts/IncidentFormPage.test.tsx +2036 -0
- package/Tests/App/Accounts/IncidentFormServerMessages.test.ts +119 -0
- package/Tests/App/Accounts/IncidentFormUtils.test.ts +1157 -0
- package/Tests/App/Accounts/LoginPasskey.test.tsx +6 -4
- package/Tests/App/Accounts/LoginSso.test.tsx +724 -0
- package/Tests/App/AdminDashboard/AdminAuthenticationRequireSso.test.tsx +338 -0
- package/Tests/App/AdminDashboard/AdminAuthenticationSsoCardLocales.test.tsx +331 -0
- package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +47 -33
- package/Tests/App/AdminDashboard/GlobalSsoOidcPages.test.tsx +1021 -0
- package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +876 -78
- package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +20 -3
- package/Tests/App/Dashboard/CephProxmoxVMwareDocumentationCards.test.tsx +359 -0
- package/Tests/App/Dashboard/CephSetupGuide.test.ts +961 -0
- package/Tests/App/Dashboard/CloudDocumentationCard.test.tsx +381 -95
- package/Tests/App/Dashboard/CloudSetupGuide.test.ts +1463 -0
- package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +267 -12
- package/Tests/App/Dashboard/ContainerSetupGuideCards.test.tsx +345 -0
- package/Tests/App/Dashboard/CoreListEmptyStates.test.tsx +501 -0
- package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +0 -1
- package/Tests/App/Dashboard/DatabaseDocumentationCard.test.tsx +400 -0
- package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +23 -6
- package/Tests/App/Dashboard/DatabaseSetupGuide.test.ts +1869 -0
- package/Tests/App/Dashboard/DatabaseTelemetryScope.test.ts +44 -0
- package/Tests/App/Dashboard/DatabaseTelemetryTabs.test.tsx +50 -9
- package/Tests/App/Dashboard/DockerSetupGuide.test.ts +899 -0
- package/Tests/App/Dashboard/DockerSwarmSetupGuide.test.ts +964 -0
- package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +141 -7
- package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +52 -39
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +7 -1
- package/Tests/App/Dashboard/GettingStartedTaskRoutes.test.tsx +331 -0
- package/Tests/App/Dashboard/HomeOverviewStatsFirstRun.test.tsx +925 -0
- package/Tests/App/Dashboard/HostDocumentationCard.test.tsx +225 -0
- package/Tests/App/Dashboard/HostSetupGuide.test.ts +1183 -0
- package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +69 -45
- package/Tests/App/Dashboard/IncidentCreateTemplateCustomFieldSettings.test.tsx +745 -0
- package/Tests/App/Dashboard/IncidentCreateTemplateOwners.test.tsx +414 -0
- package/Tests/App/Dashboard/IncidentCustomFieldCreateSettingsForm.test.ts +1042 -0
- package/Tests/App/Dashboard/IncidentCustomFieldSettingsCard.test.tsx +1816 -0
- package/Tests/App/Dashboard/IncidentFormPlan.test.ts +89 -0
- package/Tests/App/Dashboard/IncidentFormShareLinkCard.test.tsx +846 -0
- package/Tests/App/Dashboard/IncidentFormsPages.test.tsx +1324 -0
- package/Tests/App/Dashboard/IncidentTemplateCustomFieldSettings.test.tsx +630 -0
- package/Tests/App/Dashboard/IncidentsSideMenu.test.tsx +13 -0
- package/Tests/App/Dashboard/IncomingEmailMonitorLinkVerifyHint.test.tsx +104 -0
- package/Tests/App/Dashboard/InvestigationConversation.test.tsx +1107 -0
- package/Tests/App/Dashboard/InvestigationConversationData.test.ts +546 -0
- package/Tests/App/Dashboard/InvestigationEvidenceList.test.tsx +170 -5
- package/Tests/App/Dashboard/InvestigationInfrastructureTools.test.tsx +506 -0
- package/Tests/App/Dashboard/InvestigationNotStarted.test.tsx +207 -2
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +729 -34
- package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +9 -21
- package/Tests/App/Dashboard/InvestigationReportView.test.tsx +274 -37
- package/Tests/App/Dashboard/InvestigationStatusBadge.test.tsx +130 -0
- package/Tests/App/Dashboard/IoTDocumentationCard.test.tsx +218 -0
- package/Tests/App/Dashboard/IoTSetupGuide.test.ts +1124 -0
- package/Tests/App/Dashboard/KubernetesClusterAiAccessSettings.test.ts +20 -6
- package/Tests/App/Dashboard/KubernetesClusterAiDocumentationMarkdown.test.ts +107 -83
- package/Tests/App/Dashboard/KubernetesSetupGuide.test.ts +787 -0
- package/Tests/App/Dashboard/MessageQueueBreadcrumbs.test.tsx +228 -0
- package/Tests/App/Dashboard/MessageQueueBrokerHealth.test.tsx +1538 -0
- package/Tests/App/Dashboard/MessageQueueBrokerHealthMetricChart.test.tsx +969 -0
- package/Tests/App/Dashboard/MessageQueueBrokerHealthReads.test.ts +889 -0
- package/Tests/App/Dashboard/MessageQueueBrokerMetricsReach.test.ts +236 -0
- package/Tests/App/Dashboard/MessageQueueDocumentationCard.test.tsx +479 -0
- package/Tests/App/Dashboard/MessageQueueListPages.test.tsx +1232 -0
- package/Tests/App/Dashboard/MessageQueueMetricDescriptions.test.ts +244 -0
- package/Tests/App/Dashboard/MessageQueueMonitorLink.test.ts +952 -0
- package/Tests/App/Dashboard/MessageQueueMonitorLinkMonitorCreate.test.tsx +859 -0
- package/Tests/App/Dashboard/MessageQueueOverview.test.tsx +1773 -0
- package/Tests/App/Dashboard/MessageQueueOverviewPresentation.test.ts +196 -0
- package/Tests/App/Dashboard/MessageQueuePresentation.test.ts +799 -0
- package/Tests/App/Dashboard/MessageQueueProducersConsumers.test.tsx +680 -0
- package/Tests/App/Dashboard/MessageQueueRoutes.test.tsx +383 -0
- package/Tests/App/Dashboard/MessageQueueRulePages.test.tsx +278 -0
- package/Tests/App/Dashboard/MessageQueueSetupGuide.test.ts +2778 -0
- package/Tests/App/Dashboard/MessageQueueSideMenus.test.tsx +273 -0
- package/Tests/App/Dashboard/MessageQueueSpanPopulations.test.ts +930 -0
- package/Tests/App/Dashboard/MessageQueueSpanStore.ts +351 -0
- package/Tests/App/Dashboard/MessageQueueTelemetryScope.test.ts +375 -0
- package/Tests/App/Dashboard/MessageQueueTelemetryScopeTabs.test.tsx +668 -0
- package/Tests/App/Dashboard/MessageQueueViewPages.test.tsx +685 -0
- package/Tests/App/Dashboard/MonitorAndHomeNotOperationalMenus.test.tsx +342 -0
- package/Tests/App/Dashboard/MonitorCreateFirstRunDefaults.test.tsx +623 -0
- package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +442 -0
- package/Tests/App/Dashboard/MonitorLogsPageViewSummary.test.tsx +814 -0
- package/Tests/App/Dashboard/MonitorSetupCardBodies.test.tsx +246 -0
- package/Tests/App/Dashboard/NavigationSearchKeywords.test.tsx +8 -0
- package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +27 -12
- package/Tests/App/Dashboard/PlanGatedPage.test.tsx +292 -0
- package/Tests/App/Dashboard/PodmanSetupGuide.test.ts +948 -0
- package/Tests/App/Dashboard/ProductOrientation.test.tsx +5 -4
- package/Tests/App/Dashboard/ProductSettingsSectionCollapsed.test.tsx +266 -0
- package/Tests/App/Dashboard/ProxmoxSetupGuide.test.ts +1318 -0
- package/Tests/App/Dashboard/RemediationSuggestionCardDescription.test.tsx +209 -0
- package/Tests/App/Dashboard/RemediationSuggestionCardResource.test.tsx +317 -0
- package/Tests/App/Dashboard/ResourceAiAccessSettingsUtil.test.ts +921 -0
- package/Tests/App/Dashboard/ResourceAiAgentAttentionServerParity.test.ts +555 -0
- package/Tests/App/Dashboard/ResourceAiAgentInstall.test.ts +860 -0
- package/Tests/App/Dashboard/ResourceAiAgentPage.test.tsx +2010 -0
- package/Tests/App/Dashboard/ResourceAiAgentStatus.test.ts +1455 -0
- package/Tests/App/Dashboard/ResourceAiInsightsPage.test.tsx +931 -0
- package/Tests/App/Dashboard/ResourceAiNavigation.test.tsx +575 -0
- package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +16 -0
- package/Tests/App/Dashboard/ResourceConnectionGuideCard.test.tsx +444 -0
- package/Tests/App/Dashboard/ResourceConnectionGuideOverviewsInfra.test.tsx +798 -0
- package/Tests/App/Dashboard/ResourceConnectionGuideOverviewsPlatforms.test.tsx +717 -0
- package/Tests/App/Dashboard/ResourceConnectionGuides.test.ts +981 -0
- package/Tests/App/Dashboard/ResourceConnectionState.test.ts +132 -0
- package/Tests/App/Dashboard/RumDocumentationCard.test.tsx +293 -0
- package/Tests/App/Dashboard/RumSessionReplayRetentionSettings.test.tsx +467 -0
- package/Tests/App/Dashboard/RumSetupGuide.test.ts +758 -0
- package/Tests/App/Dashboard/RunbookStepTypeMaps.test.ts +38 -7
- package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +25 -0
- package/Tests/App/Dashboard/ServerlessDocumentationCard.test.tsx +254 -0
- package/Tests/App/Dashboard/ServerlessSetupGuide.test.ts +1074 -0
- package/Tests/App/Dashboard/SetupGuide.test.ts +246 -0
- package/Tests/App/Dashboard/SetupGuideCard.test.tsx +756 -0
- package/Tests/App/Dashboard/SloListSideMenu.test.tsx +120 -0
- package/Tests/App/Dashboard/SsoPages.test.tsx +833 -0
- package/Tests/App/Dashboard/TelemetryDocumentation.test.tsx +253 -0
- package/Tests/App/Dashboard/TelemetryRetentionShells.test.tsx +730 -0
- package/Tests/App/Dashboard/VMwareSetupGuide.test.ts +1033 -0
- package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +87 -7
- package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +61 -10
- package/Tests/Models/DatabaseModels/IncidentFormModel.test.ts +1250 -0
- package/Tests/Models/DatabaseModels/MessageQueueModels.test.ts +1983 -0
- package/Tests/Models/DatabaseModels/ResourceAiAccessColumns.test.ts +738 -0
- package/Tests/Models/DatabaseModels/ResourceAiAgentModel.test.ts +842 -0
- package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
- package/Tests/Models/DatabaseModels/TeamComplianceSettingModel.test.ts +190 -14
- package/Tests/Models/IncidentTemplateCustomFieldSettingsColumn.test.ts +291 -0
- package/Tests/Server/API/AIInvestigationConversationAPI.test.ts +412 -0
- package/Tests/Server/API/AutoRemediationApproveResourceRound.test.ts +835 -0
- package/Tests/Server/API/GlobalConfigLicense.test.ts +38 -9
- package/Tests/Server/API/IncidentFormAPI.test.ts +942 -0
- package/Tests/Server/API/IncidentFormPublicRoutes.test.ts +1653 -0
- package/Tests/Server/API/KubernetesClusterAiAccessAPI.test.ts +2 -1
- package/Tests/Server/API/ResourceAiAccessAPI.test.ts +2730 -0
- package/Tests/Server/API/{SsoProviderListingsEdition.test.ts → SsoProviderListings.test.ts} +164 -110
- package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +76 -54
- package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +125 -42
- package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +36 -10
- package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +51 -9
- package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +13 -8
- package/Tests/Server/Enterprise/SsoInCommunityEdition.test.ts +540 -0
- package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
- package/Tests/Server/Infrastructure/Postgres/AddDatabaseServerTablesMigration.test.ts +60 -0
- package/Tests/Server/Infrastructure/Postgres/AddIncidentFormsMigration.test.ts +438 -0
- package/Tests/Server/Infrastructure/Postgres/AddResourceAiAgentsMigration.test.ts +659 -0
- package/Tests/Server/Infrastructure/Postgres/AddTeamComplianceRuleNotificationChannelsMigration.test.ts +255 -0
- package/Tests/Server/Infrastructure/Postgres/MessageQueueTablesMigration.test.ts +637 -0
- package/Tests/Server/Infrastructure/SemaphoreMutex.test.ts +31 -0
- package/Tests/Server/Middleware/IncidentFormRateLimit.test.ts +1630 -0
- package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +63 -5
- package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerPinnedKey.test.ts +103 -5
- package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerRateLimit.test.ts +19 -1
- package/Tests/Server/Middleware/UserAuthorization.test.ts +16 -17
- package/Tests/Server/Middleware/UserAuthorizationSsoEnforcement.test.ts +544 -0
- package/Tests/Server/Services/AIServiceDailyBudget.test.ts +37 -8
- package/Tests/Server/Services/AutoRemediationResourceRuleEngine.test.ts +1279 -0
- package/Tests/Server/Services/DatabaseServerService.test.ts +55 -0
- package/Tests/Server/Services/GroupTelemetryUsageExcludeNames.test.ts +299 -0
- package/Tests/Server/Services/HostServiceFindOrCreateMemo.test.ts +44 -0
- package/Tests/Server/Services/IncidentCreatedFeedTitle.test.ts +212 -0
- package/Tests/Server/Services/IncidentCustomFieldDeleteFormQuestions.test.ts +297 -0
- package/Tests/Server/Services/IncidentFormOwnersCreatedNotification.test.ts +497 -0
- package/Tests/Server/Services/IncidentFormPostgres.test.ts +958 -0
- package/Tests/Server/Services/IncidentFormPublicForm.test.ts +1260 -0
- package/Tests/Server/Services/IncidentFormPublicSubmission.test.ts +2520 -0
- package/Tests/Server/Services/IncidentFormRegistration.test.ts +159 -0
- package/Tests/Server/Services/IncidentFormService.test.ts +663 -0
- package/Tests/Server/Services/IncidentFormSubmissionService.test.ts +430 -0
- package/Tests/Server/Services/IncidentFormSubmissionTemplateBranch.test.ts +473 -0
- package/Tests/Server/Services/IncidentGroupingTemplateSubstitution.test.ts +81 -0
- package/Tests/Server/Services/IncidentTemplateCustomFieldSettings.test.ts +262 -0
- package/Tests/Server/Services/IncidentTemplateOwnersOnDeclare.test.ts +566 -0
- package/Tests/Server/Services/IncidentTitleMarkdownSinks.test.ts +640 -0
- package/Tests/Server/Services/LlmLogServiceTokenAggregateParams.test.ts +3 -3
- package/Tests/Server/Services/MessageQueueOwnerServices.test.ts +440 -0
- package/Tests/Server/Services/MessageQueueRegistries.test.ts +577 -0
- package/Tests/Server/Services/MessageQueueRuleEngines.test.ts +900 -0
- package/Tests/Server/Services/MessageQueueService.test.ts +2210 -0
- package/Tests/Server/Services/MessageQueueSqlPostgres.test.ts +1271 -0
- package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +45 -6
- package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +28 -1
- package/Tests/Server/Services/OpenTelemetryRetentionOverrideEdition.test.ts +474 -0
- package/Tests/Server/Services/OpenTelemetryServiceResolutionCache.test.ts +21 -0
- package/Tests/Server/Services/OwnerRowUniqueness.test.ts +3 -0
- package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +0 -1
- package/Tests/Server/Services/RecordingRuleReservedMetricName.test.ts +171 -0
- package/Tests/Server/Services/ResourceAiAccessChangeAuthorization.test.ts +256 -0
- package/Tests/Server/Services/ResourceAiAccessService.test.ts +1373 -0
- package/Tests/Server/Services/ResourceAiAgentJobService.test.ts +375 -0
- package/Tests/Server/Services/ResourceAiAgentServiceHelpers.test.ts +1114 -0
- package/Tests/Server/Services/ResourceAiAgentServiceLifecycle.test.ts +1050 -0
- package/Tests/Server/Services/ResourceAiAgentServiceRegister.test.ts +2251 -0
- package/Tests/Server/Services/ResourceAiSettingsCreate.test.ts +373 -0
- package/Tests/Server/Services/ResourceAiSettingsPermission.test.ts +1042 -0
- package/Tests/Server/Services/ResourceServiceDeleteCleansUpAi.test.ts +319 -0
- package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +56 -6
- package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +30 -1
- package/Tests/Server/Services/RunnerJobEnqueueKubectl.test.ts +105 -0
- package/Tests/Server/Services/RunnerJobEnqueueResourceCommand.test.ts +986 -0
- package/Tests/Server/Services/RunnerJobResourceCommandLane.test.ts +211 -0
- package/Tests/Server/Services/RunnerJobResourceCommandTimeoutAndRedaction.test.ts +352 -0
- package/Tests/Server/Services/SsoRequirementReads.test.ts +454 -0
- package/Tests/Server/Services/SsoRequirementWrites.test.ts +529 -0
- package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +3 -3
- package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +107 -89
- package/Tests/Server/Services/TeamComplianceSettingPostgres.test.ts +1068 -176
- package/Tests/Server/Services/TeamComplianceSettingService.test.ts +1962 -200
- package/Tests/Server/Services/TelemetryUsageBillingSloExclusion.test.ts +218 -0
- package/Tests/Server/TestingUtils/Services/FakeRunnerJobCount.ts +145 -0
- package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +654 -297
- package/Tests/Server/Types/Database/Permissions/RetentionOverrideColumns.test.ts +784 -0
- package/Tests/Server/Types/Database/Permissions/SsoScalePlanGate.test.ts +418 -0
- package/Tests/Server/Utils/AI/AIAlertGating.test.ts +0 -1
- package/Tests/Server/Utils/AI/AIInvestigationEngineRunLimits.test.ts +136 -0
- package/Tests/Server/Utils/AI/AIInvestigationQueue.test.ts +15 -14
- package/Tests/Server/Utils/AI/AgentContextCompactor.test.ts +351 -0
- package/Tests/Server/Utils/AI/ChatAgentRunnerSharedThread.test.ts +842 -0
- package/Tests/Server/Utils/AI/ChatRunCancellation.test.ts +195 -0
- package/Tests/Server/Utils/AI/CodeFixReadiness.test.ts +10 -57
- package/Tests/Server/Utils/AI/FixRunBudget.test.ts +20 -24
- package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +7 -30
- package/Tests/Server/Utils/AI/InvestigationClusterAccessWiring.test.ts +225 -29
- package/Tests/Server/Utils/AI/InvestigationInfrastructureAccessWiring.test.ts +694 -0
- package/Tests/Server/Utils/AI/InvestigationInfrastructureReport.test.ts +721 -0
- package/Tests/Server/Utils/AI/InvestigationThread.test.ts +580 -0
- package/Tests/Server/Utils/AI/InvestigationThreadService.test.ts +801 -0
- package/Tests/Server/Utils/AI/KubectlInvestigationToolkit.test.ts +525 -43
- package/Tests/Server/Utils/AI/KubectlJobRunner.test.ts +4 -2
- package/Tests/Server/Utils/AI/LLMServiceUnreachableProvider.test.ts +435 -0
- package/Tests/Server/Utils/AI/ObservabilityAssistantLimits.test.ts +462 -0
- package/Tests/Server/Utils/AI/RemediationCommandTools.test.ts +94 -1
- package/Tests/Server/Utils/AI/RemediationCommandToolsResource.test.ts +1530 -0
- package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +14 -25
- package/Tests/Server/Utils/AI/RemediationExecutionRunnerResourceMode.test.ts +1251 -0
- package/Tests/Server/Utils/AI/RemediationPlanRunner.test.ts +117 -0
- package/Tests/Server/Utils/AI/RemediationResourceCopyParity.test.ts +463 -0
- package/Tests/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.test.ts +1004 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceAccessContext.test.ts +266 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.test.ts +1220 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.test.ts +569 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.test.ts +834 -0
- package/Tests/Server/Utils/AI/ToolOutputPager.test.ts +382 -0
- package/Tests/Server/Utils/AI/ToolResultSerializer.test.ts +23 -4
- package/Tests/Server/Utils/AI/Toolbox/LogTools.test.ts +25 -6
- package/Tests/Server/Utils/AI/Toolbox/Serializer.test.ts +14 -3
- package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorResource.test.ts +717 -0
- package/Tests/Server/Utils/AutoRemediation/RemediationVerifierResourceFollowUp.test.ts +338 -0
- package/Tests/Server/Utils/EditionEnforcement.test.ts +107 -147
- package/Tests/Server/Utils/Monitor/Criteria/SessionReplayBudgetTemplateCriteria.test.ts +422 -0
- package/Tests/Server/Utils/{CommunityEditionSsoReport.test.ts → RelaxedScimTeamLocksReport.test.ts} +212 -208
- package/Tests/Server/Utils/SameOriginRequest.test.ts +372 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.test.ts +1647 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayUsage.test.ts +143 -1
- package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +20 -0
- package/Tests/Server/Utils/Telemetry/MessageQueueDiscovery.test.ts +2590 -0
- package/Tests/Server/Utils/Telemetry/MessageQueueSpanQueryTwin.ts +246 -0
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +23 -0
- package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +33 -3
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsAccountNotLinked.test.ts +1093 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.test.ts +1049 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.test.ts +1676 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCards.test.ts +2884 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.test.ts +2490 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateSubmit.test.ts +2293 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateSubmitServerTimezone.test.ts +386 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.test.ts +1477 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.test.ts +1967 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsStripHtmlTags.test.ts +92 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsSubmittedFormRemoval.test.ts +1819 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.test.ts +1033 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezoneServerZone.test.ts +610 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsBotMessageHandling.test.ts +2610 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsCreateCommandsEndToEnd.test.ts +4672 -0
- package/Tests/Server/Utils/Workspace/WorkspaceCreateProjectReferences.test.ts +190 -65
- package/Tests/Types/AI/AIAgentRunLimits.test.ts +255 -0
- package/Tests/Types/AutoRemediation/AiRemediationCommandPlan.test.ts +10 -4
- package/Tests/Types/AutoRemediation/AiRemediationCommandPlanResourceCommand.test.ts +305 -0
- package/Tests/Types/Code/JsonSyntax.test.ts +1300 -0
- package/Tests/Types/CustomField/CustomFieldCreateSettings.test.ts +1113 -0
- package/Tests/Types/CustomField/CustomFieldMappingCatalog.test.ts +91 -0
- package/Tests/Types/CustomField/CustomFieldValueValidator.test.ts +30 -0
- package/Tests/Types/Incident/IncidentFormIpAllowlist.test.ts +227 -0
- package/Tests/Types/Incident/IncidentFormPublic.test.ts +1916 -0
- package/Tests/Types/MessageQueue/MessageQueueEntityKey.test.ts +916 -0
- package/Tests/Types/MessageQueue/MessageQueueIdentity.test.ts +567 -0
- package/Tests/Types/MessageQueue/MessageQueueManualIdentity.test.ts +686 -0
- package/Tests/Types/MessageQueue/MessageQueueMetricCatalog.test.ts +1726 -0
- package/Tests/Types/MessageQueue/MessageQueueMetricResolution.test.ts +1758 -0
- package/Tests/Types/MessageQueue/MessagingInstrumentationFixtures.test.ts +4686 -0
- package/Tests/Types/MessageQueue/MessagingSystem.test.ts +840 -0
- package/Tests/Types/MessageQueue/MessagingTelemetryFixtures.ts +3287 -0
- package/Tests/Types/MessageQueue/MessagingTelemetryResolver.test.ts +2966 -0
- package/Tests/Types/Monitor/MessageQueueAlertTemplates.test.ts +5401 -0
- package/Tests/Types/Monitor/MetricEngineFold.ts +154 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +277 -13
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +113 -0
- package/Tests/Types/Monitor/RumAlertTemplates.test.ts +773 -2
- package/Tests/Types/ResourceAiAgent/AiResourceType.test.ts +419 -0
- package/Tests/Types/ResourceAiAgent/ResourceAiAccess.test.ts +519 -0
- package/Tests/Types/Runbook/RunbookStepType.test.ts +147 -8
- package/Tests/Types/Team/ComplianceRule.test.ts +588 -37
- package/Tests/Types/Team/TeamComplianceStatus.test.ts +64 -11
- package/Tests/Types/XML.test.ts +51 -0
- package/Tests/UI/Components/CodeEditor/CodeEditor.test.tsx +2362 -0
- package/Tests/UI/Components/CodeEditor/CodeEditorCommands.test.ts +810 -0
- package/Tests/UI/Components/CodeEditor/CodeEditorHighlight.test.ts +338 -0
- package/Tests/UI/Components/CodeEditor/CodeEditorLanguages.test.ts +222 -0
- package/Tests/UI/Components/CodeEditor/CodeEditorStyles.test.ts +807 -0
- package/Tests/UI/Components/CodeEditor/NoMonaco.test.ts +245 -0
- package/Tests/UI/Components/CodeEditor/YamlEditor.test.tsx +729 -0
- package/Tests/UI/Components/CopyTextButton.test.tsx +76 -0
- package/Tests/UI/Components/EditionLabelLapseCopy.ts +51 -14
- package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +131 -23
- package/Tests/UI/Components/ErrorMessageAction.test.tsx +142 -0
- package/Tests/UI/Components/FacetSidebarInScope.test.tsx +459 -0
- package/Tests/UI/Components/FacetValuesInScope.test.ts +270 -0
- package/Tests/UI/Components/Forms/FormFieldCodeEditors.test.tsx +294 -0
- package/Tests/UI/Components/Forms/FormFieldMarkdown.test.tsx +126 -0
- package/Tests/UI/Components/Forms/FormFieldYaml.test.tsx +22 -75
- package/Tests/UI/Components/Forms/ModelFormOnBeforeCreateMiscData.test.tsx +254 -0
- package/Tests/UI/Components/Icon.test.tsx +32 -0
- package/Tests/UI/Components/Input.test.tsx +31 -0
- package/Tests/UI/Components/LockedFilterChipScope.test.tsx +501 -0
- package/Tests/UI/Components/MarkdownConverters.test.ts +253 -1
- package/Tests/UI/Components/MarkdownEditor.test.tsx +2785 -2
- package/Tests/UI/Components/MarkdownEditorHistory.test.ts +243 -0
- package/Tests/UI/Components/MarkdownListEditing.test.ts +1118 -0
- package/Tests/UI/Components/MarkdownPaste.test.ts +1180 -0
- package/Tests/UI/Components/MarkdownViewerCopy.test.tsx +466 -0
- package/Tests/UI/Components/MarkdownVisualEditing.test.ts +1089 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableEmptyStateAction.test.tsx +623 -0
- package/Tests/UI/Components/ResetObjectID.test.tsx +282 -0
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
- package/Tests/UI/Components/Table/EmptyTableMessage.test.ts +439 -0
- package/Tests/UI/Components/Table/TableEmptyState.test.tsx +352 -0
- package/Tests/UI/Components/TableRowMobileTitles.test.tsx +78 -0
- package/Tests/UI/Components/TextArea.test.tsx +19 -0
- package/Tests/UI/Components/Workflow/ModelColumnEditor.render.test.tsx +12 -29
- package/Tests/UI/Components/fixtures/MarkdownPasteFixtures.ts +460 -0
- package/Tests/UI/EsbuildConfig.test.ts +115 -39
- package/Tests/UI/EsbuildEnterpriseAlias.test.ts +4 -4
- package/Tests/UI/Monitor/MonitorLogSummaryRender.test.tsx +377 -0
- package/Tests/UI/Rum/RecordingHealthDashboard.test.tsx +769 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +81 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +17 -0
- package/Tests/Utils/AiRemediation/Resource/CephCommandPolicy.test.ts +1653 -0
- package/Tests/Utils/AiRemediation/Resource/CephOutputRedaction.test.ts +204 -0
- package/Tests/Utils/AiRemediation/Resource/DatabaseCommandPolicy.test.ts +1077 -0
- package/Tests/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.test.ts +558 -0
- package/Tests/Utils/AiRemediation/Resource/DatabaseQueryRedactor.test.ts +834 -0
- package/Tests/Utils/AiRemediation/Resource/DockerCliGrammar.test.ts +747 -0
- package/Tests/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.test.ts +1259 -0
- package/Tests/Utils/AiRemediation/Resource/DockerOutputRedaction.test.ts +386 -0
- package/Tests/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.test.ts +782 -0
- package/Tests/Utils/AiRemediation/Resource/GovcCommandPolicy.test.ts +2259 -0
- package/Tests/Utils/AiRemediation/Resource/HostCommandPolicy.test.ts +2019 -0
- package/Tests/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.test.ts +2497 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceCommandPolicy.test.ts +1305 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.test.ts +585 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceOutputRedactor.test.ts +334 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceOutputRedactorCopyParity.test.ts +98 -0
- package/Tests/Utils/AiRemediation/Resource/ResourcePolicyImportClosure.test.ts +391 -0
- package/Tests/Utils/AiRemediation/ResourceAiAgentPolicyCopyParity.test.ts +497 -0
- package/Tests/Utils/LabelRuleImportExport.test.ts +5 -0
- package/Tests/Utils/Markdown/DashboardMarkdownRenderer.ts +81 -0
- package/Tests/Utils/Markdown/UntrustedMarkdown.test.ts +1339 -0
- package/Tests/Utils/Monitor/MonitorLogSummaryUtil.test.ts +862 -0
- package/Tests/Utils/SessionReplay/SessionReplayBudgetMetricType.test.ts +383 -0
- package/Types/AI/AIAgentRunLimits.ts +146 -0
- package/Types/AI/ResourceAiAccessApi.ts +140 -0
- package/Types/AI/ResourceAiAccessPermissions.ts +126 -0
- package/Types/AutoRemediation/AiRemediationCommandPlan.ts +183 -2
- package/Types/Code/CodeType.ts +2 -0
- package/Types/Code/JsonSyntax.ts +923 -0
- package/Types/CustomField/CustomFieldCreateSettings.ts +549 -0
- package/Types/CustomField/CustomFieldMappingCatalog.ts +77 -0
- package/Types/CustomField/CustomFieldValueValidator.ts +10 -7
- package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +1 -1
- package/Types/Icon/IconProp.ts +2 -0
- package/Types/Incident/IncidentFormIpAllowlist.ts +206 -0
- package/Types/Incident/IncidentFormPublic.ts +1145 -0
- package/Types/Kubernetes/KubernetesClusterAiAccess.ts +10 -3
- package/Types/MessageQueue/MessageQueueIdentity.ts +256 -0
- package/Types/MessageQueue/MessageQueueManualIdentity.ts +325 -0
- package/Types/MessageQueue/MessageQueueMetricCatalog.ts +1357 -0
- package/Types/MessageQueue/MessagingSystem.ts +518 -0
- package/Types/MessageQueue/MessagingTelemetryResolver.ts +2311 -0
- package/Types/Monitor/MessageQueueAlertTemplates.ts +2128 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +55 -22
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +35 -3
- package/Types/Monitor/RumAlertTemplates.ts +351 -4
- package/Types/Permission.ts +310 -0
- package/Types/ResourceAiAgent/AiResourceType.ts +310 -0
- package/Types/ResourceAiAgent/ResourceAiAccess.ts +580 -0
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +12 -0
- package/Types/Rules/RuleRun.ts +4 -0
- package/Types/Rum/SessionReplayBudgetMetricType.ts +47 -0
- package/Types/Runbook/RunbookStepType.ts +29 -0
- package/Types/Team/ComplianceNotificationChannel.ts +4 -3
- package/Types/Team/ComplianceRule.ts +71 -18
- package/Types/Team/ComplianceRuleType.ts +2 -2
- package/Types/Team/TeamComplianceStatus.ts +6 -2
- package/Types/Telemetry/EntityType.ts +16 -0
- package/Types/Telemetry/LockedFilterDetail.ts +22 -0
- package/Types/Telemetry/TelemetryIngestSurface.ts +14 -2
- package/Types/XML.ts +26 -0
- package/UI/Components/CodeEditor/CodeEditor.css +379 -0
- package/UI/Components/CodeEditor/CodeEditor.tsx +1128 -294
- package/UI/Components/CodeEditor/CodeEditorCommands.ts +774 -0
- package/UI/Components/CodeEditor/CodeEditorHighlight.ts +106 -0
- package/UI/Components/CodeEditor/CodeEditorLanguages.ts +164 -0
- package/UI/Components/CodeEditor/YamlEditor.tsx +28 -326
- package/UI/Components/CopyTextButton/CopyTextButton.tsx +5 -1
- package/UI/Components/CustomFields/CustomFieldModelFormFields.tsx +6 -25
- package/UI/Components/EditionLabel/EditionLabel.tsx +14 -13
- package/UI/Components/ErrorMessage/ErrorMessage.tsx +11 -1
- package/UI/Components/Forms/Fields/FormField.tsx +8 -0
- package/UI/Components/Forms/Types/Field.ts +8 -0
- package/UI/Components/Icon/Icon.tsx +18 -0
- package/UI/Components/Input/Input.tsx +11 -4
- package/UI/Components/LogsViewer/LogsViewer.tsx +4 -0
- package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +21 -3
- package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
- package/UI/Components/Markdown.tsx/MarkdownEditor.tsx +877 -79
- package/UI/Components/Markdown.tsx/MarkdownEditorHistory.ts +284 -0
- package/UI/Components/Markdown.tsx/MarkdownListEditing.ts +1362 -0
- package/UI/Components/Markdown.tsx/MarkdownPaste.ts +1326 -0
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +106 -10
- package/UI/Components/Markdown.tsx/MarkdownVisualEditing.ts +1032 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +85 -7
- package/UI/Components/ResetObjectID/ResetObjectID.tsx +35 -9
- package/UI/Components/Table/EmptyTableMessage.ts +81 -0
- package/UI/Components/Table/Table.tsx +50 -21
- package/UI/Components/Table/TableRow.tsx +9 -1
- package/UI/Components/TelemetryViewer/FacetVisibility.ts +97 -2
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +13 -0
- package/UI/Components/TelemetryViewer/components/LockedFilterChip.tsx +214 -7
- package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +21 -3
- package/UI/Components/TextArea/TextArea.tsx +9 -2
- package/UI/Components/Workflow/ModelFieldPicker.tsx +10 -12
- package/UI/Styles/Theme.css +8 -0
- package/UI/esbuild-config.js +2 -32
- package/Utils/AI/InvestigationReport.ts +121 -15
- package/Utils/AiRemediation/Resource/CephCommandPolicy.ts +1936 -0
- package/Utils/AiRemediation/Resource/DatabaseCommandPolicy.ts +166 -0
- package/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.ts +1532 -0
- package/Utils/AiRemediation/Resource/DatabaseQueryRedactor.ts +1394 -0
- package/Utils/AiRemediation/Resource/DockerCliGrammar.ts +1839 -0
- package/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.ts +490 -0
- package/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.ts +687 -0
- package/Utils/AiRemediation/Resource/GovcCommandPolicy.ts +2096 -0
- package/Utils/AiRemediation/Resource/HostCommandPolicy.ts +2982 -0
- package/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.ts +1679 -0
- package/Utils/AiRemediation/Resource/ResourceCommandPolicy.ts +851 -0
- package/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.ts +593 -0
- package/Utils/AiRemediation/Resource/ResourceOutputRedactor.ts +2812 -0
- package/Utils/LabelRuleImportExport.ts +2 -0
- package/Utils/Markdown/UntrustedMarkdown.ts +1513 -0
- package/Utils/Monitor/IncomingEmailMonitorRequestUtil.ts +41 -0
- package/Utils/Monitor/MonitorLogSummaryUtil.ts +212 -0
- package/Utils/SessionReplay/SessionReplayBudgetMetricType.ts +184 -0
- package/Utils/Telemetry/EntityKey.ts +48 -0
- package/build/dist/Models/DatabaseModels/AIConversation.js +125 -1
- package/build/dist/Models/DatabaseModels/AIConversation.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js +62 -0
- package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CephCluster.js +231 -0
- package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CloudResource.js +12 -0
- package/build/dist/Models/DatabaseModels/CloudResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseServer.js +231 -0
- package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerHost.js +231 -0
- package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js +231 -0
- package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalOidc.js +0 -4
- package/build/dist/Models/DatabaseModels/GlobalOidc.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalOidcProject.js +0 -4
- package/build/dist/Models/DatabaseModels/GlobalOidcProject.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalSso.js +0 -4
- package/build/dist/Models/DatabaseModels/GlobalSso.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalSsoProject.js +0 -4
- package/build/dist/Models/DatabaseModels/GlobalSsoProject.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Host.js +231 -0
- package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentForm.js +605 -0
- package/build/dist/Models/DatabaseModels/IncidentForm.js.map +1 -0
- package/build/dist/Models/DatabaseModels/IncidentFormSubmission.js +299 -0
- package/build/dist/Models/DatabaseModels/IncidentFormSubmission.js.map +1 -0
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js +60 -0
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +16 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IoTFleet.js +12 -0
- package/build/dist/Models/DatabaseModels/IoTFleet.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js +12 -0
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MessageQueue.js +1106 -0
- package/build/dist/Models/DatabaseModels/MessageQueue.js.map +1 -0
- package/build/dist/Models/DatabaseModels/MessageQueueLabelRule.js +562 -0
- package/build/dist/Models/DatabaseModels/MessageQueueLabelRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerRule.js +643 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerTeam.js +506 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerUser.js +505 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerUser.js.map +1 -0
- package/build/dist/Models/DatabaseModels/PodmanHost.js +231 -0
- package/build/dist/Models/DatabaseModels/PodmanHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +61 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProjectOidc.js +0 -4
- package/build/dist/Models/DatabaseModels/ProjectOidc.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProjectSso.js +0 -4
- package/build/dist/Models/DatabaseModels/ProjectSso.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +231 -0
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ResourceAiAgent.js +439 -0
- package/build/dist/Models/DatabaseModels/ResourceAiAgent.js.map +1 -0
- package/build/dist/Models/DatabaseModels/RumApplication.js +12 -0
- package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RunnerJob.js +145 -0
- package/build/dist/Models/DatabaseModels/RunnerJob.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServerlessFunction.js +12 -0
- package/build/dist/Models/DatabaseModels/ServerlessFunction.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Service.js +12 -0
- package/build/dist/Models/DatabaseModels/Service.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageOidc.js +0 -4
- package/build/dist/Models/DatabaseModels/StatusPageOidc.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageSso.js +0 -4
- package/build/dist/Models/DatabaseModels/StatusPageSso.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js +49 -3
- package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js.map +1 -1
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js +231 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js.map +1 -1
- package/build/dist/Server/API/AIChatAPI.js +9 -103
- package/build/dist/Server/API/AIChatAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +3 -3
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationConversationAPI.js +162 -0
- package/build/dist/Server/API/AIInvestigationConversationAPI.js.map +1 -0
- package/build/dist/Server/API/AutoRemediationAPI.js +231 -1
- package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
- package/build/dist/Server/API/IncidentFormAPI.js +245 -0
- package/build/dist/Server/API/IncidentFormAPI.js.map +1 -0
- package/build/dist/Server/API/ProjectOIDC.js +16 -24
- package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
- package/build/dist/Server/API/ProjectSSO.js +16 -24
- package/build/dist/Server/API/ProjectSSO.js.map +1 -1
- package/build/dist/Server/API/ResourceAiAccessAPI.js +1119 -0
- package/build/dist/Server/API/ResourceAiAccessAPI.js.map +1 -0
- package/build/dist/Server/API/StatusPageAPI.js +42 -75
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/Enterprise/EnterpriseEdition.js +79 -25
- package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -1
- package/build/dist/Server/Enterprise/EnterpriseFeature.js +24 -3
- package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -1
- package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +1 -1
- package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.js +168 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.js +63 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.js +41 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.js +40 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.js +183 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Semaphore.js +6 -0
- package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
- package/build/dist/Server/Middleware/IncidentFormRateLimit.js +559 -0
- package/build/dist/Server/Middleware/IncidentFormRateLimit.js.map +1 -0
- package/build/dist/Server/Middleware/TelemetryIngest.js +12 -5
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Middleware/UserAuthorization.js +11 -30
- package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +10 -13
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +26 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +601 -3
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterService.js +104 -0
- package/build/dist/Server/Services/CephClusterService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseServerService.js +99 -0
- package/build/dist/Server/Services/DatabaseServerService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostService.js +104 -0
- package/build/dist/Server/Services/DockerHostService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterService.js +104 -0
- package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
- package/build/dist/Server/Services/HostService.js +114 -2
- package/build/dist/Server/Services/HostService.js.map +1 -1
- package/build/dist/Server/Services/IncidentCustomFieldService.js +83 -0
- package/build/dist/Server/Services/IncidentCustomFieldService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeMemberService.js +8 -4
- package/build/dist/Server/Services/IncidentEpisodeMemberService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeService.js +10 -1
- package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/IncidentFormService.js +1202 -0
- package/build/dist/Server/Services/IncidentFormService.js.map +1 -0
- package/build/dist/Server/Services/IncidentFormSubmissionService.js +91 -0
- package/build/dist/Server/Services/IncidentFormSubmissionService.js.map +1 -0
- package/build/dist/Server/Services/IncidentGroupingEngineService.js +20 -8
- package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +106 -4
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentTemplateService.js +18 -0
- package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +14 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MessageQueueLabelRuleEngineService.js +262 -0
- package/build/dist/Server/Services/MessageQueueLabelRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueLabelRuleService.js +13 -0
- package/build/dist/Server/Services/MessageQueueLabelRuleService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueOwnerRuleEngineService.js +334 -0
- package/build/dist/Server/Services/MessageQueueOwnerRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueOwnerRuleService.js +13 -0
- package/build/dist/Server/Services/MessageQueueOwnerRuleService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueOwnerTeamService.js +62 -0
- package/build/dist/Server/Services/MessageQueueOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueOwnerUserService.js +62 -0
- package/build/dist/Server/Services/MessageQueueOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueService.js +1140 -0
- package/build/dist/Server/Services/MessageQueueService.js.map +1 -0
- package/build/dist/Server/Services/MetricRecordingRuleService.js +46 -0
- package/build/dist/Server/Services/MetricRecordingRuleService.js.map +1 -1
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +25 -4
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostService.js +104 -0
- package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +0 -54
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterService.js +104 -0
- package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
- package/build/dist/Server/Services/ResourceAiAccessService.js +1028 -0
- package/build/dist/Server/Services/ResourceAiAccessService.js.map +1 -0
- package/build/dist/Server/Services/ResourceAiAgentJobService.js +173 -0
- package/build/dist/Server/Services/ResourceAiAgentJobService.js.map +1 -0
- package/build/dist/Server/Services/ResourceAiAgentService.js +1687 -0
- package/build/dist/Server/Services/ResourceAiAgentService.js.map +1 -0
- package/build/dist/Server/Services/RunnerJobService.js +344 -5
- package/build/dist/Server/Services/RunnerJobService.js.map +1 -1
- package/build/dist/Server/Services/StatusPagePrivateUserService.js +1 -4
- package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +0 -46
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/TeamComplianceSettingService.js +120 -31
- package/build/dist/Server/Services/TeamComplianceSettingService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryUsageBillingService.js +26 -0
- package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
- package/build/dist/Server/Services/TraceRecordingRuleService.js +37 -0
- package/build/dist/Server/Services/TraceRecordingRuleService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationRuleService.js +8 -1
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/VMwareVCenterService.js +104 -0
- package/build/dist/Server/Services/VMwareVCenterService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js +12 -3
- package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +6 -3
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +109 -37
- package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +16 -0
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/TablePermission.js +3 -3
- package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +9 -6
- package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/AgentContextCompactor.js +128 -0
- package/build/dist/Server/Utils/AI/Chat/AgentContextCompactor.js.map +1 -0
- package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +192 -50
- package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ChatRunCancellation.js +133 -0
- package/build/dist/Server/Utils/AI/Chat/ChatRunCancellation.js.map +1 -0
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +53 -13
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +1 -1
- package/build/dist/Server/Utils/AI/Chat/ToolOutputPager.js +206 -0
- package/build/dist/Server/Utils/AI/Chat/ToolOutputPager.js.map +1 -0
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js +53 -26
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js.map +1 -1
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js +4 -2
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js +1 -29
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +24 -24
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +1036 -32
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +661 -41
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js +21 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js +354 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessContext.js +160 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessContext.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.js +33 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.js +640 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.js +226 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js +602 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +90 -14
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +73 -10
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +73 -10
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js +15 -18
- package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationThread.js +412 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationThread.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationThreadService.js +495 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationThreadService.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/Serializer.js +10 -3
- package/build/dist/Server/Utils/AI/Toolbox/Serializer.js.map +1 -1
- package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js +290 -13
- package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js.map +1 -1
- package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js +29 -1
- package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js.map +1 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +9 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
- package/build/dist/Server/Utils/EditionEnforcement.js +20 -158
- package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -1
- package/build/dist/Server/Utils/LLM/LLMService.js +193 -54
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/RelaxedScimTeamLocksReport.js +160 -0
- package/build/dist/Server/Utils/RelaxedScimTeamLocksReport.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +25 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
- package/build/dist/Server/Utils/SameOriginRequest.js +151 -0
- package/build/dist/Server/Utils/SameOriginRequest.js.map +1 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.js +627 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.js.map +1 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js +60 -5
- package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js.map +1 -1
- package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js +2 -0
- package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +4 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js +1015 -0
- package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +4 -1
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
- package/build/dist/Server/Utils/VendorAssets.js +3 -3
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js +19 -15
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js +19 -15
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js +17 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +186 -210
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +22 -16
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js +233 -167
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +273 -111
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.js +129 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.js +266 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.js +258 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.js +104 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.js +183 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.js +123 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.js.map +1 -0
- package/build/dist/Types/AI/AIAgentRunLimits.js +91 -0
- package/build/dist/Types/AI/AIAgentRunLimits.js.map +1 -0
- package/build/dist/Types/AI/ResourceAiAccessApi.js +30 -0
- package/build/dist/Types/AI/ResourceAiAccessApi.js.map +1 -0
- package/build/dist/Types/AI/ResourceAiAccessPermissions.js +98 -0
- package/build/dist/Types/AI/ResourceAiAccessPermissions.js.map +1 -0
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js +116 -29
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js.map +1 -1
- package/build/dist/Types/Code/CodeType.js +2 -0
- package/build/dist/Types/Code/CodeType.js.map +1 -1
- package/build/dist/Types/Code/JsonSyntax.js +604 -0
- package/build/dist/Types/Code/JsonSyntax.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldCreateSettings.js +310 -0
- package/build/dist/Types/CustomField/CustomFieldCreateSettings.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js +38 -0
- package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js.map +1 -1
- package/build/dist/Types/CustomField/CustomFieldValueValidator.js +10 -7
- package/build/dist/Types/CustomField/CustomFieldValueValidator.js.map +1 -1
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +1 -1
- package/build/dist/Types/Icon/IconProp.js +2 -0
- package/build/dist/Types/Icon/IconProp.js.map +1 -1
- package/build/dist/Types/Incident/IncidentFormIpAllowlist.js +119 -0
- package/build/dist/Types/Incident/IncidentFormIpAllowlist.js.map +1 -0
- package/build/dist/Types/Incident/IncidentFormPublic.js +678 -0
- package/build/dist/Types/Incident/IncidentFormPublic.js.map +1 -0
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js +10 -3
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js.map +1 -1
- package/build/dist/Types/MessageQueue/MessageQueueIdentity.js +184 -0
- package/build/dist/Types/MessageQueue/MessageQueueIdentity.js.map +1 -0
- package/build/dist/Types/MessageQueue/MessageQueueManualIdentity.js +190 -0
- package/build/dist/Types/MessageQueue/MessageQueueManualIdentity.js.map +1 -0
- package/build/dist/Types/MessageQueue/MessageQueueMetricCatalog.js +1057 -0
- package/build/dist/Types/MessageQueue/MessageQueueMetricCatalog.js.map +1 -0
- package/build/dist/Types/MessageQueue/MessagingSystem.js +394 -0
- package/build/dist/Types/MessageQueue/MessagingSystem.js.map +1 -0
- package/build/dist/Types/MessageQueue/MessagingTelemetryResolver.js +1768 -0
- package/build/dist/Types/MessageQueue/MessagingTelemetryResolver.js.map +1 -0
- package/build/dist/Types/Monitor/MessageQueueAlertTemplates.js +1207 -0
- package/build/dist/Types/Monitor/MessageQueueAlertTemplates.js.map +1 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +47 -21
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +5 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
- package/build/dist/Types/Monitor/RumAlertTemplates.js +199 -3
- package/build/dist/Types/Monitor/RumAlertTemplates.js.map +1 -1
- package/build/dist/Types/Permission.js +274 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/ResourceAiAgent/AiResourceType.js +242 -0
- package/build/dist/Types/ResourceAiAgent/AiResourceType.js.map +1 -0
- package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js +281 -0
- package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js.map +1 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +12 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
- package/build/dist/Types/Rules/RuleRun.js +4 -0
- package/build/dist/Types/Rules/RuleRun.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplayBudgetMetricType.js +45 -0
- package/build/dist/Types/Rum/SessionReplayBudgetMetricType.js.map +1 -0
- package/build/dist/Types/Runbook/RunbookStepType.js +27 -0
- package/build/dist/Types/Runbook/RunbookStepType.js.map +1 -1
- package/build/dist/Types/Team/ComplianceNotificationChannel.js +4 -3
- package/build/dist/Types/Team/ComplianceNotificationChannel.js.map +1 -1
- package/build/dist/Types/Team/ComplianceRule.js +48 -14
- package/build/dist/Types/Team/ComplianceRule.js.map +1 -1
- package/build/dist/Types/Team/ComplianceRuleType.js +2 -2
- package/build/dist/Types/Telemetry/EntityType.js +16 -0
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +13 -2
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -1
- package/build/dist/Types/XML.js +23 -0
- package/build/dist/Types/XML.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js +641 -266
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditorCommands.js +464 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorCommands.js.map +1 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorHighlight.js +69 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorHighlight.js.map +1 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorLanguages.js +108 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorLanguages.js.map +1 -0
- package/build/dist/UI/Components/CodeEditor/YamlEditor.js +14 -186
- package/build/dist/UI/Components/CodeEditor/YamlEditor.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/CustomFieldModelFormFields.js +5 -14
- package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +14 -13
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js +1 -1
- package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +8 -3
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +8 -0
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +11 -3
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +2 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +14 -4
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js +710 -65
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditorHistory.js +238 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditorHistory.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownListEditing.js +1028 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownListEditing.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownPaste.js +1088 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownPaste.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +70 -10
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownVisualEditing.js +887 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownVisualEditing.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +57 -6
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ResetObjectID/ResetObjectID.js +7 -5
- package/build/dist/UI/Components/ResetObjectID/ResetObjectID.js.map +1 -1
- package/build/dist/UI/Components/Table/EmptyTableMessage.js +51 -0
- package/build/dist/UI/Components/Table/EmptyTableMessage.js.map +1 -0
- package/build/dist/UI/Components/Table/Table.js +30 -11
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +9 -2
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js +63 -1
- package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +4 -2
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js +91 -10
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +14 -4
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/TextArea/TextArea.js +9 -3
- package/build/dist/UI/Components/TextArea/TextArea.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ModelFieldPicker.js +1 -2
- package/build/dist/UI/Components/Workflow/ModelFieldPicker.js.map +1 -1
- package/build/dist/Utils/AI/InvestigationReport.js +71 -11
- package/build/dist/Utils/AI/InvestigationReport.js.map +1 -1
- package/build/dist/Utils/AiRemediation/Resource/CephCommandPolicy.js +1462 -0
- package/build/dist/Utils/AiRemediation/Resource/CephCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseCommandPolicy.js +122 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.js +1139 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseQueryRedactor.js +1060 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseQueryRedactor.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerCliGrammar.js +1301 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerCliGrammar.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.js +370 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.js +498 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/GovcCommandPolicy.js +1565 -0
- package/build/dist/Utils/AiRemediation/Resource/GovcCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/HostCommandPolicy.js +2206 -0
- package/build/dist/Utils/AiRemediation/Resource/HostCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.js +1129 -0
- package/build/dist/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicy.js +565 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.js +408 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceOutputRedactor.js +1910 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceOutputRedactor.js.map +1 -0
- package/build/dist/Utils/LabelRuleImportExport.js +2 -0
- package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
- package/build/dist/Utils/Markdown/UntrustedMarkdown.js +988 -0
- package/build/dist/Utils/Markdown/UntrustedMarkdown.js.map +1 -0
- package/build/dist/Utils/Monitor/IncomingEmailMonitorRequestUtil.js +34 -0
- package/build/dist/Utils/Monitor/IncomingEmailMonitorRequestUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorLogSummaryUtil.js +148 -0
- package/build/dist/Utils/Monitor/MonitorLogSummaryUtil.js.map +1 -0
- package/build/dist/Utils/SessionReplay/SessionReplayBudgetMetricType.js +160 -0
- package/build/dist/Utils/SessionReplay/SessionReplayBudgetMetricType.js.map +1 -0
- package/build/dist/Utils/Telemetry/EntityKey.js +36 -0
- package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
- package/package.json +1 -3
- package/Server/Utils/CommunityEditionSsoReport.ts +0 -361
- package/Tests/App/Accounts/LoginSsoEdition.test.tsx +0 -616
- package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +0 -217
- package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +0 -271
- package/Tests/App/Dashboard/CloudDocumentationMarkdown.test.ts +0 -215
- package/Tests/App/Dashboard/TelemetryResourceRetentionSettings.test.tsx +0 -784
- package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +0 -518
- package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +0 -419
- package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +0 -769
- package/Tests/UI/Components/CodeEditor.test.tsx +0 -638
- package/Tests/UI/Components/MonacoLoader.test.ts +0 -67
- package/Tests/UI/Components/MonacoRuntime.test.ts +0 -121
- package/Tests/UI/Components/Telemetry/TelemetryRetentionConfigForm.test.tsx +0 -329
- package/Tests/UI/Components/YamlEditor.test.tsx +0 -847
- package/UI/Components/CodeEditor/MonacoLoader.ts +0 -36
- package/UI/Components/Telemetry/TelemetryRetentionConfigForm.tsx +0 -319
- package/UI/Components/Telemetry/TelemetryRetentionConfigSummary.tsx +0 -223
- package/build/dist/Server/Utils/CommunityEditionSsoReport.js +0 -223
- package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +0 -1
- package/build/dist/UI/Components/CodeEditor/MonacoLoader.js +0 -34
- package/build/dist/UI/Components/CodeEditor/MonacoLoader.js.map +0 -1
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js +0 -171
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js.map +0 -1
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigSummary.js +0 -119
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigSummary.js.map +0 -1
|
@@ -0,0 +1,2206 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The host command policy: tiers the host's own diagnostic CLIs, which a
|
|
3
|
+
* Host AI agent runs through nsenter (`nsenter -t 1 -m -u -i -n -p --
|
|
4
|
+
* PROGRAM ARGS`) from a privileged container that shares the host's pid
|
|
5
|
+
* namespace — so every command acts on the host itself, as root.
|
|
6
|
+
*
|
|
7
|
+
* Programs are exact names (HOST_COMMAND_PROGRAMS), never paths, and every
|
|
8
|
+
* command is an argv the agent spawns without a shell. What this policy
|
|
9
|
+
* bounds is therefore each program's own vocabulary, and it reads that
|
|
10
|
+
* vocabulary the way the program does:
|
|
11
|
+
* - getopt_long programs (systemctl, journalctl, df, free, uptime, ss,
|
|
12
|
+
* dmesg, lsblk, uname, top): flags anywhere (GNU permutes), clusters of
|
|
13
|
+
* short flags read letter by letter (`-rf` is -r then -f), a short
|
|
14
|
+
* flag's value attached (`-n50`, and `-n=50` is the value "=50", as
|
|
15
|
+
* getopt reads it) or in the next word, `--flag=value`, and "--" ends
|
|
16
|
+
* the flags. A flag that takes a value takes the next word exactly when
|
|
17
|
+
* the program would — journalctl's -n and -b only when that word parses
|
|
18
|
+
* as their value, top's -w only when it is a number — and a value that
|
|
19
|
+
* starts with "-" is refused unless the flag's values may (a relative
|
|
20
|
+
* time, a boot offset, a descending sort key), so a denied flag can
|
|
21
|
+
* never hide as another flag's value. getopt_long also accepts any
|
|
22
|
+
* unambiguous abbreviation of a long flag; this policy does not: a long
|
|
23
|
+
* flag is matched in full or refused, so no flag hides behind a prefix.
|
|
24
|
+
* - ip reads its own options by prefix (`-b` is -batch, `-n` is -netns)
|
|
25
|
+
* and only before the object; ps mixes UNIX (`-ef`), BSD (`aux`) and
|
|
26
|
+
* GNU (`--sort`) options; kill takes one signal and then pids. Each has
|
|
27
|
+
* its own reader below.
|
|
28
|
+
* - Unknown flags, unknown commands and anything not modelled are Denied,
|
|
29
|
+
* with a reason that names what IS allowed. Every word must be
|
|
30
|
+
* printable ASCII: a look-alike dash or letter is refused, not guessed.
|
|
31
|
+
*
|
|
32
|
+
* Tiers:
|
|
33
|
+
* - Read: systemctl status / is-active / is-failed / is-enabled /
|
|
34
|
+
* is-system-running / list-units / list-unit-files / list-timers /
|
|
35
|
+
* list-sockets / list-jobs / list-dependencies / show (only with -p and
|
|
36
|
+
* only SYSTEMCTL_SHOW_PROPERTIES — never Environment); journalctl
|
|
37
|
+
* bounded by -n (at most MAX_JOURNALCTL_LINES) or --since, never
|
|
38
|
+
* following; df, free, uptime, ps (never the BSD `e` that prints
|
|
39
|
+
* environments), top once in batch mode, ss, ip show/list and route get,
|
|
40
|
+
* dmesg without clearing or following, lsblk, cat of
|
|
41
|
+
* HOST_READABLE_FILES only, uname, hostnamectl and timedatectl status.
|
|
42
|
+
* - SafeWrite: restart, start, reload, try-restart, reload-or-restart or
|
|
43
|
+
* reset-failed of exactly ONE service, socket, timer or path unit — a
|
|
44
|
+
* reversible change to one named object.
|
|
45
|
+
* - RiskyWrite: stop of one unit; any of those verbs on several units;
|
|
46
|
+
* reset-failed with no unit (every failed unit); journalctl
|
|
47
|
+
* --vacuum-size / --vacuum-time / --vacuum-files (target "journal").
|
|
48
|
+
* - RiskyWrite + requiresHuman (never unattended, whatever the mode or
|
|
49
|
+
* allowlist): any write to a unit in PROTECTED_HOST_UNIT_PATTERNS (ssh,
|
|
50
|
+
* systemd-*, dbus, the network stack, getty, the container runtimes,
|
|
51
|
+
* the firewall, the package-upgrade units, ...); start/stop/restart/reload of a target, mount,
|
|
52
|
+
* automount or swap unit (they fan out to other units or filesystems);
|
|
53
|
+
* and kill of a pid.
|
|
54
|
+
* - Denied: every other systemctl command (enable/disable/mask/edit/cat/
|
|
55
|
+
* daemon-reload/isolate/kill/set-property/the environment verbs/the
|
|
56
|
+
* power and run-state verbs, ...), writes to slices, scopes, devices,
|
|
57
|
+
* templates without an instance, the power or run-state units
|
|
58
|
+
* (reboot.target, rescue.target, runlevel6.target,
|
|
59
|
+
* systemd-poweroff.service, ...) and debug-shell.service (a root shell
|
|
60
|
+
* with no password on tty9), the
|
|
61
|
+
* flags that reach another machine, root, image or user manager or that
|
|
62
|
+
* force a change, journalctl -f and every journal-maintenance flag but
|
|
63
|
+
* vacuum, kill of pid 1, pid 0 or a process group, and every other
|
|
64
|
+
* program.
|
|
65
|
+
*
|
|
66
|
+
* Targets (what the agent's protectedTargets and ONEUPTIME_AI_WRITE_TARGETS
|
|
67
|
+
* globs are compared with) are canonical: a unit's full name as systemd
|
|
68
|
+
* resolves it ("nginx" is nginx.service), "pid:N" for a process, and
|
|
69
|
+
* "journal" for a vacuum.
|
|
70
|
+
*
|
|
71
|
+
* Part of the import-closed resource policy directory that the resource AI
|
|
72
|
+
* agent carries a byte-identical copy of: relative imports of that set only.
|
|
73
|
+
*/
|
|
74
|
+
import { ResourceCommandTier } from "../../../Types/ResourceAiAgent/ResourceAiAccess";
|
|
75
|
+
import { deniedResult, globMatchesTarget, renderResourceDisplayCommand, } from "./ResourceCommandPolicyCore";
|
|
76
|
+
// The programs, in the order the Host entry of AI_RESOURCE_TYPE_INFO lists them.
|
|
77
|
+
export const HOST_COMMAND_PROGRAMS = [
|
|
78
|
+
"systemctl",
|
|
79
|
+
"journalctl",
|
|
80
|
+
"df",
|
|
81
|
+
"free",
|
|
82
|
+
"uptime",
|
|
83
|
+
"ps",
|
|
84
|
+
"ss",
|
|
85
|
+
"ip",
|
|
86
|
+
"dmesg",
|
|
87
|
+
"lsblk",
|
|
88
|
+
"cat",
|
|
89
|
+
"top",
|
|
90
|
+
"uname",
|
|
91
|
+
"hostnamectl",
|
|
92
|
+
"timedatectl",
|
|
93
|
+
"kill",
|
|
94
|
+
];
|
|
95
|
+
// The most journal lines one journalctl -n may ask for.
|
|
96
|
+
export const MAX_JOURNALCTL_LINES = 2000;
|
|
97
|
+
// The most journal lines systemctl status -n may append.
|
|
98
|
+
export const MAX_SYSTEMCTL_STATUS_LINES = 200;
|
|
99
|
+
// The widest top -w may make its output.
|
|
100
|
+
const MAX_TOP_WIDTH = 512;
|
|
101
|
+
// The largest pid Linux hands out (pid_max may be raised to 2^22).
|
|
102
|
+
const MAX_PID = 4194304;
|
|
103
|
+
/*
|
|
104
|
+
* The only files cat reads: kernel counters and the OS release. Compared
|
|
105
|
+
* exactly, so "/proc/../etc/shadow" or "/proc//loadavg" is not one of them.
|
|
106
|
+
*/
|
|
107
|
+
export const HOST_READABLE_FILES = [
|
|
108
|
+
"/proc/loadavg",
|
|
109
|
+
"/proc/meminfo",
|
|
110
|
+
"/proc/uptime",
|
|
111
|
+
"/proc/pressure/cpu",
|
|
112
|
+
"/proc/pressure/memory",
|
|
113
|
+
"/proc/pressure/io",
|
|
114
|
+
"/proc/mdstat",
|
|
115
|
+
"/proc/swaps",
|
|
116
|
+
"/proc/mounts",
|
|
117
|
+
"/proc/vmstat",
|
|
118
|
+
"/proc/stat",
|
|
119
|
+
"/proc/sys/fs/file-nr",
|
|
120
|
+
"/proc/net/sockstat",
|
|
121
|
+
"/etc/os-release",
|
|
122
|
+
];
|
|
123
|
+
/*
|
|
124
|
+
* The unit properties systemctl show may print. Environment and
|
|
125
|
+
* EnvironmentFiles (and every other property) are left out on purpose:
|
|
126
|
+
* units keep secrets there.
|
|
127
|
+
*/
|
|
128
|
+
export const SYSTEMCTL_SHOW_PROPERTIES = [
|
|
129
|
+
"ActiveState",
|
|
130
|
+
"SubState",
|
|
131
|
+
"LoadState",
|
|
132
|
+
"Result",
|
|
133
|
+
"NRestarts",
|
|
134
|
+
"ExecMainStatus",
|
|
135
|
+
"ExecMainCode",
|
|
136
|
+
"MainPID",
|
|
137
|
+
"ExecMainPID",
|
|
138
|
+
"MemoryCurrent",
|
|
139
|
+
"MemoryPeak",
|
|
140
|
+
"CPUUsageNSec",
|
|
141
|
+
"TasksCurrent",
|
|
142
|
+
"ActiveEnterTimestamp",
|
|
143
|
+
"InactiveEnterTimestamp",
|
|
144
|
+
"StateChangeTimestamp",
|
|
145
|
+
"UnitFileState",
|
|
146
|
+
"FragmentPath",
|
|
147
|
+
"Restart",
|
|
148
|
+
"RestartUSec",
|
|
149
|
+
"TimeoutStopUSec",
|
|
150
|
+
"Description",
|
|
151
|
+
"Id",
|
|
152
|
+
];
|
|
153
|
+
/*
|
|
154
|
+
* Units a write never touches without a human, whatever the mode or the
|
|
155
|
+
* allowlist: remote access, the service manager and its helpers, the
|
|
156
|
+
* message bus and authorization, the network stack, consoles, the
|
|
157
|
+
* container runtimes and node agents, the firewall, user managers, and
|
|
158
|
+
* the package upgrades a distribution runs on a timer (they install
|
|
159
|
+
* packages and may reboot the host). Globs over the unit's name without
|
|
160
|
+
* its type suffix, compared case-insensitively (over-matching is the safe
|
|
161
|
+
* direction). The check sees the name as written, so the aliases systemd
|
|
162
|
+
* ships for these units are listed too: autovt@ is getty@, udev is
|
|
163
|
+
* systemd-udevd (Debian, Ubuntu), dbus-org.freedesktop.* name systemd-*.
|
|
164
|
+
*/
|
|
165
|
+
export const PROTECTED_HOST_UNIT_PATTERNS = [
|
|
166
|
+
"ssh",
|
|
167
|
+
"ssh@*",
|
|
168
|
+
"sshd",
|
|
169
|
+
"sshd@*",
|
|
170
|
+
"sshd-*",
|
|
171
|
+
"systemd-*",
|
|
172
|
+
"udev",
|
|
173
|
+
"dbus*",
|
|
174
|
+
"polkit*",
|
|
175
|
+
"NetworkManager*",
|
|
176
|
+
"networking",
|
|
177
|
+
"network*",
|
|
178
|
+
"getty@*",
|
|
179
|
+
"serial-getty@*",
|
|
180
|
+
"autovt@*",
|
|
181
|
+
"console-getty",
|
|
182
|
+
"container-getty@*",
|
|
183
|
+
"apt-daily*",
|
|
184
|
+
"unattended-upgrades",
|
|
185
|
+
"dnf-automatic*",
|
|
186
|
+
"yum-cron",
|
|
187
|
+
"packagekit*",
|
|
188
|
+
"system-update*",
|
|
189
|
+
"docker",
|
|
190
|
+
"containerd",
|
|
191
|
+
"podman*",
|
|
192
|
+
"crio",
|
|
193
|
+
"cri-o",
|
|
194
|
+
"kubelet",
|
|
195
|
+
"k3s*",
|
|
196
|
+
"rke2*",
|
|
197
|
+
"firewalld",
|
|
198
|
+
"nftables",
|
|
199
|
+
"iptables",
|
|
200
|
+
"ip6tables",
|
|
201
|
+
"ufw",
|
|
202
|
+
"user@*",
|
|
203
|
+
"user-runtime-dir@*",
|
|
204
|
+
];
|
|
205
|
+
/*
|
|
206
|
+
* Units that power off, reboot, suspend or change the run state of the
|
|
207
|
+
* whole host when started (reboot.target, rescue.target,
|
|
208
|
+
* systemd-poweroff.service, ...). Every write to one is Denied: it is the
|
|
209
|
+
* same change as the systemctl reboot/rescue/... verbs, reached another way.
|
|
210
|
+
* The SysV runlevel targets are aliases systemd ships for them
|
|
211
|
+
* (runlevel0.target is poweroff.target, runlevel1 rescue, runlevel6
|
|
212
|
+
* reboot, runlevel2-5 multi-user or graphical), so every one is here.
|
|
213
|
+
*/
|
|
214
|
+
const HOST_STATE_UNIT_PATTERNS = [
|
|
215
|
+
"poweroff",
|
|
216
|
+
"reboot",
|
|
217
|
+
"halt",
|
|
218
|
+
"kexec",
|
|
219
|
+
"shutdown",
|
|
220
|
+
"suspend",
|
|
221
|
+
"hibernate",
|
|
222
|
+
"hybrid-sleep",
|
|
223
|
+
"suspend-then-hibernate",
|
|
224
|
+
"sleep",
|
|
225
|
+
"soft-reboot",
|
|
226
|
+
"rescue",
|
|
227
|
+
"emergency",
|
|
228
|
+
"exit",
|
|
229
|
+
"ctrl-alt-del",
|
|
230
|
+
"final",
|
|
231
|
+
"umount",
|
|
232
|
+
"default",
|
|
233
|
+
"runlevel*",
|
|
234
|
+
"initrd*",
|
|
235
|
+
"factory-reset",
|
|
236
|
+
"systemd-poweroff",
|
|
237
|
+
"systemd-reboot",
|
|
238
|
+
"systemd-halt",
|
|
239
|
+
"systemd-kexec",
|
|
240
|
+
"systemd-suspend",
|
|
241
|
+
"systemd-hibernate",
|
|
242
|
+
"systemd-hybrid-sleep",
|
|
243
|
+
"systemd-suspend-then-hibernate",
|
|
244
|
+
"systemd-soft-reboot",
|
|
245
|
+
"systemd-exit",
|
|
246
|
+
];
|
|
247
|
+
/*
|
|
248
|
+
* Units no AI change ever starts, whatever a human approves: they hand out
|
|
249
|
+
* a root shell with no password (debug-shell.service runs /bin/sh on tty9
|
|
250
|
+
* for anyone at the console, serial line, IPMI or VNC session).
|
|
251
|
+
*/
|
|
252
|
+
const ROOT_SHELL_UNIT_PATTERNS = ["debug-shell"];
|
|
253
|
+
const ROOT_SHELL_REASON = "it opens a root shell with no password on a console (tty9), for anyone who can reach the console, serial line, IPMI or VNC session";
|
|
254
|
+
// The unit types systemd knows; a name without one of these is a service.
|
|
255
|
+
const SYSTEMD_UNIT_TYPES = [
|
|
256
|
+
"service",
|
|
257
|
+
"socket",
|
|
258
|
+
"device",
|
|
259
|
+
"mount",
|
|
260
|
+
"automount",
|
|
261
|
+
"swap",
|
|
262
|
+
"target",
|
|
263
|
+
"path",
|
|
264
|
+
"timer",
|
|
265
|
+
"slice",
|
|
266
|
+
"scope",
|
|
267
|
+
];
|
|
268
|
+
// Unit types a start/stop/restart/reload fans out from: a human decides.
|
|
269
|
+
const FAN_OUT_UNIT_TYPES = [
|
|
270
|
+
"target",
|
|
271
|
+
"mount",
|
|
272
|
+
"automount",
|
|
273
|
+
"swap",
|
|
274
|
+
];
|
|
275
|
+
// Unit types no AI change ever acts on directly.
|
|
276
|
+
const UNWRITABLE_UNIT_TYPES = [
|
|
277
|
+
"slice",
|
|
278
|
+
"scope",
|
|
279
|
+
"device",
|
|
280
|
+
];
|
|
281
|
+
// A unit name (no globs): letters, digits and @ _ . : \ -, not led by "-".
|
|
282
|
+
const UNIT_NAME_REGEX = /^[A-Za-z0-9@_.:\\][A-Za-z0-9@_.:\\-]{0,255}$/;
|
|
283
|
+
// A unit pattern (list-units, journalctl -u): a unit name that may glob.
|
|
284
|
+
const UNIT_PATTERN_REGEX = /^[A-Za-z0-9@_.:\\*?[\]][A-Za-z0-9@_.:\\*?[\]-]{0,255}$/;
|
|
285
|
+
const DIGITS_REGEX = /^[0-9]+$/;
|
|
286
|
+
const LEADING_DIGIT_REGEX = /^[0-9]/;
|
|
287
|
+
// Every word must be printable ASCII: no look-alike dashes or letters.
|
|
288
|
+
const PRINTABLE_ASCII_REGEX = /^[\x20-\x7e]*$/;
|
|
289
|
+
/*
|
|
290
|
+
* The canonical name of a unit as systemd resolves it: a name without a
|
|
291
|
+
* known type suffix is a service ("nginx" -> nginx.service,
|
|
292
|
+
* "nginx.foo" -> nginx.foo.service).
|
|
293
|
+
*/
|
|
294
|
+
export function canonicalSystemdUnitName(name) {
|
|
295
|
+
const dot = name.lastIndexOf(".");
|
|
296
|
+
const suffix = dot >= 0 ? name.slice(dot + 1) : "";
|
|
297
|
+
return SYSTEMD_UNIT_TYPES.includes(suffix) ? name : `${name}.service`;
|
|
298
|
+
}
|
|
299
|
+
function unitStem(canonicalName) {
|
|
300
|
+
return canonicalName.slice(0, canonicalName.lastIndexOf("."));
|
|
301
|
+
}
|
|
302
|
+
function unitType(canonicalName) {
|
|
303
|
+
return canonicalName.slice(canonicalName.lastIndexOf(".") + 1);
|
|
304
|
+
}
|
|
305
|
+
// The first pattern that names this unit stem, case-insensitively.
|
|
306
|
+
function matchingUnitPattern(patterns, stem) {
|
|
307
|
+
const folded = stem.toLowerCase();
|
|
308
|
+
return patterns.find((pattern) => {
|
|
309
|
+
return globMatchesTarget(pattern.toLowerCase(), folded);
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
// "a" -> a, ["a","b"] -> "a and b", ["a","b","c"] -> "a, b and c".
|
|
313
|
+
function joinWords(words) {
|
|
314
|
+
if (words.length <= 1) {
|
|
315
|
+
return words[0] || "";
|
|
316
|
+
}
|
|
317
|
+
return `${words.slice(0, -1).join(", ")} and ${words[words.length - 1]}`;
|
|
318
|
+
}
|
|
319
|
+
/*
|
|
320
|
+
* ---------------------------------------------------------------------------
|
|
321
|
+
* What each program allows, appended to every refusal so the model learns
|
|
322
|
+
* what it CAN run, not just what it cannot.
|
|
323
|
+
* ---------------------------------------------------------------------------
|
|
324
|
+
*/
|
|
325
|
+
const SYSTEMCTL_ALLOWED = "systemctl reads with status, is-active, is-failed, is-enabled, is-system-running, list-units, list-unit-files, list-timers, list-sockets, list-jobs, list-dependencies and show UNIT -p PROPERTY, and changes units with restart, start, reload, try-restart, reload-or-restart, reset-failed and stop (flags: --no-pager, -l, -a, -q, -n N, -o short|cat|json, --plain, --no-legend, --failed, --state=S, --type=T, --reverse, --value)";
|
|
326
|
+
const JOURNALCTL_ALLOWED = `journalctl reads with -u UNIT, -t IDENTIFIER, -p PRIORITY, -g REGEX, -k, -b [BOOT], -S/--since and -U/--until TIME, -o short|short-iso|short-precise|short-monotonic|cat|json|with-unit, -r, -x, -q, --utc, --no-hostname and --no-pager, bounded by -n N (at most ${MAX_JOURNALCTL_LINES}) or --since; --list-boots and --disk-usage work too, and --vacuum-size=, --vacuum-time= and --vacuum-files= remove archived journal files (a change that needs approval)`;
|
|
327
|
+
const DF_ALLOWED = "df takes -h, -H, -i, -k, -T, -P, -a, -l, --total, -t TYPE, -x TYPE and absolute paths";
|
|
328
|
+
const FREE_ALLOWED = "free takes -b, -k, -m, -g, -h, -w, -t and --si and runs once (-s and -c would repeat until killed)";
|
|
329
|
+
const UPTIME_ALLOWED = "uptime takes -p and -s";
|
|
330
|
+
const PS_ALLOWED = "ps takes BSD options a, u, x, w, f and o FORMAT (ps aux, ps axo pid,comm), UNIX options -e, -A, -f, -F, -l, -H, -L, -T, -w, -o FORMAT, -p PID, -u USER and -C COMMAND, and --sort KEY, --no-headers and --forest";
|
|
331
|
+
const TOP_ALLOWED = "top runs once in batch mode — top -b -n 1 — optionally with -o FIELD, -c, -w N and -H";
|
|
332
|
+
const SS_ALLOWED = "ss takes -t, -u, -l, -n, -p, -a, -s, -x, -4, -6, -e, -i, -m, -o, -r and -H, plus a filter expression (state established, dport = :443, ...)";
|
|
333
|
+
const IP_ALLOWED = "ip takes -br, -s, -d, -j, -p, -4 and -6, then one of addr, link, route, neigh or rule followed by show, list, ls or nothing (with optional filters such as dev eth0), or route get ADDRESS";
|
|
334
|
+
const DMESG_ALLOWED = "dmesg takes -T, -t, -k, -x and -l LEVELS";
|
|
335
|
+
const LSBLK_ALLOWED = "lsblk takes -f, -o COLUMNS, -b, -p, -J, -d, -a, -l, -n and /dev device paths";
|
|
336
|
+
const CAT_ALLOWED = `cat takes no flags and reads only ${joinWords(HOST_READABLE_FILES)}`;
|
|
337
|
+
const UNAME_ALLOWED = "uname takes -a, -r, -s, -m, -n, -v and -o";
|
|
338
|
+
const HOSTNAMECTL_ALLOWED = "hostnamectl runs as `hostnamectl` or `hostnamectl status`, with no flags";
|
|
339
|
+
const TIMEDATECTL_ALLOWED = "timedatectl runs as `timedatectl`, `timedatectl status`, `timedatectl show` or `timedatectl timesync-status`, with no flags";
|
|
340
|
+
const KILL_ALLOWED = "kill takes at most one signal (-TERM, -15, -HUP, -INT, -KILL, -9 or -s NAME; TERM when omitted) and then one or more pids from 2 up";
|
|
341
|
+
/*
|
|
342
|
+
* ---------------------------------------------------------------------------
|
|
343
|
+
* A getopt_long reader, shared by the programs that parse with it.
|
|
344
|
+
* ---------------------------------------------------------------------------
|
|
345
|
+
*/
|
|
346
|
+
var FlagArity;
|
|
347
|
+
(function (FlagArity) {
|
|
348
|
+
// A switch: `-l`, `--no-pager`. `--flag=value` is an error to the program.
|
|
349
|
+
FlagArity["None"] = "None";
|
|
350
|
+
// Always takes a value: attached (`-uNAME`, `--unit=NAME`) or the next word.
|
|
351
|
+
FlagArity["Required"] = "Required";
|
|
352
|
+
/*
|
|
353
|
+
* Takes an attached value; takes the NEXT word only when takesNextWord
|
|
354
|
+
* says the program would (journalctl -n/-b, top -w).
|
|
355
|
+
*/
|
|
356
|
+
FlagArity["Optional"] = "Optional";
|
|
357
|
+
})(FlagArity || (FlagArity = {}));
|
|
358
|
+
function findFlag(grammar, spelling) {
|
|
359
|
+
return grammar.flags.find((flag) => {
|
|
360
|
+
return flag.spellings.includes(spelling);
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
function findFlagByKey(grammar, key) {
|
|
364
|
+
return grammar.flags.find((flag) => {
|
|
365
|
+
return flag.key === key;
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
function findDeniedFlag(grammar, spelling) {
|
|
369
|
+
return grammar.denied.find((flag) => {
|
|
370
|
+
return flag.spellings.includes(spelling);
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
// ` (in "-rf")` when the flag was read out of a cluster or an `=` form.
|
|
374
|
+
function whereInToken(token, spelling) {
|
|
375
|
+
return token === spelling ? "" : ` (in "${token}")`;
|
|
376
|
+
}
|
|
377
|
+
function describeFlagProblem(grammar, spelling, token) {
|
|
378
|
+
const denied = findDeniedFlag(grammar, spelling);
|
|
379
|
+
const where = whereInToken(token, spelling);
|
|
380
|
+
if (denied) {
|
|
381
|
+
return `${grammar.program} ${spelling}${where} is never allowed: ${denied.reason}; ${grammar.allowed}`;
|
|
382
|
+
}
|
|
383
|
+
const abbreviation = spelling.startsWith("--")
|
|
384
|
+
? " (long flags must be written in full — an abbreviation is refused)"
|
|
385
|
+
: "";
|
|
386
|
+
return `${spelling}${where} is not a ${grammar.program} flag this policy allows${abbreviation}; ${grammar.allowed}`;
|
|
387
|
+
}
|
|
388
|
+
/*
|
|
389
|
+
* Read args (the program already removed) the way getopt_long would, then
|
|
390
|
+
* check every flag's value and repetition. The first problem wins.
|
|
391
|
+
*/
|
|
392
|
+
function parseGetoptArgs(args, grammar) {
|
|
393
|
+
const positionals = [];
|
|
394
|
+
const flags = [];
|
|
395
|
+
let afterDoubleDash = false;
|
|
396
|
+
const fail = (problem) => {
|
|
397
|
+
return { positionals, flags, problem };
|
|
398
|
+
};
|
|
399
|
+
for (let i = 0; i < args.length; i++) {
|
|
400
|
+
const token = args[i];
|
|
401
|
+
if (afterDoubleDash || token === "-" || !token.startsWith("-")) {
|
|
402
|
+
positionals.push(token);
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
if (token === "--") {
|
|
406
|
+
afterDoubleDash = true;
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
if (token.startsWith("--")) {
|
|
410
|
+
const eq = token.indexOf("=");
|
|
411
|
+
const spelling = eq >= 0 ? token.slice(0, eq) : token;
|
|
412
|
+
const spec = findFlag(grammar, spelling);
|
|
413
|
+
if (!spec || findDeniedFlag(grammar, spelling)) {
|
|
414
|
+
return fail(describeFlagProblem(grammar, spelling, token));
|
|
415
|
+
}
|
|
416
|
+
if (spec.arity === FlagArity.None) {
|
|
417
|
+
if (eq >= 0) {
|
|
418
|
+
return fail(`${spelling} takes no value (in "${token}"); ${grammar.allowed}`);
|
|
419
|
+
}
|
|
420
|
+
flags.push({ key: spec.key, spelling, value: null });
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
423
|
+
if (eq >= 0) {
|
|
424
|
+
flags.push({ key: spec.key, spelling, value: token.slice(eq + 1) });
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
const next = args[i + 1];
|
|
428
|
+
if (spec.arity === FlagArity.Required) {
|
|
429
|
+
if (next === undefined) {
|
|
430
|
+
return fail(`${spelling} needs a value; ${grammar.allowed}`);
|
|
431
|
+
}
|
|
432
|
+
flags.push({ key: spec.key, spelling, value: next });
|
|
433
|
+
i++;
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
436
|
+
if (next !== undefined &&
|
|
437
|
+
spec.takesNextWord !== undefined &&
|
|
438
|
+
spec.takesNextWord(next)) {
|
|
439
|
+
flags.push({ key: spec.key, spelling, value: next });
|
|
440
|
+
i++;
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
flags.push({ key: spec.key, spelling, value: null });
|
|
444
|
+
}
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
// "-abc": a cluster of short flags, read letter by letter like getopt.
|
|
448
|
+
let rest = token.slice(1);
|
|
449
|
+
while (rest.length > 0) {
|
|
450
|
+
const spelling = `-${rest.charAt(0)}`;
|
|
451
|
+
const spec = findFlag(grammar, spelling);
|
|
452
|
+
if (!spec || findDeniedFlag(grammar, spelling)) {
|
|
453
|
+
return fail(describeFlagProblem(grammar, spelling, token));
|
|
454
|
+
}
|
|
455
|
+
if (spec.arity === FlagArity.None) {
|
|
456
|
+
flags.push({ key: spec.key, spelling, value: null });
|
|
457
|
+
rest = rest.slice(1);
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
// getopt: everything after the letter is the value — "=" included.
|
|
461
|
+
const attached = rest.slice(1);
|
|
462
|
+
if (attached.length > 0) {
|
|
463
|
+
flags.push({ key: spec.key, spelling, value: attached });
|
|
464
|
+
break;
|
|
465
|
+
}
|
|
466
|
+
const next = args[i + 1];
|
|
467
|
+
if (spec.arity === FlagArity.Required) {
|
|
468
|
+
if (next === undefined) {
|
|
469
|
+
return fail(`${spelling} needs a value; ${grammar.allowed}`);
|
|
470
|
+
}
|
|
471
|
+
flags.push({ key: spec.key, spelling, value: next });
|
|
472
|
+
i++;
|
|
473
|
+
break;
|
|
474
|
+
}
|
|
475
|
+
if (next !== undefined &&
|
|
476
|
+
spec.takesNextWord !== undefined &&
|
|
477
|
+
spec.takesNextWord(next)) {
|
|
478
|
+
flags.push({ key: spec.key, spelling, value: next });
|
|
479
|
+
i++;
|
|
480
|
+
}
|
|
481
|
+
else {
|
|
482
|
+
flags.push({ key: spec.key, spelling, value: null });
|
|
483
|
+
}
|
|
484
|
+
break;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
const valueProblem = checkParsedFlags(flags, grammar);
|
|
488
|
+
return valueProblem
|
|
489
|
+
? fail(valueProblem)
|
|
490
|
+
: { positionals, flags, problem: null };
|
|
491
|
+
}
|
|
492
|
+
function checkParsedFlags(flags, grammar) {
|
|
493
|
+
const seen = [];
|
|
494
|
+
for (const flag of flags) {
|
|
495
|
+
const spec = findFlagByKey(grammar, flag.key);
|
|
496
|
+
if (!spec) {
|
|
497
|
+
return `${flag.spelling} is not a ${grammar.program} flag this policy allows; ${grammar.allowed}`;
|
|
498
|
+
}
|
|
499
|
+
if (spec.arity !== FlagArity.None) {
|
|
500
|
+
if (seen.includes(flag.key) && spec.repeatable !== true) {
|
|
501
|
+
return `give ${spec.spellings.join("/")} only once; ${grammar.allowed}`;
|
|
502
|
+
}
|
|
503
|
+
seen.push(flag.key);
|
|
504
|
+
}
|
|
505
|
+
if (flag.value === null) {
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
if (flag.value.startsWith("-") && spec.valueMayStartWithDash !== true) {
|
|
509
|
+
return `the value of ${flag.spelling} ("${flag.value}") starts with "-": a word that looks like a flag is never taken as a value; ${grammar.allowed}`;
|
|
510
|
+
}
|
|
511
|
+
const problem = spec.checkValue
|
|
512
|
+
? spec.checkValue(flag.value)
|
|
513
|
+
: null;
|
|
514
|
+
if (problem) {
|
|
515
|
+
return `${flag.spelling} ${problem}; ${grammar.allowed}`;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
return null;
|
|
519
|
+
}
|
|
520
|
+
function hasFlag(parsed, key) {
|
|
521
|
+
return parsed.flags.some((flag) => {
|
|
522
|
+
return flag.key === key;
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
// A switch: `-l`/`--full`.
|
|
526
|
+
function switchFlag(key, ...spellings) {
|
|
527
|
+
return { spellings, key, arity: FlagArity.None };
|
|
528
|
+
}
|
|
529
|
+
/*
|
|
530
|
+
* ---------------------------------------------------------------------------
|
|
531
|
+
* Value checks. Each returns why the value is refused, or null.
|
|
532
|
+
* ---------------------------------------------------------------------------
|
|
533
|
+
*/
|
|
534
|
+
function checkWholeNumber(min, max) {
|
|
535
|
+
return (value) => {
|
|
536
|
+
if (!DIGITS_REGEX.test(value) || value.length > 7) {
|
|
537
|
+
return `must be a whole number from ${min} to ${max}, not "${value}"`;
|
|
538
|
+
}
|
|
539
|
+
const parsed = parseInt(value, 10);
|
|
540
|
+
return parsed < min || parsed > max
|
|
541
|
+
? `must be a whole number from ${min} to ${max}, not "${value}"`
|
|
542
|
+
: null;
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
function checkOneOf(allowed) {
|
|
546
|
+
return (value) => {
|
|
547
|
+
return allowed.includes(value)
|
|
548
|
+
? null
|
|
549
|
+
: `must be one of ${allowed.join(", ")}, not "${value}"`;
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
/*
|
|
553
|
+
* A comma-separated list whose every item passes `itemRegex` (and, when
|
|
554
|
+
* given, is one of `allowedItems`).
|
|
555
|
+
*/
|
|
556
|
+
function checkList(itemRegex, description, allowedItems) {
|
|
557
|
+
return (value) => {
|
|
558
|
+
const items = value.split(",");
|
|
559
|
+
if (value.length > 512 || items.length > 32) {
|
|
560
|
+
return `is too long a list ("${value.slice(0, 64)}...")`;
|
|
561
|
+
}
|
|
562
|
+
for (const item of items) {
|
|
563
|
+
if (!itemRegex.test(item)) {
|
|
564
|
+
return `must be ${description}, not "${value}"`;
|
|
565
|
+
}
|
|
566
|
+
if (allowedItems && !allowedItems.includes(item)) {
|
|
567
|
+
return `may only name ${allowedItems.join(", ")} — "${item}" is not one of them`;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
return null;
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
function checkPattern(regex, description) {
|
|
574
|
+
return (value) => {
|
|
575
|
+
return regex.test(value) ? null : `must be ${description}, not "${value}"`;
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
/*
|
|
579
|
+
* ---------------------------------------------------------------------------
|
|
580
|
+
* systemctl
|
|
581
|
+
* ---------------------------------------------------------------------------
|
|
582
|
+
*/
|
|
583
|
+
const SYSTEMCTL_OUTPUT_FORMATS = [
|
|
584
|
+
"short",
|
|
585
|
+
"cat",
|
|
586
|
+
"json",
|
|
587
|
+
];
|
|
588
|
+
const SYSTEMCTL_GRAMMAR = {
|
|
589
|
+
program: "systemctl",
|
|
590
|
+
allowed: SYSTEMCTL_ALLOWED,
|
|
591
|
+
flags: [
|
|
592
|
+
switchFlag("no-pager", "--no-pager"),
|
|
593
|
+
switchFlag("full", "-l", "--full"),
|
|
594
|
+
switchFlag("all", "-a", "--all"),
|
|
595
|
+
switchFlag("quiet", "-q", "--quiet"),
|
|
596
|
+
switchFlag("plain", "--plain"),
|
|
597
|
+
switchFlag("no-legend", "--no-legend"),
|
|
598
|
+
switchFlag("failed", "--failed"),
|
|
599
|
+
switchFlag("reverse", "--reverse"),
|
|
600
|
+
switchFlag("value", "--value"),
|
|
601
|
+
{
|
|
602
|
+
spellings: ["-n", "--lines"],
|
|
603
|
+
key: "lines",
|
|
604
|
+
arity: FlagArity.Required,
|
|
605
|
+
checkValue: checkWholeNumber(0, MAX_SYSTEMCTL_STATUS_LINES),
|
|
606
|
+
},
|
|
607
|
+
{
|
|
608
|
+
spellings: ["-o", "--output"],
|
|
609
|
+
key: "output",
|
|
610
|
+
arity: FlagArity.Required,
|
|
611
|
+
checkValue: checkOneOf(SYSTEMCTL_OUTPUT_FORMATS),
|
|
612
|
+
},
|
|
613
|
+
{
|
|
614
|
+
spellings: ["--state"],
|
|
615
|
+
key: "state",
|
|
616
|
+
arity: FlagArity.Required,
|
|
617
|
+
repeatable: true,
|
|
618
|
+
checkValue: checkList(/^[a-z][a-z-]{0,31}$/, "unit states such as failed,running"),
|
|
619
|
+
},
|
|
620
|
+
{
|
|
621
|
+
spellings: ["-t", "--type"],
|
|
622
|
+
key: "type",
|
|
623
|
+
arity: FlagArity.Required,
|
|
624
|
+
repeatable: true,
|
|
625
|
+
checkValue: checkList(/^[a-z][a-z-]{0,31}$/, "unit types such as service,timer"),
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
spellings: ["-p", "--property"],
|
|
629
|
+
key: "property",
|
|
630
|
+
arity: FlagArity.Required,
|
|
631
|
+
repeatable: true,
|
|
632
|
+
checkValue: checkList(/^[A-Za-z]{1,64}$/, "property names", SYSTEMCTL_SHOW_PROPERTIES),
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
spellings: ["-P"],
|
|
636
|
+
key: "property-value",
|
|
637
|
+
arity: FlagArity.Required,
|
|
638
|
+
repeatable: true,
|
|
639
|
+
checkValue: checkList(/^[A-Za-z]{1,64}$/, "property names", SYSTEMCTL_SHOW_PROPERTIES),
|
|
640
|
+
},
|
|
641
|
+
],
|
|
642
|
+
denied: [
|
|
643
|
+
{
|
|
644
|
+
spellings: ["-H", "--host"],
|
|
645
|
+
reason: "it runs the command on another machine over SSH",
|
|
646
|
+
},
|
|
647
|
+
{
|
|
648
|
+
spellings: ["-M", "--machine"],
|
|
649
|
+
reason: "it talks to a container's or another machine's service manager",
|
|
650
|
+
},
|
|
651
|
+
{
|
|
652
|
+
spellings: ["-C", "--capsule"],
|
|
653
|
+
reason: "it talks to a capsule's service manager",
|
|
654
|
+
},
|
|
655
|
+
{
|
|
656
|
+
spellings: ["--root", "--image", "--image-policy"],
|
|
657
|
+
reason: "it operates on another root directory or a disk image",
|
|
658
|
+
},
|
|
659
|
+
{
|
|
660
|
+
spellings: ["--user", "--global"],
|
|
661
|
+
reason: "it acts on user service managers; the agent acts on the host's system manager only",
|
|
662
|
+
},
|
|
663
|
+
{
|
|
664
|
+
spellings: ["--runtime"],
|
|
665
|
+
reason: "it makes a unit-file change for the current boot",
|
|
666
|
+
},
|
|
667
|
+
{
|
|
668
|
+
spellings: ["-f", "--force"],
|
|
669
|
+
reason: "it overrides systemd's safety checks",
|
|
670
|
+
},
|
|
671
|
+
{
|
|
672
|
+
spellings: ["-i", "--ignore-inhibitors", "--check-inhibitors"],
|
|
673
|
+
reason: "it overrides shutdown and sleep inhibitors",
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
spellings: ["--job-mode"],
|
|
677
|
+
reason: "it changes how queued jobs are replaced (isolate, flush and fail can stop other units)",
|
|
678
|
+
},
|
|
679
|
+
{
|
|
680
|
+
spellings: ["--wait"],
|
|
681
|
+
reason: "it blocks until the unit exits, so the command would hang",
|
|
682
|
+
},
|
|
683
|
+
{
|
|
684
|
+
spellings: ["-s", "--signal", "--kill-whom", "--kill-value"],
|
|
685
|
+
reason: "it picks a signal for systemctl kill, which is not allowed",
|
|
686
|
+
},
|
|
687
|
+
{
|
|
688
|
+
spellings: ["--now"],
|
|
689
|
+
reason: "it pairs enable/disable with a start/stop",
|
|
690
|
+
},
|
|
691
|
+
{
|
|
692
|
+
spellings: [
|
|
693
|
+
"--firmware-setup",
|
|
694
|
+
"--boot-loader-menu",
|
|
695
|
+
"--boot-loader-entry",
|
|
696
|
+
"--reboot-argument",
|
|
697
|
+
"--when",
|
|
698
|
+
],
|
|
699
|
+
reason: "it configures a reboot or power-off",
|
|
700
|
+
},
|
|
701
|
+
],
|
|
702
|
+
};
|
|
703
|
+
// How many unit words a read verb takes.
|
|
704
|
+
var UnitOperands;
|
|
705
|
+
(function (UnitOperands) {
|
|
706
|
+
// No words (list-jobs, is-system-running).
|
|
707
|
+
UnitOperands["None"] = "None";
|
|
708
|
+
// Any number of unit names, none included (status).
|
|
709
|
+
UnitOperands["AnyUnits"] = "AnyUnits";
|
|
710
|
+
// At least one unit name (is-active, show).
|
|
711
|
+
UnitOperands["SomeUnits"] = "SomeUnits";
|
|
712
|
+
// At most one unit name (list-dependencies).
|
|
713
|
+
UnitOperands["AtMostOneUnit"] = "AtMostOneUnit";
|
|
714
|
+
// Any number of unit patterns that may glob (list-units).
|
|
715
|
+
UnitOperands["Patterns"] = "Patterns";
|
|
716
|
+
})(UnitOperands || (UnitOperands = {}));
|
|
717
|
+
const LIST_FLAGS = [
|
|
718
|
+
"no-pager",
|
|
719
|
+
"full",
|
|
720
|
+
"all",
|
|
721
|
+
"plain",
|
|
722
|
+
"no-legend",
|
|
723
|
+
"output",
|
|
724
|
+
"quiet",
|
|
725
|
+
];
|
|
726
|
+
const SYSTEMCTL_READ_VERBS = {
|
|
727
|
+
status: {
|
|
728
|
+
flags: ["no-pager", "full", "all", "lines", "output", "quiet"],
|
|
729
|
+
operands: UnitOperands.AnyUnits,
|
|
730
|
+
shows: "the status and recent log lines of units (or of the whole service manager)",
|
|
731
|
+
},
|
|
732
|
+
"is-active": {
|
|
733
|
+
flags: ["no-pager", "quiet"],
|
|
734
|
+
operands: UnitOperands.SomeUnits,
|
|
735
|
+
shows: "whether units are active",
|
|
736
|
+
},
|
|
737
|
+
"is-failed": {
|
|
738
|
+
flags: ["no-pager", "quiet"],
|
|
739
|
+
operands: UnitOperands.SomeUnits,
|
|
740
|
+
shows: "whether units have failed",
|
|
741
|
+
},
|
|
742
|
+
"is-enabled": {
|
|
743
|
+
flags: ["no-pager", "quiet", "full"],
|
|
744
|
+
operands: UnitOperands.SomeUnits,
|
|
745
|
+
shows: "whether units start at boot",
|
|
746
|
+
},
|
|
747
|
+
"is-system-running": {
|
|
748
|
+
flags: ["no-pager", "quiet"],
|
|
749
|
+
operands: UnitOperands.None,
|
|
750
|
+
shows: "the overall state of the service manager",
|
|
751
|
+
},
|
|
752
|
+
"list-units": {
|
|
753
|
+
flags: [...LIST_FLAGS, "failed", "state", "type"],
|
|
754
|
+
operands: UnitOperands.Patterns,
|
|
755
|
+
shows: "the loaded units and their states",
|
|
756
|
+
},
|
|
757
|
+
"list-unit-files": {
|
|
758
|
+
flags: [...LIST_FLAGS, "state", "type"],
|
|
759
|
+
operands: UnitOperands.Patterns,
|
|
760
|
+
shows: "the installed unit files and whether they are enabled",
|
|
761
|
+
},
|
|
762
|
+
"list-timers": {
|
|
763
|
+
flags: [...LIST_FLAGS, "state"],
|
|
764
|
+
operands: UnitOperands.Patterns,
|
|
765
|
+
shows: "the timers and when they fire next",
|
|
766
|
+
},
|
|
767
|
+
"list-sockets": {
|
|
768
|
+
flags: [...LIST_FLAGS, "state"],
|
|
769
|
+
operands: UnitOperands.Patterns,
|
|
770
|
+
shows: "the listening socket units",
|
|
771
|
+
},
|
|
772
|
+
"list-jobs": {
|
|
773
|
+
flags: LIST_FLAGS,
|
|
774
|
+
operands: UnitOperands.None,
|
|
775
|
+
shows: "the queued jobs",
|
|
776
|
+
},
|
|
777
|
+
"list-dependencies": {
|
|
778
|
+
flags: ["no-pager", "full", "all", "plain", "no-legend", "reverse"],
|
|
779
|
+
operands: UnitOperands.AtMostOneUnit,
|
|
780
|
+
shows: "a unit's dependency tree",
|
|
781
|
+
},
|
|
782
|
+
show: {
|
|
783
|
+
flags: ["no-pager", "full", "all", "property", "property-value", "value"],
|
|
784
|
+
operands: UnitOperands.SomeUnits,
|
|
785
|
+
shows: "the allowed properties of units",
|
|
786
|
+
},
|
|
787
|
+
};
|
|
788
|
+
// The changes, and how each reads on an approval card.
|
|
789
|
+
const SYSTEMCTL_WRITE_VERBS = {
|
|
790
|
+
restart: "restarts",
|
|
791
|
+
start: "starts",
|
|
792
|
+
reload: "reloads the configuration of",
|
|
793
|
+
"try-restart": "restarts (if it is running)",
|
|
794
|
+
"reload-or-restart": "reloads (or else restarts)",
|
|
795
|
+
"reset-failed": "clears the failed state of",
|
|
796
|
+
stop: "stops",
|
|
797
|
+
};
|
|
798
|
+
// The flags a change may carry.
|
|
799
|
+
const SYSTEMCTL_WRITE_FLAGS = ["no-pager", "quiet"];
|
|
800
|
+
const PERSISTENT_CONFIG_REASON = "it changes which units start at boot or how they are configured, and persistent configuration is left to a human";
|
|
801
|
+
const HOST_STATE_REASON = "it powers off, reboots, suspends or changes the run state of the whole host";
|
|
802
|
+
const ENVIRONMENT_REASON = "the service manager's environment can hold secrets";
|
|
803
|
+
const SYSTEMCTL_DENIED_VERBS = {
|
|
804
|
+
enable: PERSISTENT_CONFIG_REASON,
|
|
805
|
+
disable: PERSISTENT_CONFIG_REASON,
|
|
806
|
+
reenable: PERSISTENT_CONFIG_REASON,
|
|
807
|
+
preset: PERSISTENT_CONFIG_REASON,
|
|
808
|
+
"preset-all": PERSISTENT_CONFIG_REASON,
|
|
809
|
+
mask: PERSISTENT_CONFIG_REASON,
|
|
810
|
+
unmask: PERSISTENT_CONFIG_REASON,
|
|
811
|
+
link: PERSISTENT_CONFIG_REASON,
|
|
812
|
+
revert: PERSISTENT_CONFIG_REASON,
|
|
813
|
+
"add-wants": PERSISTENT_CONFIG_REASON,
|
|
814
|
+
"add-requires": PERSISTENT_CONFIG_REASON,
|
|
815
|
+
"set-default": PERSISTENT_CONFIG_REASON,
|
|
816
|
+
edit: "it opens an editor and writes a drop-in that persists",
|
|
817
|
+
cat: "unit files can hold secrets (Environment=, credentials); read state with systemctl show UNIT -p PROPERTY instead",
|
|
818
|
+
"show-environment": ENVIRONMENT_REASON,
|
|
819
|
+
"set-environment": ENVIRONMENT_REASON,
|
|
820
|
+
"unset-environment": ENVIRONMENT_REASON,
|
|
821
|
+
"import-environment": ENVIRONMENT_REASON,
|
|
822
|
+
"daemon-reload": "it reloads the service manager itself",
|
|
823
|
+
"daemon-reexec": "it re-executes the service manager itself",
|
|
824
|
+
isolate: "it stops every unit the target does not need",
|
|
825
|
+
kill: "it signals every process of a unit; use systemctl restart or stop",
|
|
826
|
+
"set-property": "it changes a unit's resource controls persistently",
|
|
827
|
+
clean: "it deletes a unit's state, cache, log or runtime directories",
|
|
828
|
+
freeze: "it freezes every process of a unit",
|
|
829
|
+
thaw: "it thaws a frozen unit's processes",
|
|
830
|
+
bind: "it mounts paths into a unit's namespace",
|
|
831
|
+
"mount-image": "it mounts an image into a unit's namespace",
|
|
832
|
+
cancel: "it cancels queued jobs",
|
|
833
|
+
"log-level": "it changes the service manager's logging",
|
|
834
|
+
"log-target": "it changes the service manager's logging",
|
|
835
|
+
"service-log-level": "it changes a service's logging",
|
|
836
|
+
"service-log-target": "it changes a service's logging",
|
|
837
|
+
"service-watchdogs": "it changes the service manager's watchdogs",
|
|
838
|
+
poweroff: HOST_STATE_REASON,
|
|
839
|
+
reboot: HOST_STATE_REASON,
|
|
840
|
+
halt: HOST_STATE_REASON,
|
|
841
|
+
kexec: HOST_STATE_REASON,
|
|
842
|
+
"soft-reboot": HOST_STATE_REASON,
|
|
843
|
+
suspend: HOST_STATE_REASON,
|
|
844
|
+
hibernate: HOST_STATE_REASON,
|
|
845
|
+
"hybrid-sleep": HOST_STATE_REASON,
|
|
846
|
+
"suspend-then-hibernate": HOST_STATE_REASON,
|
|
847
|
+
sleep: HOST_STATE_REASON,
|
|
848
|
+
"switch-root": HOST_STATE_REASON,
|
|
849
|
+
default: HOST_STATE_REASON,
|
|
850
|
+
rescue: HOST_STATE_REASON,
|
|
851
|
+
emergency: HOST_STATE_REASON,
|
|
852
|
+
exit: HOST_STATE_REASON,
|
|
853
|
+
};
|
|
854
|
+
function hasOwn(record, key) {
|
|
855
|
+
return Object.prototype.hasOwnProperty.call(record, key);
|
|
856
|
+
}
|
|
857
|
+
function describeUnitProblem(operand, verb) {
|
|
858
|
+
return `"${operand}" is not a unit name systemctl ${verb} can take here: unit names use letters, digits and @ _ . : \\ - only, and globs (* ? [ ]) belong to list-units patterns; ${SYSTEMCTL_ALLOWED}`;
|
|
859
|
+
}
|
|
860
|
+
function evaluateSystemctl(argv) {
|
|
861
|
+
var _a;
|
|
862
|
+
const parsed = parseGetoptArgs(argv.slice(1), SYSTEMCTL_GRAMMAR);
|
|
863
|
+
if (parsed.problem) {
|
|
864
|
+
return deniedResult(argv, parsed.problem);
|
|
865
|
+
}
|
|
866
|
+
// No command word is list-units, as systemctl reads it.
|
|
867
|
+
const verb = (_a = parsed.positionals[0]) !== null && _a !== void 0 ? _a : "list-units";
|
|
868
|
+
const operands = parsed.positionals.slice(1);
|
|
869
|
+
if (hasOwn(SYSTEMCTL_DENIED_VERBS, verb)) {
|
|
870
|
+
return deniedResult(argv, `systemctl ${verb} is never allowed: ${SYSTEMCTL_DENIED_VERBS[verb]}; ${SYSTEMCTL_ALLOWED}`);
|
|
871
|
+
}
|
|
872
|
+
const isWrite = hasOwn(SYSTEMCTL_WRITE_VERBS, verb);
|
|
873
|
+
const readVerb = hasOwn(SYSTEMCTL_READ_VERBS, verb)
|
|
874
|
+
? SYSTEMCTL_READ_VERBS[verb]
|
|
875
|
+
: undefined;
|
|
876
|
+
if (!isWrite && !readVerb) {
|
|
877
|
+
return deniedResult(argv, `"${verb}" is not a systemctl command this policy allows (commands are lowercase and written in full); ${SYSTEMCTL_ALLOWED}`);
|
|
878
|
+
}
|
|
879
|
+
const allowedFlags = readVerb
|
|
880
|
+
? readVerb.flags
|
|
881
|
+
: SYSTEMCTL_WRITE_FLAGS;
|
|
882
|
+
const misplaced = parsed.flags.find((flag) => {
|
|
883
|
+
return !allowedFlags.includes(flag.key);
|
|
884
|
+
});
|
|
885
|
+
if (misplaced) {
|
|
886
|
+
return deniedResult(argv, `${misplaced.spelling} does not apply to systemctl ${verb}${isWrite ? " (a change takes only --no-pager and --quiet)" : ""}; ${SYSTEMCTL_ALLOWED}`);
|
|
887
|
+
}
|
|
888
|
+
if (readVerb) {
|
|
889
|
+
return evaluateSystemctlRead(argv, verb, readVerb, operands, parsed);
|
|
890
|
+
}
|
|
891
|
+
return evaluateSystemctlWrite(argv, verb, operands);
|
|
892
|
+
}
|
|
893
|
+
function evaluateSystemctlRead(argv, verb, readVerb, operands, parsed) {
|
|
894
|
+
switch (readVerb.operands) {
|
|
895
|
+
case UnitOperands.None:
|
|
896
|
+
if (operands.length > 0) {
|
|
897
|
+
return deniedResult(argv, `systemctl ${verb} takes no unit names; ${SYSTEMCTL_ALLOWED}`);
|
|
898
|
+
}
|
|
899
|
+
break;
|
|
900
|
+
case UnitOperands.SomeUnits:
|
|
901
|
+
if (operands.length === 0) {
|
|
902
|
+
return deniedResult(argv, `systemctl ${verb} needs at least one unit name: systemctl ${verb} UNIT; ${SYSTEMCTL_ALLOWED}`);
|
|
903
|
+
}
|
|
904
|
+
break;
|
|
905
|
+
case UnitOperands.AtMostOneUnit:
|
|
906
|
+
if (operands.length > 1) {
|
|
907
|
+
return deniedResult(argv, `systemctl ${verb} takes at most one unit name; ${SYSTEMCTL_ALLOWED}`);
|
|
908
|
+
}
|
|
909
|
+
break;
|
|
910
|
+
default:
|
|
911
|
+
break;
|
|
912
|
+
}
|
|
913
|
+
const operandRegex = readVerb.operands === UnitOperands.Patterns
|
|
914
|
+
? UNIT_PATTERN_REGEX
|
|
915
|
+
: UNIT_NAME_REGEX;
|
|
916
|
+
const badOperand = operands.find((operand) => {
|
|
917
|
+
return !operandRegex.test(operand);
|
|
918
|
+
});
|
|
919
|
+
if (badOperand !== undefined) {
|
|
920
|
+
return deniedResult(argv, describeUnitProblem(badOperand, verb));
|
|
921
|
+
}
|
|
922
|
+
if (verb === "show" &&
|
|
923
|
+
!hasFlag(parsed, "property") &&
|
|
924
|
+
!hasFlag(parsed, "property-value")) {
|
|
925
|
+
return deniedResult(argv, `systemctl show must name the properties it prints with -p (for example -p ActiveState,SubState,Result,NRestarts): without -p it prints every property, Environment included, which can hold secrets. Allowed properties: ${SYSTEMCTL_SHOW_PROPERTIES.join(", ")}`);
|
|
926
|
+
}
|
|
927
|
+
return {
|
|
928
|
+
tier: ResourceCommandTier.Read,
|
|
929
|
+
reason: `systemctl ${verb} shows ${readVerb.shows}; it changes nothing`,
|
|
930
|
+
program: argv[0] || "",
|
|
931
|
+
args: argv.slice(1),
|
|
932
|
+
verb,
|
|
933
|
+
displayCommand: renderResourceDisplayCommand(argv),
|
|
934
|
+
targets: [],
|
|
935
|
+
};
|
|
936
|
+
}
|
|
937
|
+
function evaluateSystemctlWrite(argv, verb, operands) {
|
|
938
|
+
const action = SYSTEMCTL_WRITE_VERBS[verb] || verb;
|
|
939
|
+
if (operands.length === 0) {
|
|
940
|
+
if (verb === "reset-failed") {
|
|
941
|
+
return {
|
|
942
|
+
tier: ResourceCommandTier.RiskyWrite,
|
|
943
|
+
reason: "systemctl reset-failed with no unit clears the failed state of EVERY failed unit (name one unit to make it a safe change)",
|
|
944
|
+
program: argv[0] || "",
|
|
945
|
+
args: argv.slice(1),
|
|
946
|
+
verb,
|
|
947
|
+
displayCommand: renderResourceDisplayCommand(argv),
|
|
948
|
+
targets: [],
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
return deniedResult(argv, `systemctl ${verb} needs the unit it acts on: systemctl ${verb} UNIT; ${SYSTEMCTL_ALLOWED}`);
|
|
952
|
+
}
|
|
953
|
+
const targets = [];
|
|
954
|
+
let humanReason = null;
|
|
955
|
+
for (const operand of operands) {
|
|
956
|
+
if (!UNIT_NAME_REGEX.test(operand)) {
|
|
957
|
+
return deniedResult(argv, describeUnitProblem(operand, verb));
|
|
958
|
+
}
|
|
959
|
+
const unit = canonicalSystemdUnitName(operand);
|
|
960
|
+
const stem = unitStem(unit);
|
|
961
|
+
const type = unitType(unit);
|
|
962
|
+
if (!stem || stem.startsWith(".") || stem.endsWith("@")) {
|
|
963
|
+
return deniedResult(argv, `systemctl ${verb} ${operand} does not name one unit instance (${unit}); name the instance, as in getty@tty1.service; ${SYSTEMCTL_ALLOWED}`);
|
|
964
|
+
}
|
|
965
|
+
const stateUnit = matchingUnitPattern(HOST_STATE_UNIT_PATTERNS, stem);
|
|
966
|
+
if (stateUnit !== undefined) {
|
|
967
|
+
return deniedResult(argv, `systemctl ${verb} ${unit} is never allowed: it is a power or run-state unit (${stateUnit}), and ${HOST_STATE_REASON}; ${SYSTEMCTL_ALLOWED}`);
|
|
968
|
+
}
|
|
969
|
+
const rootShellUnit = matchingUnitPattern(ROOT_SHELL_UNIT_PATTERNS, stem);
|
|
970
|
+
if (rootShellUnit !== undefined && verb !== "reset-failed") {
|
|
971
|
+
return deniedResult(argv, `systemctl ${verb} ${unit} is never allowed: ${ROOT_SHELL_REASON}; ${SYSTEMCTL_ALLOWED}`);
|
|
972
|
+
}
|
|
973
|
+
if (verb !== "reset-failed") {
|
|
974
|
+
if (UNWRITABLE_UNIT_TYPES.includes(type)) {
|
|
975
|
+
return deniedResult(argv, `systemctl ${verb} ${unit} is never allowed: a ${type} unit groups other processes or hardware, so the change would reach everything under it — act on the one service instead; ${SYSTEMCTL_ALLOWED}`);
|
|
976
|
+
}
|
|
977
|
+
if (humanReason === null && FAN_OUT_UNIT_TYPES.includes(type)) {
|
|
978
|
+
humanReason = `${unit} is a ${type} unit, so the change reaches ${type === "target"
|
|
979
|
+
? "every unit the target pulls in"
|
|
980
|
+
: "a filesystem or swap area and everything using it"}`;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
const protectedPattern = matchingUnitPattern(PROTECTED_HOST_UNIT_PATTERNS, stem);
|
|
984
|
+
if (humanReason === null && protectedPattern !== undefined) {
|
|
985
|
+
humanReason = `${unit} is a protected unit (${protectedPattern}): remote access, the service manager, the network, consoles, the firewall, the container runtimes and package upgrades are only ever changed with a human's approval`;
|
|
986
|
+
}
|
|
987
|
+
if (!targets.includes(unit)) {
|
|
988
|
+
targets.push(unit);
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
const unitList = joinWords(targets);
|
|
992
|
+
const several = targets.length > 1;
|
|
993
|
+
const base = {
|
|
994
|
+
program: argv[0] || "",
|
|
995
|
+
args: argv.slice(1),
|
|
996
|
+
verb,
|
|
997
|
+
displayCommand: renderResourceDisplayCommand(argv),
|
|
998
|
+
targets,
|
|
999
|
+
};
|
|
1000
|
+
if (humanReason !== null) {
|
|
1001
|
+
return Object.assign(Object.assign({}, base), { tier: ResourceCommandTier.RiskyWrite, reason: `${action} ${unitList}; ${humanReason}`, requiresHuman: true });
|
|
1002
|
+
}
|
|
1003
|
+
if (several) {
|
|
1004
|
+
return Object.assign(Object.assign({}, base), { tier: ResourceCommandTier.RiskyWrite, reason: `${action} ${targets.length} units (${unitList}); a change to more than one unit needs approval` });
|
|
1005
|
+
}
|
|
1006
|
+
if (verb === "stop") {
|
|
1007
|
+
return Object.assign(Object.assign({}, base), { tier: ResourceCommandTier.RiskyWrite, reason: `stops ${unitList}, which stays down until someone starts it again` });
|
|
1008
|
+
}
|
|
1009
|
+
return Object.assign(Object.assign({}, base), { tier: ResourceCommandTier.SafeWrite, reason: `${action} one unit (${unitList}): a reversible change to that unit only` });
|
|
1010
|
+
}
|
|
1011
|
+
/*
|
|
1012
|
+
* ---------------------------------------------------------------------------
|
|
1013
|
+
* journalctl
|
|
1014
|
+
* ---------------------------------------------------------------------------
|
|
1015
|
+
*/
|
|
1016
|
+
const JOURNALCTL_OUTPUT_FORMATS = [
|
|
1017
|
+
"short",
|
|
1018
|
+
"short-iso",
|
|
1019
|
+
"short-precise",
|
|
1020
|
+
"short-monotonic",
|
|
1021
|
+
"cat",
|
|
1022
|
+
"json",
|
|
1023
|
+
"with-unit",
|
|
1024
|
+
];
|
|
1025
|
+
const PRIORITY_WORD = "(?:emerg|alert|crit|err|warning|notice|info|debug|[0-7])";
|
|
1026
|
+
const PRIORITY_REGEX = new RegExp(`^${PRIORITY_WORD}(?:\\.\\.${PRIORITY_WORD})?$`);
|
|
1027
|
+
/*
|
|
1028
|
+
* A time journalctl reads: "2024-05-01 10:00:00", "yesterday", "-1h",
|
|
1029
|
+
* "1 hour ago", "@1714550400", "10:00 UTC". Anything that looks like a flag
|
|
1030
|
+
* ("-f", "--follow") is not a time.
|
|
1031
|
+
*/
|
|
1032
|
+
const JOURNAL_TIME_REGEX = /^(?!-[A-Za-z-])[A-Za-z0-9 :.+@-]{1,64}$/;
|
|
1033
|
+
// What journalctl -n reads out of the next word (and consumes it for).
|
|
1034
|
+
const JOURNAL_LINES_WORD_REGEX = /^(?:all|\+?[0-9]+)$/;
|
|
1035
|
+
// A boot: an offset (0, -1, +2), a 32-hex boot id with an optional offset, or all.
|
|
1036
|
+
const JOURNAL_BOOT_REGEX = /^(?:all|[+-]?[0-9]{1,6}|[0-9a-fA-F]{32}(?:[+-][0-9]{1,6})?)$/;
|
|
1037
|
+
const JOURNAL_IDENTIFIER_REGEX = /^[A-Za-z0-9_.@:/+][A-Za-z0-9_.@:/+-]{0,127}$/;
|
|
1038
|
+
const JOURNAL_SIZE_REGEX = /^[0-9]{1,6}[KMGT]?$/;
|
|
1039
|
+
const JOURNAL_TIME_SPAN_REGEX = /^[0-9]{1,6}(?:s|sec|m|min|h|hr|d|day|days|w|week|weeks|M|month|months|y|year|years)?$/;
|
|
1040
|
+
function checkJournalLines(value) {
|
|
1041
|
+
if (value === "all") {
|
|
1042
|
+
return `must be a number of lines (at most ${MAX_JOURNALCTL_LINES}): "all" is unbounded`;
|
|
1043
|
+
}
|
|
1044
|
+
return checkWholeNumber(0, MAX_JOURNALCTL_LINES)(value.replace(/^\+/, ""));
|
|
1045
|
+
}
|
|
1046
|
+
const JOURNALCTL_GRAMMAR = {
|
|
1047
|
+
program: "journalctl",
|
|
1048
|
+
allowed: JOURNALCTL_ALLOWED,
|
|
1049
|
+
flags: [
|
|
1050
|
+
{
|
|
1051
|
+
spellings: ["-u", "--unit"],
|
|
1052
|
+
key: "unit",
|
|
1053
|
+
arity: FlagArity.Required,
|
|
1054
|
+
repeatable: true,
|
|
1055
|
+
checkValue: checkPattern(UNIT_PATTERN_REGEX, "a unit name or pattern"),
|
|
1056
|
+
},
|
|
1057
|
+
{
|
|
1058
|
+
spellings: ["-t", "--identifier"],
|
|
1059
|
+
key: "identifier",
|
|
1060
|
+
arity: FlagArity.Required,
|
|
1061
|
+
repeatable: true,
|
|
1062
|
+
checkValue: checkPattern(JOURNAL_IDENTIFIER_REGEX, "a syslog identifier such as sshd or kernel"),
|
|
1063
|
+
},
|
|
1064
|
+
{
|
|
1065
|
+
spellings: ["-n", "--lines"],
|
|
1066
|
+
key: "lines",
|
|
1067
|
+
arity: FlagArity.Optional,
|
|
1068
|
+
takesNextWord: (word) => {
|
|
1069
|
+
return JOURNAL_LINES_WORD_REGEX.test(word);
|
|
1070
|
+
},
|
|
1071
|
+
checkValue: checkJournalLines,
|
|
1072
|
+
},
|
|
1073
|
+
{
|
|
1074
|
+
spellings: ["-S", "--since"],
|
|
1075
|
+
key: "since",
|
|
1076
|
+
arity: FlagArity.Required,
|
|
1077
|
+
valueMayStartWithDash: true,
|
|
1078
|
+
checkValue: checkPattern(JOURNAL_TIME_REGEX, 'a time such as "2024-05-01 10:00", "-1h", "yesterday" or "1 hour ago"'),
|
|
1079
|
+
},
|
|
1080
|
+
{
|
|
1081
|
+
spellings: ["-U", "--until"],
|
|
1082
|
+
key: "until",
|
|
1083
|
+
arity: FlagArity.Required,
|
|
1084
|
+
valueMayStartWithDash: true,
|
|
1085
|
+
checkValue: checkPattern(JOURNAL_TIME_REGEX, 'a time such as "2024-05-01 10:00", "-1h", "yesterday" or "1 hour ago"'),
|
|
1086
|
+
},
|
|
1087
|
+
{
|
|
1088
|
+
spellings: ["-p", "--priority"],
|
|
1089
|
+
key: "priority",
|
|
1090
|
+
arity: FlagArity.Required,
|
|
1091
|
+
checkValue: checkPattern(PRIORITY_REGEX, "a priority (emerg, alert, crit, err, warning, notice, info, debug or 0-7) or a range such as err..warning"),
|
|
1092
|
+
},
|
|
1093
|
+
{
|
|
1094
|
+
spellings: ["-g", "--grep"],
|
|
1095
|
+
key: "grep",
|
|
1096
|
+
arity: FlagArity.Required,
|
|
1097
|
+
checkValue: (value) => {
|
|
1098
|
+
return value.length >= 1 && value.length <= 256
|
|
1099
|
+
? null
|
|
1100
|
+
: "must be a pattern of 1 to 256 characters";
|
|
1101
|
+
},
|
|
1102
|
+
},
|
|
1103
|
+
{
|
|
1104
|
+
spellings: ["-b", "--boot"],
|
|
1105
|
+
key: "boot",
|
|
1106
|
+
arity: FlagArity.Optional,
|
|
1107
|
+
valueMayStartWithDash: true,
|
|
1108
|
+
takesNextWord: (word) => {
|
|
1109
|
+
return JOURNAL_BOOT_REGEX.test(word);
|
|
1110
|
+
},
|
|
1111
|
+
checkValue: checkPattern(JOURNAL_BOOT_REGEX, "a boot offset (0, -1, ...) or a boot id"),
|
|
1112
|
+
},
|
|
1113
|
+
{
|
|
1114
|
+
spellings: ["-o", "--output"],
|
|
1115
|
+
key: "output",
|
|
1116
|
+
arity: FlagArity.Required,
|
|
1117
|
+
checkValue: checkOneOf(JOURNALCTL_OUTPUT_FORMATS),
|
|
1118
|
+
},
|
|
1119
|
+
switchFlag("dmesg", "-k", "--dmesg"),
|
|
1120
|
+
switchFlag("no-pager", "--no-pager"),
|
|
1121
|
+
switchFlag("utc", "--utc"),
|
|
1122
|
+
switchFlag("reverse", "-r", "--reverse"),
|
|
1123
|
+
switchFlag("no-hostname", "--no-hostname"),
|
|
1124
|
+
switchFlag("catalog", "-x", "--catalog"),
|
|
1125
|
+
switchFlag("quiet", "-q", "--quiet"),
|
|
1126
|
+
switchFlag("list-boots", "--list-boots"),
|
|
1127
|
+
switchFlag("disk-usage", "--disk-usage"),
|
|
1128
|
+
{
|
|
1129
|
+
spellings: ["--vacuum-size"],
|
|
1130
|
+
key: "vacuum-size",
|
|
1131
|
+
arity: FlagArity.Required,
|
|
1132
|
+
checkValue: checkPattern(JOURNAL_SIZE_REGEX, "a size such as 500M or 2G"),
|
|
1133
|
+
},
|
|
1134
|
+
{
|
|
1135
|
+
spellings: ["--vacuum-time"],
|
|
1136
|
+
key: "vacuum-time",
|
|
1137
|
+
arity: FlagArity.Required,
|
|
1138
|
+
checkValue: checkPattern(JOURNAL_TIME_SPAN_REGEX, "a time span such as 7d, 2weeks or 12h"),
|
|
1139
|
+
},
|
|
1140
|
+
{
|
|
1141
|
+
spellings: ["--vacuum-files"],
|
|
1142
|
+
key: "vacuum-files",
|
|
1143
|
+
arity: FlagArity.Required,
|
|
1144
|
+
checkValue: checkWholeNumber(1, 100000),
|
|
1145
|
+
},
|
|
1146
|
+
],
|
|
1147
|
+
denied: [
|
|
1148
|
+
{
|
|
1149
|
+
spellings: ["-f", "--follow"],
|
|
1150
|
+
reason: "it follows the journal forever, so the command would only end at its timeout — bound it with -n N or --since instead",
|
|
1151
|
+
},
|
|
1152
|
+
{
|
|
1153
|
+
spellings: [
|
|
1154
|
+
"-D",
|
|
1155
|
+
"--directory",
|
|
1156
|
+
"--file",
|
|
1157
|
+
"-i",
|
|
1158
|
+
"--root",
|
|
1159
|
+
"--image",
|
|
1160
|
+
"--image-policy",
|
|
1161
|
+
],
|
|
1162
|
+
reason: "it reads journal files from another place than the host's journal",
|
|
1163
|
+
},
|
|
1164
|
+
{
|
|
1165
|
+
spellings: ["-M", "--machine", "--namespace"],
|
|
1166
|
+
reason: "it reads another machine's or namespace's journal",
|
|
1167
|
+
},
|
|
1168
|
+
{
|
|
1169
|
+
spellings: [
|
|
1170
|
+
"--rotate",
|
|
1171
|
+
"--flush",
|
|
1172
|
+
"--sync",
|
|
1173
|
+
"--relinquish-var",
|
|
1174
|
+
"--smart-relinquish-var",
|
|
1175
|
+
],
|
|
1176
|
+
reason: "it changes how journald stores the journal",
|
|
1177
|
+
},
|
|
1178
|
+
{
|
|
1179
|
+
spellings: [
|
|
1180
|
+
"--setup-keys",
|
|
1181
|
+
"--verify",
|
|
1182
|
+
"--verify-key",
|
|
1183
|
+
"--interval",
|
|
1184
|
+
"--force",
|
|
1185
|
+
],
|
|
1186
|
+
reason: "it manages Forward Secure Sealing keys",
|
|
1187
|
+
},
|
|
1188
|
+
{
|
|
1189
|
+
spellings: ["--update-catalog"],
|
|
1190
|
+
reason: "it rewrites the message catalog",
|
|
1191
|
+
},
|
|
1192
|
+
{
|
|
1193
|
+
spellings: ["--cursor-file"],
|
|
1194
|
+
reason: "it writes a cursor file on the host",
|
|
1195
|
+
},
|
|
1196
|
+
],
|
|
1197
|
+
};
|
|
1198
|
+
const VACUUM_KEYS = [
|
|
1199
|
+
"vacuum-size",
|
|
1200
|
+
"vacuum-time",
|
|
1201
|
+
"vacuum-files",
|
|
1202
|
+
];
|
|
1203
|
+
function evaluateJournalctl(argv) {
|
|
1204
|
+
const parsed = parseGetoptArgs(argv.slice(1), JOURNALCTL_GRAMMAR);
|
|
1205
|
+
if (parsed.problem) {
|
|
1206
|
+
return deniedResult(argv, parsed.problem);
|
|
1207
|
+
}
|
|
1208
|
+
if (parsed.positionals.length > 0) {
|
|
1209
|
+
return deniedResult(argv, `journalctl takes no match words or paths here ("${parsed.positionals[0]}"): filter with -u UNIT, -t IDENTIFIER, -p PRIORITY, -g REGEX, -k or -b; ${JOURNALCTL_ALLOWED}`);
|
|
1210
|
+
}
|
|
1211
|
+
const base = {
|
|
1212
|
+
program: argv[0] || "",
|
|
1213
|
+
args: argv.slice(1),
|
|
1214
|
+
displayCommand: renderResourceDisplayCommand(argv),
|
|
1215
|
+
targets: [],
|
|
1216
|
+
};
|
|
1217
|
+
const vacuums = parsed.flags.filter((flag) => {
|
|
1218
|
+
return VACUUM_KEYS.includes(flag.key);
|
|
1219
|
+
});
|
|
1220
|
+
if (vacuums.length > 0) {
|
|
1221
|
+
const other = parsed.flags.find((flag) => {
|
|
1222
|
+
return (!VACUUM_KEYS.includes(flag.key) &&
|
|
1223
|
+
flag.key !== "no-pager" &&
|
|
1224
|
+
flag.key !== "quiet");
|
|
1225
|
+
});
|
|
1226
|
+
if (other) {
|
|
1227
|
+
return deniedResult(argv, `run a journal vacuum on its own (${other.spelling} does not go with it), as in journalctl --vacuum-time=7d; ${JOURNALCTL_ALLOWED}`);
|
|
1228
|
+
}
|
|
1229
|
+
return Object.assign(Object.assign({}, base), { tier: ResourceCommandTier.RiskyWrite, verb: "vacuum", reason: `journalctl ${vacuums
|
|
1230
|
+
.map((flag) => {
|
|
1231
|
+
return `${flag.spelling}=${flag.value || ""}`;
|
|
1232
|
+
})
|
|
1233
|
+
.join(" ")} permanently deletes archived journal files beyond the limit`, targets: ["journal"] });
|
|
1234
|
+
}
|
|
1235
|
+
const bounded = hasFlag(parsed, "lines") ||
|
|
1236
|
+
hasFlag(parsed, "since") ||
|
|
1237
|
+
hasFlag(parsed, "list-boots") ||
|
|
1238
|
+
hasFlag(parsed, "disk-usage");
|
|
1239
|
+
if (!bounded) {
|
|
1240
|
+
return deniedResult(argv, `journalctl must be bounded: add -n N (at most ${MAX_JOURNALCTL_LINES} lines) or --since TIME, as in journalctl -u nginx.service -n 200 --no-pager; ${JOURNALCTL_ALLOWED}`);
|
|
1241
|
+
}
|
|
1242
|
+
let verb = "logs";
|
|
1243
|
+
let reason = "journalctl reads a bounded slice of the journal";
|
|
1244
|
+
if (hasFlag(parsed, "list-boots")) {
|
|
1245
|
+
verb = "list-boots";
|
|
1246
|
+
reason = "journalctl --list-boots lists the recorded boots";
|
|
1247
|
+
}
|
|
1248
|
+
else if (hasFlag(parsed, "disk-usage")) {
|
|
1249
|
+
verb = "disk-usage";
|
|
1250
|
+
reason = "journalctl --disk-usage shows how much disk the journal uses";
|
|
1251
|
+
}
|
|
1252
|
+
return Object.assign(Object.assign({}, base), { tier: ResourceCommandTier.Read, verb, reason });
|
|
1253
|
+
}
|
|
1254
|
+
/*
|
|
1255
|
+
* ---------------------------------------------------------------------------
|
|
1256
|
+
* The one-shot getopt programs: df, free, uptime, uname, dmesg, lsblk, ss, top
|
|
1257
|
+
* ---------------------------------------------------------------------------
|
|
1258
|
+
*/
|
|
1259
|
+
const FILESYSTEM_TYPE_REGEX = /^[a-z0-9][a-z0-9_.-]{0,31}$/;
|
|
1260
|
+
/*
|
|
1261
|
+
* An absolute path df may stat (hasDotDotStep refuses a ".." step). Steps
|
|
1262
|
+
* are separated by exactly one "/", so a long word that is not a path can
|
|
1263
|
+
* never make the regex backtrack.
|
|
1264
|
+
*/
|
|
1265
|
+
const ABSOLUTE_PATH_REGEX = /^\/(?:[A-Za-z0-9_@:+,=%.-]+(?:\/[A-Za-z0-9_@:+,=%.-]+){0,31}\/?)?$/;
|
|
1266
|
+
const DEVICE_PATH_REGEX = /^\/dev\/[A-Za-z0-9_:@+.-]+(?:\/[A-Za-z0-9_:@+.-]+){0,8}$/;
|
|
1267
|
+
function hasDotDotStep(path) {
|
|
1268
|
+
return path.split("/").some((step) => {
|
|
1269
|
+
return step === "..";
|
|
1270
|
+
});
|
|
1271
|
+
}
|
|
1272
|
+
const DF_GRAMMAR = {
|
|
1273
|
+
program: "df",
|
|
1274
|
+
allowed: DF_ALLOWED,
|
|
1275
|
+
flags: [
|
|
1276
|
+
switchFlag("human", "-h", "--human-readable"),
|
|
1277
|
+
switchFlag("si", "-H", "--si"),
|
|
1278
|
+
switchFlag("inodes", "-i", "--inodes"),
|
|
1279
|
+
switchFlag("kilobytes", "-k"),
|
|
1280
|
+
switchFlag("print-type", "-T", "--print-type"),
|
|
1281
|
+
switchFlag("portability", "-P", "--portability"),
|
|
1282
|
+
switchFlag("all", "-a", "--all"),
|
|
1283
|
+
switchFlag("local", "-l", "--local"),
|
|
1284
|
+
switchFlag("total", "--total"),
|
|
1285
|
+
{
|
|
1286
|
+
spellings: ["-t", "--type"],
|
|
1287
|
+
key: "type",
|
|
1288
|
+
arity: FlagArity.Required,
|
|
1289
|
+
repeatable: true,
|
|
1290
|
+
checkValue: checkPattern(FILESYSTEM_TYPE_REGEX, "a filesystem type such as ext4"),
|
|
1291
|
+
},
|
|
1292
|
+
{
|
|
1293
|
+
spellings: ["-x", "--exclude-type"],
|
|
1294
|
+
key: "exclude-type",
|
|
1295
|
+
arity: FlagArity.Required,
|
|
1296
|
+
repeatable: true,
|
|
1297
|
+
checkValue: checkPattern(FILESYSTEM_TYPE_REGEX, "a filesystem type such as tmpfs"),
|
|
1298
|
+
},
|
|
1299
|
+
],
|
|
1300
|
+
denied: [],
|
|
1301
|
+
};
|
|
1302
|
+
const FREE_GRAMMAR = {
|
|
1303
|
+
program: "free",
|
|
1304
|
+
allowed: FREE_ALLOWED,
|
|
1305
|
+
flags: [
|
|
1306
|
+
switchFlag("bytes", "-b", "--bytes"),
|
|
1307
|
+
switchFlag("kibi", "-k", "--kibi"),
|
|
1308
|
+
switchFlag("mebi", "-m", "--mebi"),
|
|
1309
|
+
switchFlag("gibi", "-g", "--gibi"),
|
|
1310
|
+
switchFlag("human", "-h", "--human"),
|
|
1311
|
+
switchFlag("wide", "-w", "--wide"),
|
|
1312
|
+
switchFlag("total", "-t", "--total"),
|
|
1313
|
+
switchFlag("si", "--si"),
|
|
1314
|
+
],
|
|
1315
|
+
denied: [
|
|
1316
|
+
{
|
|
1317
|
+
spellings: ["-s", "--seconds", "-c", "--count"],
|
|
1318
|
+
reason: "it repeats the report, so the command would run until its timeout",
|
|
1319
|
+
},
|
|
1320
|
+
],
|
|
1321
|
+
};
|
|
1322
|
+
const UPTIME_GRAMMAR = {
|
|
1323
|
+
program: "uptime",
|
|
1324
|
+
allowed: UPTIME_ALLOWED,
|
|
1325
|
+
flags: [
|
|
1326
|
+
switchFlag("pretty", "-p", "--pretty"),
|
|
1327
|
+
switchFlag("since", "-s", "--since"),
|
|
1328
|
+
],
|
|
1329
|
+
denied: [],
|
|
1330
|
+
};
|
|
1331
|
+
const UNAME_GRAMMAR = {
|
|
1332
|
+
program: "uname",
|
|
1333
|
+
allowed: UNAME_ALLOWED,
|
|
1334
|
+
flags: [
|
|
1335
|
+
switchFlag("all", "-a", "--all"),
|
|
1336
|
+
switchFlag("kernel-release", "-r", "--kernel-release"),
|
|
1337
|
+
switchFlag("kernel-name", "-s", "--kernel-name"),
|
|
1338
|
+
switchFlag("machine", "-m", "--machine"),
|
|
1339
|
+
switchFlag("nodename", "-n", "--nodename"),
|
|
1340
|
+
switchFlag("kernel-version", "-v", "--kernel-version"),
|
|
1341
|
+
switchFlag("operating-system", "-o", "--operating-system"),
|
|
1342
|
+
],
|
|
1343
|
+
denied: [],
|
|
1344
|
+
};
|
|
1345
|
+
const DMESG_LEVEL_REGEX = /^\+?(?:emerg|alert|crit|err|warn|notice|info|debug)\+?$/;
|
|
1346
|
+
const DMESG_GRAMMAR = {
|
|
1347
|
+
program: "dmesg",
|
|
1348
|
+
allowed: DMESG_ALLOWED,
|
|
1349
|
+
flags: [
|
|
1350
|
+
switchFlag("ctime", "-T", "--ctime"),
|
|
1351
|
+
switchFlag("notime", "-t", "--notime"),
|
|
1352
|
+
switchFlag("kernel", "-k", "--kernel"),
|
|
1353
|
+
switchFlag("decode", "-x", "--decode"),
|
|
1354
|
+
{
|
|
1355
|
+
spellings: ["-l", "--level"],
|
|
1356
|
+
key: "level",
|
|
1357
|
+
arity: FlagArity.Required,
|
|
1358
|
+
checkValue: checkList(DMESG_LEVEL_REGEX, "levels such as err,warn (emerg, alert, crit, err, warn, notice, info, debug)"),
|
|
1359
|
+
},
|
|
1360
|
+
],
|
|
1361
|
+
denied: [
|
|
1362
|
+
{
|
|
1363
|
+
spellings: ["-w", "--follow", "-W", "--follow-new"],
|
|
1364
|
+
reason: "it waits for new messages forever, so the command would only end at its timeout",
|
|
1365
|
+
},
|
|
1366
|
+
{
|
|
1367
|
+
spellings: ["-c", "--read-clear", "-C", "--clear"],
|
|
1368
|
+
reason: "it clears the kernel ring buffer",
|
|
1369
|
+
},
|
|
1370
|
+
{
|
|
1371
|
+
spellings: [
|
|
1372
|
+
"-n",
|
|
1373
|
+
"--console-level",
|
|
1374
|
+
"-D",
|
|
1375
|
+
"--console-off",
|
|
1376
|
+
"-E",
|
|
1377
|
+
"--console-on",
|
|
1378
|
+
],
|
|
1379
|
+
reason: "it changes what the kernel prints to the console",
|
|
1380
|
+
},
|
|
1381
|
+
{
|
|
1382
|
+
spellings: ["-F", "--file", "-K", "--kmsg-file"],
|
|
1383
|
+
reason: "it reads a file instead of the kernel ring buffer",
|
|
1384
|
+
},
|
|
1385
|
+
{
|
|
1386
|
+
spellings: ["-H", "--human"],
|
|
1387
|
+
reason: "it starts a pager; use -T for readable timestamps",
|
|
1388
|
+
},
|
|
1389
|
+
],
|
|
1390
|
+
};
|
|
1391
|
+
const LSBLK_COLUMNS_REGEX = /^\+?[A-Za-z][A-Za-z0-9%:_-]{0,31}$/;
|
|
1392
|
+
const LSBLK_GRAMMAR = {
|
|
1393
|
+
program: "lsblk",
|
|
1394
|
+
allowed: LSBLK_ALLOWED,
|
|
1395
|
+
flags: [
|
|
1396
|
+
switchFlag("fs", "-f", "--fs"),
|
|
1397
|
+
switchFlag("bytes", "-b", "--bytes"),
|
|
1398
|
+
switchFlag("paths", "-p", "--paths"),
|
|
1399
|
+
switchFlag("json", "-J", "--json"),
|
|
1400
|
+
switchFlag("nodeps", "-d", "--nodeps"),
|
|
1401
|
+
switchFlag("all", "-a", "--all"),
|
|
1402
|
+
switchFlag("list", "-l", "--list"),
|
|
1403
|
+
switchFlag("noheadings", "-n", "--noheadings"),
|
|
1404
|
+
{
|
|
1405
|
+
spellings: ["-o", "--output"],
|
|
1406
|
+
key: "output",
|
|
1407
|
+
arity: FlagArity.Required,
|
|
1408
|
+
checkValue: checkList(LSBLK_COLUMNS_REGEX, "column names such as NAME,SIZE,TYPE,MOUNTPOINTS"),
|
|
1409
|
+
},
|
|
1410
|
+
],
|
|
1411
|
+
denied: [
|
|
1412
|
+
{
|
|
1413
|
+
spellings: ["--sysroot"],
|
|
1414
|
+
reason: "it reads another root directory",
|
|
1415
|
+
},
|
|
1416
|
+
],
|
|
1417
|
+
};
|
|
1418
|
+
/*
|
|
1419
|
+
* One word of an ss filter expression (state established, dport = :443,
|
|
1420
|
+
* ( ... )), or a whole expression quoted as one word.
|
|
1421
|
+
*/
|
|
1422
|
+
const SS_FILTER_WORD_REGEX = /^[A-Za-z0-9_.:/()!=<>[\]%*,][A-Za-z0-9_.:/()!=<>[\]%*, -]{0,255}$/;
|
|
1423
|
+
const SS_GRAMMAR = {
|
|
1424
|
+
program: "ss",
|
|
1425
|
+
allowed: SS_ALLOWED,
|
|
1426
|
+
flags: [
|
|
1427
|
+
switchFlag("tcp", "-t", "--tcp"),
|
|
1428
|
+
switchFlag("udp", "-u", "--udp"),
|
|
1429
|
+
switchFlag("listening", "-l", "--listening"),
|
|
1430
|
+
switchFlag("numeric", "-n", "--numeric"),
|
|
1431
|
+
switchFlag("processes", "-p", "--processes"),
|
|
1432
|
+
switchFlag("all", "-a", "--all"),
|
|
1433
|
+
switchFlag("summary", "-s", "--summary"),
|
|
1434
|
+
switchFlag("unix", "-x", "--unix"),
|
|
1435
|
+
switchFlag("ipv4", "-4", "--ipv4"),
|
|
1436
|
+
switchFlag("ipv6", "-6", "--ipv6"),
|
|
1437
|
+
switchFlag("extended", "-e", "--extended"),
|
|
1438
|
+
switchFlag("info", "-i", "--info"),
|
|
1439
|
+
switchFlag("memory", "-m", "--memory"),
|
|
1440
|
+
switchFlag("options", "-o", "--options"),
|
|
1441
|
+
switchFlag("resolve", "-r", "--resolve"),
|
|
1442
|
+
switchFlag("no-header", "-H", "--no-header"),
|
|
1443
|
+
],
|
|
1444
|
+
denied: [
|
|
1445
|
+
{
|
|
1446
|
+
spellings: ["-K", "--kill"],
|
|
1447
|
+
reason: "it forcibly closes the sockets it lists",
|
|
1448
|
+
},
|
|
1449
|
+
{
|
|
1450
|
+
spellings: ["-D", "--diag"],
|
|
1451
|
+
reason: "it writes raw socket data to a file",
|
|
1452
|
+
},
|
|
1453
|
+
{
|
|
1454
|
+
spellings: ["-F", "--filter"],
|
|
1455
|
+
reason: "it reads the filter from a file; write the filter as words instead",
|
|
1456
|
+
},
|
|
1457
|
+
{
|
|
1458
|
+
spellings: ["-N", "--net"],
|
|
1459
|
+
reason: "it switches to another network namespace",
|
|
1460
|
+
},
|
|
1461
|
+
{
|
|
1462
|
+
spellings: ["-E", "--events"],
|
|
1463
|
+
reason: "it streams socket events forever, so the command would only end at its timeout",
|
|
1464
|
+
},
|
|
1465
|
+
],
|
|
1466
|
+
};
|
|
1467
|
+
const TOP_FIELD_REGEX = /^[+-]?[A-Za-z%][A-Za-z0-9%+._-]{0,15}$/;
|
|
1468
|
+
const TOP_GRAMMAR = {
|
|
1469
|
+
program: "top",
|
|
1470
|
+
allowed: TOP_ALLOWED,
|
|
1471
|
+
flags: [
|
|
1472
|
+
switchFlag("batch", "-b", "--batch-mode"),
|
|
1473
|
+
{
|
|
1474
|
+
spellings: ["-n", "--iterations"],
|
|
1475
|
+
key: "iterations",
|
|
1476
|
+
arity: FlagArity.Required,
|
|
1477
|
+
checkValue: (value) => {
|
|
1478
|
+
return value === "1"
|
|
1479
|
+
? null
|
|
1480
|
+
: `must be 1 (top runs exactly once), not "${value}"`;
|
|
1481
|
+
},
|
|
1482
|
+
},
|
|
1483
|
+
{
|
|
1484
|
+
spellings: ["-o", "--sort-override"],
|
|
1485
|
+
key: "sort",
|
|
1486
|
+
arity: FlagArity.Required,
|
|
1487
|
+
valueMayStartWithDash: true,
|
|
1488
|
+
checkValue: checkPattern(TOP_FIELD_REGEX, "a field name such as %CPU or %MEM"),
|
|
1489
|
+
},
|
|
1490
|
+
switchFlag("cmdline", "-c", "--cmdline-toggle"),
|
|
1491
|
+
{
|
|
1492
|
+
spellings: ["-w", "--width"],
|
|
1493
|
+
key: "width",
|
|
1494
|
+
arity: FlagArity.Optional,
|
|
1495
|
+
takesNextWord: (word) => {
|
|
1496
|
+
return LEADING_DIGIT_REGEX.test(word);
|
|
1497
|
+
},
|
|
1498
|
+
checkValue: checkWholeNumber(1, MAX_TOP_WIDTH),
|
|
1499
|
+
},
|
|
1500
|
+
switchFlag("threads", "-H", "--threads-show"),
|
|
1501
|
+
],
|
|
1502
|
+
denied: [],
|
|
1503
|
+
};
|
|
1504
|
+
const SIMPLE_PROGRAMS = {
|
|
1505
|
+
df: {
|
|
1506
|
+
grammar: DF_GRAMMAR,
|
|
1507
|
+
checkOperand: (operand) => {
|
|
1508
|
+
return ABSOLUTE_PATH_REGEX.test(operand) && !hasDotDotStep(operand)
|
|
1509
|
+
? null
|
|
1510
|
+
: `"${operand}" is not an absolute path df can report on`;
|
|
1511
|
+
},
|
|
1512
|
+
reason: "df shows filesystem space and inode use; it changes nothing",
|
|
1513
|
+
},
|
|
1514
|
+
free: {
|
|
1515
|
+
grammar: FREE_GRAMMAR,
|
|
1516
|
+
checkOperand: null,
|
|
1517
|
+
reason: "free shows memory and swap use once; it changes nothing",
|
|
1518
|
+
},
|
|
1519
|
+
uptime: {
|
|
1520
|
+
grammar: UPTIME_GRAMMAR,
|
|
1521
|
+
checkOperand: null,
|
|
1522
|
+
reason: "uptime shows how long the host has run and its load; it changes nothing",
|
|
1523
|
+
},
|
|
1524
|
+
uname: {
|
|
1525
|
+
grammar: UNAME_GRAMMAR,
|
|
1526
|
+
checkOperand: null,
|
|
1527
|
+
reason: "uname shows the kernel and machine; it changes nothing",
|
|
1528
|
+
},
|
|
1529
|
+
dmesg: {
|
|
1530
|
+
grammar: DMESG_GRAMMAR,
|
|
1531
|
+
checkOperand: null,
|
|
1532
|
+
reason: "dmesg reads the kernel ring buffer without clearing it; it changes nothing",
|
|
1533
|
+
},
|
|
1534
|
+
lsblk: {
|
|
1535
|
+
grammar: LSBLK_GRAMMAR,
|
|
1536
|
+
checkOperand: (operand) => {
|
|
1537
|
+
return DEVICE_PATH_REGEX.test(operand) && !hasDotDotStep(operand)
|
|
1538
|
+
? null
|
|
1539
|
+
: `"${operand}" is not a /dev device path lsblk can list`;
|
|
1540
|
+
},
|
|
1541
|
+
reason: "lsblk lists block devices; it changes nothing",
|
|
1542
|
+
},
|
|
1543
|
+
ss: {
|
|
1544
|
+
grammar: SS_GRAMMAR,
|
|
1545
|
+
checkOperand: (operand) => {
|
|
1546
|
+
return SS_FILTER_WORD_REGEX.test(operand)
|
|
1547
|
+
? null
|
|
1548
|
+
: `"${operand}" is not a word of an ss filter expression`;
|
|
1549
|
+
},
|
|
1550
|
+
reason: "ss lists sockets; it changes nothing",
|
|
1551
|
+
},
|
|
1552
|
+
};
|
|
1553
|
+
function evaluateSimpleProgram(argv, simple) {
|
|
1554
|
+
const parsed = parseGetoptArgs(argv.slice(1), simple.grammar);
|
|
1555
|
+
if (parsed.problem) {
|
|
1556
|
+
return deniedResult(argv, parsed.problem);
|
|
1557
|
+
}
|
|
1558
|
+
for (const operand of parsed.positionals) {
|
|
1559
|
+
const problem = simple.checkOperand
|
|
1560
|
+
? simple.checkOperand(operand)
|
|
1561
|
+
: `${simple.grammar.program} takes no words besides its flags ("${operand}")`;
|
|
1562
|
+
if (problem) {
|
|
1563
|
+
return deniedResult(argv, `${problem}; ${simple.grammar.allowed}`);
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
return {
|
|
1567
|
+
tier: ResourceCommandTier.Read,
|
|
1568
|
+
reason: simple.reason,
|
|
1569
|
+
program: argv[0] || "",
|
|
1570
|
+
args: argv.slice(1),
|
|
1571
|
+
verb: argv[0] || "",
|
|
1572
|
+
displayCommand: renderResourceDisplayCommand(argv),
|
|
1573
|
+
targets: [],
|
|
1574
|
+
};
|
|
1575
|
+
}
|
|
1576
|
+
function evaluateTop(argv) {
|
|
1577
|
+
const parsed = parseGetoptArgs(argv.slice(1), TOP_GRAMMAR);
|
|
1578
|
+
if (parsed.problem) {
|
|
1579
|
+
return deniedResult(argv, parsed.problem);
|
|
1580
|
+
}
|
|
1581
|
+
if (parsed.positionals.length > 0) {
|
|
1582
|
+
return deniedResult(argv, `top takes no words besides its flags ("${parsed.positionals[0]}"); ${TOP_ALLOWED}`);
|
|
1583
|
+
}
|
|
1584
|
+
if (!hasFlag(parsed, "batch") || !hasFlag(parsed, "iterations")) {
|
|
1585
|
+
return deniedResult(argv, `top must run once in batch mode with -b and -n 1 (without them it waits for a terminal until its timeout); ${TOP_ALLOWED}`);
|
|
1586
|
+
}
|
|
1587
|
+
return {
|
|
1588
|
+
tier: ResourceCommandTier.Read,
|
|
1589
|
+
reason: "top prints one batch snapshot of the busiest processes; it changes nothing",
|
|
1590
|
+
program: argv[0] || "",
|
|
1591
|
+
args: argv.slice(1),
|
|
1592
|
+
verb: "top",
|
|
1593
|
+
displayCommand: renderResourceDisplayCommand(argv),
|
|
1594
|
+
targets: [],
|
|
1595
|
+
};
|
|
1596
|
+
}
|
|
1597
|
+
/*
|
|
1598
|
+
* ---------------------------------------------------------------------------
|
|
1599
|
+
* ps: UNIX (-ef), BSD (aux) and GNU (--sort) options, as procps reads them
|
|
1600
|
+
* ---------------------------------------------------------------------------
|
|
1601
|
+
*/
|
|
1602
|
+
/*
|
|
1603
|
+
* The output keys -o/o may print and --sort may order by. Nothing here
|
|
1604
|
+
* prints a process's environment (only the BSD `e` modifier does, and it is
|
|
1605
|
+
* Denied).
|
|
1606
|
+
*/
|
|
1607
|
+
const PS_FORMAT_KEYS = [
|
|
1608
|
+
"pid",
|
|
1609
|
+
"ppid",
|
|
1610
|
+
"pgid",
|
|
1611
|
+
"pgrp",
|
|
1612
|
+
"sid",
|
|
1613
|
+
"sess",
|
|
1614
|
+
"tid",
|
|
1615
|
+
"lwp",
|
|
1616
|
+
"spid",
|
|
1617
|
+
"nlwp",
|
|
1618
|
+
"thcount",
|
|
1619
|
+
"user",
|
|
1620
|
+
"euser",
|
|
1621
|
+
"ruser",
|
|
1622
|
+
"uname",
|
|
1623
|
+
"uid",
|
|
1624
|
+
"euid",
|
|
1625
|
+
"ruid",
|
|
1626
|
+
"group",
|
|
1627
|
+
"egroup",
|
|
1628
|
+
"rgroup",
|
|
1629
|
+
"gid",
|
|
1630
|
+
"egid",
|
|
1631
|
+
"rgid",
|
|
1632
|
+
"%cpu",
|
|
1633
|
+
"pcpu",
|
|
1634
|
+
"c",
|
|
1635
|
+
"cp",
|
|
1636
|
+
"%mem",
|
|
1637
|
+
"pmem",
|
|
1638
|
+
"rss",
|
|
1639
|
+
"rssize",
|
|
1640
|
+
"rsz",
|
|
1641
|
+
"vsz",
|
|
1642
|
+
"vsize",
|
|
1643
|
+
"sz",
|
|
1644
|
+
"size",
|
|
1645
|
+
"drs",
|
|
1646
|
+
"trs",
|
|
1647
|
+
"stat",
|
|
1648
|
+
"state",
|
|
1649
|
+
"s",
|
|
1650
|
+
"start",
|
|
1651
|
+
"start_time",
|
|
1652
|
+
"stime",
|
|
1653
|
+
"lstart",
|
|
1654
|
+
"bsdstart",
|
|
1655
|
+
"etime",
|
|
1656
|
+
"etimes",
|
|
1657
|
+
"time",
|
|
1658
|
+
"cputime",
|
|
1659
|
+
"cputimes",
|
|
1660
|
+
"bsdtime",
|
|
1661
|
+
"tty",
|
|
1662
|
+
"tt",
|
|
1663
|
+
"tname",
|
|
1664
|
+
"comm",
|
|
1665
|
+
"ucmd",
|
|
1666
|
+
"ucomm",
|
|
1667
|
+
"cmd",
|
|
1668
|
+
"args",
|
|
1669
|
+
"command",
|
|
1670
|
+
"ni",
|
|
1671
|
+
"nice",
|
|
1672
|
+
"pri",
|
|
1673
|
+
"priority",
|
|
1674
|
+
"psr",
|
|
1675
|
+
"wchan",
|
|
1676
|
+
"class",
|
|
1677
|
+
"cls",
|
|
1678
|
+
"policy",
|
|
1679
|
+
"rtprio",
|
|
1680
|
+
"f",
|
|
1681
|
+
"flags",
|
|
1682
|
+
"cgroup",
|
|
1683
|
+
"unit",
|
|
1684
|
+
"slice",
|
|
1685
|
+
"maj_flt",
|
|
1686
|
+
"min_flt",
|
|
1687
|
+
"majflt",
|
|
1688
|
+
"minflt",
|
|
1689
|
+
"oom",
|
|
1690
|
+
"oomadj",
|
|
1691
|
+
];
|
|
1692
|
+
// One -o item: KEY, KEY:WIDTH or KEY=HEADER.
|
|
1693
|
+
const PS_FORMAT_ITEM_REGEX = /^([a-z%_]{1,16})(?::[0-9]{1,4})?(?:=[A-Za-z0-9_%-]{0,32})?$/;
|
|
1694
|
+
const PS_SORT_ITEM_REGEX = /^[+-]?([a-z%_]{1,16})$/;
|
|
1695
|
+
const PS_PID_LIST_REGEX = /^[0-9]{1,7}(?:[, ][0-9]{1,7}){0,63}$/;
|
|
1696
|
+
const PS_USER_LIST_REGEX = /^[A-Za-z0-9_][A-Za-z0-9_.-]{0,31}(?:[, ][A-Za-z0-9_][A-Za-z0-9_.-]{0,31}){0,31}$/;
|
|
1697
|
+
const PS_COMMAND_LIST_REGEX = /^[A-Za-z0-9_.:@+][A-Za-z0-9_.:@+-]{0,63}(?:,[A-Za-z0-9_.:@+][A-Za-z0-9_.:@+-]{0,63}){0,31}$/;
|
|
1698
|
+
function checkPsFormat(value) {
|
|
1699
|
+
const items = value.split(/[, ]/);
|
|
1700
|
+
if (value.length > 512 || items.length > 64) {
|
|
1701
|
+
return "is too long a format list";
|
|
1702
|
+
}
|
|
1703
|
+
for (const item of items) {
|
|
1704
|
+
const match = PS_FORMAT_ITEM_REGEX.exec(item);
|
|
1705
|
+
if (!match || !PS_FORMAT_KEYS.includes(match[1] || "")) {
|
|
1706
|
+
return `must list output keys such as pid,ppid,user,%cpu,%mem,etime,stat,args — "${item}" is not one`;
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
return null;
|
|
1710
|
+
}
|
|
1711
|
+
function checkPsSort(value) {
|
|
1712
|
+
const items = value.split(",");
|
|
1713
|
+
if (value.length > 256 || items.length > 16) {
|
|
1714
|
+
return "is too long a sort list";
|
|
1715
|
+
}
|
|
1716
|
+
for (const item of items) {
|
|
1717
|
+
const match = PS_SORT_ITEM_REGEX.exec(item);
|
|
1718
|
+
if (!match || !PS_FORMAT_KEYS.includes(match[1] || "")) {
|
|
1719
|
+
return `must list sort keys such as -%cpu or -rss — "${item}" is not one`;
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
return null;
|
|
1723
|
+
}
|
|
1724
|
+
// UNIX switches (-e) and the UNIX options that take a value (-o FORMAT).
|
|
1725
|
+
const PS_UNIX_SWITCHES = [
|
|
1726
|
+
"e",
|
|
1727
|
+
"A",
|
|
1728
|
+
"f",
|
|
1729
|
+
"F",
|
|
1730
|
+
"l",
|
|
1731
|
+
"H",
|
|
1732
|
+
"L",
|
|
1733
|
+
"T",
|
|
1734
|
+
"w",
|
|
1735
|
+
];
|
|
1736
|
+
const PS_UNIX_VALUE_OPTIONS = {
|
|
1737
|
+
o: checkPsFormat,
|
|
1738
|
+
p: checkPattern(PS_PID_LIST_REGEX, "a list of pids such as 1234,5678"),
|
|
1739
|
+
u: checkPattern(PS_USER_LIST_REGEX, "a list of user names or ids"),
|
|
1740
|
+
C: checkPattern(PS_COMMAND_LIST_REGEX, "a list of command names such as nginx"),
|
|
1741
|
+
};
|
|
1742
|
+
const PS_BSD_SWITCHES = ["a", "u", "x", "w", "f"];
|
|
1743
|
+
const PS_BSD_VALUE_OPTIONS = {
|
|
1744
|
+
o: checkPsFormat,
|
|
1745
|
+
};
|
|
1746
|
+
const PS_GNU_SWITCHES = [
|
|
1747
|
+
"--no-headers",
|
|
1748
|
+
"--no-heading",
|
|
1749
|
+
"--forest",
|
|
1750
|
+
];
|
|
1751
|
+
function evaluatePs(argv) {
|
|
1752
|
+
const args = argv.slice(1);
|
|
1753
|
+
const deny = (problem) => {
|
|
1754
|
+
return deniedResult(argv, `${problem}; ${PS_ALLOWED}`);
|
|
1755
|
+
};
|
|
1756
|
+
for (let i = 0; i < args.length; i++) {
|
|
1757
|
+
const token = args[i];
|
|
1758
|
+
if (token === "" || token === "-" || token === "--") {
|
|
1759
|
+
return deny(`"${token}" is not a ps option`);
|
|
1760
|
+
}
|
|
1761
|
+
if (token.startsWith("--")) {
|
|
1762
|
+
const eq = token.indexOf("=");
|
|
1763
|
+
const name = eq >= 0 ? token.slice(0, eq) : token;
|
|
1764
|
+
if (PS_GNU_SWITCHES.includes(name)) {
|
|
1765
|
+
if (eq >= 0) {
|
|
1766
|
+
return deny(`${name} takes no value (in "${token}")`);
|
|
1767
|
+
}
|
|
1768
|
+
continue;
|
|
1769
|
+
}
|
|
1770
|
+
if (name !== "--sort") {
|
|
1771
|
+
return deny(`${name} is not a ps option this policy allows (long options must be written in full)`);
|
|
1772
|
+
}
|
|
1773
|
+
let value = eq >= 0 ? token.slice(eq + 1) : undefined;
|
|
1774
|
+
if (value === undefined) {
|
|
1775
|
+
value = args[i + 1];
|
|
1776
|
+
i++;
|
|
1777
|
+
}
|
|
1778
|
+
if (value === undefined) {
|
|
1779
|
+
return deny("--sort needs a key such as -%cpu");
|
|
1780
|
+
}
|
|
1781
|
+
const problem = checkPsSort(value);
|
|
1782
|
+
if (problem) {
|
|
1783
|
+
return deny(`--sort ${problem}`);
|
|
1784
|
+
}
|
|
1785
|
+
continue;
|
|
1786
|
+
}
|
|
1787
|
+
const isUnix = token.startsWith("-");
|
|
1788
|
+
const switches = isUnix
|
|
1789
|
+
? PS_UNIX_SWITCHES
|
|
1790
|
+
: PS_BSD_SWITCHES;
|
|
1791
|
+
const valueOptions = isUnix ? PS_UNIX_VALUE_OPTIONS : PS_BSD_VALUE_OPTIONS;
|
|
1792
|
+
let rest = isUnix ? token.slice(1) : token;
|
|
1793
|
+
while (rest.length > 0) {
|
|
1794
|
+
const letter = rest.charAt(0);
|
|
1795
|
+
const spelling = isUnix ? `-${letter}` : letter;
|
|
1796
|
+
const where = whereInToken(token, spelling);
|
|
1797
|
+
if (!isUnix && letter === "e") {
|
|
1798
|
+
return deny(`the BSD e option${where} prints every process's environment, where secrets live, so it is never allowed`);
|
|
1799
|
+
}
|
|
1800
|
+
if (switches.includes(letter)) {
|
|
1801
|
+
rest = rest.slice(1);
|
|
1802
|
+
continue;
|
|
1803
|
+
}
|
|
1804
|
+
if (!hasOwn(valueOptions, letter)) {
|
|
1805
|
+
return deny(`${isUnix ? spelling : `the BSD ${letter} option`}${where} is not a ps option this policy allows`);
|
|
1806
|
+
}
|
|
1807
|
+
// procps: the rest of the word is the value, else the next word.
|
|
1808
|
+
let value = rest.slice(1);
|
|
1809
|
+
if (!value) {
|
|
1810
|
+
value = args[i + 1];
|
|
1811
|
+
i++;
|
|
1812
|
+
}
|
|
1813
|
+
if (value === undefined) {
|
|
1814
|
+
return deny(`${spelling}${where} needs a value`);
|
|
1815
|
+
}
|
|
1816
|
+
const check = valueOptions[letter];
|
|
1817
|
+
const problem = check ? check(value) : null;
|
|
1818
|
+
if (problem) {
|
|
1819
|
+
return deny(`${spelling} ${problem}`);
|
|
1820
|
+
}
|
|
1821
|
+
break;
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
return {
|
|
1825
|
+
tier: ResourceCommandTier.Read,
|
|
1826
|
+
reason: "ps lists processes; it changes nothing",
|
|
1827
|
+
program: argv[0] || "",
|
|
1828
|
+
args: argv.slice(1),
|
|
1829
|
+
verb: "ps",
|
|
1830
|
+
displayCommand: renderResourceDisplayCommand(argv),
|
|
1831
|
+
targets: [],
|
|
1832
|
+
};
|
|
1833
|
+
}
|
|
1834
|
+
/*
|
|
1835
|
+
* ---------------------------------------------------------------------------
|
|
1836
|
+
* ip: its own option loop (prefix matching, options before the object)
|
|
1837
|
+
* ---------------------------------------------------------------------------
|
|
1838
|
+
*/
|
|
1839
|
+
// The option spellings allowed, after "--x" is read as "-x" the way ip does.
|
|
1840
|
+
const IP_ALLOWED_OPTIONS = [
|
|
1841
|
+
"-br",
|
|
1842
|
+
"-brief",
|
|
1843
|
+
"-s",
|
|
1844
|
+
"-stats",
|
|
1845
|
+
"-statistics",
|
|
1846
|
+
"-d",
|
|
1847
|
+
"-details",
|
|
1848
|
+
"-j",
|
|
1849
|
+
"-json",
|
|
1850
|
+
"-p",
|
|
1851
|
+
"-pretty",
|
|
1852
|
+
"-4",
|
|
1853
|
+
"-6",
|
|
1854
|
+
];
|
|
1855
|
+
const IP_DENIED_OPTIONS = [
|
|
1856
|
+
{
|
|
1857
|
+
name: "-batch",
|
|
1858
|
+
minimumLength: 2,
|
|
1859
|
+
reason: "it reads more ip commands from a file",
|
|
1860
|
+
},
|
|
1861
|
+
{
|
|
1862
|
+
name: "-force",
|
|
1863
|
+
minimumLength: 3,
|
|
1864
|
+
reason: "it keeps going past errors in batch mode",
|
|
1865
|
+
},
|
|
1866
|
+
{
|
|
1867
|
+
name: "-netns",
|
|
1868
|
+
minimumLength: 2,
|
|
1869
|
+
reason: "it switches to another network namespace",
|
|
1870
|
+
},
|
|
1871
|
+
];
|
|
1872
|
+
// Every spelling of the objects ip may read, with the name used in labels.
|
|
1873
|
+
const IP_OBJECTS = {
|
|
1874
|
+
a: "address",
|
|
1875
|
+
addr: "address",
|
|
1876
|
+
address: "address",
|
|
1877
|
+
l: "link",
|
|
1878
|
+
link: "link",
|
|
1879
|
+
r: "route",
|
|
1880
|
+
route: "route",
|
|
1881
|
+
n: "neigh",
|
|
1882
|
+
neigh: "neigh",
|
|
1883
|
+
neighbor: "neigh",
|
|
1884
|
+
neighbour: "neigh",
|
|
1885
|
+
ru: "rule",
|
|
1886
|
+
rule: "rule",
|
|
1887
|
+
};
|
|
1888
|
+
const IP_DENIED_OBJECTS = {
|
|
1889
|
+
netns: "it creates, deletes or runs commands in network namespaces",
|
|
1890
|
+
xfrm: "its state shows IPsec keys",
|
|
1891
|
+
monitor: "it streams events forever",
|
|
1892
|
+
};
|
|
1893
|
+
const IP_READ_ACTIONS = ["show", "list", "ls"];
|
|
1894
|
+
const IP_WRITE_ACTIONS = [
|
|
1895
|
+
"add",
|
|
1896
|
+
"append",
|
|
1897
|
+
"change",
|
|
1898
|
+
"chg",
|
|
1899
|
+
"del",
|
|
1900
|
+
"delete",
|
|
1901
|
+
"flush",
|
|
1902
|
+
"prepend",
|
|
1903
|
+
"replace",
|
|
1904
|
+
"restore",
|
|
1905
|
+
"save",
|
|
1906
|
+
"set",
|
|
1907
|
+
"test",
|
|
1908
|
+
];
|
|
1909
|
+
// One filter word after show: dev eth0, table all, scope global, 10.0.0.0/8.
|
|
1910
|
+
const IP_FILTER_WORD_REGEX = /^[A-Za-z0-9_.:/@%+][A-Za-z0-9_.:/@%+-]{0,63}$/;
|
|
1911
|
+
const IP_ADDRESS_REGEX = /^(?=[^/]*[.:])[0-9a-fA-F:.]{2,45}(?:\/[0-9]{1,3})?$/;
|
|
1912
|
+
function evaluateIp(argv) {
|
|
1913
|
+
const deny = (problem) => {
|
|
1914
|
+
return deniedResult(argv, `${problem}; ${IP_ALLOWED}`);
|
|
1915
|
+
};
|
|
1916
|
+
let index = 1;
|
|
1917
|
+
while (index < argv.length && argv[index].startsWith("-")) {
|
|
1918
|
+
const token = argv[index];
|
|
1919
|
+
if (token === "--") {
|
|
1920
|
+
return deny(`ip needs no "--"`);
|
|
1921
|
+
}
|
|
1922
|
+
// ip reads "--brief" as "-brief".
|
|
1923
|
+
const option = token.startsWith("--") ? token.slice(1) : token;
|
|
1924
|
+
if (!IP_ALLOWED_OPTIONS.includes(option)) {
|
|
1925
|
+
const denied = IP_DENIED_OPTIONS.find((entry) => {
|
|
1926
|
+
return (option.length >= entry.minimumLength &&
|
|
1927
|
+
entry.name.startsWith(option));
|
|
1928
|
+
});
|
|
1929
|
+
if (denied) {
|
|
1930
|
+
return deny(`ip ${token} is never allowed: ip reads it as ${denied.name}, and ${denied.reason}`);
|
|
1931
|
+
}
|
|
1932
|
+
return deny(`${token} is not an ip option this policy allows (options are written in full and come before the object)`);
|
|
1933
|
+
}
|
|
1934
|
+
index++;
|
|
1935
|
+
}
|
|
1936
|
+
const objectWord = argv[index];
|
|
1937
|
+
if (objectWord === undefined) {
|
|
1938
|
+
return deny("ip needs an object to show");
|
|
1939
|
+
}
|
|
1940
|
+
if (hasOwn(IP_DENIED_OBJECTS, objectWord)) {
|
|
1941
|
+
return deny(`ip ${objectWord} is never allowed: ${IP_DENIED_OBJECTS[objectWord]}`);
|
|
1942
|
+
}
|
|
1943
|
+
if (!hasOwn(IP_OBJECTS, objectWord)) {
|
|
1944
|
+
return deny(`ip ${objectWord} is not an object this policy reads`);
|
|
1945
|
+
}
|
|
1946
|
+
const object = IP_OBJECTS[objectWord] || objectWord;
|
|
1947
|
+
const rest = argv.slice(index + 1);
|
|
1948
|
+
const action = rest[0];
|
|
1949
|
+
const read = (label) => {
|
|
1950
|
+
return {
|
|
1951
|
+
tier: ResourceCommandTier.Read,
|
|
1952
|
+
reason: `ip ${label} shows the host's network configuration; it changes nothing`,
|
|
1953
|
+
program: argv[0] || "",
|
|
1954
|
+
args: argv.slice(1),
|
|
1955
|
+
verb: label,
|
|
1956
|
+
displayCommand: renderResourceDisplayCommand(argv),
|
|
1957
|
+
targets: [],
|
|
1958
|
+
};
|
|
1959
|
+
};
|
|
1960
|
+
if (action === undefined) {
|
|
1961
|
+
return read(`${object} show`);
|
|
1962
|
+
}
|
|
1963
|
+
if (IP_READ_ACTIONS.includes(action)) {
|
|
1964
|
+
const badFilter = rest
|
|
1965
|
+
.slice(1)
|
|
1966
|
+
.find((word) => {
|
|
1967
|
+
return !IP_FILTER_WORD_REGEX.test(word);
|
|
1968
|
+
});
|
|
1969
|
+
if (badFilter !== undefined) {
|
|
1970
|
+
return deny(`"${badFilter}" is not a filter word ip ${objectWord} ${action} can take (such as dev eth0 or table all)`);
|
|
1971
|
+
}
|
|
1972
|
+
return read(`${object} show`);
|
|
1973
|
+
}
|
|
1974
|
+
if (object === "route" && action === "get") {
|
|
1975
|
+
if (rest.length !== 2 || !IP_ADDRESS_REGEX.test(rest[1] || "")) {
|
|
1976
|
+
return deny("ip route get takes exactly one IP address, as in ip route get 1.1.1.1");
|
|
1977
|
+
}
|
|
1978
|
+
return read("route get");
|
|
1979
|
+
}
|
|
1980
|
+
if (IP_WRITE_ACTIONS.includes(action)) {
|
|
1981
|
+
return deny(`ip ${objectWord} ${action} changes the host's network configuration, which is never allowed`);
|
|
1982
|
+
}
|
|
1983
|
+
return deny(`"${action}" is not an ip ${object} read (write show, list or ls in full)`);
|
|
1984
|
+
}
|
|
1985
|
+
/*
|
|
1986
|
+
* ---------------------------------------------------------------------------
|
|
1987
|
+
* cat, hostnamectl, timedatectl
|
|
1988
|
+
* ---------------------------------------------------------------------------
|
|
1989
|
+
*/
|
|
1990
|
+
function evaluateCat(argv) {
|
|
1991
|
+
const operands = argv.slice(1);
|
|
1992
|
+
if (operands.length === 0) {
|
|
1993
|
+
return deniedResult(argv, `cat needs a file to read; ${CAT_ALLOWED}`);
|
|
1994
|
+
}
|
|
1995
|
+
for (const operand of operands) {
|
|
1996
|
+
if (operand.startsWith("-")) {
|
|
1997
|
+
return deniedResult(argv, `cat takes no flags ("${operand}"); ${CAT_ALLOWED}`);
|
|
1998
|
+
}
|
|
1999
|
+
if (!HOST_READABLE_FILES.includes(operand)) {
|
|
2000
|
+
return deniedResult(argv, `cat may not read "${operand}"; ${CAT_ALLOWED}`);
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
return {
|
|
2004
|
+
tier: ResourceCommandTier.Read,
|
|
2005
|
+
reason: "cat reads kernel counters or the OS release; it changes nothing",
|
|
2006
|
+
program: argv[0] || "",
|
|
2007
|
+
args: argv.slice(1),
|
|
2008
|
+
verb: "cat",
|
|
2009
|
+
displayCommand: renderResourceDisplayCommand(argv),
|
|
2010
|
+
targets: [],
|
|
2011
|
+
};
|
|
2012
|
+
}
|
|
2013
|
+
function evaluateStatusTool(argv, readCommands, allowed, shows) {
|
|
2014
|
+
var _a;
|
|
2015
|
+
const operands = argv.slice(1);
|
|
2016
|
+
const flag = operands.find((word) => {
|
|
2017
|
+
return word.startsWith("-");
|
|
2018
|
+
});
|
|
2019
|
+
if (flag !== undefined) {
|
|
2020
|
+
return deniedResult(argv, `${argv[0]} takes no flags here ("${flag}"); ${allowed}`);
|
|
2021
|
+
}
|
|
2022
|
+
const command = (_a = operands[0]) !== null && _a !== void 0 ? _a : "status";
|
|
2023
|
+
if (operands.length > 1 || !readCommands.includes(command)) {
|
|
2024
|
+
return deniedResult(argv, `${renderResourceDisplayCommand(argv)} is not allowed: only the read commands run, and settings are never changed; ${allowed}`);
|
|
2025
|
+
}
|
|
2026
|
+
return {
|
|
2027
|
+
tier: ResourceCommandTier.Read,
|
|
2028
|
+
reason: `${argv[0]} ${command} shows ${shows}; it changes nothing`,
|
|
2029
|
+
program: argv[0] || "",
|
|
2030
|
+
args: argv.slice(1),
|
|
2031
|
+
verb: command,
|
|
2032
|
+
displayCommand: renderResourceDisplayCommand(argv),
|
|
2033
|
+
targets: [],
|
|
2034
|
+
};
|
|
2035
|
+
}
|
|
2036
|
+
/*
|
|
2037
|
+
* ---------------------------------------------------------------------------
|
|
2038
|
+
* kill
|
|
2039
|
+
* ---------------------------------------------------------------------------
|
|
2040
|
+
*/
|
|
2041
|
+
// Signal spellings kill accepts here, each with the name shown on the card.
|
|
2042
|
+
const KILL_SIGNALS = {
|
|
2043
|
+
TERM: "TERM",
|
|
2044
|
+
SIGTERM: "TERM",
|
|
2045
|
+
"15": "TERM",
|
|
2046
|
+
HUP: "HUP",
|
|
2047
|
+
SIGHUP: "HUP",
|
|
2048
|
+
INT: "INT",
|
|
2049
|
+
SIGINT: "INT",
|
|
2050
|
+
KILL: "KILL",
|
|
2051
|
+
SIGKILL: "KILL",
|
|
2052
|
+
"9": "KILL",
|
|
2053
|
+
};
|
|
2054
|
+
const PID_REGEX = /^[1-9][0-9]{0,6}$/;
|
|
2055
|
+
function evaluateKill(argv) {
|
|
2056
|
+
const args = argv.slice(1);
|
|
2057
|
+
const deny = (problem) => {
|
|
2058
|
+
return deniedResult(argv, `${problem}; ${KILL_ALLOWED}`);
|
|
2059
|
+
};
|
|
2060
|
+
let signal = "TERM";
|
|
2061
|
+
let index = 0;
|
|
2062
|
+
const first = args[0];
|
|
2063
|
+
if (first === "-s") {
|
|
2064
|
+
const name = args[1];
|
|
2065
|
+
if (name === undefined || !hasOwn(KILL_SIGNALS, name)) {
|
|
2066
|
+
return deny(`-s needs one of the allowed signals (${Object.keys(KILL_SIGNALS).join(", ")})`);
|
|
2067
|
+
}
|
|
2068
|
+
signal = KILL_SIGNALS[name] || name;
|
|
2069
|
+
index = 2;
|
|
2070
|
+
}
|
|
2071
|
+
else if (first !== undefined && first.startsWith("-") && first !== "--") {
|
|
2072
|
+
const name = first.slice(1);
|
|
2073
|
+
if (!hasOwn(KILL_SIGNALS, name)) {
|
|
2074
|
+
return deny(`"${first}" is not a signal this policy sends (-TERM, -15, -HUP, -INT, -KILL or -9)`);
|
|
2075
|
+
}
|
|
2076
|
+
signal = KILL_SIGNALS[name] || name;
|
|
2077
|
+
index = 1;
|
|
2078
|
+
}
|
|
2079
|
+
const pidWords = args.slice(index);
|
|
2080
|
+
if (pidWords.length === 0) {
|
|
2081
|
+
return deny("kill needs the pid it signals");
|
|
2082
|
+
}
|
|
2083
|
+
const targets = [];
|
|
2084
|
+
for (const word of pidWords) {
|
|
2085
|
+
if (word.startsWith("-")) {
|
|
2086
|
+
return deny(`"${word}" is never allowed after the signal: a negative pid signals a whole process group (-1 is every process), and "--" or a second option is not needed`);
|
|
2087
|
+
}
|
|
2088
|
+
if (!PID_REGEX.test(word) || parseInt(word, 10) > MAX_PID) {
|
|
2089
|
+
return deny(`"${word}" is not a pid (a whole number from 2 to ${MAX_PID}, no leading zeros)`);
|
|
2090
|
+
}
|
|
2091
|
+
if (word === "1") {
|
|
2092
|
+
return deny("pid 1 is the host's init system; kill 1 is never allowed");
|
|
2093
|
+
}
|
|
2094
|
+
const target = `pid:${word}`;
|
|
2095
|
+
if (!targets.includes(target)) {
|
|
2096
|
+
targets.push(target);
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
return {
|
|
2100
|
+
tier: ResourceCommandTier.RiskyWrite,
|
|
2101
|
+
reason: `kill sends SIG${signal} to ${targets.length === 1 ? "process" : `${targets.length} processes:`} ${joinWords(targets.map((target) => {
|
|
2102
|
+
return target.slice("pid:".length);
|
|
2103
|
+
}))}; ending a process on the host always needs a human's approval`,
|
|
2104
|
+
program: argv[0] || "",
|
|
2105
|
+
args: argv.slice(1),
|
|
2106
|
+
verb: "kill",
|
|
2107
|
+
displayCommand: renderResourceDisplayCommand(argv),
|
|
2108
|
+
targets,
|
|
2109
|
+
requiresHuman: true,
|
|
2110
|
+
};
|
|
2111
|
+
}
|
|
2112
|
+
/*
|
|
2113
|
+
* ---------------------------------------------------------------------------
|
|
2114
|
+
* Dispatch
|
|
2115
|
+
* ---------------------------------------------------------------------------
|
|
2116
|
+
*/
|
|
2117
|
+
const PROGRAM_EVALUATORS = {
|
|
2118
|
+
systemctl: evaluateSystemctl,
|
|
2119
|
+
journalctl: evaluateJournalctl,
|
|
2120
|
+
df: (argv) => {
|
|
2121
|
+
return evaluateSimpleProgram(argv, SIMPLE_PROGRAMS["df"]);
|
|
2122
|
+
},
|
|
2123
|
+
free: (argv) => {
|
|
2124
|
+
return evaluateSimpleProgram(argv, SIMPLE_PROGRAMS["free"]);
|
|
2125
|
+
},
|
|
2126
|
+
uptime: (argv) => {
|
|
2127
|
+
return evaluateSimpleProgram(argv, SIMPLE_PROGRAMS["uptime"]);
|
|
2128
|
+
},
|
|
2129
|
+
ps: evaluatePs,
|
|
2130
|
+
ss: (argv) => {
|
|
2131
|
+
return evaluateSimpleProgram(argv, SIMPLE_PROGRAMS["ss"]);
|
|
2132
|
+
},
|
|
2133
|
+
ip: evaluateIp,
|
|
2134
|
+
dmesg: (argv) => {
|
|
2135
|
+
return evaluateSimpleProgram(argv, SIMPLE_PROGRAMS["dmesg"]);
|
|
2136
|
+
},
|
|
2137
|
+
lsblk: (argv) => {
|
|
2138
|
+
return evaluateSimpleProgram(argv, SIMPLE_PROGRAMS["lsblk"]);
|
|
2139
|
+
},
|
|
2140
|
+
cat: evaluateCat,
|
|
2141
|
+
top: evaluateTop,
|
|
2142
|
+
uname: (argv) => {
|
|
2143
|
+
return evaluateSimpleProgram(argv, SIMPLE_PROGRAMS["uname"]);
|
|
2144
|
+
},
|
|
2145
|
+
hostnamectl: (argv) => {
|
|
2146
|
+
return evaluateStatusTool(argv, ["status"], HOSTNAMECTL_ALLOWED, "the host name, OS and hardware");
|
|
2147
|
+
},
|
|
2148
|
+
timedatectl: (argv) => {
|
|
2149
|
+
return evaluateStatusTool(argv, ["status", "show", "timesync-status"], TIMEDATECTL_ALLOWED, "the clock, time zone and time synchronization");
|
|
2150
|
+
},
|
|
2151
|
+
kill: evaluateKill,
|
|
2152
|
+
};
|
|
2153
|
+
function evaluateHostArgv(raw) {
|
|
2154
|
+
if (!Array.isArray(raw) || raw.length === 0) {
|
|
2155
|
+
return deniedResult([], "Empty command.");
|
|
2156
|
+
}
|
|
2157
|
+
if (raw.some((word) => {
|
|
2158
|
+
return typeof word !== "string";
|
|
2159
|
+
})) {
|
|
2160
|
+
return deniedResult(raw, "Every word of the command must be a string.");
|
|
2161
|
+
}
|
|
2162
|
+
const argv = raw.slice();
|
|
2163
|
+
const program = argv[0];
|
|
2164
|
+
if (!hasOwn(PROGRAM_EVALUATORS, program)) {
|
|
2165
|
+
return deniedResult(argv, `"${program}" is not a program the host command policy runs: a host command starts with ${HOST_COMMAND_PROGRAMS.join(", ")} (the name alone, never a path)`);
|
|
2166
|
+
}
|
|
2167
|
+
const nonAscii = argv.find((word) => {
|
|
2168
|
+
return !PRINTABLE_ASCII_REGEX.test(word);
|
|
2169
|
+
});
|
|
2170
|
+
if (nonAscii !== undefined) {
|
|
2171
|
+
return deniedResult(argv, `"${nonAscii}" holds a character that is not printable ASCII (a look-alike dash, quote or letter, or a control character); retype the command in plain ASCII`);
|
|
2172
|
+
}
|
|
2173
|
+
const evaluator = PROGRAM_EVALUATORS[program];
|
|
2174
|
+
return evaluator(argv);
|
|
2175
|
+
}
|
|
2176
|
+
const READ_COMMAND_GUIDE = [
|
|
2177
|
+
"- Services: `systemctl status UNIT --no-pager -n 50`, `systemctl is-active|is-failed|is-enabled UNIT`, `systemctl list-units --failed --no-pager` (also --type=service, --state=S, --all, PATTERN), `systemctl list-timers --all`, `systemctl list-dependencies UNIT`, `systemctl show UNIT -p ActiveState,SubState,Result,NRestarts,ExecMainStatus,MainPID,MemoryCurrent` (-p is required and only unit-state properties are allowed — never Environment, and never systemctl cat)",
|
|
2178
|
+
`- Logs: \`journalctl -u UNIT -n 200 --no-pager\` — every read needs -n N (at most ${MAX_JOURNALCTL_LINES}) or --since TIME; also -p err, -k, -b [-1], --until, -g REGEX, -t IDENTIFIER, -o short-iso|json, -r, --utc; \`journalctl --list-boots\`, \`journalctl --disk-usage\`; never -f`,
|
|
2179
|
+
"- Resources: `uptime`, `free -m`, `df -h`, `df -i`, `lsblk -f`, `uname -a`, `hostnamectl`, `timedatectl`, `dmesg -T --level=err,warn`",
|
|
2180
|
+
"- Processes: `ps aux --sort=-%cpu`, `ps -eo pid,ppid,user,%cpu,%mem,etime,stat,args --sort=-%mem`, `top -b -n 1 -o %MEM` (top needs -b -n 1)",
|
|
2181
|
+
"- Network: `ss -tulpn`, `ss -s`, `ss -tn state established`, `ip -br addr`, `ip -br link`, `ip route`, `ip route get 1.1.1.1`, `ip neigh`, `ip -s link`",
|
|
2182
|
+
`- Kernel counters: \`cat /proc/loadavg\` — cat reads only ${HOST_READABLE_FILES.join(", ")}`,
|
|
2183
|
+
"- One program per command, named without a path: no pipes, redirects, sudo, shells or other programs",
|
|
2184
|
+
].join("\n");
|
|
2185
|
+
const WRITE_COMMAND_GUIDE = [
|
|
2186
|
+
"- SafeWrite (runs unattended when allowed): `systemctl restart|start|reload|try-restart|reload-or-restart|reset-failed UNIT` for exactly ONE service, socket, timer or path unit (targets are full unit names: nginx is nginx.service)",
|
|
2187
|
+
"- RiskyWrite (needs approval unless the allowlist or Bypass approval covers it): `systemctl stop UNIT`; any of the verbs above on several units; `systemctl reset-failed` with no unit; `journalctl --vacuum-time=7d` / `--vacuum-size=500M` / `--vacuum-files=N` (target journal)",
|
|
2188
|
+
"- Always a human: any change to a protected unit (ssh/sshd, systemd-*, udev, dbus, polkit, NetworkManager, networking, getty/autovt, docker, containerd, podman, kubelet, firewalld, nftables, iptables, ufw, user@, and the package-upgrade units apt-daily*, unattended-upgrades, dnf-automatic*, packagekit*), start/stop/restart/reload of a .target, .mount, .automount or .swap unit, and `kill [-TERM|-15|-HUP|-INT|-KILL|-9] PID` (pids from 2 up)",
|
|
2189
|
+
"- Never: systemctl enable/disable/mask/unmask/edit/cat/daemon-reload/daemon-reexec/isolate/kill/set-property/*-environment/clean, the power and run-state verbs and units (reboot, poweroff, halt, suspend, rescue, emergency, runlevelN, ...), debug-shell (a passwordless root shell), slices, scopes and devices, --force/--user/--host/--machine/--root, journalctl -f/--rotate/--flush, dmesg --clear, ss -K, ip changes, killing pid 1 or a process group",
|
|
2190
|
+
].join("\n");
|
|
2191
|
+
const HostCommandPolicy = {
|
|
2192
|
+
name: "host",
|
|
2193
|
+
programs: HOST_COMMAND_PROGRAMS,
|
|
2194
|
+
readCommandGuide: READ_COMMAND_GUIDE,
|
|
2195
|
+
writeCommandGuide: WRITE_COMMAND_GUIDE,
|
|
2196
|
+
evaluateArgv(argv) {
|
|
2197
|
+
try {
|
|
2198
|
+
return evaluateHostArgv(argv);
|
|
2199
|
+
}
|
|
2200
|
+
catch (_a) {
|
|
2201
|
+
return deniedResult(Array.isArray(argv) ? argv : [], "the host command policy could not evaluate this command");
|
|
2202
|
+
}
|
|
2203
|
+
},
|
|
2204
|
+
};
|
|
2205
|
+
export default HostCommandPolicy;
|
|
2206
|
+
//# sourceMappingURL=HostCommandPolicy.js.map
|