add feature license management

This commit is contained in:
Warp Agent
2026-01-04 12:54:25 +07:00
parent 7543b3a850
commit 2bb64620d4
29 changed files with 5447 additions and 22 deletions

View File

@@ -871,3 +871,143 @@ func (s *Service) GetNTPSettings(ctx context.Context) (*NTPSettings, error) {
return settings, nil
}
// ExecuteCommand executes a shell command and returns the output
// service parameter is optional and can be: system, scst, storage, backup, tape
func (s *Service) ExecuteCommand(ctx context.Context, command string, service string) (string, error) {
// Sanitize command - basic security check
command = strings.TrimSpace(command)
if command == "" {
return "", fmt.Errorf("command cannot be empty")
}
// Block dangerous commands that could harm the system
dangerousCommands := []string{
"rm -rf /",
"dd if=",
":(){ :|:& };:",
"mkfs",
"fdisk",
"parted",
"format",
"> /dev/sd",
"mkfs.ext",
"mkfs.xfs",
"mkfs.btrfs",
"wipefs",
}
commandLower := strings.ToLower(command)
for _, dangerous := range dangerousCommands {
if strings.Contains(commandLower, dangerous) {
return "", fmt.Errorf("command blocked for security reasons")
}
}
// Service-specific command handling
switch service {
case "scst":
// Allow SCST admin commands
if strings.HasPrefix(command, "scstadmin") {
// SCST commands are safe
break
}
case "backup":
// Allow bconsole commands
if strings.HasPrefix(command, "bconsole") {
// Backup console commands are safe
break
}
case "storage":
// Allow ZFS and storage commands
if strings.HasPrefix(command, "zfs") || strings.HasPrefix(command, "zpool") || strings.HasPrefix(command, "lsblk") {
// Storage commands are safe
break
}
case "tape":
// Allow tape library commands
if strings.HasPrefix(command, "mtx") || strings.HasPrefix(command, "lsscsi") || strings.HasPrefix(command, "sg_") {
// Tape commands are safe
break
}
}
// Execute command with timeout (30 seconds)
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
// Check if command already has sudo (reuse commandLower from above)
hasSudo := strings.HasPrefix(commandLower, "sudo ")
// Determine if command needs sudo based on service and command type
needsSudo := false
if !hasSudo {
// Commands that typically need sudo
sudoCommands := []string{
"scstadmin",
"systemctl",
"zfs",
"zpool",
"mount",
"umount",
"ip link",
"ip addr",
"iptables",
"journalctl",
}
for _, sudoCmd := range sudoCommands {
if strings.HasPrefix(commandLower, sudoCmd) {
needsSudo = true
break
}
}
// Service-specific sudo requirements
switch service {
case "scst":
// All SCST admin commands need sudo
if strings.HasPrefix(commandLower, "scstadmin") {
needsSudo = true
}
case "storage":
// ZFS commands typically need sudo
if strings.HasPrefix(commandLower, "zfs") || strings.HasPrefix(commandLower, "zpool") {
needsSudo = true
}
case "system":
// System commands like systemctl need sudo
if strings.HasPrefix(commandLower, "systemctl") || strings.HasPrefix(commandLower, "journalctl") {
needsSudo = true
}
}
}
// Build command with or without sudo
var cmd *exec.Cmd
if needsSudo && !hasSudo {
// Use sudo for privileged commands (if not already present)
cmd = exec.CommandContext(ctx, "sudo", "sh", "-c", command)
} else {
// Regular command (or already has sudo)
cmd = exec.CommandContext(ctx, "sh", "-c", command)
}
cmd.Env = append(os.Environ(), "TERM=xterm-256color")
cmd.Env = append(os.Environ(), "TERM=xterm-256color")
output, err := cmd.CombinedOutput()
if err != nil {
// Return output even if there's an error (some commands return non-zero exit codes)
outputStr := string(output)
if len(outputStr) > 0 {
return outputStr, nil
}
return "", fmt.Errorf("command execution failed: %w", err)
}
return string(output), nil
}