Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access control in Cgit

I would like to introduce access control to cgit once the cgi of cgit has been launched. The idea would be to list all the repos available in gitolite but enable/disable the directory listing based on user authentication.

I managed to get access control before apache is executing the cgit cgi:

 AllowOverride None
 AuthType Basic
 AuthName "Restricted Files"
 AuthUserFile /var/lib/git_alfonso/passwords

  Options +ExecCGI
   Order allow,deny
   Allow from all

Alias /cgit.png /var/www/htdocs/cgit/cgit.png
Alias /cgit.css /var/www/htdocs/cgit/cgit.css
ScriptAlias /cgit "/var/www/htdocs/cgit/cgit.cgi"
RewriteRule ^$ / [R]
RewriteRule ^/(.*)$ /cgit.cgi/$1****

But I don't know how to get the same effect once the repositories paths are accessed, I tried with the directory directive and adding the authentication there but once cgit is launched apache doesn't apply any other directive stated in the http.conf file.

Any clue on how to achieve it?

Thanks a lot in advance.

Br Alfonso.

like image 491
user2381132 Avatar asked Jul 22 '13 07:07

user2381132


1 Answers

I have done precisely that in my own cgit config.

# CGit on @PORT_HTTP_CGIT@
Listen @PORT_HTTP_CGIT@
<VirtualHost @FQN@:@PORT_HTTP_CGIT@>
ServerName @FQN@
ServerAlias @HOSTNAME@
SetEnv GIT_HTTP_BACKEND "@H@/usr/local/apps/git/libexec/git-core/git-http-backend"
DocumentRoot @H@/cgit
Alias /cgit @H@/cgit
<Directory @H@/cgit>
  SetEnv GIT_PROJECT_ROOT=@H@/repositories
  AddHandler cgi-script .cgi .pl
  DirectoryIndex cgit.pl

(The @xx@ are template placeholder for values)

The idea is to wrap cgit.cgi with a custom script cgit.pl (here a perl script but you can use any other scripting language you want), which will:

  • call gitolite
  • only display what is authorized by gitolite

You can see the full cgit.pl script here.

This is when you are trying to access to a specific repo:

if ($request_uri ne "/cgit/" && $request_uri ne "/cgit/cgit.pl/") {
  (my $repo)=($path_info =~ /\/([^\/]+)/);
  my $perm = "R";
  if ($repo ne "") {
  my $aperm = access( $repo, $user, 'R', 'any' );
  # my ($aperm, $creator) = &repo_rights($repo);
    $perm=$aperm;
  }
  if ($perm !~ /DENIED/) {
    system("@H@/cgit/cgit.cgi");
  }
}

This is when you are calling cgit without a repo: it should list only the repos you are authorized to see.
For that, call the native cgit.cgi, and then filter the output, removing any line corresponding to a "denied" repo:

    my $fname="$user.".timestamp().".tpl";
    system("@H@/cgit/cgit.cgi > $fname");
    open(INFO, $fname); # Open the file
    @lines = <INFO>; # Read it into an array
    close(INFO);
    unlink($fname);
    pop(@lines);
    foreach (@lines) {
      my $line=$_;
      (my $repo)=($line =~ /title='([^']+)'/); #'
      my $perm = "R";
      if ($repo ne "") {
      my $aperm = access( $repo, $user, 'R', 'any' );
        # my ($aperm, $creator) = &repo_rights($repo);
        $perm=$aperm;
      }
      if ($perm !~ /DENIED/) {
        print $line;
      }
    }
like image 86
VonC Avatar answered Sep 21 '22 13:09

VonC