macOS BuildCaptain heftet deine Jenkins-Pipelines an die macOS-Menüleiste – Status, Logs und Build-Steuerung nur einen Klick entfernt.

Jenkins-API-Tokens: erstellen, eingrenzen, rotieren, widerrufen

Wie sich Jenkins-API-Tokens von Passwörtern unterscheiden, wie du eines erstellst, was sich eingrenzen lässt – und was nicht – und wie du Tokens speicherst und rotierst, ohne deinen CI-Server preiszugeben.

Loris Siegenthaler Geschrieben von Loris Siegenthaler · Macher von BuildCaptain
9 Min. Lesezeit
Aktualisiert am 7. August 2026

Ein API-Token ist das Credential, das du allem in die Hand gibst, was kein Mensch vor einem Browser ist: einem Skript, einer Deployment-Pipeline, einem Monitoring-Tool, einem Desktop-Client. Jenkins macht das Erstellen leicht – und deshalb landen so viele davon in einem Shell-Skript in einem Repository und sind drei Jahre später immer noch gültig.

Dieser Guide begleitet den kompletten Lebenszyklus – was ein Token wirklich ist, wie du eines erstellst, die Scoping-Einschränkung, vor der dich niemand warnt, und wie du rotierst und widerrufst, ohne etwas kaputtzumachen.

Tokens versus Passwörter

Beide funktionieren für HTTP-Basic-Authentifizierung gegen Jenkins – auf der Leitung sehen sie also identisch aus. Der Unterschied steckt in allem drumherum.

  • Tokens sind einzeln widerrufbar. Ein Token pro Abnehmer heißt: Du kannst das geleakte killen, ohne das Passwort zu ändern, das alle anderen Abnehmer verwenden.
  • Tokens überleben SSO. Authentifiziert sich dein Jenkins gegen SAML, OIDC, LDAP oder GitHub OAuth, gibt es oft gar kein Passwort, das du senden könntest – das Token ist das einzige Credential, das für nicht-interaktiven Zugriff funktioniert.
  • Tokens umgehen den CSRF-Crumb. Jenkins schützt zustandsändernde Anfragen mit einem Crumb (seinem CSRF-Token), und die Dokumentation sagt ausdrücklich, dass Anfragen, die sich mit einem API-Token authentifizieren, davon ausgenommen sind. Deshalb funktioniert curl -X POST mit einem Token einfach, während dieselbe Anfrage mit einem Session-Cookie ein 403 „No valid crumb was included“ bekommt, sofern du nicht vorher einen Crumb von /crumbIssuer/api/json holst. Genau aus diesem Grund bevorzugt Jenkins’ eigene Remote-Access-Doku Tokens gegenüber Crumb-Jonglage.
  • Tokens sind nachvollziehbar. Jedes trägt den Namen, den du ihm gegeben hast, ein Erstellungsdatum und einen Nutzungszähler – du siehst also, welche tatsächlich benutzt werden und welche für ein Skript geprägt wurden, das es längst nicht mehr gibt.

Was Tokens nicht sind: ein Credential mit weniger Rechten. Siehe den Scoping-Abschnitt unten – das ist die Stelle, an der die meisten stolpern.

Ein Token erstellen

Klicke oben rechts auf deinen Namen, dann in der Seitenleiste auf Security (ältere Versionen nennen die Seite Configure). /me/security ist die Abkürzung auf jedem Jenkins. Wähle unter API Token den Punkt Add new token, gib ihm einen Namen, der sagt, wer es benutzt – deploy-script, grafana, buildcaptain-laptop, nicht token1 – und klicke auf Generate.

Kopiere den Wert jetzt. Jenkins sagt es selbst: „Kopiere dieses Token jetzt, denn es kann später nicht wiederhergestellt werden.“ Gespeichert wird nur ein Hash.

Administratoren können dasselbe für einen Service-Account tun, dessen Passwort sie gar nicht haben – unter /user/<username>/security (über Manage Jenkins → Security → Users). So provisionierst du einen Bot-Account, ohne dich je als er anzumelden.

Jenkins hat das alte einzelne Token pro Benutzer in Weekly 2.129 / LTS 2.138.1 durch mehrere benannte, widerrufbare Tokens ersetzt. Auf Instanzen, die von davor aktualisiert wurden, kann auf einem Account noch ein einsehbares Legacy-Token existieren, markiert mit einer Warnung auf der Security-Seite des Benutzers. Ziehe alles, was es nutzt, auf ein benanntes Token um und widerrufe es dann – einmal widerrufen lässt es sich nicht neu erzeugen, und genau das ist der Sinn. Administratoren können Legacy-Tokens auch instanzweit deaktivieren; auf aktualisierten Instanzen steht diese Einstellung standardmäßig auf „weiterhin erlaubt“.

Tokens lassen sich auch ohne UI erstellen – genau das wollen Provisionierungs-Skripte:

curl -X POST -u "alice:$JENKINS_ADMIN_TOKEN" \
  "https://jenkins.example.com/user/jenkins-bot/descriptorByName/jenkins.security.ApiTokenProperty/generateNewToken" \
  --data "newTokenName=deploy-script"

Der Endpunkt akzeptiert nur POST. Die Antwort ist JSON mit einem data-Objekt, das tokenName, tokenUuid und tokenValue enthält. Behalte die UUID – sie ist das, was der passende Widerrufs-Aufruf entgegennimmt:

curl -X POST -u "alice:$JENKINS_ADMIN_TOKEN" \
  "https://jenkins.example.com/user/jenkins-bot/descriptorByName/jenkins.security.ApiTokenProperty/revoke" \
  --data "tokenUuid=$TOKEN_UUID"

Nutze /me/… statt /user/<id>/… für deinen eigenen Account. So oder so musst du dieser Benutzer sein – oder Jenkins-Administrator.

Ein Token verwenden

Alles in Jenkins hat eine JSON-Repräsentation – hänge /api/json an fast jede URL, die du im Browser öffnen kannst.

# Who am I, and what can I see?
curl -u "jenkins-bot:$JENKINS_TOKEN" \
  "https://jenkins.example.com/api/json?pretty=true"

# The last five builds of one job, only the fields you need
curl -u "jenkins-bot:$JENKINS_TOKEN" \
  "https://jenkins.example.com/job/my-app/api/json?tree=builds[number,result,timestamp]{0,5}"

# The console log of a specific build
curl -u "jenkins-bot:$JENKINS_TOKEN" \
  "https://jenkins.example.com/job/my-app/42/consoleText"

Den tree-Parameter lernst du am besten früh. Ohne ihn liefert /api/json auf einem viel benutzten Job eine Payload in Megabyte-Größe; mit ihm bekommst du die vier Felder, nach denen du gefragt hast.

Builds auszulösen sollte ein POST sein. Jenkins-Core akzeptiert auf beiden Build-Endpunkten faktisch auch GET, aber POST ist das, was die Dokumentation verwendet und was jeder Proxy, jedes Log und jeder Reviewer von einem zustandsändernden Aufruf erwartet – und ein bloßes GET auf /build eines parametrisierten Jobs rendert das Parameter-Formular, statt irgendetwas zu starten. Das kostet dich fünf ratlose Minuten.

# A job with no parameters
curl -X POST -u "jenkins-bot:$JENKINS_TOKEN" \
  "https://jenkins.example.com/job/my-app/build"

# A parameterised job
curl -X POST -u "jenkins-bot:$JENKINS_TOKEN" \
  "https://jenkins.example.com/job/my-app/buildWithParameters" \
  --data-urlencode "BRANCH=release/2.4" \
  --data-urlencode "DEPLOY=false"

Ein erfolgreicher Trigger liefert 201 Created mit einem Location-Header, der auf das Queue-Item zeigt – nicht auf einen Build. Die Build-Nummer existiert noch nicht; der Build muss die Queue erst verlassen. Polle das /api/json des Queue-Items, bis ein executable-Objekt auftaucht, und lies die Nummer dort ab.

Eine Anmerkung zur Shell-Hygiene: -u user:token legt das Token in die Prozessliste, wo jeder andere Benutzer der Maschine es lesen kann. Nutze auf einem geteilten Host curl --netrc-file mit einer 0600-Datei oder pipe das Credential hinein, statt es in die Kommandozeile zu interpolieren.

Scoping: der Teil, der überrascht

Ein Jenkins-API-Token hat keinen Scope. Es ist kein eingegrenztes Credential mit angehängter Berechtigungsliste, wie es ein feingranulares GitHub-Token ist. Es authentifiziert sich als du – und trägt deshalb jede Berechtigung, die dein Account hat.

Bist du Jenkins-Administrator und fügst ein Token in ein Shell-Skript ein, kann dieses Skript jetzt Jobs umkonfigurieren, Plugins installieren und beliebiges Groovy auf dem Controller ausführen. Dass du eigentlich nur einen Build-Status lesen wolltest, spielt keine Rolle.

Da es kein Scoping pro Token gibt, grenze stattdessen den Benutzer ein. Lege pro Abnehmer einen eigenen Service-Account an und gib ihm das Minimum:

  • Read-only-MonitoringOverall/Read, Job/Read und View/Read. Genug, um Jobs zu listen, Build-Ergebnisse zu lesen und Konsolen-Logs zu holen.
  • Builds auslösen – ergänze Job/Build, und Job/Cancel, wenn das Tool Läufe stoppen können muss.
  • NiemalsOverall/Administer, Job/Configure oder Run/Replay auf einem Service-Account. Gerade Run/Replay bedeutet die Ausführung beliebigen Pipeline-Codes.

Praktisch machen das zwei Plugins: Matrix Authorization Strategy (matrix-auth – ein Raster aus Benutzern gegen Berechtigungen, optional pro Ordner oder pro Job) und Role-based Authorization Strategy (role-strategy – benannte Rollen, angewendet auf Benutzer und auf Job-Namensmuster). Matrix ist einfacher und reicht bis zu ein paar Dutzend Accounts; die Rollenstrategie skaliert besser, sobald es echte Teams gibt. Das Ziel ist in beiden Fällen dasselbe: Der Schadensradius eines geleakten Tokens ist das, was dieser eine Service-Account tun konnte.

Ordnerbezogene Berechtigungen sind hier der unterschätzte Trick. Gib dem Service-Account Job/Read nur auf dem Ordner platform/, und ein geleaktes Token kann nicht einmal den Rest deiner Jobs aufzählen.

Rotation und Widerruf

Jenkins-Tokens laufen nicht ab. Von selbst erinnert dich nichts daran – also leg einen Zeitplan fest: quartalsweise als vernünftiger Standard, sofort bei jedem Verdacht und immer, wenn jemand das Team verlässt.

Benannte Tokens machen die Rotation zur Formsache, sofern du diese Reihenfolge einhältst:

  1. Erstelle ein neues Token auf demselben Account, benannt nach demselben Abnehmer plus Datum: deploy-script-2026-08.
  2. Rolle es an den Abnehmer aus und bestätige, dass es funktioniert.
  3. Widerrufe das alte Token unter Security → API Token.

Widerrufe niemals zuerst. Genau für dieses Überlappungsfenster gibt es mehrere benannte Tokens.

Der Nutzungszähler neben jedem Token verrät dir, ob eine Rotation wirklich gegriffen hat: Ist das neue Token einen Tag im Einsatz, sollte der Zähler des alten stehen geblieben sein. Er ist auch der schnellste Weg, tote Tokens zu finden – alles ohne kürzliche Nutzung ist entweder ein Skript, das niemand mehr ausführt, oder ein Credential, das jemand kopiert und vergessen hat, und beides gehört widerrufen.

Ist ein Token geleakt, widerrufst du zuerst – alles andere kommt danach. Prüfe dann Manage Jenkins → System Log und das Access-Log deines Reverse-Proxys darauf, was dieser Account getan hat, und rotiere auch die übrigen Tokens des Accounts – ein Leak von einem geteilten Laptop oder aus einem öffentlichen Repository betrifft selten genau ein Geheimnis.

Ein Administrator kann die Tokens eines anderen Benutzers über dessen Konfigurationsseite widerrufen – genau das willst du an dem Tag, an dem jemand geht. Den Account selbst zu löschen oder zu deaktivieren macht alle seine Tokens auf einmal ungültig.

Wo das Token hingehört

Die Regeln, kürzeste Fassung:

  • Nicht in ein Repository. Nicht in ein Skript, nicht in eine .env, nicht in eine YAML-Datei, nicht in einen Kommentar. Git vergisst nicht; die History nachträglich umzuschreiben ist ein Krampf – und trotzdem nur ein halber Fix.
  • Nicht in CI-Logs. Gib ein Token niemals per echo aus, und sei vorsichtig mit set -x in einem Shell-Step – es druckt bereitwillig das ganze curl-Kommando.
  • Nicht in eine geteilte Passwort-Notiz. Ein Token pro Abnehmer – darauf beruht der ganze Mechanismus; ein Token für vier Tools hebelt ihn aus.

Auf macOS ist der richtige Speicher der Keychain – und er ist skriptbar:

# Store it once (the -w flag prompts, so it never lands in your shell history)
security add-generic-password -a jenkins-bot -s jenkins-api-token -w

# Read it back when you need it
JENKINS_TOKEN=$(security find-generic-password -a jenkins-bot -s jenkins-api-token -w)

Innerhalb von Jenkins selbst gehört ein Token als „Username with password“-Credential in den Credentials-Store und kommt über withCredentials wieder heraus, was es im Build-Log maskiert:

withCredentials([usernamePassword(
    credentialsId: 'jenkins-bot-api',
    usernameVariable: 'JENKINS_USER',
    passwordVariable: 'JENKINS_TOKEN'
)]) {
    sh 'curl -sS -u "$JENKINS_USER:$JENKINS_TOKEN" "$JENKINS_URL/api/json"'
}

Beachte die einfachen Anführungszeichen um das sh-Skript. Mit doppelten interpoliert Groovy das Geheimnis in den Kommando-String, bevor Jenkins ihn je sieht – die Maskierung greift nicht, und dein Token steht im Klartext im Konsolen-Log.

Eine kurze Checkliste

  • Ein benanntes Token pro Abnehmer, benannt nach dem Abnehmer.
  • Service-Accounts statt deines eigenen Accounts für alles Automatisierte.
  • Minimale Berechtigungen über Matrix oder Role Strategy – wo möglich auf Ordner begrenzt.
  • Gespeichert in einem echten Secret-Store: Keychain, dem Jenkins-Credentials-Store oder deinem Secrets-Manager.
  • Rotiert nach Kalender, neu vor alt.
  • Widerrufen in dem Moment, in dem ein Abnehmer ausgemustert wird oder ein Laptop verschwindet.

Wenn du unsere eigene App verbindest: Die Kurzfassung von all dem steht im Help Center – Jenkins-Server verbinden führt durch das Erstellen und Eintragen des Tokens. Und um das Offensichtliche beim Namen zu nennen: BuildCaptain ist unsere App, ein nativer macOS-Menüleisten-Client für Jenkins. Sie hält sich an ihren eigenen Rat – das Token wandert in den macOS Keychain, nie in eine Config-Datei, und ein Read-only-Service-Account mit Job/Read reicht, um deine Pipelines zu beobachten.