Die vielfältigen Fähigkeiten von Git, Teil 2

Mehrere Credentials im Zugriff

Innerhalb der CI/CD-Umgebung braucht die Pumpe zwei Credentials, um auf beide Repositorys zuzugreifen. Ein gängiger Weg ist, Credentials in CI/CD-Umgebungen mit Umgebungsvariablen zur Verfügung zu stellen. Wie kann man das praktisch organisieren? Das kommt ganz auf den Zugriff an und es gibt verschiedene Möglichkeiten. Die üblichen Kandidaten sind SSH und HTTPS.

SSH Credentials

Auf ein entferntes (remote) Repository user@host.example.org (oft git@host.example.org) wird mit SSH zugegriffen. Damit der Zugriff funktioniert, sind normalerweise zwei Bedingungen zu erfüllen:

  • Der SSH-Hostkey des Servers ist lokal bekannt.
  • Der SSH-Key des lokalen Users ist auf dem Server eingetragen und mit den jeweiligen Berechtigungen versehen.

Um die erste Bedingung zu erfüllen, fängt man den Hostkey einmalig manuell mit folgender Zeile auf:

ssh -o UserKnownHostsFile=known_hosts user@host.example.org

Hat der eigene Rechner mit diesem Host schon kommuniziert, überprüft die Zeile, ob der aufgefangene Host-Key in der neuen Datei known_hosts im derzeitigen Verzeichnis mit dem in der zentralen $HOME/.ssh/known_hosts übereinstimmt. Dazu vergleicht man den Output:

ssh-keygen -F host.example.org -l -f $HOME/.ssh/known_hosts
ssh-keygen -F host.example.org -l -f known_hosts
Damit erhält man den öffentlichen Host-Key in der Datei known_hosts im derzeitigen Verzeichnis. An der Datei ist nichts Geheimes. Sie kann beispielsweise in ein Git-Repository eingecheckt oder in ein Docker-Image kopiert werden. Um sie zu nutzen, kopiert man sie ins Verzeichnis $HOME/.ssh des betreffenden Benutzers, der in der CI/CD-Umgebung die Pumpe ausführt.

Will man auf mehrere Server via SSH zugreifen, ist ein Kopieren der Angaben hintereinander in eine gemeinsame known_host notwendig.

Das eigentliche Credential für die Pumpe ist der private SSH-Schlüssel. Den erzeugt man zum Beispiel mit

ssh-keygen -N '' -f id_rsa

Der Befehl erzeugt zwei Dateien, id_rsa.pub und id_rsa. Die erste ist der öffentliche Schlüssel, den kopiert man einmalig in die UI des Git-Servers. Die Datei braucht weder Schutz noch Geheimhaltung. Die Pumpe selbst benötigt diese Datei übrigens nicht.

Der Inhalt von id_rsa ist dagegen zu schützen. Wer den Inhalt kennt, der kann auf die entsprechenden Repos auf dem Git-Server zugreifen (also genau das, was die Pumpe tun soll). Den Inhalt konfiguriert man in die UI des CI/CD-Umgebung als "Geheimnis", das während eines Laufes der Pumpe als Umgebungsvariable zur Verfügung steht, zum Beispiel GIT_PRIVATE_KEY.

Damit die Pumpe den Key nutzen kann, läuft am Anfang des Jobs:

mkdir -p "$HOME/.ssh"
touch "$HOME/.ssh/id_rsa"
chmod go-rwx "$HOME/.ssh" "$HOME/.ssh/id_rsa"
echo "$GIT_PRIVATE_KEY" > "$HOME/.ssh/id_rsa"

Die Datei known_hosts gehört ins selbe Verzeichnis $HOME/.ssh.

HTTPS Credentials

Beim Zugriff auf ein Git-Repository via HTTPS kommt man mit klassischen User- und Passwort-Angaben weiter. Die stellt ein Skript zur Verfügung, das auf den Aufruf mit dem Parameter get wartet und dann zwei Zeilen Output erzeugt: eine mit der User-Angabe, eine für das Passwort. Das Skript kann so aussehen:

#!/bin/bash

if test "$1" = get
then
echo username="${GIT_USER}"
echo password="${GIT_PASSWD}"
fi

Die nötigen Angaben konfiguriert man in der jeweiligen CI/CD-Umgebung als Geheimnisse, die in den Umgebungsvariablen GIT_USER und GIT_PASSWD zur Verfügung stehen.

Das Skript stellt man für die Pumpe zur Verfügung, im Beispiel eines Docker-Container möglicherweise als /usr/local/bin/gitcreds. Es wird für Zugriffe auf einen Git-Server https://git.example.org durch folgenden Befehl aktiviert:

git config --global credential.https://git.example.org.helper /usr/local/bin/gitcreds

Wenn man Credentials für mehrere Server braucht, arbeitet man möglicherweise mit mehreren Instanzen wie gitcreds1 und gitcreds2. Alternativ genügt ein einzelnes Skript. Indem es STDIN auswertet, kann es erfahren, welche Credentials gerade notwendig sind. Einzelheiten hierzu finden sich in der Git-Dokumentation. Der passende Einstieg ist die Beschreibung von "Credential Helpers" in API-Credentials.