Dify Sandbox實(shí)現(xiàn)文件路徑獲取與Excel數(shù)據(jù)處理 原創(chuàng)
我集中精力,花2個多小時把Dify Sandbox官方源碼研究了一下,終于理清了Sandbox 執(zhí)行代碼的邏輯,順便實(shí)現(xiàn)了在不修改官方dify-sandbox docker鏡像,用戶上傳文件后路徑的獲取和對Excel文件的數(shù)據(jù)處理。
話不多說,先看效果。一個有9406條數(shù)據(jù)的Excel文件瞬間完成了數(shù)據(jù)處理工作。
下面我來說一下,這個如何實(shí)現(xiàn)。
Dify 安裝成功后,會有10個Docker容器,其中docker-sandbox 的作用是用來執(zhí)行工作流中”代碼“這個節(jié)點(diǎn)運(yùn)行的代碼。這樣就保證了用戶的代碼不會獲取到服務(wù)器的文件資源或者執(zhí)行敏感的系統(tǒng)調(diào)用操作,保證了Dify系統(tǒng)和數(shù)據(jù)安全。
Dify后端工程師Yeuoly,是Dify sandbox的作者,她寫了一篇博客詳細(xì)講解了Dify Sandbox通過沙盒運(yùn)行代碼原理的英文博客,我借助大模型認(rèn)真研讀了一下。
總結(jié)起來,主要使用了兩種技術(shù)。
1.系統(tǒng)級隔離: 利用 Docker 的底層技術(shù):Seccomp(安全計(jì)算模式)。
在 Linux 上,Docker 是一種常見的系統(tǒng)沙箱解決方案。??Seccomp?
?充當(dāng)所有訪問系統(tǒng)的嘗試的過濾器。它攔截和控制各種作,包括但不限于文件讀/寫作、系統(tǒng)配置修改、網(wǎng)絡(luò)訪問,甚至標(biāo)準(zhǔn)輸入/輸出。這之所以有效,是因?yàn)檫@些作本質(zhì)上是 (),并且每個作都表示訪問系統(tǒng)的嘗試。
在dify的源碼 docker/volumes/sanbox文件夾下,有個文件config.yaml,可以通過allowed_syscalls參數(shù)來控制允許開放哪些系統(tǒng)調(diào)用命令,這些命令大約有400個,比如常見的文件的讀寫、文件的執(zhí)行操作等等。
allowed_syscalls: # please leave it empty if you have no idea how seccomp works
# 基礎(chǔ)文件操作
- 0 # read - 從文件描述符讀取數(shù)據(jù)
- 1 # write - 向文件描述符寫入數(shù)據(jù)
- 2 # open - 打開文件
- 3 # close - 關(guān)閉文件描述符
- 4 # stat - 獲取文件狀態(tài)
- 5 # fstat - 獲取文件描述符狀態(tài)
- 6 # lstat - 獲取符號鏈接狀態(tài)
- 7 # poll - 等待文件描述符上的事件
- 8 # lseek - 重新定位讀/寫文件偏移量
- 9 # mmap - 將文件或設(shè)備映射到內(nèi)存
- 10 # mprotect - 設(shè)置內(nèi)存區(qū)域的保護(hù)
- 11 # munmap - 取消內(nèi)存映射
- 12 # brk - 改變數(shù)據(jù)段大小
###其它參數(shù)請網(wǎng)上自己搜索
2.chroot(更改根目錄)虛擬文件系統(tǒng)
但是上面的Docker Seccomp方案只能允許或者拒絕所有文件的訪問,要么全部允許,要么全部拒絕。這樣就沒法是某些用到的文件單獨(dú)訪問了,比如Python庫文件。
所有dify-sandbox又使用了第二個解決方案,在執(zhí)行代碼進(jìn)程的時候,使用Linux chroot('/tmp')命令,將代碼所在的/tmp文件夾作為根目錄。也就是代碼只知道它位于/tmp文件夾下面,無法讀取到系統(tǒng)其它文件夾路徑。
在dify-sandbox的源碼中,是這樣實(shí)現(xiàn)的,使用的是Go 語言。
Sandbox的沙盒安全原理大致就是這樣,如果我想用代碼獲取到dify用戶剛剛上傳的文件路徑,就必須將用戶上傳文件夾的實(shí)際文件夾掛載到sandbox Docker容器中。
這里要非常感謝Awesome-Dify-Workflow這個Github開源項(xiàng)目,讓我找到了File_read.yml 這個Dify工作流。它的實(shí)現(xiàn)前提將用戶上傳文件保存路徑app/storage/upload_files文件夾的路徑掛載到sandbox Docker容器的/upload_files文件夾下面,并且要使用作者制作的Docker鏡像替換官方鏡像。
這個作者制作的鏡像權(quán)限開的太多,我反而有了安全顧慮,所有想繼續(xù)使用官方鏡像完成用戶上傳文件路徑的獲取。這時候?qū)ι厦鎐hroot命令的理解就派上用場了。
既然執(zhí)行代碼都只認(rèn)/tmp文件夾,那直接將app/storage/upload_files文件夾的路徑掛載到/tmp下面就可以了(以python代碼執(zhí)行為例)。
同時修改sandbox的python庫依賴,添加pandas等Python數(shù)據(jù)處理庫,來編寫代碼完成Excel文件的處理。
執(zhí)行 docker compose down 和 docker compose up -d 命令重建Dify Docker容器后,我們將打開Dify,將File_read.yml導(dǎo)入。
修改獲取文件路徑處的代碼,將"/upload_files"改為"/tmp/upload_files",再運(yùn)行這個工作流便大功告成。也就是文章一開始大家看到的效果。
本文轉(zhuǎn)載自公眾號九歌AI大模型 作者:九歌AI
原文鏈接:??https://mp.weixin.qq.com/s/8jKGn-k-v3_9kPdbWgQEvQ??
