package executor import ( "context" "fmt" "os/exec" "runtime" "strings" ) // runUserGrant implements `kopsc user grant `: add a user to the // sudo/admin group to grant root privileges. // // Linux: adds to 'wheel' (CentOS/RHEL) or 'sudo' (Debian/Ubuntu) // macOS: adds to 'admin' group // Windows: adds to 'Administrators' group // // This is a destructive operation requiring sudo/admin privileges. func runUserGrant(ctx context.Context, req BuiltinRequest) error { if len(req.Args) == 0 { return fmt.Errorf("缺少用户名;用法: kopsc user grant <用户名>") } username := req.Args[0] if err := checkUserExists(username); err != nil { return err } switch runtime.GOOS { case "linux": return grantLinux(ctx, username, req) case "darwin": return grantDarwin(ctx, username, req) case "windows": return grantWindows(ctx, username, req) default: return fmt.Errorf("不支持的操作系统: %s", runtime.GOOS) } } // runUserRevoke implements `kopsc user revoke `: remove a user from // the sudo/admin group to revoke root privileges. func runUserRevoke(ctx context.Context, req BuiltinRequest) error { if len(req.Args) == 0 { return fmt.Errorf("缺少用户名;用法: kopsc user revoke <用户名>") } username := req.Args[0] if err := checkUserExists(username); err != nil { return err } switch runtime.GOOS { case "linux": return revokeLinux(ctx, username, req) case "darwin": return revokeDarwin(ctx, username, req) case "windows": return revokeWindows(ctx, username, req) default: return fmt.Errorf("不支持的操作系统: %s", runtime.GOOS) } } // grantLinux adds user to wheel (CentOS/RHEL) or sudo (Debian/Ubuntu) group. func grantLinux(ctx context.Context, username string, req BuiltinRequest) error { // Detect distro by checking which group exists if groupExists("wheel") { return runCommand(ctx, "usermod", []string{"-aG", "wheel", username}, req) } if groupExists("sudo") { return runCommand(ctx, "usermod", []string{"-aG", "sudo", username}, req) } return fmt.Errorf("未找到 wheel 或 sudo 组,请确认系统配置") } // revokeLinux removes user from wheel or sudo group. func revokeLinux(ctx context.Context, username string, req BuiltinRequest) error { if groupExists("wheel") { return runCommand(ctx, "gpasswd", []string{"-d", username, "wheel"}, req) } if groupExists("sudo") { return runCommand(ctx, "gpasswd", []string{"-d", username, "sudo"}, req) } return fmt.Errorf("未找到 wheel 或 sudo 组,请确认系统配置") } // grantDarwin adds user to admin group on macOS. func grantDarwin(ctx context.Context, username string, req BuiltinRequest) error { return runCommand(ctx, "dseditgroup", []string{"-o", "edit", "-t", "user", "-a", username, "admin"}, req) } // revokeDarwin removes user from admin group on macOS. func revokeDarwin(ctx context.Context, username string, req BuiltinRequest) error { return runCommand(ctx, "dseditgroup", []string{"-o", "edit", "-t", "user", "-d", username, "admin"}, req) } // grantWindows adds user to Administrators group. func grantWindows(ctx context.Context, username string, req BuiltinRequest) error { return runCommand(ctx, "net", []string{"localgroup", "Administrators", username, "/add"}, req) } // revokeWindows removes user from Administrators group. func revokeWindows(ctx context.Context, username string, req BuiltinRequest) error { return runCommand(ctx, "net", []string{"localgroup", "Administrators", username, "/delete"}, req) } // runCommand executes a command and streams output to the request's stdout/stderr. func runCommand(ctx context.Context, name string, args []string, req BuiltinRequest) error { cmd := exec.CommandContext(ctx, name, args...) cmd.Stdout = req.Stdout cmd.Stderr = req.Stderr cmd.Stdin = req.Stdin if err := cmd.Run(); err != nil { return fmt.Errorf("执行失败: %w", err) } return nil } // groupExists checks if a Unix group exists on the system. func groupExists(name string) bool { out, err := exec.Command("getent", "group", name).Output() if err != nil { return false } return strings.TrimSpace(string(out)) != "" } // checkUserExists verifies that the given username exists on the system. // Returns a user-friendly error if the user does not exist. func checkUserExists(username string) error { var exists bool switch runtime.GOOS { case "linux", "darwin": // id command works on both Linux and macOS err := exec.Command("id", username).Run() exists = (err == nil) case "windows": // net user command on Windows err := exec.Command("net", "user", username).Run() exists = (err == nil) default: return fmt.Errorf("不支持的操作系统: %s", runtime.GOOS) } if !exists { return fmt.Errorf("用户 %q 不存在", username) } return nil }