GIT-Repository als Webanwendung mit AD-Authentifizierung

Git ist (noch) ein verteiltes Versionskontrollsystem und sehr schlecht gegen äußere Einblicke abzuschirmen.
Deshalb ist es primär für OpenSourcprojekte gedacht.
Ich musste trotzdem den Versuch unternehmen, ein GIT-REPO entsprechend zu konfigurieren.

Installation

(bis wheezy)

apt-get install winbind apache2 git-core git-web libapache2-mod-auth-pam libapache2-mod-auth-sys-group

anschließend muss der Rechner für die Authentifizierung an das Active Directory konfiguriert werden. siehe dazu : Winbind
Im AD muss eine globale Gruppe z.B. „GIT_GRUPPE“ erstellt werden und mit den berechtigten Benutzern gefüllt werden.
der APACHE muss die Module dav und dav_fs geladen haben.

a2enmod dav dav_fs cgi

(ab jessie)

apt-get install winbind apache2 git-core git-web libapache2-mod-authnzpam libapache2-mod-auth-sys-group
echo "auth required pam_succeed.so quiet user ingroup git_gruppe" >/etc/pam.d/git
/etc/apache2/conf-enabled/git.conf
 Alias /git/mygit "/daten/git/mygit"
<Directory "/daten/git/mygit">
    DAV On
    Allow from all
    AllowOverride all
    Order allow,deny
    DirectoryIndex gitweb.cgi
    SetEnv GITWEB_CONFIG /daten/git/mygit/git.conf
    SetEnv GIT_HTTP_EXPORT_ALL
    SetEnv REMOTE_USER=$REDIRECT_REMOTE_USER
    Options +ExecCGI -Includes 
    <Files gitweb.cgi>
    SetHandler cgi-script
    </Files>
    AuthType Basic
    AuthName "Git Repositories myGIT erfordern eine Anmeldung"
    AuthBasicProvider PAM
    AuthPAMService git
    require valid-user
</Directory>
/etc/init.d/winbind restart
/etc/init.d/samba restart
/etc/init.d/apache restart

Programmkonfiguration

Als Beispiel soll im Verzeichnis /daten/git_repos/ ein Repo angelegt werden.

mkdir /daten
su www-data
mkdir /daten/git_repos
cp -avr /usr/share/gitweb/* /daten/git_repos/
cp -avr /usr/lib/cgi-bin/gitweb.cgi /daten/git_repos/

editiere die Datei /daten/git_repos/gitweb.cgi:

vi /daten/git_repos/gitweb.cgi
  ...
  our $projectroot = "/daten/git_repos";
  ...

editiere die Datei /etc/gitweb.conf:

vi /etc/gitweb.conf

  # path to git projects (<project>.git)
  $projectroot = "/daten/git_repos/";
  $site_name = "GIT-Repository meiner Firma";
  # directory to use for temp files
  $git_temp = "/tmp";
  # target of the home link on top of all pages
  $home_link = $my_uri || "/";
  # html text to include at home page
  $home_text = "indextext.html";
  # file with project list; by default, simply scan the projectroot dir.
  $projects_list = $projectroot;
  # stylesheet to use
  $stylesheet = "/git/gitweb.css";
  # logo to use
  $logo = "/git/git-logo.png";
  # the 'favicon'
  $favicon = "/git/git-favicon.png";

erstelle die Datei /etc/apache2/conf.d/git:

vi /etc/apache2/conf.d/git

  # Zugriff auf das tolle GIT-Repo / rb
  Alias /git "/daten/git_repos"
  DAVLockDB "/var/lock/apache2/DAV.lock"
  <Directory "/daten/git_repos">
    DAV On
    Allow from all
    AllowOverride all
    Order allow,deny
    Options ExecCGI 
    DirectoryIndex gitweb.cgi
    SetEnv GITWEB_CONFIG /etc/gitweb.conf
    <Files gitweb.cgi>
      SetHandler cgi-script
    </Files>
    AuthType Basic
    AuthPAM_Enabled On
    AuthName "GIT Repository erfordert eine Anmeldung"
    AuthUserFile /dev/null
    AuthPAM_FallThrough On
    AuthBasicAuthoritative off
    AuthGroup_Enabled On
    #erstellte globale Gruppe klein geschrieben!
    Require group git_gruppe
 </Directory>

Anschließend muss der apache und der winbind neu gestartet werden.

/etc/init.d/apache2 restart
/etc/init.d/winbind restart

Repositoryerstellung und -konfiguration

auf dem Server:

su www-data
cd /daten/git_repos
mkdir MyGITRepo
cd /daten/git_repos/MyGITRepo
git init --bare
git config http.receivepack true
echo "meine Beschreibung zum Repo">.git/description
#bei jeder Änderung muss unbedingt ein "git update-server-info" ausgeführt werden, sonst werden die Änderungen nicht sichtbar!
chmod +x .git/hooks/postupdate
#Info: bei SUSE heisst die Datei postupdate.example und muss umbenannt werden
./git/hooks/postupdate

erster Test schon auf dem Server:
ummelden als ein normaler Benutzer.

cd
git clone https://meinserver/git/MyGITREPO
#oder lokal per
#git clone file:///daten/git_repos/MyGITREPO
cd MyGITREPO
git branch
#eine erste Datei erstellen
echo "Willkommen im Repo">willkommen.txt
git add .
git commit -a -m "initialer commit von rb"
git push origin master

Sonderfall mehrere mehrere Repos für mehrere Benutzergruppen trennen

Repo von einem Linuxclient per HTTP aus clonen

Jetzt sollte im Webbrowser die Seite http://meinserver/git/MyGITRepo für alle Mitglieder der Gruppe „GIT_GRUPPE“ nach Authentifizierung erreichbar sein.

cd 
git clone http://domuser:domuserpasswort@meinserver/git/MyGITRepo/.git/
## oder "git clone git@meingithub.dom.ain:MyGITRepo/my.git" wenn der publickey auf dem github vorhanden ist

(Jetzt wird das vollständige Repo im Homeverzeichnis des Benutzers doedel erstellt.
die Ausführung von git clone http://domuser:domuserpasswort@meinserver/git/MyGITRepo/ hat bei mir nie funktioniert!)

cd MyGITREPO
git branch
#eine erste Datei erstellen
echo "Willkommen im Repo">willkommen.txt
git add .
git commit -a -m "initialer commit per http von rb"
git push origin master

Repo von einem Linuxclient per HTTPS aus clonen

erstelle zusätzlich in Deinem Benutzerverzeichnis (z.B.) /home/doedel eine Datei .gitconfig :

[http]
sslVerify = false

alternativ ist auch das Setzen einer Umgebungsvariable möglich:

  export GIT_SSL_NO_VERIFY=true

oder:

git config --global http.sslVerify false


jetzt clonen:

cd 
git clone https://domuser:domuserpasswort@meinserver/git/MyGITRepo/.git/
cd MyGITREPO
git branch
#eine erste Datei erstellen
echo "Willkommen im Repo">willkommen.txt
git add .
git commit -a -m "initialer commit per https von rb"
git push origin master
  

Fehlerquellen

Benutzer www-data kann auf das /tmp-Verzeichnis nicht schreibend zugreifen.
Benutzer www-data kann auf das /var/lock/apache2 nicht schreibend zugreifen.
Auswerten von /var/log/apache/error.log o.ä.
Fehler:
Fehler beim Auschecken auf dem Client:

Cannot optain needed tree abcdefghijk....\\
while processing commit xyzuvw......\
error: Fetch failed

Lösung:
auf dem GIT-Server ins Repoverzeichnis gehen, dann:

git update-server-info
git fsck  
git gc


Fehler:
Fehler beim Auschecken auf dem Client:

check gnutls_handshake_set_max_packet_length().

Lösung:
einkürzen der Datei /etc/ssl/certs/ca-certificates.crt
dann apache neu reloaden

Fehler:
Fehler beim Download hinter einem Proxy:

Cloning into 'fxa-auth-server'...
fatal: unable to connect to github.com:
github.com[0: 192.30.252.128]: errno=Connection timed out

Lösung:

git config --global http.proxy http://Benutzer:Passwort@proxy:Port


dann erneut versuchen

Fehler:
Fehler beim Pushen:

error: Cannot access URL https://meinserver/git/meinrepo/,return code 22
fatal: git-http-push failed

Lösung:
GIT ist einfach zu blöde Benutzer und Passwort mitzugeben.
Der Benutzername muss mit angegeben werden!

git config --global credential.helper cache
git clone https://benutzername@meinserver/git/meinrepo
git push origin master

Fehler:
Bei Neuinstallation von gitweb auf debian jessie tauchen im /var/apache/error.log diese Meldungen auf:

 gitweb.cgi: Undefined subroutine CGI::startform

Lösung:
Änderung in der Konfigurationsdatei gitweb.cgi aller Einträge
von startform
nach start_form
von endform
nach end_form

Fehlersuche:
Lösung:

export GIT_CURL_VERBOSE=1
export GIT_TRACE=1 

Repoerstellungsscript

createGit.sh
#!/bin/bash
## usage: createGit.sh meinGitRepo1
verz=$1
 
cd /daten/git_repos/
mkdir  /daten/git_repos/$verz
cd /daten/git_repos/$verz
echo $verz
pwd
git init --bare
git config http.receivepack true
#touch git-daemon-export-ok
mv hooks/post-update.sample hooks/post-update
echo "$verz-Repository">/daten/git_repos/$verz/description
chown -R www-data:www-data /daten/git_repos/$verz
cd ..
###
cd /tmp/
git clone /daten/git/gesi/$verz
cd /tmp/$verz
git branch
echo "Willkommen im Repo $verz!">Willkommen.txt
git add .
git commit -a -m "Initialer Commit von Richard"
git push origin master
cd /daten/git/gesi
rm -rf /tmp/%verz
###

Code prüfen bevor er gepusht wird

am Beispiel von yamldateien. yamllint und git müssen installiert sein.

apt install pre-commit
#if needed# export https_proxy="http://myproxy:3128"
#if needed# export http_proxy="http://myproxy:3128"
pre-commit install
pre-commit autoupdate
cd myrepo
pre-commit sample-config  >> .pre-commit-config.yaml
pre-commit run --all-files

dann folgende Funktion in die .bashrc einfügen:

### gitte nach github.com
### Bsp.: gitpush winbind
gitpush () {

  if [[ -z "$1"  ]]
      then
          echo "usage: gitpush meincommittext"
  else
   pushd `pwd`
   cd ~/myrepo
   git add . && \
   git commit -a -m "$1" && \
      git push
   popd
  fi
}
export -f gitpush

und dann noch einmalig zur Aktivierung ausführen:

source ~/.bashrc