Zugangsdaten in Jenkins

Es ist keine gute Praxis, Zugangsdaten in Git-Repositories abzuspeichern. Es macht zugegeben aber einiges einfacher. Man brauch nicht mit zusätzlichem Aufwand die Zugangsdaten verteilen und bei jeder Änderung diese zu pflegen. Aber beim Speichern von Zugangsdaten in Git muss auch angenommen werden, dass die Zugangsdaten kompromittiert sind. Die Zugangsdaten können von allen, die Zugriff auf das Git haben, ausgelesen werden. Die einfachste Lösung ist, einfach keine Zugangsdaten in Git abzuspeichern und die Dateien mit Zugangsdaten mit der gitignore-Datei auszuschließen. Jeder Entwickler muss dann in seiner lokalen Entwicklungsumgebung selbstständig die Zugangsdaten pflegen.

Man kommt mit diesem Thema immer auch dann in Kontakt, wenn man mal DevOps für ein IT Projekt umsetzen muss. Es müssen im Rahmen dieser Arbeiten auch automatisierte Testfälle durchgeführt werden, die eventuell sogar an funktionsfähigen Testsystemen durchgeführt werden. Für manche Anwendungen müssen auch API Schlüssel mitgegeben werden, die ebenfalls geschützt werden müssen. In diesem Kontext benötigt es Lösungen. Oft bietet eine DevOps Lösung Datenstrukturen zum Speichern von Zugangsdaten. So etwas gibt es in Azure Devops. Dort lassen sich Zugangsdaten als Secret Variable speichern und nutzen. Ein ähnliches Konzept gibt es auch für Jenkins. In diesem Beitrag gehe ich auf ein paar Aspekte der Speicherung von Zugangsdaten („Credentials“) in Jenkins ein.

Speicherung

Das Speichern von Zugangsdaten erfolgt über die „Manage Credentials“ Anwendung. Es lassen sich Zugangsdaten verschiedener Art abspeichern. Die verschiedenen Arten, und wie sie gespeichert werden können auch hier nachgelesen werden.

Das Auslesen der bereits eingespeicherten Zugangsdaten ist ein weiteres Mal über die UI nicht möglich. Falls man Änderungen daran durchführen möchte, kann man diese nur überschreiben.

Auslesen

Der interessantere Teil ist, wie diese Zugangsdaten dann genutzt werden können. Das initialisieren der Zugangsdaten ist so einfach wie drei Zeilen Code in der Jenkinsfile hinzuzufügen:

environment {
    CREDENTIALS_TEST = credentials('jenkins-credentials-test')
}

Beim Definieren dieser Zeile werden drei neue Variablen angelegt.

$CREDENTIALS_TEST
$CREDENTIALS_TEST_USR
$CREDENTIALS_TEST_PSW

Diese Variablen können künftig genutzt werden. Hier ist ein Beispiel, wie das innerhalb eines NodeJS Scriptes genutzt werden kann.

Definition einer package.json

Nun stellt sich aber die Frage: Ist das wirklich so viel sicherer? Es gibt ja die Jenkins-Logs. Die Zugangsdaten werden dort sicherlich dargestellt. Wenn man das NodeJS Script nun in Jenkins ausführt bekommt man das folgende Ergebnis.

Tatsächlich erkennt Jenkins automatisch, wo auf diese Werte verwiesen wird, und zensiert diese Zeilen in den Jenkins Logs.

Fragen

Für mich ist an dieser Stelle interessant herauszufinden, wie das unter der Haube gespeichert wird. Kann man als Server-Admin oder Nutzer trotzdem irgendwie noch auf die Zugangsdaten zugreifen? Es muss ja schließlich irgendwie als Klartext gespeichert werden, damit es später auch genutzt werden kann. Tatsächlich hat sich da jemand die Mühe gemacht, und sich das näher angeschaut. Ich will das hier referenzieren und den wichtigsten Punkt kurz zitieren.

credentials.xml stores both Global and System credentials.

To directly access and decrypt that file you do NOT need admin privileges.

Der Credentials-Store wendet ein paar Sicherheitsmaßnahmen an, um die Zugangsdaten zu schützen. Es muss aber angenommen werden, dass alle Zugangsdaten im Klartext gespeichert werden. Um herauszufinden, ob das einfach oder schwer ist habe ich einfach kurz mal die Anleitung befolgt.

Das Passwort von meinem „testuser“ war „testpw“, was man im Result sieht. Es war ein Aufwand von zwei Minuten auf das Passwort zu schließen. Ich habe ein wenig erwartet, dass es technisch anspruchsvoller ist, das Passwort über das Webinterface darzustellen. Aber entgegen meiner Erwartungen geht das sehr einfach.

Fazit

7. Treat all credentials stored in Jenkins as plain text

Treat everyone with access to Jenkins as an admin user, and you will be fine. Once you give someone access, even read-only, to a Jenkins it’s game over. All developers on a project should know all secrets anyway.

https://www.codurance.com/publications/2019/05/30/accessing-and-dumping-jenkins-credentials

Dieses Zitat kann ich an dieser Stelle bestätigen. Man sollte annehmen, dass alle Passwörter in Jenkins von allen Benutzern ausgelesen werden können. Man kann Probleme vermeiden, indem man die Jenkins Instanz ausschließlich über ein VPN zugänglich macht und nur den Entwicklern die Berechtigung gibt, die auch auf die Zugangsdaten zugreifen können sollten.