使用 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) 完成了此操作。我怀疑如果出于某种原因您需要使用非裸存储库,则此解决方案需要进行一些调整(最后的想法):
简而言之:
- 在每个存储库中创建一个 link 到 git-core(这是我
怀疑如果你使用非裸机你会有问题
存储库,请参阅下面的想法)
- 使用 ScriptAliasMatch 而不是 ScriptAlias,这样您就可以匹配
仅请求请求的存储库,并将请求定向
到 symlink.
- 为每个存储库创建一个
指令,并设置
GIT_PROJECT_ROOT 每个站点都有单独的变量。这是
因为 apache 将不再提供正确的路径
存储库的 git.
- 为每个 symlink 创建一个
指令。唯一的目的
这对我来说是设置目录的选项,比如
-索引。您可以根据需要将其用于其他选项。
详情:
- 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)获取存储库的路径,另一个($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/"
- 创建
指令。在这里你可以设置 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>
- 创建
指令。对于每个存储库,为您在步骤 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 添加到存储库中。我不确定这是否可行,但有几个想法可以解决这个问题:
- 为每个 link 创建一个 git-ignore,尽管 repo 用户可能是
能够撤消此操作。
- 在其他目录中创建 symlink
存储库目录。我能想到的唯一问题是对的
现在,您可能需要添加第二层身份验证
按照您的指示。
我已经 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) 完成了此操作。我怀疑如果出于某种原因您需要使用非裸存储库,则此解决方案需要进行一些调整(最后的想法):
简而言之:
- 在每个存储库中创建一个 link 到 git-core(这是我 怀疑如果你使用非裸机你会有问题 存储库,请参阅下面的想法)
- 使用 ScriptAliasMatch 而不是 ScriptAlias,这样您就可以匹配 仅请求请求的存储库,并将请求定向 到 symlink.
- 为每个存储库创建一个
指令,并设置 GIT_PROJECT_ROOT 每个站点都有单独的变量。这是 因为 apache 将不再提供正确的路径 存储库的 git. - 为每个 symlink 创建一个
指令。唯一的目的 这对我来说是设置目录的选项,比如 -索引。您可以根据需要将其用于其他选项。
详情:
- 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)获取存储库的路径,另一个($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/"
- 创建
指令。在这里你可以设置 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>
- 创建
指令。对于每个存储库,为您在步骤 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 添加到存储库中。我不确定这是否可行,但有几个想法可以解决这个问题:
- 为每个 link 创建一个 git-ignore,尽管 repo 用户可能是 能够撤消此操作。
- 在其他目录中创建 symlink 存储库目录。我能想到的唯一问题是对的 现在,您可能需要添加第二层身份验证 按照您的指示。