使用 Apache 基本身份验证禁止 git 访问特定目录

Disabling access for git to specific Directory with Apache Basic Authentication

我已经 git 设置了我的 Apache2 服务器,它可以很好地满足 git 请求。现在我想为此设置基本身份验证,所以不是每个人都可以使用每个目录。我的目标是只有 ADMIN 组可以访问完整的 /var/www/html/git 目录,而我的 GITGROUP 只能访问 /var/www/html/git/subdir 目录。但是,虽然 Apache 要求凭据,但通过设置(如下)GITGROUP 仍然允许访问 all git 目录。我做错了什么?

SetEnv GIT_PROJECT_ROOT /var/www/html/git
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAlias /git/ /usr/lib/git-core/git-http-backend/
<Directory /usr/lib/git-core>
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
    AuthType Basic
    AuthName "Authentication Required"
    AuthUserFile "/etc/apache2/.htpasswd"
    AuthGroupFile "/etc/apache2/groups"
    Require group ADMIN GITGROUP

    Order allow,deny
    Allow from all
</Directory>
<Directory /var/www/html/git>
    AuthType Basic
    AuthName "Authentication Required"
    AuthUserFile "/etc/apache2/.htpasswd"
    AuthGroupFile "/etc/apache2/groups"
    Require group ADMIN
    Options -Indexes

    Order allow,deny
    Allow from all
</Directory>
<Directory /var/www/html/git/subdir>
    AuthType Basic
    AuthName "Authentication Required"
    AuthUserFile "/etc/apache2/.htpasswd"
    AuthGroupFile "/etc/apache2/groups"
    Require group ADMIN GITGROUP
    Options -Indexes

    Order allow,deny
    Allow from all
</Directory>

编辑:

根据@jsvendsgaard 的回答,我为 git-core 的两个符号链接创建了两条 ScriptAlias 行。之后,只需分配正确的 GIT_PROJECT_ROOT:

ScriptAlias /gitdir1/ /var/www/html/gitdir1/git-core/git-http-backend/
ScriptAlias /gitdir2/ /var/www/html/gitdir2/git-core/git-http-backend/
<Directory "/var/www/html/gitdir1/git-core">
    AuthType Basic
    AuthName "Authentication Required"
    AuthUserFile "/etc/apache2/.htpasswd"
    AuthGroupFile "/etc/apache2/groups"
    Require group ADMIN
    Options +ExecCGI -MultiViews -Indexes

    Order allow,deny
    Allow from all
</Directory>
<Directory "/var/www/html/gitdir2/git-core">
    AuthType Basic
    AuthName "Authentication Required"
    AuthUserFile "/etc/apache2/.htpasswd"
    AuthGroupFile "/etc/apache2/groups"
    Require group ADMIN GITGROUP
    Options +ExecCGI -MultiViews -Indexes

    Order allow,deny
    Allow from all
</Directory>
<Location "/gitdir1/">
    SetEnv GIT_PROJECT_ROOT /var/www/html/gitdir1
    SetEnv GIT_HTTP_EXPORT_ALL

    AuthType Basic
    AuthName "Authentication Required"
    AuthUserFile "/etc/apache2/.htpasswd"
    AuthGroupFile "/etc/apache2/groups"
    Require group ADMIN
</Location>
<Location "/gitdir2/">
    SetEnv GIT_PROJECT_ROOT /var/www/html/gitdir2
    SetEnv GIT_HTTP_EXPORT_ALL

    AuthType Basic
    AuthName "Authentication Required"
    AuthUserFile "/etc/apache2/.htpasswd"
    AuthGroupFile "/etc/apache2/groups"
    Require group ADMIN GITGROUP
</Location>

我相信我也有类似的需求。我能够让我的解决方案在 RedHat 服务器上运行。

使用 Apache 2.4 的解决方案

我发现的问题是 git-http-backend 脚本确实控制了对存储库的所有访问。此外,ScriptAlias 配置为将所有 /git/ 请求路由到 git-http-backend,而不管路径的其余部分。而且,因为您已经为 GITGROUP 提供了对此脚本的访问权限,所以该组将可以访问 URL 中以 /git/ 开头的任何存储库。根据文档,

https://git-scm.com/docs/git-http-backend

git-http-backend 知道每个存储库的位置,因为 Apache 为它提供了一个环境变量。我怀疑这意味着 git-http-backend 是服务器上唯一直接访问您的存储库然后将响应返回给 Apache 的进程。

我的解决方案增加了一些额外的步骤。本质上,您将强制对 git-http-backend 的任何访问仅在您已经对存储库位置进行身份验证之后发生,而不是之前。这是通过将 link 放置到存储库目录本身的脚本,然后验证该位置来完成的。

注意:我只使用裸存储库 (git init --bare) 完成了此操作。我怀疑如果出于某种原因您需要使用非裸存储库,则此解决方案需要进行一些调整(最后的想法):

简而言之:

  1. 在每个存储库中创建一个 link 到 git-core(这是我 怀疑如果你使用非裸机你会有问题 存储库,请参阅下面的想法)
  2. 使用 ScriptAliasMatch 而不是 ScriptAlias,这样您就可以匹配 仅请求请求的存储库,并将请求定向 到 symlink.
  3. 为每个存储库创建一个 指令,并设置 GIT_PROJECT_ROOT 每个站点都有单独的变量。这是 因为 apache 将不再提供正确的路径 存储库的 git.
  4. 为每个 symlink 创建一个 指令。唯一的目的 这对我来说是设置目录的选项,比如 -索引。您可以根据需要将其用于其他选项。

详情:

  1. link。如果您的存储库是 /var/www/html/git/subdir,并且您的 git-httpd-backend 在 /usr/libexec/git-core 中,命令将是:

ln -s /usr/libexec/git-core /var/www/html/git/subdir/git-core

  1. 别名。这将使用带有两个反向引用的正则表达式,一个($1)获取存储库的路径,另一个($2)获取命令(git-upload-pack,等等)。然后它将此别名为您在第一步中创建的 symlink。在我的正则表达式中,我还确保请求是有效的 git 请求。它假定对您网站的请求开始时看起来像 https://yoursite/git/some_repo.git:
ScriptAliasMatch \
  "(?x)^/git/(.*/)((HEAD | \
    info/refs | \
    objects/(info/[^/]+ | \
    [0-9a-f]{2}/[0-9a-f]{38} | \
    pack/pack-[0-9a-f]{40}\.(pack|idx)) | \
    git-(upload|receive)-pack))$" \
    "/var/www/html/git//git-core/git-http-backend/"
  1. 创建 指令。在这里你可以设置 git 的存储库路径,你也可以在这里添加身份验证:
<Location /git/subdir1.git>
    SetEnv GIT_PROJECT_ROOT /var/www/html/git/subdir1.git
    SetEnv GIT_HTTP_EXPORT_ALL

    AuthType Basic
    AuthName "Authorization Required"
    ... <the rest of your authentication details here> ...
</Location>

<Location /git/subdir2.git>
    SetEnv GIT_PROJECT_ROOT /var/www/html/git/subdir2.git
    SetEnv GIT_HTTP_EXPORT_ALL

    AuthType Basic
    AuthName "Authorization Required"
    ... <the rest of your authentication details here> ...
</Location>
  1. 创建 指令。对于每个存储库,为您在步骤 A 中创建的 symlink 创建一个目录:
<Directory /var/www/html/git/subdir1.git/git-core>
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch -Indexes
    Allowoverride None
</Directory>

<Directory /var/www/html/git/subdir2.git/git-core>
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch -Indexes
    Allowoverride None
</Directory>

如果您使用的不是裸存储库:

我只在 git 服务器上使用裸存储库,但我认为如果您没有裸存储库,您可能会在创建此 symlink 时遇到问题。我担心的是有人可能会以某种方式将您的 link 添加到存储库中。我不确定这是否可行,但有几个想法可以解决这个问题:

  1. 为每个 link 创建一个 git-ignore,尽管 repo 用户可能是 能够撤消此操作。
  2. 在其他目录中创建 symlink 存储库目录。我能想到的唯一问题是对的 现在,您可能需要添加第二层身份验证 按照您的指示。