Ich wollte nur [...] und dann ist das Universum explodiert.

Projects
Books
Archive
About









    Permalink
  1. Gitosis | Zweischneidigkeit des Auth-Verfahrens

    Ein Nachtrag und zugleich ein ganz besonders unschöner Zustand kam mir gestern unter die Finger. Gitosis benutzt bekanntermaßen SSH-Public-Keys zum authentifizieren der User, die in Git-Repositories arbeiten dürfen. Dieser Austausch zwischen Reporitory und Arbeitskopie passiert ebenfalls über SSH-Port 22. Die Benutzer, die sich dort anmelden, dürfen allerdings keinen direkten SSH-Zugriff bekommen. Soweit die Theorie.

    Wenn man seinen Public-Key also Gitosis zur automatischen Authentifizierung vorwirft, wird man in das System der Git-Benutzer eingespeißt.

    cp id_rsa.pub ~/gitosis/keydir/user@host.pub
    git add keydir/*
    git commit -a -m "user hinzugefügt"
    git push

    Bei erneuter Anmeldung an das System passiert folgendes:

    $ ssh user@gitserver.domain.com
    PTY allocation request failed on channel 0
    ERROR:gitosis.serve.main:Need SSH_ORIGINAL_COMMAND in environment.
    Connection to git closed.

    Ich darf mich also nicht mehr einloggen. Bin ich normaler Benutzer, der wirklich nur mit git arbeiten darf, ist das auch gut so. Denn so wird die Sicherheit des Systems gewahrt. Bin ich allerdings Administrator des git-Remote-Servers sieht das anders aus. Ich habe ab diesem Zeitpunkt keine Möglichkeit mehr mein System (auf gewohntem Wege) zu pflegen.

    Die Verbose-Ausgabe von ssh lässt darauf schließen was passiert:

    $ ssh -v user@gitserver.domain.com
    debug1: Authentications that can continue: publickey,password
    debug1: Next authentication method: publickey
    debug1: Trying private key: /home/user/.ssh/identity
    debug1: Offering public key: /home/user/.ssh/id_rsa
    debug1: Remote: Forced command: gitosis-serve user@host
    debug1: Remote: Port forwarding disabled.
    debug1: Remote: X11 forwarding disabled.
    debug1: Remote: Agent forwarding disabled.
    debug1: Remote: Pty allocation disabled.
    debug1: Server accepts key: pkalg ssh-rsa blen 277
    debug1: read PEM private key done: type RSA
    debug1: Remote: Forced command: gitosis-serve user@host
    debug1: Remote: Port forwarding disabled.
    debug1: Remote: X11 forwarding disabled.
    debug1: Remote: Agent forwarding disabled.
    debug1: Remote: Pty allocation disabled.
    debug1: Authentication succeeded (publickey).
    PTY allocation request failed on channel 0
    ERROR:gitosis.serve.main:Need SSH_ORIGINAL_COMMAND in environment.
    debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
    debug1: client_input_channel_req: channel 0 rtype eow@openssh.com reply 0
    debug1: channel 0: free: client-session, nchannels 1
    Connection to git closed.

    Die Authentifizierung mit meinen Public-Key klappt zwar, aber ich werde in eine gitosis-serve ssh-session gezwungen und damit bleibt mir der ssh-zugang ins System verwehrt. Nicht mit dieser Situation rechnend, starrte ich völlig perplex auf mein Terminal und die Reverse-Engeneering-Abteilung in meinem Kopf ratterte vor sich hin. Was passiert da und warum passiert das? Und vor allem: Wie komme ich jetzt wieder auf den Server?

    Solve it!

    1. Public-Key Auth deaktivieren
    Ohne PubKey Auth, wird der ssh-daemon nicht erkennen, das er mir eine git-serve session geben müsste. Dem lokalen ssh-client beizubringen sich nicht mit dem Public-Key am entfernten System anzumelden, wäre also eine Lösung (aber keine Schöne). Folgende Konfiguration führt dazu.
    $ vi ~/.ssh/config
    Host git
    HostName gitserver.domain.com
    User root
    pubkeyauthentication no

    2. Different User
    Die Alternative zu dieser dauerhaften Veränderung ist (wenn vorhanden) einen anderen Benutzer zu verwenden um sich ins System einzuloggen und erst anschließend zu root zu werden.

    3. gitosis-serve zurechtstutzen
    Nachdem der Zugriff auf das System  wiederhergestellt ist, gehts zum Bugfix (gitosis-serve). gitosis muss diesen Umstand in irgendeiner ssh-config erzwingen. Ich verstehe nicht ganz warum, aber gitosis schrieb mir diese Änderungen in /root/.ssh/authorized_keys.

    command="gitosis-serve user@host",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AABBB3NzaC1yc2EAAAABIwAAAQEAyjwZCinCmB4oJJZ4RuiSqrQmiYE8+C+JKpTmiPkdfojUbiB9gm3BOhsYAdu99vP7yDOaIqg9e2dk/4HGm+P8obUR7lVrinMf5NvoRkOa8EfGdPJRz4ABOGRDte454bwestyWlvLhnKyWd+a9lU07siDJg5b1NbitIXkXa76V+lGMrqkixaDC6meZQEjZlxnVMpgzC5wyEQy2cVwUnX+Swiw68gsHsMYKBNsiVgNQ7nY8fa5lhV13E6L2aYAIorVpudS1bTiQfvfXCpVtJkJVSNPP6RzUtuSSErhsqOn1o2QtVjWhH5J/Y0D1b4eeEAgmdhq7554kQupJ9LgRww== user@host

    Dieser Eintrag ist für das Verhalten verantwortlich. Auskommentieren oder entfernen aller Parameter bis ssh-rsa fixt das Problem . Happy Committing.


  2. Permalink
  3. Gitosis | Debugging, Undokumentiertes und Konfiguration

    Aktuell setze ich mich mit Gitosis auseinander. Ja, auseinander setzen ist gut ausgedrückt. Dieses widerspenstige, (standardmäßig) wenig gesprächige und nur oberflächlich dokumentierte Stück Software sträubt sich vehement gegen den tieferen Einsatz und komplexeren Ordnerhierarchien.

    Also im Klartext: Ich finde Gitosis super. Der Ansatz ist gut. Definierbare Rechte und Gruppenorganisation für Git-Repositories. Im Web findet man unzählige How-To’s die eine Standardinstallation wirklich gut und übersichtlich dokumentieren bzw. dazu anleiten. Speziellere Anpassungen und kleinere Grauzonen hingegen leider gar nicht.

    Um den Überblick über kleinere Mängel zu behalten und auch zu dokumentieren:

    (1) post-update – Hook-Problematik

    Die Funktionsweise von Gitosis ist eigentlich denkbar simpel. Konfigurationsdatei syntaxgerecht anpassen und innerhalb des admin-repos committen+pushen. Ist die neue Config gepusht und der Benutzer bzw. das neue Repo nicht ansprechbar, verbringt man lange Zeit damit, Configs und Pubkeys (siehe 2) zu kontrollieren und erneut zu initialisieren. An dieser Stelle begegnet einem schon das erste Problem, welches Kenntnis über die Funktionsweise von Gitosis voraussetzt und hervorragend schlecht dokumentiert ist.
    ERROR:gitosis.serve.main:Repository read access denied fatal: The remote end hung up unexpectedly
    Nach dem das Master-Repo die gepushte Version von Gitosis erhält, führt es einen sogenannten Hook aus. Dieser Hook ist ein Skript (bzw. ein Symlink dazu) welches die neue Konfiguration der Authentifizierungsstelle von Gitosis einließt. Der erste Fehler der (wirklich häufig) passiert ist, dass dieses Skript schlicht weg einfach nicht ausführbar ist. Das lässt sich natürlich sehr einfach durch

    chmod 755 /home/git/repositories/gitosis-admin.git/hooks/post-update

    lösen. Aber der knackende Punkt stellt (wie ich finde) die fehlende Meldung dieses Fehlers dar. Gitosis teilt einem einfach nicht mit, dass der Hook fehlschlug und die getätigten Änderungen komplett für die Katz waren.

    (2) Pub-Key-Format

    Ein weiteres undefiniertes Loch der Konfiguration ist das Format, in dem der PublicKeys im conf-File angegeben werden muss.

    Abgelegte Keys in gitosis-admin.git/keydir/ müssen mit .pub enden. Sonst werden diese nicht als Keys erkannt. Das ist das kleinere Übel. Die, für mich etwas unklare, Dokumentation darüber findet sich in den verschiedensten Varianten. Wie soll der PublicKey in der gitosis.conf hinterlegt werden?

    “Wer wird Millionär”-mäßig kann ich jetzt nach dem Trial-and-Error-Verfahren auflösen. Die endlosen Variationen von Filenamen und Config-Aufruf, die ich testen musste, damit ich mich anmelden durfte, haben sich also gelohnt.

    ( ) Name des Key-Files user@host.pub ( ) Im File hinterlegtes Suffix user@host
    (X) FQDN user@host.domain.com ( ) Nur User zB. jdoe wie dokumentiert

    (3) Gitosis, sprich mit mir.

    Ein weniger behütetes Geheimnis, ist die Gesprächigkeit von Gitosis. Im Konfigurationsfile lässt sich das LogLevel deklarieren.
    [gitosis]
    loglevel = DEBUG
    gitweb = no
    git-daemon = no

    Siehe da, Informationen!

    DEBUG:gitosis.serve.main:Got command "git-receive-pack 'repo1'"
    DEBUG:gitosis.access.haveAccess:Access check for 'user@domain.com' as 'writable' on 'repo1'...
    DEBUG:gitosis.group.getMembership:found 'user@domain.com' in 'domain.com'
    DEBUG:gitosis.access.haveAccess:Access ok for 'user@domain.com' as 'writable' on 'repo1'
    DEBUG:gitosis.access.haveAccess:Using prefix 'repositories' for 'repo1'
    Initialized empty Git repository in /home/git/repositories/repo1.git/
    DEBUG:gitosis.gitdaemon:Global default is 'deny'
    DEBUG:gitosis.gitdaemon:Walking '.', seeing ['repo1', 'repo2', 'repo3', 'gitosis-admin.git']
    DEBUG:gitosis.gitdaemon:Deny 'gitosis-admin'
    DEBUG:gitosis.gitdaemon:Walking 'repo1', seeing ['justatest.git']
    DEBUG:gitosis.gitdaemon:Deny 'repo1/justatest'
    DEBUG:gitosis.serve.main:Serving git-receive-pack 'repositories/repo1.git'

    Diese Infos werden nun zu fast jeder Gelegenheit ausgegeben. Pushen lokal, Authentifizieren per Remote usw. Für weitere Administration mit Gitosis unabdingbar.

    (4) Subdirectories handhaben

    Angenommen ich habe oder möchte eine Ordnerstruktur meiner Projekte die nicht alle in repositories/ liegen. Dieser kleine total untriviale Umstand, lässt sich einfach nirgends nachlesen. Um das Ganze zu verdeutlichen, habe ich kurz eine kleine Umgebung angelegt und mit tree -L 2 ausgegeben:

    `-- repositories
        |-- subdir1
        |   |-- repo1.git
        |   |-- repo2.git
        |   `-- repo3.git
        |-- subdir2
        |   `-- test.git
        `-- subdir3

    Angelege und initalisierte Repos werden zwar in der DEBUG-Ausgabe von Gitosis wargenommen (siehe 3.), aber einfach übergangen. Stattdessen wird ein neues Repo in repositories/ angelegt. Zumindest, wenn man der Konfiguration folgt, wie sie in 95% der Fällen im Netz zu finden ist. Als Faustregel für Unterordner gilt also: Zwingend jeden(!) Pfad mit Angabe des Subdirs angeben.
    Remote add:
    git remote add origin git@gitserver.org:subdir1/repo2.git
    gitosis.conf:
    [group subrepo]
    members = user@host.com
    writable = subdir1/repo2.git

    Es klingt logisch. Aber ohne Dokumentation, ist es hart herauszubekommen.

    Letztlich möchte ich kurz noch erwähnen, dass dieser Post keinerlei Vorwurf, Flame oder Sh!t-Storm gegen Gitosis darstellen soll. Gitosis ist ein wunderbarer Ansatz einer Benutzerverwaltung für Git-Remotes. Allerdings abenteuerlich bei nicht alltäglicher Nutzung. In diesem Sinne. Happy committing.


  4. Permalink
  5. Git | Repositories auf Server anlegen

    git-logoIch bin ja zukunftsorientiert. Mir wurde einbläut zukunftsorientierte Software zu verwenden und sich nicht mit Relikten alter Generationen rumzuprügeln. Nachdem die letzten Wochen mit SVN etwas holprig waren, mir allerdings halfen das prinzipielle System einer Versionsverwaltung zu verstehen, tat ich mir Git an. Git. Der Name ist ja erstmal unterirdisch wenn mans so auf sich wirken lässt. Ganz im Gegensatz zum Banner der Projekt-Homepage www.git-scm.com, welches ich sehr nett finde. Aber Schluss mit EyeCandy.

    Erstellte gezwungenermaßen freiwillig mit ein paar (Obacht, zwei Links in einem Wort) How-To’s ein Git-Repository auf zwetschge.org. Mithilfe der How-Tos, Gitosis, git-daemon-run und git-core war das relativ schnell geschafft. Allerdings kann ich mir beim besten Willen nicht merken wie ich ein Repository für ein neues Projekt erstelle. An der Stelle setzt der Blogpost an.
    Serverside:
    $ mkdir /home/git/repositories/project.git #Simpler Ordner
    $ cd /home/git/repositories/project.git #Selbsterklärend
    $ git --bare init #ServerGitRepo bauen

    Clientside:
    $ cd /home/Code/OrdermitProjekt
    $ git init #Projekt einlesen
    $ git add . #Alle Inhalte adden
    $ git commit -a -m "Inital commit of Software XY" #LokalCommit
    $ git remote add origin git@server.com:project.git #RepoServer in .git hinterlegen
    $ git push origin master #Push zum Server

    #Bei Verwendung von Gitosis - zuerst:
    Gitosis:
    $ gitosis-init < /tmp/pubkeyofmember.pub
    $ vim gitosis.conf
    [group Projectteam]
    members = user@host #Letzen Inhalte von Public-SSHKey
    writable = project #Projektname abgleitet von project.git
    $ git commit -a -m "Gitosis update for new Project" #LokalCommit für Rechte
    $ git push #Auf RepoServer pushen