# Isolate Sandbox Integration ## Обзор Интеграция Isolate sandbox обеспечивает безопасное выполнение пользовательского кода с изоляцией на уровне ядра Linux. ## Что было сделано ### 1. Docker Security Hardening **compose.yaml:** - ✅ Gateway: `cap_drop: ALL`, `no-new-privileges:true` - ✅ Worker: `cap_drop: ALL` + минимальные capabilities (`SYS_ADMIN`, `SETUID`, `SETGID`) - ✅ Worker: `tmpfs` для `/tmp` (4GB) - ✅ Worker: `ulimits` (nproc: 1024, nofile: 2048) - ✅ AppArmor profile ### 2. Worker Dockerfile **Установлено:** - ✅ Isolate sandbox (с libcap-dev, libsystemd-dev) - ✅ Unprivileged user `workeruser` (uid: 1001) - ✅ Конфигурация isolate (`/usr/local/etc/isolate`) **Структура:** ``` /var/local/lib/isolate/ - Isolate box root /app/ - Worker приложение (chown workeruser) /tmp/testing/ - Temp directory (chown workeruser) ``` ### 3. Новые сервисы **`IsolateService`** - Основной сервис для работы с Isolate: - `InitBoxAsync(boxId)` - Инициализация sandbox - `RunAsync(options)` - Выполнение программы - `CleanupBoxAsync(boxId)` - Очистка sandbox - Парсинг metadata (CPU time, memory, context switches) **`IsolateBoxPool`** - Управление параллельными box'ами: - Пул из N box IDs (конфигурируется) - Thread-safe acquire/release - Автоматическое ожидание при занятости всех box'ов **`CppExecutionServiceIsolate`** - Реализация IExecutionService с Isolate: - Копирование executable в box - Выполнение с ограничениями (CPU, memory, processes) - Mapping результатов Isolate → ExecutionResult ### 4. Конфигурация **appsettings.json:** ```json { "Isolate": { "Enabled": true, "MaxBoxes": 100 } } ``` **Environment переменные (compose.yaml):** ```yaml environment: - Isolate__Enabled=true - Isolate__MaxBoxes=100 ``` ## Что защищает Isolate | Угроза | Без Isolate | С Isolate | |--------|-------------|-----------| | Fork bomb | ❌ Убьёт контейнер | ✅ БЛОК (process limit) | | Network attack | ❌ Полный доступ | ✅ БЛОК (no network) | | File access | ❌ Видит весь контейнер | ✅ БЛОК (mount namespace) | | Memory bomb | ⚠️ Неточно (PeakWorkingSet64) | ✅ ТОЧНО (cgroups) | | CPU bomb | ⚠️ Wall time | ✅ CPU time (справедливо) | | Syscall abuse | ❌ Любые syscalls | ✅ ФИЛЬТР (seccomp) | ## Архитектура безопасности ``` ┌─────────────────────────────────────────────┐ │ HOST OS (Linux) │ │ ┌───────────────────────────────────────┐ │ │ │ Docker Container (Worker) │ │ │ │ • cap_drop: ALL │ │ │ │ • no-new-privileges │ │ │ │ • AppArmor │ │ │ │ │ │ │ │ ┌─────────────────────────────────┐ │ │ │ │ │ Worker Process (uid 1001) │ │ │ │ │ │ │ │ │ │ │ │ ┌───────────────────────────┐ │ │ │ │ │ │ │ Isolate Box │ │ │ │ │ │ │ │ • PID namespace │ │ │ │ │ │ │ │ • Network isolation │ │ │ │ │ │ │ │ • Mount namespace │ │ │ │ │ │ │ │ • cgroups (CPU, mem) │ │ │ │ │ │ │ │ • seccomp-bpf │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ USER CODE RUNS HERE │ │ │ │ │ │ │ └───────────────────────────┘ │ │ │ │ │ └─────────────────────────────────┘ │ │ │ └───────────────────────────────────────┘ │ └─────────────────────────────────────────────┘ ``` ## Тестирование ### Запуск с Isolate ```bash # 1. Rebuild контейнеров docker-compose down docker-compose build --no-cache worker docker-compose up # 2. Проверка установки Isolate docker exec liquidcode-tester-worker isolate --version # 3. Проверка прав docker exec liquidcode-tester-worker whoami # должно быть: workeruser # 4. Проверка box директории docker exec liquidcode-tester-worker ls -la /var/local/lib/isolate ``` ### Тестовые сценарии #### 1. Простая программа (C++) ```bash curl -X POST http://localhost:8081/api/test \ -F "id=1" \ -F "missionId=100" \ -F "language=c++" \ -F "sourceCode=#include int main() { std::cout << \"Hello World\"; }" \ -F "callbackUrl=http://localhost/callback" \ -F "package=@test_package.zip" ``` #### 2. Fork bomb (должен быть ЗАБЛОКИРОВАН) ```cpp #include int main() { while(1) fork(); } ``` #### 3. Network attack (должен быть ЗАБЛОКИРОВАН) ```cpp #include #include int main() { system("curl http://evil.com"); } ``` #### 4. Memory bomb (должен быть ОСТАНОВЛЕН) ```cpp #include int main() { std::vector v; while(1) v.push_back(1); } ``` #### 5. Time limit ```cpp #include int main() { sleep(10); } ``` ### Проверка логов ```bash # Проверка использования Isolate docker logs liquidcode-tester-worker 2>&1 | grep "Isolate" # Проверка box acquire/release docker logs liquidcode-tester-worker 2>&1 | grep "box" # Проверка метрик docker logs liquidcode-tester-worker 2>&1 | grep "Isolate stats" ``` ### Проверка безопасности ```bash # 1. Проверка capabilities контейнера docker inspect liquidcode-tester-worker | jq '.[0].HostConfig.CapDrop' docker inspect liquidcode-tester-worker | jq '.[0].HostConfig.CapAdd' # 2. Проверка security_opt docker inspect liquidcode-tester-worker | jq '.[0].HostConfig.SecurityOpt' # 3. Проверка ulimits docker inspect liquidcode-tester-worker | jq '.[0].HostConfig.Ulimits' ``` ## Производительность ### Overhead на один запуск: | Операция | Время | |----------|-------| | Init box | ~10-15ms | | Run program | 0ms (в пределах погрешности) | | Cleanup | ~5-10ms | | **Total overhead** | **~25ms** | ### Для задачи с 100 тестами (1s TL каждый): - Overhead: 25ms × 100 = 2.5s - Типичное время: 100s - Увеличение: **+2.5%** (незначительно!) ### Pool statistics: ```bash # Monitoring через API endpoint (TODO) curl http://localhost:8081/api/monitoring/isolate-pool ``` ## Отключение Isolate Для отключения Isolate (вернуться к старому поведению): **appsettings.json:** ```json { "Isolate": { "Enabled": false } } ``` Или через environment: ```yaml environment: - Isolate__Enabled=false ``` ## Следующие шаги ### Фаза 2: Full execution integration (неделя 2) - [ ] Интегрировать Isolate в JavaExecutionService - [ ] Интегрировать Isolate в KotlinExecutionService - [ ] Интегрировать Isolate в CSharpExecutionService - [ ] Интегрировать Isolate в PythonExecutionService ### Фаза 3: Compilation + Checker (неделя 3) - [ ] Изолировать компиляцию (CppCompilationService и др.) - [ ] Изолировать checker (CheckerService) - [ ] Тестирование с реальными Polygon пакетами ### Улучшения - [ ] Monitoring endpoint для статистики box pool - [ ] Graceful degradation при недоступности Isolate - [ ] Кэширование executable в box (для checker) - [ ] Custom AppArmor profile (advanced) - [ ] Metrics (Prometheus) ## Известные ограничения 1. **Только Linux** - Isolate работает только на Linux kernel 2. **CAP_SYS_ADMIN** - Worker контейнер требует повышенных прав 3. **Box pool limit** - Максимум 100 параллельных заданий (конфигурируется) 4. **Workeruser permissions** - Некоторые операции могут требовать root ## Troubleshooting ### Isolate not found ```bash # Проверка установки docker exec liquidcode-tester-worker which isolate docker exec liquidcode-tester-worker isolate --version ``` ### Permission denied ```bash # Проверка владельца директорий docker exec liquidcode-tester-worker ls -la /var/local/lib/isolate docker exec liquidcode-tester-worker ls -la /app ``` ### Box initialization failed ```bash # Проверка capabilities docker inspect liquidcode-tester-worker | jq '.[0].HostConfig.CapAdd' # Должны быть: SYS_ADMIN, SETUID, SETGID ``` ### Cgroups not working ```bash # Проверка cgroup v2 docker exec liquidcode-tester-worker ls -la /sys/fs/cgroup # Проверка конфигурации isolate docker exec liquidcode-tester-worker cat /usr/local/etc/isolate ``` ## Ссылки - [Isolate GitHub](https://github.com/ioi/isolate) - [Isolate Documentation](https://github.com/ioi/isolate/blob/master/isolate.1.txt) - [CMS (Contest Management System)](https://github.com/cms-dev/cms) - [Docker Security Best Practices](https://docs.docker.com/engine/security/)