有没有办法用pytest进行沙箱测试执行,尤其是文件系统访问?

时间:2016-02-10 17:51:38

标签: python unit-testing testing docker pytest

我有兴趣在某种类型的沙盒中使用pytest执行可能不受信任的测试,例如docker,类似于持续集成服务。

我理解为了正确沙箱化一个python进程你需要操作系统级隔离,比如在一次性chroot /容器中运行测试,但在我的用例中我不需要防止故意恶意代码,只有从配对的危险行为"随机"带参数的函数。因此,较不严格的沙箱仍然可以接受。但我没有找到任何能够支持任何形式沙盒的插件。

在pytest中沙盒测试执行的最佳方法是什么?

更新:此问题与python sandboxing in general无关,因为测试'代码由pytest运行,我无法改变执行方式以使用execast或其他任何内容。不幸的是,使用pypy-sandbox并不是一个选择,因为它只是一个原型"根据{{​​3}}。

更新2 :用于用户级隔离的pytest-dev邮件列表PyPy feature page上的Hoger Krekel:

py.test --tx ssh=OTHERUSER@localhost --dist=each

suggests using a dedicated testuser via pytest-xdist我的CI用例:

  

拥有"一次性"环境与孤立一样重要   一,所以每个测试或每个会话都从同一个初始运行   状态,它不受旧会话可能留下的影响   在 testuser 可写的文件夹上(/ home / testuser,/ tmp,/ var / tmp,   等)。

所以testuser + xdist接近一个解决方案,但不是那么。

仅针对上下文我需要隔离才能运行made me realise

2 个答案:

答案 0 :(得分:7)

经过相当多的研究后,我没有找到任何现成的方法让pytest在操作系统级隔离和一次性环境中运行项目测试。许多方法都是可能的,并且有优点和缺点,但是大多数方法都有更多我觉得舒服的活动部件。

我设计的绝对最小(但固执己见)的方法如下:

  • 使用以下命令构建python docker镜像:
    • 专用的非root用户:pytest
    • 来自requirements.txt
    • 的所有项目依赖项
    • 以开发模式安装的项目
  • 在一个容器中运行py.test,该容器将主机上的项目文件夹挂载为pytest user
  • 的主目录

要实施此方法,请将以下Dockerfile添加到要在requirements.txtsetup.py文件旁边测试的项目的顶部文件夹中:

FROM python:3

# setup pytest user
RUN adduser --disabled-password --gecos "" --uid 7357 pytest
COPY ./ /home/pytest
WORKDIR /home/pytest

# setup the python and pytest environments
RUN pip install --upgrade pip setuptools pytest
RUN pip install --upgrade -r requirements.txt
RUN python setup.py develop

# setup entry point
USER pytest
ENTRYPOINT ["py.test"]

使用以下方法构建图像:

docker build -t pytest .

在容器内运行py.test,将项目文件夹作为卷放在/ home / pytest上,并使用:

docker run --rm -it -v `pwd`:/home/pytest pytest [USUAL_PYTEST_OPTIONS]

请注意,-v将卷安装为uid 1000,因此pytest用户无法写入主机文件,而uid强制为7357。

现在,您应该能够使用操作系统级隔离开发和测试项目。

更新:如果您还在主机上运行测试,则可能需要删除容器内无法写入的python和pytest缓存。在主机上运行:

rm -rf .cache/ && find . -name __pycache__  | xargs rm -rf

答案 1 :(得分:2)

老实说,对于像docker这样的东西来说,这似乎是一个很好的用例。当然,你只是不使用python完全干净地处理它,但你可以滥用主机操作系统,而不必担心长期损坏。此外,与许多CI解决方案不同,它可以在您的开发机器上轻松运行。

另请注意,无论您的代码是否有意恶意,具有这种隔离效果仍然有助于防止以下事故:

rm -rf /usr/local/share/ myapp