- vi 编辑包进 bwrap 沙箱:只暴露 workspace(挂/home) + 只读系统目录 - --unshare-user/pid/ipc/uts/net 隔离,no_new_privileges 阻断 sudo setuid - bwrap 缺失时拒绝终端(安全优先,不给完整 shell)
84 lines
2.5 KiB
Plaintext
84 lines
2.5 KiB
Plaintext
import os
|
||
import shlex
|
||
import shutil
|
||
|
||
file_id = (params_kw or {}).get('id', '').strip()
|
||
|
||
uid = await get_user()
|
||
if not uid:
|
||
uid = 'user-01'
|
||
|
||
dbname = get_module_dbname('pipeline-sdlc')
|
||
workspace_base = '/d/pipeline/workspaces'
|
||
|
||
async with DBPools().sqlorContext(dbname) as sor:
|
||
recs = await sor.sqlExe(
|
||
"SELECT current_project_id FROM pipeline_agent_settings WHERE user_id=${u}$", {"u": uid})
|
||
pid = getattr(recs[0], 'current_project_id', '') if recs else ''
|
||
ws_dir = ''
|
||
if pid:
|
||
proj = await sor.sqlExe("SELECT name, org_id, workspace_dir FROM sd_projects WHERE id=${p}$", {"p": pid})
|
||
if proj:
|
||
ws = getattr(proj[0], 'workspace_dir', '') or ''
|
||
if ws.startswith('/'):
|
||
ws_dir = ws
|
||
else:
|
||
pname = getattr(proj[0], 'name', '')
|
||
org_id = getattr(proj[0], 'org_id', '0') or '0'
|
||
ws_dir = workspace_base + '/' + org_id + '/' + pname
|
||
|
||
if not file_id or not ws_dir:
|
||
r = DictObject()
|
||
r.host = 'localhost'
|
||
r.username = 'pipeline'
|
||
r.cmdargs = ['echo 未指定文件']
|
||
return r
|
||
|
||
full_path = ws_dir + '/' + file_id
|
||
|
||
# 路径穿越校验
|
||
real_ws = os.path.realpath(ws_dir)
|
||
real_full = os.path.realpath(full_path)
|
||
if not real_full.startswith(real_ws + os.sep):
|
||
r = DictObject()
|
||
r.host = 'localhost'
|
||
r.username = 'pipeline'
|
||
r.cmdargs = ['echo 非法路径']
|
||
return r
|
||
|
||
# bwrap 沙箱路径(不存在则拒绝终端,安全优先,不给完整 shell)
|
||
bwrap = shutil.which('bwrap')
|
||
if not bwrap and os.path.exists('/d/pipeline/pipeline-app/bin/bwrap'):
|
||
bwrap = '/d/pipeline/pipeline-app/bin/bwrap'
|
||
|
||
r = DictObject()
|
||
r.host = 'localhost'
|
||
r.username = 'pipeline'
|
||
|
||
if not bwrap:
|
||
r.cmdargs = ['echo 沙箱不可用,已拒绝终端访问']
|
||
return r
|
||
|
||
# bwrap 沙箱:只暴露 workspace(挂载到 /home 可写)+ 只读系统目录,
|
||
# 隔离 user/pid/ipc/uts/net,防 rm -rf /、sudo 提权、越界访问、网络攻击
|
||
cmd = (
|
||
bwrap +
|
||
' --unshare-user --unshare-pid --unshare-ipc --unshare-uts --unshare-net'
|
||
' --die-with-parent'
|
||
' --ro-bind /usr /usr'
|
||
' --ro-bind /bin /bin'
|
||
' --ro-bind /sbin /sbin'
|
||
' --ro-bind /lib /lib'
|
||
' --ro-bind /lib64 /lib64'
|
||
' --ro-bind /etc /etc'
|
||
' --proc /proc'
|
||
' --dev /dev'
|
||
' --tmpfs /tmp'
|
||
' --bind ' + shlex.quote(real_ws) + ' /home'
|
||
' --chdir /home'
|
||
' --setenv HOME /home'
|
||
' -- vi ' + shlex.quote(file_id)
|
||
)
|
||
r.cmdargs = [cmd]
|
||
return r
|