我编写了一个小型自定义 REST 服务,该服务通过 gunicorn 下的 python3 wsgi 应用程序运行,并通过 upstart init 脚本在系统上进行管理。(主机是 ubuntu 14.04.1)。该服务是一个 git 提交后钩子,git-hook
为简单起见,我将在这里调用它。
该服务通过 jenkins 管道部署,部署作业执行停止/更新/启动序列,以帐户身份release
更新文件并重新启动服务。
问题是,当詹金斯工作到达运行步骤时
sudo service stop git-hook
似乎在该步骤失败,部署被中止。如果命令失败,这就是作业应该做的事情,但无法 100% 确定失败的具体原因,只能确定在尝试运行该步骤时出现了问题。
以下是我所知道的情况:
服务有效
- 如果我使用 (非 root) 管理员帐户以交互方式执行 init 命令,该帐户基本上具有完全 sudo 权限,则服务本身可以 100% 正确运行,并且符合预期。具体来说,命令是
sudo /usr/sbin/service git-hook start|stop
该服务不会在release
用户
- “release”帐户已被授予有限的 sudo 访问权限,可以为此服务运行相同的启动|停止命令,但是当我以帐户身份交互尝试任何一个命令时
release
,它总是失败并显示以下消息git-hook: unrecognized service
sudo 规则似乎有效(至少就“sudo”功能而言)
- 以任何用户身份运行 start|stop 时,系统都会记录 sudo 命令,但不会给出任何失败的迹象(尽管从功能上讲它对用户来说总是失败
release
) - 当我运行 sudo 命令
release
时不是有权访问,它确实正确地失败了密码提示,并且 sudo 记录了该命令不被允许。 - sudoer 文件在语法上有效,已用 检查
visudo
。 - 相同的 sudoer 文件对该用户有其他规则,并且这些规则运行良好,所以我至少知道它正在正确加载。
权限似乎正确
- “release”帐户拥有所有钩子服务应用程序文件,因为它需要完全写入才能部署新代码
- 用户
www-data
还通过拥有应用程序文件的公共组的成员身份拥有等效的读/写权限。这是因为实际的 wsgi 应用程序以用户身份运行www-data
。
以下是 sudoers 规则,作为单独的文件实现/etc/sudoers.d/
:
Host_Alias TOOLS = tools??.*.ourdomain.com
Cmnd_Alias RELEASE_GITHOOK_SERVICE =\
/usr/sbin/service git-hook stop,\
/usr/sbin/service git-hook start
release TOOLS = NOPASSWD:\
RELEASE_GITHOOK_SERVICE
这是 upstart 初始化文件,/etc/init/git-hook.conf
它具有权限:-rw-r--r--
和所有权root:root
description "git-hook service"
start on (filesystem)
stop on runlevel [016]
respawn
setuid www-data
setgid deploy
env APPHOME="/var/www/git_hook"
env GUNICORN="/var/www/git_hook/venv/bin/gunicorn"
env HOSTNAME="0.0.0.0"
env PORT="5000"
script
chdir $APPHOME
exec $GUNICORN --workers 4 --bind $HOSTNAME:$PORT hook:app
end script
所以问题是,为什么 init 命令在一个帐户下可以正常工作,而在另一个帐户下却不行?这似乎与更严格的 sudo 规则有关,但 sudo 调用似乎确实成功了,所以也许它调用的某些东西就是失败的原因。是否还有其他/usr/sbin/service
运行的隐含命令,我也需要为其制定规则?或者我缺少其他访问权限?