Home > Uncategorized > Trac and git-http-backend

Trac and git-http-backend

Here is how to setup a git repository to be used with Trac and served only by HTTP.

Prerequisites

First install the required software. On Debian Squeeze just do:

apt-get install git trac-git gitweb

Trac configuration

Once the Trac project has been created modify the trac.ini file to enable the git plugin:

[git]
#comment/remove git_bin:
#git_bin = git
#or give the full path
#git_bin = /usr/bin/git

[components]
tracext.git.* = enabled

[trac]
repository_dir = /srv/scm/git/dagobah.git
repository_type = git

Git repository creation

As easy as:

mkdir /srv/scm/git/dagobah.git/
cd /srv/scm/git/dagobah.git/
git init --bare
git config http.getanyfile true
git config http.uploadpack true
git config http.receivepack true

Apache and git-http-backend

git-http-backend doesn’t have any builtin access control mecanism. It relies on Apache for that. Having different ACL for different git repository is probably possible with only Apache configuration but it’s beyond my field of expertise. So I wrote a wrapper around git-http-backend to manage ACLs and also, to dispatch requests between git-web and git-http-backend:

#!/usr/bin/python

GIT_PROJECT_ROOT='/srv/scm/git'
GIT_HTTP_BACKEND='/usr/lib/git-core/git-http-backend'
GIT_WEB='/usr/share/gitweb/index.cgi'
GITWEB_CONFIG='/etc/gitweb.conf'

import os
import subprocess
import csv
import re

#I find easier to change git-http-backend settings here than in the
#apache config file but both work
os.environ['GIT_PROJECT_ROOT']=GIT_PROJECT_ROOT
os.environ['GIT_HTTP_EXPORT_ALL']="1"
os.environ['GITWEB_CONFIG']=GITWEB_CONFIG

def print_env():
    """For debugging"""
    print "Content-type: text/html\n"
    e = os.environ
    for n in e:
       print n + " " + e[n] +"\n"

user = os.environ.get('REMOTE_USER')
script_name = os.environ.get('SCRIPT_NAME')
path_info = os.environ.get('REQUEST_URI')
path_info = path_info[ len(script_name): ]

is_gitweb = re.search(r"^/[^/]*/(HEAD|info/refs.*|objects/info/[^/]+|git-(upload|receive)-pack)$", path_info) == None

if is_gitweb:
    match = re.search(r"\?p=([^;]*)", path_info)
    if match :
        project_name = match.group(1)
    else:
        project_name = path_info.split("/")[1]
    is_writing = False
else:
    project_name = path_info.split("/")[1]
    is_writing = path_info.endswith("git-receive-pack")

valid_user = False
try:
    acl_file="/".join([GIT_PROJECT_ROOT,project_name,"acl.conf"])
    reader = csv.reader(open(acl_file, "rb"), delimiter=' ')
    for l in reader:
        if len(l)==2 and (user == l[0] or l[0]=='*') and ( (l[1] == 'r' and not is_writing) or l[1]=='rw'):
            valid_user = True
            break
except IOError:
    pass

if valid_user:
    if is_gitweb:
        subprocess.call([GIT_WEB])
    else:
        subprocess.call([GIT_HTTP_BACKEND])
else:
    print "Content-type: text/html"
    print "Status: 403 Forbidden\n"
    print "The user "+str(user)+" is not allowed to access to this page."

This script read ACLs from a file named &ltgit repository&gt/acl.conf. The format is simple and allows to specify read or read/write access:

$cat /srv/scm/git/dagobah.git/acl.conf
yoda rw
leia r
r2d2 rw
obiwan r

To use this wrapper just add this line to the Apache configuration:

ScriptAlias /git /var/www/cgi/git-http-backend-wrapper.cgi

Ensure that the directory containing the cgi file have the +ExecCGI option.

References

Advertisements
Tags: ,
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: