避免让 subversion 修改 Linux 文件权限。

Posted

技术标签:

【中文标题】避免让 subversion 修改 Linux 文件权限。【英文标题】:Avoid having subversion modify Linux file permissions. 【发布时间】:2011-08-22 15:06:10 【问题描述】:

我的所有代码库都存储在一个 subversion 存储库中,我分散在负载平衡的 Apache Web 服务器中,从而可以轻松地检查代码、运行更新以及无缝地将开发中的代码投入生产。

我确信有一个很容易解决的不便之处(除了在每次结帐时执行脚本),就是在使用 subversion 更新或签出的文件上设置(返回)Linux 权限。我们的安全团队将OwnerGroup设置在httpd.conf文件中,documentRoot中的所有目录都获得700的权限,所有非可执行文件(例如*.php, *.smarty, *.png) 获得 600 的 Linux 权限,所有可执行文件获得 700(例如 *.sh、*.pl、*.py)。所有文件的所有者和组都必须设置为apache:apache,才能被 httpd 服务读取,因为只有文件所有者被设置为通过权限访问。

每次我运行svn updatesvn co 时,即使文件可能未创建(即svn update),我发现文件的所有权被设置为运行 svn 命令,通常情况下,文件权限被设置为不同于原来的权限(即更新前的 .htm 文件为 600,但在和svn update 之后,它被设置为 755,甚至第777章)。

绕过 subversion 更新文件权限和所有权的最简单方法是什么?在 svn 客户端或 Linux 服务器上可以做些什么来保留原始文件权限?我正在运行 RHEL5(现在在一些选定的实例上运行 6 个)。

【问题讨论】:

【参考方案1】:

您可以在 Subversion 中的文件上存储属性(请参阅http://svnbook.red-bean.com/en/1.0/ch07s02.html)。您对 svn:executable 属性特别感兴趣,它将确保存储可执行权限。

不过,没有针对所有权限执行此操作的通用方法。 Subversion 也不存储所有权——它假定,如果你签出某些东西,你就拥有它。

【讨论】:

【参考方案2】:

文件的所有者将被设置为运行 svn 命令的用户,因为它如何实现底层的 up 命令 - 它删除和替换更新的文件,这将导致所有权“更改”为相关用户。防止这种情况的唯一方法是实际执行 svn up 作为文件应该拥有的用户。如果您想确保它们归特定用户所有,请以该用户身份运行命令。

关于权限,svn 只服从账户的 umask 设置——可能是 066 之类的东西——为了确保文件不能被组和其他账户访问,你需要先发出 'umask 077'执行 svn up,这样可以确保文件只能由发出命令的用户帐户访问。

除非 .svn 目录是安全的,否则我会注意将颠覆数据部署到 Web 服务器的安全问题。

【讨论】:

+1 提醒人们注意 .svn 的潜在后果。好电话。 我遇到了同样的问题。在我使用svnkit(一个java svn)之前,没有这种行为,它能够保留文件的所有者......但它很慢......是什么让我改变了原来的svn版本。我错过了很多这个“功能”。 这不准确。您可以在目录上使用setgid 来强制将组作为所有者。我在这里回答了详细信息:***.com/a/42800354/2578286 您也可以使用目录的ACL默认权限来覆盖svn在co/up上设置的文件权限。例如看这个答案:unix.stackexchange.com/questions/396619/… 另外我发现临时目录上的默认ACL对svn创建的文件的权限设置有影响。【参考方案3】:

您可能会考虑做的一件事是将svn 二进制文件安装在您的路径之外,并在路径中放置一个替换脚本(位于并称为/usr/bin/svn 或其他任何内容)。脚本看起来像这样:

#!/bin/sh

# set umask, whatever else you need to do before svn commands

/opt/svn/svn $* # pass all arguments to the actual svn binary, stored outside the PATH

# run chmod, whatever else you need to do after svn commands

一个明显的缺点是您可能必须对传递给 svn 的参数进行一些解析,即您可以将相同的路径传递给您的 chmod,而不是为大多数 svn 命令运行 chmod,等等。

这里可能还有一些安全考虑。我不知道您的部署环境是什么样的,但您可能应该进一步调查一下。

【讨论】:

【参考方案4】:

我写了一个小脚本来存储权限和所有者,执行你的 SVN 命令并恢复权限和所有者。 它可能不是防黑客的,但对于私人用途,它可以完成这项工作。

svnupdate.sh:

#!/usr/bin/env bash
if [ $# -eq 0 ]; then
    echo "Syntax: $0 <filename>"
    exit
fi

IGNORENEXT=0
COMMANDS=''
FILES='';
for FILENAME in "$@"
do
    if [[ $IGNORENEXT > 0 ]]; then
        IGNORENEXT=0
    else
        case $FILENAME in
            # global, shift argument if needed
            --username|--password|--config-dir|--config-option)
            IGNORENEXT=1
            ;;
            --no-auth-cache|--non-interactive|--trust-server-cert)
            ;;
            # update arguments, shift argument if needed
            -r|--revision|--depth|--set-depth|--diff3-cmd|--changelist|--editor-cmd|--accept)
            IGNORENEXT=1
            ;;
            -N|--non-recursive|-q|--quiet|--force|--ignore-externals)
            ;;
            *)
            if [ -f $FILENAME ]; then
                FILES="$FILES $FILENAME"
                OLDPERM=$(stat -c%a $FILENAME)
                OLDOWNER=$(stat -c%U $FILENAME)
                OLDGROUP=$(stat -c%G $FILENAME)
                FILECOMMANDS="chmod $OLDPERM $FILENAME; chown $OLDOWNER.$OLDGROUP $FILENAME;"
                COMMANDS="$COMMANDS $FILECOMMANDS"
                echo "COMMANDS: $FILECOMMANDS"
            else
                echo "File not found: $FILENAME"
            fi
            ;;
        esac
    fi
done
OUTPUT=$(svn update "$@")
echo "$OUTPUT"
if [[ ( $? -eq 0 ) && ( $OUTPUT != Skipped* ) && ( $OUTPUT != "At revision"* ) ]]; then
    bash -c "$COMMANDS"
    ls -l $FILES
fi

【讨论】:

【参考方案5】:

我也有类似的问题。 我发现了一个很酷的脚本:asvn (Archive SVN)。

你可以在这里下载: https://svn.apache.org/repos/asf/subversion/trunk/contrib/client-side/asvn

Description:
Archive SVN (asvn) will allow the recording of file types not
normally handled by svn. Currently this includes devices,
symlinks and file ownership/permissions.

Every file and directory has a 'file:permissions' property set and
every directory has a 'dir:devices' and 'dir:symlinks' for
recording the extra information.

Run this script instead of svn with the normal svn arguments.

这篇博文(帮助我找到脚本)http://jon.netdork.net/2010/06/28/configuration-management-part-ii-setting-up-svn/ 展示了一个简单的用法。

【讨论】:

【参考方案6】:

你可以解决这个问题。使用setgid

    你有apache:apache在运行服务器

    设置所有文件和目录的组权限。服务器将按其组读取文件

    在所有目录上设置setgid - 仅在目录上:在文件上设置这个有不同的功能

    示例('2' 是 setgid):

    chmod 2750

    apache设为所有目录的组

会发生什么

任何帐户创建的新文件和目录将归apache 组所有

新目录将继承setgid,从而毫不费力地保留结构

见https://en.wikipedia.org/wiki/Setuid#setuid_and_setgid_on_directories

【讨论】:

以上是关于避免让 subversion 修改 Linux 文件权限。的主要内容,如果未能解决你的问题,请参考以下文章

怎么让subversion忽略指定文件和目录

允许用户修改Subversion日志的钩子脚本 (linux)

图形化SVN管理搭建 subversion edge自行修改密码

吐血整理SVN命令行,Subversion的正确使用姿势,让版本控制更简单~

Linux下的SVN服务器搭建

v1.6中的Subversion分支重新集成[重复]