在 OpenBSD 上以及使用 OpenBSDcron
和crontab
,是否可以存储crontab(5)
中的用户的git
同一用户的存储库?
完成这样的事情的正确方法是什么?
(为了将答案引向正确的方向,我不会反对更改系统中的某些权限,尽管我宁愿不必重新编译二进制文件,也不必违反任何良好的安全范例。)
答案1
所有用户的crontab都存储在一个目录中,用户无法直接访问该目录,需要使用特权命令crontab
。
不要将实际的 crontab 文件存储在版本控制中,而是编写一个提交钩子运行crontab
以推送最新版本。
crontab "$HOSTNAME.crontab"
最简单的钩子就是一个post-commit
钩子。运行git rev-parse --abbrev-ref HEAD
查找当前分支和git show --format=format: --name-status HEAD
.
#!/bin/sh
commit=$(git rev-parse HEAD)
branch=$(git rev-parse --name-status "$commit")
git show --format=format: --name-status "$commit" |
while read -r status filename; do
if [ "$branch" = "master" ] &&
[ "$status" = "A" -o "$status" = "M" ] &&
[ "$filename" = "crontabs/$HOSTNAME.crontab" ]; then
crontab "$filename"
fi
done
这不处理合并或变基,并且如果crontab
失败也不会在历史记录中注册任何内容。这里存在一些范式冲突,因为 git 基本上有多个分支,但在任何给定时间在给定机器上只有一个 crontab。为了增加健壮性,您可能更喜欢为实时 crontab 建立一个专用分支,并在更改工作分支上的 crontab 文件时合并到该分支。
答案2
很复杂,因为在单个目录下cron
查找crontab
文件,这不适合每用户 git 存储库。我想你可以/usr/bin/crontab
用代码替换,除了模拟之外crontab(1)
,还可以找出用户是谁,检索或创建他们的 git 存储的 cron 数据,提交任何更改,然后cron(8)
通过调用原始的crontab(1)
(由于 setgid 位),或被 setgid 本身(危险危险安全警告!)。系统更新也会很复杂,因为在升级过程中,需要安装更新/usr/bin/crontab
,然后将其移到一边以安装支持 git 的包装器(对于任何涉及 的补丁也是如此crontab
)。
知道原始版本在哪里的用户crontab(1)
将能够绕过 git 的东西;为了避免这种情况,您的实现必须是 setgid crontab
,这可能会导致任意覆盖任何用户的 crontab 文件安全问题,或者换句话说,这是一种允许整个系统受损的好方法(攻击者写入root
crontab文件,他们赢了!)如果您的代码包含任何安全问题。
同样复杂的是,如果用户弄清楚他们的 per-cron git 存储库在哪里,然后就搞砸了;如果这是一个问题,那么这些存储库需要由其他用户拥有,然后自定义crontab(5)
客户端将与某些确实拥有这些存储库权限的守护进程进行对话(例如sshd
privsep 是如何做的)。
(rcs
如果您只需要跟踪一段时间内的变化,并且提供的绳索比 少,那么可能就足够了git
。)