Gitlab in Docker mit SSH Standardport

Im Docker basierten Setup von Gitlab wird ein SSH Daemon mitgeliefert, der im Normalfall aber auf einem anderen Port laufen muss wie der native SSH-Daemon vom Betriebssystem. Möchte man den SSH Daemon von Gitlab öffentlich betreiben und hat nur eine öffentliche IP-Adresse zur Verfügung gibt es verschiedene Möglichkeiten (die letzte wird hier beschrieben):

  • Gitlab-SSH auf anderem Port als den des Betriebssystem lauschen lassen
  • System-SSH auf anderen Port binden um 22 für Gitlab frei zu räumen
  • System-SSH mit Gitlab-SSH verknüpfen (wird hier beschrieben)

Erklärung

Gitlab stellt für den eigenen SSH-Daemon ein Script bereit, das alle registrierten SSH-Keys zurückmeldet. Diese werden vom SSH-Daemon genutzt um zu prüfen, ob ein zu verbindener Klient generell zugelassen werden kann. Dieses vorgehen ist generell beim OpenSSH-Server möglich, nur weiß der des Betriebssystems nichts von Dingen die im Docker Container passieren. Der nötige Befehl wird mittels Wrapper-Script und docker exec zur Verfügung gestellt, damit der Betriebssystem-SSH-Daemon die Keys abfragen kann. Der Gitlab-Befehl erhält alle nötigen Informationen über die SSH Verbindung um diese für weitere Verarbeitungen heranziehen zu können.

Script und Konfiguration

SSH-Daemon Konfiguration

Zunächst benötigen wir einen System-Benutzer git der im Regelfall in der Distribution bereits angelegt ist. Der Pfad zum Script kann angepasst werden, falls man docker-volumes nutzt und das Script lieber wo anders liegen haben möchte (z.B. /usr/local/bin/). Im SSH-Daemon wird folgendes konfiguriert:

# File: /etc/ssh/sshd_config

Match User git
    AuthorizedKeysCommand /srv/docker/containers/gitlab/scripts/gitlab_authorized_keys
    # muss root sein, weil das gitlab_authorized_keys root:root gehoert!
    AuthorizedKeysCommandUser root
Neustart

Es bietet sich an die bestehende Verbindung nicht zu trennen, bevor nach dem Restart ein erfolgreicher Verbindungsaufbau durchgeführt wurde! Falsche Konfigurationen in der sshd_config können zum Aussperren führen…

systemctl restart sshd.service
Gitlab Authorized-Keys

Dieses Script wird vom SSH-Daemon initial abgerufen um die Keys zu lesen. Es ist wichtig, dass der Pfad angepasst wird, je nachdem wo euer Gitlab seine Daten speichert. Dies kann z.B. auch ein Docker Volume sein (/var/lib/docker/volumes/ghitlab/data/.ssh/authorized_keys).

Das verwendete Script enthält folgendes:

# File /srv/docker/containers/gitlab/scripts/gitlab_authorized_keys

#!/bin/bash

# docker exec -u git gitlab cat /var/opt/gitlab/.ssh/authorized_keys
f="/srv/docker/containers/gitlab/data/.ssh/authorized_keys"

if [[ -f "${f}" ]];then
        cat /srv/docker/containers/gitlab/data/.ssh/authorized_keys
fi

In dem authorized_keys File von Gitlab stehen alle gültigen SSH Keys, allerdings wird beim Verbinden das Ausführen eines Scripts erzwungen (siehe command=…):

# File: /srv/docker/containers/gitlab/data/.ssh/authorized_keys

command="/opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell key-1",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3Nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==
Gitlab-Shell Wrapper-Script

Somit wird unser SSH-Daemon dieses Script ausführen wollen. Deshalb legen wir unser Wrapper-Script an den gewünschten Ort (/opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell):

# File: /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell

#!/bin/bash
docker exec -u git -i -e SSH_CONNECTION="$SSH_CONNECTION" -e SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" gitlab /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell $*

Wichtig sind noch die Berechtigungen. Diese sollten noch korrigiert werden um sicherzustellen, dass nur git das Skript ausführen kann.

chown git:git /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell
chmod 0750 /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell

Außerdem muss der git-Benutzer noch in die Gruppe docker, damit er auf den Docker-Socket zugreifen kann (docker exec …):

usermod -a -G docker git

Test der Funktion

Mit funktionierendem Agent / SSH-Key:

git clone git@my.gitlab.server.com:repo/something.git

Sollte etwas nicht funktionieren kann im Journal nachgesehen werden:

journalctl -u sshd.service -f

https://docs.gitlab.com/ce/install/docker.html