cnitch(snitch 或 container snitch)是一个简单的框架和命令行工具,用于监控 Docker 容器以识别任何以 root 身份运行的进程。
为什么这是一件坏事?如果您还没有访问过 can I haz non-privileged containers? by mhausenblas,那么我建议您现在就去那里获取所有信息。
在开发 cnitch 时,我遇到了一个我认为是应用程序错误的问题:cnitch 报告自身在 Docker 容器中是一个 root 进程。我不确定为什么会这样,因为 Dockerfile 明确声明我正在创建一个不以 root 身份运行的用户。经过大量调试和验证后,我决定再次检查 Dockerfile,结果发现了这个:
FROM alpine
RUN adduser -h /home/cnitch -D cnitch cnitch
COPY ./cmd/cnitch /home/cnitch/
RUN chmod +x /home/cnitch/cnitch
#USER cnitch
ENTRYPOINT ["/home/cnitch/cnitch"]
当时我在测试应用容器以找出 Docker 套接字权限问题时,一定是不小心注释掉了 USER 命令。这真是元(meta),cnitch 帮助发现了 cnitch 自身的问题,这完全会被纳入集成测试中。
cnitch 通过 API 连接到 Docker 引擎,查询当前正在运行的容器,然后检查这些容器内运行的进程,识别出任何以 root 用户身份运行的进程。 当发现 root 进程时,此信息会发送到可配置的报告模块,供您审计或对其采取行动。
2017/07/29 16:04:27 Starting Cnitch: Monitoring Docker Processes at: tcp://172.16.255.128:2376
2017/07/29 16:04:27 Checking for root processes every: 10s
2017/07/29 16:05:08 Checking image: ubuntu, id: 7bd489560a310343c39186500daa680290289c27f7a730524a31355a3aaf0430
2017/07/29 16:05:08 >> WARNING: found process running as root: tail -f /dev/null pid: 365
目前,cnitch 能够向 StatsD 和 StdOut 报告。报告后端是可扩展的,以便轻松支持任何后端,例如,构建一个支持日志仓库或其他日志文件聚合工具的后端将是相当简单的过程。
异常以计数形式发送到 statsD 端点,使用 cnitch.exception.root_process 指标。这些指标还带有 cnitch 实例的 host 名称和 container 名称的标签。
StdOut 记录器是一个简单的输出记录器,它将报告异常发送到 StdOut。
无论您是在 Docker 容器中运行 cnitch,还是作为二进制文件运行,它都需要通过设置环境变量 DOCKER_HOST 来访问 Docker API,该变量指向服务器 URL 或 socket 路径。
--hostname=[主机名]:用于指标聚合的名称或 IP 地址--statsd-server=[主机名:端口]:statsd 收集器的 URI,如果省略,将禁用 statsd 报告--check=[持续时间,例如 10s(10秒),1m(1分钟)]:cnitch 扫描 root 进程的检查频率设置环境变量 DOCKER_HOST 指向您的 Docker 引擎 API,然后使用所需标志运行 cnitch。
$ cnitch --hostname=myhost --statsd-server=127.0.0.1:8125 --check=10s
cnitch 在非特权容器中运行,如果您希望使用 Docker 套接字访问 API,则需要将 cnitch 用户添加到 docker 组。这可以通过 --group-add 标志实现,设置为 docker 用户组的组 ID。
例如:
--group-add=$(stat -f "%g" /var/run/docker.sock
使用 Docker 套接字文件进行 API 访问的示例
$ docker run -i -t --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
--group-add=$(stat -f "%g" /var/run/docker.sock) \
-e "DOCKER_HOST:unix:///var/run/docker.sock" \
quay.io/nicholasjackson/cnitch [选项]
如果您在 Mac 上使用 Docker Machine,Docker 套接字位于 VM 内部,因此您无法使用 stat 命令发现组 ID。
./example 文件夹中有一个 Docker Compose 示例栈,展示了 cnitch 如何将数据导出到 statsd。要运行此示例:
$ cd ./example
$ docker-compose up
所有组件启动后,在浏览器中打开 http://[docker 主机 IP]:3000,您应该会看到 Grafana 登录屏幕。

使用以下凭据登录 Grafana:
然后选择 cnitch 仪表板。此仪表板显示当前正在运行的 root 进程。

如果您没有使用 /var/run/docker.sock 与 Docker 主机通信,则需要更改文件 ./example/docker-compose.yml 中的一些设置以匹配您的环境。
实现 Docker Bench 安全脚本中的功能 https://github.com/docker/docker-bench-security
[ ] 1.1 确保已为容器创建独立分区
[ ] 1.2 确保容器主机已加固
[ ] 1.3 确保 Docker 是最新版本
[ ] 1.4 确保只有受信任的用户才能控制 Docker 守护进程
[ ] 1.5 确保已为 Docker 守护进程配置审计
[ ] 1.6 确保已为 Docker 文件和目录(/var/lib/docker)配置审计
[ ] 1.7 确保已为 Docker 文件和目录(/etc/docker)配置审计
[ ] 1.8 确保已为 Docker 文件和目录(docker.service)配置审计
[ ] 1.9 确保已为 Docker 文件和目录(docker.socket)配置审计
[ ] 1.10 确保已为 Docker 文件和目录(/etc/default/docker)配置审计
[ ] 1.11 确保已为 Docker 文件和目录(/etc/docker/daemon.json)配置审计
[ ] 1.12 确保已为 Docker 文件和目录(/usr/bin/docker-containerd)配置审计
[ ] 1.13 确保已为 Docker 文件和目录(/usr/bin/docker-runc)配置审计
[ ] 2.1 确保默认网桥上容器之间的网络流量受到限制
[ ] 2.2 确保日志级别设置为 'info'
[ ] 2.3 确保允许 Docker 更改 iptables
[ ] 2.4 确保不使用不安全注册表
[ ] 2.5 确保不使用 aufs 存储驱动
[ ] 2.6 确保配置了 Docker 守护进程的 TLS 身份验证
[ ] 2.7 确保正确配置默认 ulimit
[ ] 2.8 启用用户命名空间支持
[ ] 2.9 确保已确认默认 cgroup 使用情况
[ ] 2.10 确保在需要之前不更改基础设备大小
[ ] 2.11 确保已启用 Docker 客户端命令的授权
[ ] 2.12 确保已配置集中式和远程日志记录
[ ] 2.13 确保禁用旧版注册表(v1)上的操作
[ ] 2.14 确保启用实时恢复
[ ] 2.15 确保禁用用户空间代理
[ ] 2.16 确保根据需要应用了守护进程级别的自定义 seccomp 配置文件
[ ] 2.17 确保在生产环境中避免使用实验性功能
[ ] 2.18 确保容器被限制获取新特权
[ ] 3.x ...
[x] 4.1 确保已为容器创建用户
[ ] 4.2 确保容器使用受信任的基础镜像
[ ] 4.3 确保未在容器中安装不必要的软件包
[ ] 4.4 确保扫描镜像并重建以包含安全补丁
[ ] 4.5 确保启用 Docker 的内容信任
[ ] 4.6 确保在容器镜像中添加了 HEALTHCHECK 指令
[ ] 4.7 确保不要在 Dockerfile 中单独使用更新指令
[ ] 4.8 确保移除镜像中的 setuid 和 setgid 权限
[ ] 4.9 确保在 Dockerfile 中使用 COPY 而不是 ADD
[ ] 4.10 确保不要将秘密存储在 Dockerfile 中
[ ] 4.11 确保仅安装经过验证的软件包
[ ] 5.x ...
[ ] 6.x ...
[ ] 7.x ...