如何防止 root 访问我的 docker 容器

2024-02-13

我正在努力强化我们的 docker 镜像,但我对它的理解已经有点薄弱了。话虽如此,我当前要做的步骤是阻止用户以 root 身份运行容器。对我来说,这意味着“当用户运行‘docker exec -it my-container bash’时,他将是一个非特权用户”(如果我错了,请纠正我)。

当我通过 docker-compose 启动容器时,运行的启动脚本需要以 root 身份运行,因为它处理导入证书和挂载文件(在外部创建并通过卷挂载查看)。完成后,我希望用户成为“appuser”以供将来访问。这个问题似乎与我正在寻找的内容非常匹配,但我使用的是 docker-compose,而不是 docker run:如何禁用docker容器的root访问权限? https://stackoverflow.com/questions/43814416/how-to-disable-the-root-access-of-a-docker-container

这似乎是相关的,因为启动命令与 tomcat 不同。我们正在运行一个 Spring Boot 应用程序,我们使用一个简单的“java -jar jarFile”启动该应用程序,并且该映像是使用 maven 的 dockerfile-maven-plugin 构建的。话虽如此,我应该在运行之前还是之后将用户更改为非特权用户?

我相信更改 Dockerfile 内部的用户而不是启动脚本可以做到这一点......但随后它不会以 root 身份运行启动脚本,从而导致需要 root 的调用崩溃。我也搞乱了 ENTRYPOINT 的使用,但可能在那里做错了。同样,在 yml 文件中使用“user:”似乎会使 start.sh 脚本以该用户而不是 root 身份运行,因此这不起作用。

Dockerfile:

FROM parent/image:latest

ENV APP_HOME                            /apphome
ENV APP_USER                            appuser
ENV APP_GROUP                           appgroup

# Folder containing our application, i.e. jar file, resources, and scripts.
# This comes from unpacking our maven dependency
ADD target/classes/app ${APP_HOME}/

# Primarily just our start script, but some others
ADD target/classes/scripts /scripts/

# Need to create a folder that will be used at runtime
RUN mkdir -p ${APP_HOME}/data && \
    chmod +x /scripts/*.sh && \
    chmod +x ${APP_HOME}/*.*

# Create unprivileged user
RUN groupadd -r ${APP_GROUP} && \
    useradd -g ${APP_GROUP} -d ${APP_HOME} -s /sbin/nologin  -c "Unprivileged User" ${APP_USER} && \
    chown -R ${APP_USER}:${APP_GROUP} ${APP_HOME}

WORKDIR $APP_HOME

EXPOSE 8443

CMD /opt/scripts/start.sh

启动.sh脚本:

#!/bin/bash

# setup SSL, modify java command, etc

# run our java application
java -jar "boot.jar"

# Switch users to always be unprivileged from here on out? 
# Whatever "hardening" wants...  Should this be before starting our application?
exec su -s "/bin/bash" $APP_USER

app.yml 文件:

version: '3.3'

services:
  app:
    image: app_image:latest
    labels:
      c2core.docker.compose.display-name: My Application
      c2core.docker.compose.profiles: a_profile
    volumes:
      - "data_mount:/apphome/data"
      - "cert_mount:/certs"
    hostname: some-hostname
    domainname: some-domain
    ports:
    - "8243:8443"
    environment:
      - some_env_vars
    depends_on:
    - another-app
    networks:
      a_network:
        aliases:
          - some-network
networks:
  a_network:
    driver: bridge
volumes:
  data_mount:
  cert_mount:

docker-compose shell 脚本:

docker-compose -f app.yml -f another-app.yml $@

我期望的是,任何试图在内部访问容器的人都会以 appuser 而不是 root 的身份进行操作。目标是防止有人弄乱他们不应该弄乱的东西(即 docker 本身)。

发生的情况是,脚本将在应用程序启动后更改用户(通过 echo 命令证明),但它似乎没有得到维护。如果我执行它,我仍然是root。


正如 David 提到的,一旦有人可以访问 docker 套接字(通过 API 或使用dockerCLI),这通常意味着他们拥有您主机的 root 访问权限。使用该访问权限来运行具有主机命名空间和卷挂载的特权容器是很简单的,这让攻击者可以做任何事情。

当您需要使用以 root 身份运行的步骤来初始化容器时,我建议gosu https://stackoverflow.com/a/37931896/596285在类似的事情上su since su不是为容器设计的,并且会让进程作为 root pid 运行。确保您exec打电话给gosu这将消除以 root 身份运行的任何内容。但是,您启动容器的用户与用于启动容器的用户相同docker exec,并且由于您需要以 root 身份启动,因此您的 exec 将以 root 身份运行,除非您用-u flag.

一般来说,您可以采取其他步骤来锁定 docker:

  1. Use 用户命名空间 https://docs.docker.com/engine/security/userns-remap/。这些是在整个守护进程上定义的,要求您销毁所有容器,然后再次拉取映像,因为 uid 映射会影响映像层的存储。用户命名空间偏移 docker 使用的 uid,以便容器内的 root 不是主机上的 root,而在容器内您仍然可以绑定到低编号端口并运行管理活动。

  2. 考虑授权插件 https://docs.docker.com/engine/extend/plugins_authorization/。据我所知,开放策略代理和 Twistlock 是两个,但我不知道它们是否允许您限制某个用户的用户。docker exec命令。他们可能要求您为用户提供连接到 docker 的证书,而不是让他们直接访问 docker 套接字,因为套接字接收到的 API 请求中不包含任何用户详细信息。

  3. 考虑无根码头工人 https://docs.docker.com/engine/security/rootless/。这仍然是实验性的,但由于 docker 不是以 root 身份运行,因此它无法返回主机来执行 root 活动,从而缓解了容器以 root 身份运行时出现的许多问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何防止 root 访问我的 docker 容器 的相关文章

随机推荐

  • 加载本地数据谷歌colab

    我有一个 npy 文件 largeFIle npy 保存在我的谷歌驱动器上的同一个 colab笔记本 文件夹中 我保存了我的谷歌colab笔记本 我正在尝试使用下面的代码将数据加载到我的笔记本中 但是我收到以下错误 当我在笔记本电脑上本地运
  • C# 从 List 获取键和值

    给定一个列表 private List
  • java 的 servicewrapper 的替代品?

    我用过服务包装器 http wrapper tanukisoftware org doc english download jsp然而 在过去的几次 双重许可证对于商业产品来说有些复杂 通常你必须付费 是否有具有类似功能的完全自由和开源软件
  • 寻找 C# 代码解析器 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一组类 最好在 net 框架中 它们将解析 C 代码并返回带有参数的函数列表 类及其方法 属
  • 为什么 Dockerized Hadoop 数据节点注册了错误的 IP 地址?

    我有 Hadoop 2 7 1 名称节点和数据节点的单独 Docker 1 9 1 映像 我可以从中创建容器 并让它们通过用户定义的 Docker 网络进行通信 然而 数据节点似乎报告自己拥有网络网关的 IP 地址 而不是它自己的 IP 地
  • 将 admin date_hierarchy 设置为foreignkey日期字段

    当我尝试设置时 date hierarchy schedule date 其中 Schedule 是外键 我收到以下错误 TestAdmin date hierarchy refers to field schedule date that
  • 使用 Express 后端将 create-react-app 部署到 heroku 在浏览器中返回无效的主机标头

    标题说明了一切 我在这里构建了一个最小的工作示例 https github com sehailey proxytest https github com sehailey proxytest 我已经尝试过 所以我可能已经记不清了 尽管它们
  • 在 sed -i (正则表达式?)bash 内部使用变量

    我看过另一个sed这里的页面 我找不到使用的页面 i在正则表达式搜索部分有一个变量 我正在尝试剪切文件中请求的行myresolv conf并获取其行号 我班5个人都卡住了 任何帮助都很棒 line grep n 3 myresolv con
  • std::u16string、std::u32string、std::string、length()、size()、代码点和字符

    我很高兴看到std u16string and std u32string在 C 11 中 但我想知道为什么没有std u8string处理 UTF 8 情况 我的印象是std string是为UTF 8设计的 但似乎做得不太好 我的意思是
  • VSTO Outlook:获取选定的附件

    我正在尝试对 Outlook 2010 中选定的附件执行操作 我在VS2012中创建了一个Outlook VSTO项目 这是用于在附件功能区上添加按钮的 XML
  • 如何在 WPF 应用程序中动态导入 3D 模型

    我已经搜索了很长一段时间但找不到合适的方法 当用户选择模型时 如何在运行时将 3D 模型导入 WPF 应用程序中 它可以在任何一种流行的 3D 建模软件中构建 例如 3DS max Maya Blender 等 但并非全部 需要导入 3DS
  • Java作业-打印三角形图案?

    我正在为一项任务而苦苦挣扎 我知道这完全是我的错 但我在课堂上落后了 而且在完成这项作业时遇到了困难 我的目标是打印以下图案 使用 嵌套 for 循环 有人能给我一些关于如何解决这个问题的提示吗 我已经成功打印了一个方形的星号 但我无法弄清
  • 在 Chrome 上单击时链接不会获得焦点

    我在 Chrome 上遇到了一个非常奇怪的行为 这对我来说似乎是一个错误 当您单击链接时 该链接没有获得焦点 更糟糕的是 身体反而成为焦点 可以在这里观察到这种行为 http jsfiddle net YfbR7 4 http jsfidd
  • Emacs - 取消定义前缀键

    我设法将 M 大写 em 键定义为 sqlplus 模式下的前缀键 这阻止了我输入 M 如何在此模式下取消设置此前缀键 短期修复 M x local set key M self insert command 长期修复 请在 emacs 文
  • Boost 程序选项 bool 始终为 True

    通过程序选项 我正在检查参数的有效组合 但由于某种原因 gpu 参数是一个布尔值 无论我是否在命令行上将其设置为 false 它始终为 true 如果我在命令行上指定 gpu 选项 有没有办法可以为 false 我希望能够创建一个布尔变量来
  • 恢复已被覆盖的内置方法

    假设我们的脚本包含在网页中 并且先前的脚本 已执行 执行了以下操作 String prototype split function return U MAD BRO So the split字符串方法已被覆盖 我们想使用这个方法 所以我们需
  • 如何将 CupertinoApp 包装在 Localizations 小部件中,以便我可以在其中使用 Material 小部件?

    我正在使用 CupertinoApp 小部件来包装我的应用程序 同时尝试在其中使用 Material TextFormField 小部件 例如 当我触发文本选择模式 双击文本字段 时 我收到以下错误 因为它尝试打开需要材质本地化的覆盖小部件
  • 来自其他容器的 Docker mongo 映像“连接被拒绝”

    我是码头工人的新手 我正在尝试创建一个 MongoDB 容器和一个 NodeJS 容器 我的文件看起来 version 2 services backend image node 5 11 onbuild ports 3001 3001 v
  • 代码沙箱内的路由,由于 withRouter 而失败

    当我点击提交按钮时 我需要重定向到此页面 pageOne 所以我用谷歌搜索并找到了一个反应路由器并使用了这一行this props history push anotherPage 但它没有重定向 它抛出一个错误 Invariant fai
  • 如何防止 root 访问我的 docker 容器

    我正在努力强化我们的 docker 镜像 但我对它的理解已经有点薄弱了 话虽如此 我当前要做的步骤是阻止用户以 root 身份运行容器 对我来说 这意味着 当用户运行 docker exec it my container bash 时 他