简介
su-exec是一个理想的用于身份切换和权限控制的工具,尤其适合对性能和空间有要求的环境。无论是开发人员还是系统管理员,都值得将它纳入工具箱,以提高工作效率和系统的安全性
官方网站:GitHub - ncopa/su-exec: switch user and group id and exec
背景说明
通常我们启动镜像前需要使用 shell 调整下启动状态,做准备。比如:生成配置文件,检查路径挂载等等。然后再拉起服务,但会遇到两个问题:
- 普通用户权限不够,必须启动 root ,但使用 root 启动服务又不安全。
- 使用 shell 启动进程会导致 shell 进程本身 PID 为 1。而我们所启动服务 PID 不是 1,这就会导致服务本身接收不到 SIGTERM 信号而正常关闭。
解决方案:
1. 使用su-exec
指定特定权限。
- 这需要使用 apk等包管理命令安装或者编译安装
- 需要提前创建好相应账号
2. 使用 exec
命令将启动的服务进程替换当前进程,从而将 PID=1 传递给服务进程
说明: 这里使用 su-exec 而不使用 sudo 的原因是传统 sudo 会新创建出一个进程运行服务,导致 PID 不能为 1,进而导致无法接收到 signal 信号而正常关闭服务
编译安装和使用示例
# centos 7 编译yum install gcc make libtool# 拉取源码git clone https://github.com/ncopa/su-exec.gitcd su-exec make# 拷贝可执行文件
cp su-exec /usr/bin/# 使用示例su-exec apache:1000 /usr/sbin/httpd -f /opt/www/httpd.conf将httpd服务以apache用户和组id 1000的身份启动,并且直接执行提供的配置文件
应用场景
- 在Docker容器中以特定用户运行应用,提升安全性。
- 系统服务管理中,根据服务需求以非root用户身份执行,减少潜在风险。
- 控制资源访问权限的场景,如限制某个程序对特定目录的读写权限。
- 在自动化脚本中,灵活切换执行者的权限。
项目特点
简洁高效:su-exec体积小巧,只有大约10KB,对比同类工具gosu(约1.8MB),大大减少了依赖和存储占用。
直接执行:避免了su和sudo创建子进程的问题,提高了程序执行效率,解决了TTY和信号传递的问题。
易用性强:支持用户名、用户ID和组ID的数字表示,以及用户名:组名的形式,使得使用更灵活。
安全可靠:仅能由root用户执行,确保了权限变更的安全性。
ES容器启动脚本示例
#!/bin/bashset -e# Add elasticsearch as command if needed
if [ "${1:0:1}" = '-' ]; thenset -- elasticsearch "$@"
fi# Drop root privileges if we are running elasticsearch
# allow the container to be started with `--user`
if [ "$1" = 'elasticsearch' -a "$(id -u)" = '0' ]; then# Change the ownership of user-mutable directories to elasticsearchfor path in \/usr/share/elasticsearch/data \/usr/share/elasticsearch/logs \; dochown -R elasticsearch:elasticsearch "$path"doneset -- su-exec elasticsearch "$@"#exec su-exec elasticsearch "$BASH_SOURCE" "$@"
fi# As argument is not related to elasticsearch,
# then assume that user wants to run his own process,
# for example a `bash` shell to explore this image
exec "$@"
其他示例
# Dockerfile 内容如下:FROM alpine:3.16
# 创建用户
RUN addgroup -S -g 1000 redis && adduser -S -G redis -u 999 redis
# 安装 su-exec 命令
RUN apk add --no-cache 'su-exec>=0.2'############################################################
#
# 其它部署 内容
#
############################################################ENTRYPOINT ["/usr/bin/entrypoint.sh"]# /usr/bin/entrypoint.sh 内容如下:#!/bin/sh
set -e############################################################
#
# 启动准备脚本内容
#
############################################################# 最终启动命令
exec su-exec redis redis-server "$@"
参考资料:
https://zhuanlan.zhihu.com/p/558116410