# sandbox

## 项目概述

sandbox 是一个基于 Go 语言开发的轻量级沙箱环境，用于安全地执行代码，支持 Python 和 Node.js 等运行时。该项目主要用于低代码框架的测试和验证，提供了网络访问控制、资源限制等安全特性。

## 功能特点

- **多语言支持**：内置支持 Python 和 Node.js 运行时，其他运行时可以通过 RegisterRuntime 注册。
- **网络控制**：
  - 支持允许/阻止互联网访问
  - 支持允许特定端口监听
  - 支持 IP 白名单和黑名单
- **资源限制**：
  - CPU 使用率限制
  - 内存使用限制
  - SWAP 限制
  - /dev/shm 和 /tmp 大小限制
- **环境配置**：支持自定义环境变量
- **安全隔离**：提供安全的执行环境，防止恶意代码影响系统
- **跨平台支持**：支持 Linux 和 macOS 操作系统
- **状态管理**：支持沙箱状态持久化和恢复

## 项目架构

### 核心代码结构

```
sandbox/
├── plugin.go            # 插件入口，注册 sandbox 模块到 gojs 框架
├── sandbox.go           # 定义沙箱的核心结构和配置
├── master.go            # 管理沙箱的生命周期和状态
├── runtime.go           # 运行时管理
├── sandbox_linux.go     # Linux 平台实现
├── sandbox_darwin.go    # macOS 平台实现
├── pythonRuntime.go     # Python 运行时实现
├── nodejsRuntime.go     # Node.js 运行时实现
├── util.go              # 工具函数
├── base_test.js         # 测试入口文件
├── testcase/            # 测试用例目录
│   ├── base_allow.py    # 允许模式测试
│   ├── base_deny.py     # 拒绝模式测试
│   ├── secret.py        # 敏感信息测试
│   └── base_allow.js    # Node.js 环境测试
└── README.md            # 项目说明文档
```

### 核心组件

1. **Plugin 模块**：
   - 注册 sandbox 模块到 gojs 框架
   - 提供 Start、Fetch、Query 等 API 接口
   - 管理沙箱的启动和恢复

2. **Sandbox 核心**：
   - 定义沙箱的配置结构（Config）
   - 管理沙箱的状态和生命周期
   - 提供资源限制和网络控制功能

3. **运行时管理**：
   - 支持 Python 和 Node.js 运行时
   - 处理不同运行时的启动和配置

4. **平台适配**：
   - Linux 平台实现（sandbox_linux.go）
   - macOS 平台实现（sandbox_darwin.go）

## 技术实现

### 沙箱隔离机制

- **文件系统隔离**：使用挂载点和只读挂载
- **网络隔离**：通过 namespace 机制控制网络访问
- **资源限制**：使用 cgroups（Linux）或等效机制限制资源使用
- **进程隔离**：创建独立的进程环境

### 核心 API

| API | 说明 |
|-----|------|
| Start(config) | 创建并启动新的沙箱实例 |
| Fetch(id) | 根据 ID 获取沙箱实例 |
| Query(name) | 根据名称查询沙箱实例 |
| Sandbox.status() | 获取沙箱状态 |
| Sandbox.wait(timeout) | 等待沙箱执行完成 |
| Sandbox.kill() | 终止沙箱进程（适用于服务类或运行过久的场景，简单一次性场景不需要调用） |

## 安装与使用

### 基本使用

1. 导入 sandbox 模块：

```javascript
import sandbox from 'apigo.cc/gojs/sandbox'
```

2. 配置并启动沙箱：

```javascript
const sb = sandbox.start({
  projectDir: "data",
  runtime: { language: "python", venv: "test", version: "3.12" },
  startArgs: ["-c", "print('Hello, sandbox!')"],
  network: {
    allowInternet: true,
    allowListen: [19999]
  },
  limits: { cpu: 0.5, mem: 0.2 }
})
```

3. 等待执行完成：

```javascript
sb.wait(10000) // 等待最多 10 秒
```

4. 查看执行状态：

```javascript
const status = sb.status()
console.log(status)
```

## 配置选项

| 选项 | 类型 | 说明 |
|------|------|------|
| Name | string | 沙盒名称 |
| projectDir | string | 宿主机的工作目录（自动映射到沙盒内workDir） |
| workDir | string | 沙盒内的工作目录 |
| envs | map[string]string | 环境变量，支持$变量 |
| volumes | []Volume | 挂载列表 |
| limits | Limits | 资源限制 |
| network | struct | 网络配置 |
| gpu | struct | GPU 配置 |
| extraOptions | []string | 额外参数 |
| autoStart | bool | 是否自动启动沙盒进程 |
| startCmd | string | 启动命令 |
| startArgs | []string | 启动参数 |
| runtime | struct | 运行时配置 |
| noLog | bool | 是否不显示沙盒运行日志 |

### 资源限制配置

| 选项 | 类型 | 说明 |
|------|------|------|
| Cpu | float64 | CPU 核心限制 (如 0.5) |
| Mem | float64 | 内存限制 (单位: GB) |
| Swap | float64 | SWAP 限制 (单位: GB) |
| Shm | uint | /dev/shm 大小 (单位: MB) |
| Tmp | uint | /tmp 大小 (单位: MB) |

### 网络配置

| 选项 | 类型 | 说明 |
|------|------|------|
| AllowInternet | bool | 是否允许出站网络连接 |
| AllowLocalNetwork | bool | 是否允许访问本地网络 |
| AllowListen | []int | 允许监听端口列表 |
| AllowList | []string | 允许出站访问的 IP/端口 列表 |
| BlockList | []string | 拒绝访问的 IP/端口 列表 |

## 测试说明

### 运行测试

```bash
go test -v .
```

### 测试用例说明

1. **base_allow.py**：测试允许模式下的功能，包括：
   - 内存使用限制（128M 允许，512M 拒绝）
   - CPU 使用率限制
   - 网络监听（允许特定端口）
   - 网络访问（允许互联网访问，阻止特定 IP）
   - 环境变量配置
   - 外部依赖安装（cowsay）

2. **base_deny.py**：测试拒绝模式下的功能，包括：
   - 网络监听（只允许特定端口）
   - 网络访问（只允许白名单 IP 和端口）

3. **secret.py**：测试敏感信息处理

4. **base_allow.js**：测试 Node.js 环境下的功能

### 压力测试

测试脚本还包含了压力测试，会并发执行多个沙箱实例，测试系统的稳定性和性能。

## 日志管理

沙盒内的stdout会自动重定向到日志文件，stderr也会被重定向到日志文件。

日志存储在 `[projectDir]/logs/` 目录中，包括：

- 标准输出日志（stdout_*.log）
- 标准错误日志（stderr_*.log）

## 注意事项

1. **macOS 限制**：macOS 系统不支持某些 Linux 特有的功能，如 cgroup 限制和 IP 过滤。测试脚本会自动检测操作系统并调整测试逻辑。

2. **资源限制**：在 macOS 上，资源限制（CPU 和内存）不会生效。

3. **网络限制**：在 macOS 上，网络细化限制（IP 过滤）不会生效。

4. **权限要求**：在 Linux 上，建议以 root 权限运行，否则也能运行但部分功能会受限。

## 许可证

本项目采用 MIT 许可证，详见 LICENSE 文件。