nodejs.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. package nodejs
  2. import (
  3. _ "embed"
  4. "fmt"
  5. "os"
  6. "os/exec"
  7. "path"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "github.com/langgenius/dify-sandbox/internal/core/runner"
  12. "github.com/langgenius/dify-sandbox/internal/core/runner/types"
  13. "github.com/langgenius/dify-sandbox/internal/static"
  14. )
  15. type NodeJsRunner struct {
  16. runner.TempDirRunner
  17. }
  18. //go:embed prescript.js
  19. var nodejs_sandbox_fs []byte
  20. var (
  21. REQUIRED_FS = []string{
  22. path.Join(LIB_PATH, PROJECT_NAME, "node_temp"),
  23. path.Join(LIB_PATH, LIB_NAME),
  24. "/etc/ssl/certs/ca-certificates.crt",
  25. "/etc/nsswitch.conf",
  26. "/etc/resolv.conf",
  27. "/run/systemd/resolve/stub-resolv.conf",
  28. "/etc/hosts",
  29. }
  30. )
  31. func (p *NodeJsRunner) Run(
  32. code string,
  33. timeout time.Duration,
  34. stdin []byte,
  35. preload string,
  36. options *types.RunnerOptions,
  37. ) (chan []byte, chan []byte, chan bool, error) {
  38. configuration := static.GetDifySandboxGlobalConfigurations()
  39. // capture the output
  40. output_handler := runner.NewOutputCaptureRunner()
  41. output_handler.SetTimeout(timeout)
  42. err := p.WithTempDir("/", REQUIRED_FS, func(root_path string) error {
  43. output_handler.SetAfterExitHook(func() {
  44. os.RemoveAll(root_path)
  45. os.Remove(root_path)
  46. })
  47. // initialize the environment
  48. script_path, err := p.InitializeEnvironment(code, preload, root_path)
  49. if err != nil {
  50. return err
  51. }
  52. // create a new process
  53. cmd := exec.Command(
  54. static.GetDifySandboxGlobalConfigurations().NodejsPath,
  55. script_path,
  56. strconv.Itoa(static.SANDBOX_USER_UID),
  57. strconv.Itoa(static.SANDBOX_GROUP_ID),
  58. options.Json(),
  59. )
  60. cmd.Env = []string{}
  61. if len(configuration.AllowedSyscalls) > 0 {
  62. cmd.Env = append(
  63. cmd.Env,
  64. fmt.Sprintf("ALLOWED_SYSCALLS=%s", strings.Trim(
  65. strings.Join(strings.Fields(fmt.Sprint(configuration.AllowedSyscalls)), ","), "[]",
  66. )),
  67. )
  68. }
  69. // capture the output
  70. err = output_handler.CaptureOutput(cmd)
  71. if err != nil {
  72. return err
  73. }
  74. return nil
  75. })
  76. if err != nil {
  77. return nil, nil, nil, err
  78. }
  79. return output_handler.GetStdout(), output_handler.GetStderr(), output_handler.GetDone(), nil
  80. }
  81. func (p *NodeJsRunner) InitializeEnvironment(code string, preload string, root_path string) (string, error) {
  82. if !checkLibAvaliable() {
  83. releaseLibBinary()
  84. }
  85. node_sandbox_file := string(nodejs_sandbox_fs)
  86. if preload != "" {
  87. node_sandbox_file = fmt.Sprintf("%s\n%s", preload, node_sandbox_file)
  88. }
  89. // join nodejs_sandbox_fs and code
  90. code = node_sandbox_file + code
  91. // override root_path/tmp/sandbox-nodejs-project/prescript.js
  92. script_path := path.Join(root_path, LIB_PATH, PROJECT_NAME, "node_temp/node_temp/test.js")
  93. err := os.WriteFile(script_path, []byte(code), 0755)
  94. if err != nil {
  95. return "", err
  96. }
  97. return script_path, nil
  98. }