You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

在Kubernetes的Docker容器中启用命令行审计日志及权限问题解决

解决Docker容器中命令行审计日志(含非root用户)的方案

这个问题在多用户容器环境下很常见——root用户能直接写入/proc/1/fd/1记录命令,但非root用户因为权限限制无法操作。下面给你几个经过验证的可行方案,按复杂度和实用性排序:

方案一:使用日志管道转发(推荐,轻量且通用)

核心思路是创建一个所有用户都能写入的管道,由root权限的后台进程把管道内容转发到容器主日志(/proc/1/fd/1),这样非root用户只需写管道即可,不需要直接操作主日志文件。

步骤1:编写Dockerfile和入口脚本

首先,在你的Docker镜像中添加管道创建和转发逻辑:

FROM your-base-image  # 替换为你的基础镜像,比如ubuntu:20.04

# 创建全局可写的审计日志管道
RUN mkfifo -m 666 /var/log/command_audit.fifo

# 添加自定义入口脚本
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# 创建非root用户(如果你的应用需要以非root运行)
RUN useradd -m appuser

# 保持root身份执行入口脚本,确保能操作/proc/1/fd/1
ENTRYPOINT ["/entrypoint.sh"]

然后编写entrypoint.sh脚本:

#!/bin/bash

# 启动后台转发进程:持续读取管道内容并写入容器主日志
while true; do
    cat /var/log/command_audit.fifo
done > /proc/1/fd/1 &

# 给所有用户的bash会话添加命令审计trap
# 这里同时写入/etc/profile(全局登录shell)和/etc/bash.bashrc(全局交互式bash)
echo '
# 仅在交互式shell中记录命令
if [[ $- == *i* ]]; then
    trap '\''echo "$(date +"%Y-%m-%d %H:%M:%S") $USER: $BASH_COMMAND" > /var/log/command_audit.fifo'\'' DEBUG
fi
' >> /etc/profile
echo '
# 仅在交互式shell中记录命令
if [[ $- == *i* ]]; then
    trap '\''echo "$(date +"%Y-%m-%d %H:%M:%S") $USER: $BASH_COMMAND" > /var/log/command_audit.fifo'\'' DEBUG
fi
' >> /etc/bash.bashrc

# 如果需要以非root用户运行主应用,切换用户并执行命令
exec su - appuser -c "$*"

为什么这个方案有效?

  • 管道/var/log/command_audit.fifo设置了666权限,所有用户都能写入;
  • 后台转发进程以root身份运行,有权限写入/proc/1/fd/1
  • 通过if [[ $- == *i* ]]判断交互式shell,避免记录脚本自动执行的大量命令,只记录用户手动输入的命令。

方案二:使用Linux审计系统(auditd,适合严格审计场景)

如果你的环境需要更全面的系统级审计,可以使用Linux的auditd工具,它能记录所有execve系统调用(即命令执行行为)。不过这个方案需要容器额外的权限和配置:

步骤1:运行容器时添加必要权限

启动容器时需要添加AUDIT_WRITE能力,让容器能向主机审计系统发送事件:

kubectl run audit-demo --image=your-audit-image --cap-add=AUDIT_WRITE

步骤2:在容器内配置auditd

以Debian/Ubuntu为例,在镜像中安装并配置:

FROM ubuntu:20.04

RUN apt-get update && apt-get install -y auditd

# 添加审计规则:记录所有用户的execve调用,标记为command_audit
RUN echo '-a exit,always -F arch=b64 -S execve -k command_audit' >> /etc/audit/rules.d/command-audit.rules

# 启动auditd并将日志转发到容器主日志
COPY entrypoint-audit.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

entrypoint-audit.sh脚本:

#!/bin/bash

# 启动auditd
service auditd start

# 持续将audit日志转发到容器主日志
tail -f /var/log/audit/audit.log > /proc/1/fd/1 &

# 执行主应用
exec "$@"

注意事项

  • 日志格式比较复杂,需要用ausearch工具解析才能看到可读的命令内容;
  • 主机需要支持审计系统(大多数现代Linux发行版默认支持);
  • 容器需要CAP_AUDIT_WRITE权限,可能不符合某些安全策略。

为什么你之前的方案失效?

你尝试直接让非root用户写入/proc/1/fd/1,但这个文件的属主是容器主进程的用户(通常是root),普通用户没有写权限——Docker容器的主日志文件权限是由主进程的用户身份决定的,无法直接修改/proc/1/fd/1的权限(因为它是主进程的文件描述符,动态关联)。

而管道转发方案绕开了这个限制:非root用户只需要写入全局可写的管道,由root进程负责把内容同步到主日志,完美解决了权限问题。

内容的提问来源于stack exchange,提问作者EDUARD I

火山引擎 最新活动