Shell脚本如何配置容器进程降权

wen 实用脚本 1

本文目录导读:

Shell脚本如何配置容器进程降权

  1. 使用非root用户运行
  2. 利用capabilities降权
  3. 使用docker run参数降权
  4. 完整的降权脚本示例
  5. Docker Compose示例
  6. 最佳实践建议

在Shell脚本中配置容器进程降权,主要有以下几种安全实践:

使用非root用户运行

创建专用用户(在Dockerfile中)

FROM alpine:latest
# 创建非root用户
RUN addgroup -S appgroup && \
    adduser -S appuser -G appgroup
# 设置工作目录权限
RUN mkdir -p /app && \
    chown -R appuser:appgroup /app
WORKDIR /app
# 切换到非root用户
USER appuser
COPY --chown=appuser:appgroup . .
CMD ["./start.sh"]

Shell脚本中动态创建用户

#!/bin/sh
# 动态创建非root用户
if ! id "appuser" &>/dev/null; then
    addgroup -S appgroup 2>/dev/null || groupadd -r appgroup
    adduser -S appuser -G appgroup 2>/dev/null || useradd -r -g appgroup appuser
fi
# 设置文件权限
chown -R appuser:appgroup /app
# 切换到非root用户执行
exec su -s /bin/sh -c "exec $@" appuser

利用capabilities降权

丢弃不需要的权限

#!/bin/sh
# 启动容器时使用 --cap-drop
# docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE ...
# 或在脚本中直接使用capsh
capsh --drop=cap_net_raw,cap_net_admin -- \
    -c "exec /usr/local/bin/myapp"

实际应用示例

#!/bin/sh
# 保留最小必要权限
echo "Starting with limited capabilities..."
# 使用setpriv(需要安装util-linux)
setpriv --no-new-privs \
        --inh-caps=-all \
        --bounding-set=-all \
        /usr/local/bin/myapp

使用docker run参数降权

#!/bin/bash
# Docker运行时的降权配置
docker run -d \
    --user 1000:1000 \                    # 指定UID/GID
    --cap-drop=ALL \                      # 丢弃所有capabilities
    --cap-add=NET_BIND_SERVICE \          # 只添加需要的
    --security-opt=no-new-privileges \    # 禁止提权
    --security-opt seccomp=default.json \ # 使用seccomp
    --read-only-rootfs \                  # 只读根目录
    -v /tmp:/tmp:rw \                     # 挂载可写卷
    myapp:latest

完整的降权脚本示例

#!/bin/sh
# ========== 容器进程降权脚本 ==========
set -e
APP_USER="appuser"
APP_GROUP="appgroup"
APP_DIR="/app"
# 1. 创建专用用户
create_user() {
    if ! id "$APP_USER" &>/dev/null; then
        echo "Creating user $APP_USER..."
        # Alpine使用addgroup/adduser
        if command -v addgroup &>/dev/null; then
            addgroup -S "$APP_GROUP"
            adduser -S "$APP_USER" -G "$APP_GROUP"
        else
            # Ubuntu/Debian使用groupadd/useradd
            groupadd -r "$APP_GROUP" 2>/dev/null
            useradd -r -g "$APP_GROUP" -d "$APP_DIR" -s /sbin/nologin "$APP_USER"
        fi
    fi
}
# 2. 设置目录权限
setup_permissions() {
    echo "Setting directory permissions..."
    chown -R "$APP_USER:$APP_GROUP" "$APP_DIR"
    chmod 750 "$APP_DIR"
}
# 3. 移除不需要的capabilities
drop_capabilities() {
    echo "Dropping capabilities..."
    # 如果安装了libcap2-bin
    if command -v capsh &>/dev/null; then
        capsh --drop=cap_sys_admin,cap_net_admin,cap_dac_override \
              --print 2>/dev/null
    fi
}
# 4. 降权执行应用
run_as_user() {
    echo "Running application as $APP_USER..."
    # 方法1: 使用su
    # exec su -s /bin/sh -c "exec $@" "$APP_USER"
    # 方法2: 使用gosu (推荐)
    if command -v gosu &>/dev/null; then
        exec gosu "$APP_USER" "$@"
    fi
    # 方法3: 使用chpst (runit工具)
    if command -v chpst &>/dev/null; then
        exec chpst -u "$APP_USER:$APP_GROUP" "$@"
    fi
    # 方法4: 使用sudo (需要配置NOPASSWD)
    if command -v sudo &>/dev/null; then
        exec sudo -u "$APP_USER" "$@"
    fi
    # 最后备选
    exec su -c "exec $*" "$APP_USER"
}
# 5. 验证安全配置
verify_security() {
    echo "Verifying security configuration..."
    # 检查是否以root运行
    if [ "$(id -u)" -eq 0 ]; then
        echo "WARNING: Running as root, but will drop privileges"
    fi
    # 检查no-new-privileges设置
    if [ -f /proc/self/status ]; then
        grep "NoNewPrivs" /proc/self/status
    fi
}
# 主流程
main() {
    echo "Starting container security setup..."
    create_user
    setup_permissions
    drop_capabilities
    verify_security
    # 执行应用
    run_as_user "$@"
}
# 如果直接执行脚本
if [ "$(basename "$0")" = "entrypoint.sh" ]; then
    main "$@"
fi

Docker Compose示例

version: '3.8'
services:
  app:
    build: .
    user: 1000:1000
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    read_only: true
    tmpfs:
      - /tmp
    volumes:
      - app_data:/app/data

最佳实践建议

  1. 最小权限原则

    • 只赋予必要的权限
    • 使用 --cap-drop=ALL 然后单独添加
  2. 用户映射

    • 使用 --userUSER 指令
    • 避免使用UID 0
  3. 文件系统安全

    • --read-only-rootfs 只读根文件系统
    • 挂载临时目录用于写入
  4. 内核安全特性

    • 启用seccomp过滤器
    • 使用AppArmor或SELinux
  5. 网络隔离

    • 避免使用 --privileged
    • 限制网络capabilities

这样配置后,容器进程将以非root用户运行,并且只拥有最小必要权限,大大提高了容器安全性。

抱歉,评论功能暂时关闭!