简体   繁体   English

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

[英]Disabling access for git to specific Directory with Apache Basic Authentication

I have git setup with my Apache2 server and it serves git request just fine.我的 Apache2 服务器设置了 git,它可以很好地满足 git 请求。 Now I want to setup Basic Authentication for this, so not everybody can use every directory.现在我想为此设置基本身份验证,所以不是每个人都可以使用每个目录。 My goal is that only the ADMIN group has access to the complete /var/www/html/git directory and my GITGROUP can access only /var/www/html/git/subdir directories.我的目标是只有 ADMIN 组可以访问完整的/var/www/html/git目录,而我的 GITGROUP只能访问/var/www/html/git/subdir目录。 However, while Apache is asking for credentials, with the setup (below) GITGROUP is still allowed to access all git directories.然而,虽然 Apache 要求提供凭据,但通过设置(如下)仍然允许 GITGROUP 访问所有git 目录。 What am I doing wrong?我究竟做错了什么?

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>

EDIT:编辑:

Based on the answer by @jsvendsgaard I created two ScriptAlias lines for two symlinks to git-core.根据@jsvendsgaard 的回答,我为两个指向 git-core 的符号链接创建了两条 ScriptAlias 行。 After that it is only a matter of assigning the correct GIT_PROJECT_ROOT:之后,只需分配正确的 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>

I believe I had a similar need.我相信我也有类似的需求。 I was able to get my solution working on a RedHat server.我能够让我的解决方案在 RedHat 服务器上运行。

Solution Using Apache 2.4使用 Apache 2.4 的解决方案

The problem I found is that the git-http-backend script really controls all access to the repositories.我发现的问题是 git-http-backend 脚本确实控制了对存储库的所有访问。 Additionally, ScriptAlias is configured as such that it will be routing all /git/ requests to git-http-backend, regardless of the rest of the path.此外,ScriptAlias 配置为将所有 /git/ 请求路由到 git-http-backend,而不考虑路径的 rest。 And, because you have provided access to this script for GITGROUP, that group will have access to any repository starting with /git/ in the URL.而且,由于您已为 GITGROUP 提供了对该脚本的访问权限,因此该组将有权访问 URL 中以 /git/ 开头的任何存储库。 As per the documentation,根据文档,

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

git-http-backend knows the location to each repository because Apache is providing it with an environment variable. git-http-backend 知道每个存储库的位置,因为 Apache 为它提供了一个环境变量。 I suspect this means that git-http-backend is the only process on the server that directly accesses your repositories, and then provides the response back to Apache.我怀疑这意味着 git-http-backend 是服务器上唯一直接访问您的存储库的进程,然后将响应返回给 Apache。

My solution adds a few extra steps.我的解决方案增加了一些额外的步骤。 Essentially, you would force any access to git-http-backend to occur only after you have already authenticated to the location of your repository, not before.本质上,您将强制对 git-http-backend 的任何访问仅在您已经对存储库的位置进行身份验证之后才会发生,而不是之前。 This is done by placing a link to the script in the repository directory itself, and then authenticating that location.这是通过在存储库目录本身中放置脚本的链接,然后验证该位置来完成的。

NOTE: I've only done this with bare repositories (git init --bare).注意:我只使用裸存储库(git init --bare)完成此操作。 I suspect that if for some reason you need to use a non-bare repository, this solution would need some tweaking (Ideas on that at the end):我怀疑如果由于某种原因您需要使用非裸存储库,则此解决方案需要进行一些调整(最后的想法):

In a nutshell:简而言之:

  1. Create a link to git-core in each repository (This is where I suspect you would have an issue if you were to use a non-bare repository, see below for idea on that)在每个存储库中创建一个指向 git-core 的链接(如果您要使用非裸存储库,我怀疑您会遇到问题,请参阅下面的想法)
  2. Use ScriptAliasMatch rather than ScriptAlias, so that you can match the request to the requested repository only, and direct the request to the symlink.使用 ScriptAliasMatch 而不是 ScriptAlias,以便您可以仅将请求与请求的存储库匹配,并将请求定向到符号链接。
  3. Create a <Location> directive for each repository, and set the GIT_PROJECT_ROOT variable individually for each site there.为每个存储库创建一个 <Location> 指令,并为那里的每个站点单独设置 GIT_PROJECT_ROOT 变量。 This is because apache is no longer going to be providing the correct path of the repository to git.这是因为 apache 将不再向 git 提供存储库的正确路径。
  4. Create a <Directory> directive for each symlink.为每个符号链接创建一个 <Directory> 指令。 The sole purpose of this for me was to set the options for the directory, like -Indexes.对我来说,这样做的唯一目的是设置目录的选项,例如 -Indexes。 You might use this for other options as needed.您可以根据需要将其用于其他选项。

Details:细节:

  1. The link.链接。 If your repository is /var/www/html/git/subdir, and your git-httpd-backend is in /usr/libexec/git-core, the command would be:如果您的存储库是 /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 ln -s /usr/libexec/git-core /var/www/html/git/subdir/git-core

  1. The Alias.别名。 This will use a regex with two backreferences, one ($1) to grab the path of the repository, and another ($2) to get the command (git-upload-pack, etc).这将使用带有两个反向引用的正则表达式,一个 ($1) 获取存储库的路径,另一个 ($2) 获取命令(git-upload-pack 等)。 It then aliases this to the symlink you created in step one.然后,它会将其别名为您在第一步中创建的符号链接。 In my regex, I also ensure that the request is a valid git request.在我的正则表达式中,我还确保请求是有效的 git 请求。 It assumes a request to your site would start look like https://yoursite/git/some_repo.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/$1/git-core/git-http-backend/$2"
  1. Create the <Location> directives.创建 <Location> 指令。 This is where you can set the path to the repository for git, and you can also add authentication here:您可以在此处设置 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. Create the <Directory> directive.创建 <Directory> 指令。 For each repository, create a directory for the symlink you created in step A:对于每个存储库,为您在步骤 A 中创建的符号链接创建一个目录:
 <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>

If you're not using a bare repository:如果您不使用裸存储库:

I only use bare repositories on the git server, but I think that you might see an issue creating this symlink if you didn't have bare repositories.我只在 git 服务器上使用裸存储库,但我认为如果您没有裸存储库,您可能会看到创建此符号链接的问题。 What I'm worried is that someone could somehow add your link to the repository.我担心的是有人会以某种方式将您的链接添加到存储库。 I'm not sure if this is possible, but a couple of ideas to get around it:我不确定这是否可能,但有几个想法可以解决它:

  1. Create a git-ignore for each link, although the repo user might be able to undo this.为每个链接创建一个 git-ignore,尽管 repo 用户可能能够撤消此操作。
  2. Create the symlink in some other directory, outside of the repository directory.在存储库目录之外的某个其他目录中创建符号链接。 The only issue with this I can think of right now, is that you might need to add a second layer of authentication to your directive.我现在能想到的唯一问题是,您可能需要在指令中添加第二层身份验证。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM