Secrets in Ansible maskieren

Ansible-Playbooks benötigen häufig Passwörter und API-Tokens, um sich mit Servern zu verbinden und Anwendungen bereitzustellen. Diese Werte können auch in der Aufgabenausgabe auftauchen, etwa wenn ein Befehl einen Fehler zurückgibt, der ein Passwort enthält.

Ansible führt dafür die Maskierung von Secrets ein. Bekannte geheime Werte werden in der Ausgabe durch $REDACTED$ ersetzt, während der Rest der Meldung lesbar bleibt. Die Aufgaben verwenden weiterhin die ursprünglichen Werte.

Die Funktion wurde mit dem Pull Request für die Secret Masking API hinzugefügt, der am 10. September 2026 zusammengeführt wurde. Zum Zeitpunkt dieses Beitrags ist sie in Entwicklungsbuilds von ansible-core 2.22 verfügbar. Sie ist noch nicht Teil einer stabilen Version.

Sehen wir uns ein einfaches Playbook an und anschließend, wie wir diese Funktion in Semaphore UI einsetzen wollen.

Zuerst ein Secret registrieren

Ansible muss wissen, welche Werte maskiert werden sollen. Die neue API registriert Werte aus bekannten Secret-Quellen, etwa mit Vault verschlüsselte Variablen und mit no_log markierte Modulparameter.

Für eine gewöhnliche Variable können wir den Filter register_secret verwenden. Auch eine über --extra-vars übergebene Variable muss registriert werden. Der Name db_password allein reicht nicht aus.

Für dieses Beispiel verwenden wir ein fiktives Datenbankpasswort. Erstelle ein Playbook namens masking.yml:

- name: Try secret masking
  hosts: localhost
  gather_facts: false
  vars:
    db_password: "example-db-password-123456"

  tasks:
    - name: Register the password before using it
      ansible.builtin.set_fact:
        db_password: "{{ db_password | ansible.builtin.register_secret }}"

    - name: Show a message containing the password
      ansible.builtin.debug:
        msg: "Connecting to db.internal with password={{ db_password }}"

Die erste Aufgabe registriert das Passwort. Der Filter gibt den ursprünglichen Wert zurück, sodass das Playbook ihn weiterhin für die Verbindung zur Datenbank nutzen kann. Die Registrierung muss stattfinden, bevor eine Aufgabe den Wert ausgibt.

Führe das Playbook mit einem Entwicklungsbuild von ansible-core 2.22 aus:

ansible-playbook -i localhost, -c local masking.yml

Die zweite Aufgabe zeigt diese Meldung an:

Connecting to db.internal with password=$REDACTED$

Wir geben das Passwort hier nur aus, um die Maskierung zu demonstrieren. Beziehe es in einem echten Playbook aus deiner Secret-Quelle und vermeide es, Zugangsdaten absichtlich auszugeben.

Integration mit Semaphore UI

Semaphore UI weiß bereits, welche Variablen du als geheim markiert hast. Wir planen, diese Information in künftigen Versionen zu nutzen, um die Werte automatisch bei Ansible zu registrieren.

Dafür werden wir Ansibles Option _SECRETS_INPUT_FILES verwenden. Sie wird über die Umgebungsvariable _ANSIBLE_SECRETS_INPUT_FILES konfiguriert und ermöglicht es Ansible, vor dem Start eines Playbooks eine Liste von Secrets einzulesen.

Die Eingabe kann als YAML oder JSON vorliegen. Ein Dokument mit unserem Beispielpasswort sieht so aus:

version: 1
secrets:
  - example-db-password-123456

Diese Liste teilt Ansible mit, was maskiert werden soll. Die Variablen selbst werden dem Playbook weiterhin separat übergeben.

Die geplante Integration wird geheime Werte aus folgenden Quellen abdecken:

  • Variablengruppen (Variable Groups) — Secrets, die zur Verwendung in deinen Aufgaben gespeichert sind.
  • Abfragen (Surveys) — geheime Antworten, die beim Start einer Aufgabe eingegeben werden.

Für diese Werte müsstest du nicht jedem Playbook eine Aufgabe mit register_secret hinzufügen.

Geplante Integration in Semaphore UI: Das Secret wird dem Playbook übergeben und separat über _SECRETS_INPUT_FILES registriert. Aufgaben verwenden den echten Wert, während Ansible ihn im Aufgabenprotokoll durch $REDACTED$ ersetzt.

Wir haben diesen Ansatz mit einem Entwicklungsbuild von ansible-core 2.22 getestet. Registrierte Werte wurden in debug-Meldungen, Befehlsergebnissen, Fehlermeldungen, ausführlichen Ausgaben und der Ansible-Protokolldatei maskiert. Auch die Übergabe der Liste über eine Pipe funktionierte, ohne eine separate Secret-Datei auf die Festplatte zu schreiben.

Die Option ist derzeit intern und kann sich ändern. Die Unterstützung in Semaphore UI ist für eine künftige Version geplant und wird eine kompatible Ansible-Version voraussetzen.

Beispiel: Eine Anwendung bereitstellen

Angenommen, wir haben eine Aufgabenvorlage (Task Template), die eine Anwendung bereitstellt. Das Deployment-Skript verwendet ein API-Token, das als Secret in einer Variablengruppe gespeichert ist.

Mit der geplanten Integration wird die Aufgabe wie folgt ablaufen:

  1. Semaphore UI übergibt das Token an das Playbook.
  2. Vor der Ausführung übergibt es das Token außerdem über _SECRETS_INPUT_FILES an Ansibles Maskierungsliste.
  3. Das Playbook führt das Deployment-Skript mit dem echten Token aus.
  4. Falls das Skript dieses Token in seine Ausgabe aufnimmt, maskiert Ansible es im angezeigten Ergebnis.

Ein abgelaufenes Token könnte beispielsweise diese Meldung im Aufgabenprotokoll erzeugen:

Deployment rejected: service=payments environment=staging token=$REDACTED$ reason=token expired

Wir sehen, welches Deployment fehlgeschlagen ist und warum, ohne das Token allen Lesern des Protokolls zu zeigen. Derselbe Ablauf wird für ein temporäres Token gelten, das über ein geheimes Survey-Feld eingegeben wurde.

Einschränkungen

Die Maskierung arbeitet mit registrierten Werten. Die Entwicklungsimplementierung überspringt Secrets mit weniger als vier Zeichen. Ein kodierter oder anderweitig umgewandelter Wert muss möglicherweise separat registriert werden.

Sie schützt auch keine Zugangsdaten in Prozessargumenten, in Dateien, die ein Playbook schreibt, oder in Protokollen außerhalb von Ansible. Verwende weiterhin no_log: true für Aufgaben, deren gesamte Ausgabe vertraulich bleiben soll.

Mit dieser Integration werden die in Semaphore UI markierten Secrets auch Ansibles Maskierungssystem bekannt sein. So lassen sich Zugangsdaten aus Aufgabenprotokollen fernhalten, während nützliche Informationen zur Fehlerdiagnose erhalten bleiben.