Maskering af hemmeligheder i Ansible

Ansible-playbooks har ofte brug for adgangskoder og API-tokens til at oprette forbindelse til servere og udrulle applikationer. Disse værdier kan også forekomme i opgaveoutput, for eksempel når en kommando returnerer en fejl, der indeholder en adgangskode.

Ansible tilføjer nu maskering af hemmeligheder for at hjælpe med dette. Det erstatter kendte hemmelige værdier med $REDACTED$ i outputtet, mens resten af meddelelsen holdes læselig. Opgaver fortsætter med at bruge de originale værdier.

Funktionen blev tilføjet af Secret Masking API pull request, som blev merged den 10. september 2026. På skrivende tidspunkt er den tilgængelig i ansible-core 2.22 udviklingsbuilds. Den er endnu ikke en del af en stabil udgivelse.

Lad os se på en simpel playbook og derefter undersøge, hvordan vi planlægger at bruge denne funktion i Semaphore UI.

Først skal du registrere en hemmelighed

Ansible skal vide, hvilke værdier der skal maskeres. Det nye API registrerer værdier fra kendte hemmelighedskilder, såsom vaulted variabler og modulparametre markeret med no_log.

For en almindelig variabel kan vi bruge filteret register_secret. En variabel, der sendes via --extra-vars, skal også registreres; det er ikke nok blot at kalde den db_password.

I dette eksempel bruger vi en fiktiv databaseadgangskode. Opret en playbook ved navn 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 }}"

Den første opgave registrerer adgangskoden. Filteret returnerer den oprindelige værdi, så playbooken stadig kan bruge den til at oprette forbindelse til databasen. Registreringen skal ske, før nogen opgave udskriver værdien.

Kør din playbook med et ansible-core 2.22 udviklingsbuild:

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

Den anden opgave viser denne meddelelse:

Connecting to db.internal with password=$REDACTED$

Vi udskriver kun adgangskoden her for at demonstrere maskering. I en rigtig playbook bør du hente den fra din hemmelighedskilde og undgå bevidst at udskrive legitimationsoplysninger.

Integration med Semaphore UI

Semaphore UI ved allerede, hvilke variabler du har markeret som hemmelige. Vi planlægger at bruge disse oplysninger i fremtidige versioner til automatisk at registrere disse værdier hos Ansible.

Til dette vil vi bruge Ansibles indstilling _SECRETS_INPUT_FILES. Den konfigureres via miljøvariablen _ANSIBLE_SECRETS_INPUT_FILES og lader Ansible læse en liste over hemmeligheder, før en playbook starter.

Inputtet kan være YAML eller JSON. Et dokument med vores eksempeladgangskode ser således ud:

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

Denne liste fortæller Ansible, hvad der skal maskeres. Selve variablerne sendes stadig til playbooken separat.

Den planlagte integration vil dække hemmelige værdier fra:

  • Variabelgrupper (Variable Groups) — hemmeligheder gemt til brug for dine opgaver.
  • Undersøgelser (Surveys) — hemmelige svar indtastet ved start af en opgave.

For disse værdier behøver du ikke at tilføje en register_secret-opgave til hver playbook.

Planlagt Semaphore UI-integration: hemmeligheden sendes til playbooken og registreres separat via _SECRETS_INPUT_FILES. Opgaver bruger den reelle værdi, mens Ansible maskerer den som $REDACTED$ i opgaveloggen.

Vi testede denne tilgang på et ansible-core 2.22 udviklingsbuild. Registrerede værdier blev maskeret i debug-meddelelser, kommandoresultater, fejlmeddelelser, verbose output og Ansibles logfil. Overførsel af listen via en pipe fungerede også uden at skrive en separat hemmelighedsfil til disken.

Indstillingen er i øjeblikket intern og kan ændre sig. Semaphore UI-understøttelse er planlagt til en fremtidig udgivelse og vil kræve en kompatibel Ansible-version.

Eksempel: udrulning af en applikation

Antag, at vi har en opgaveskabelon, der udruller en applikation. Udrulningsscriptet bruger et API-token gemt som en hemmelighed i en variabelgruppe.

Med den planlagte integration vil opgaven fungere som følger:

  1. Semaphore UI sender tokenet til playbooken.
  2. Den leverer også tokenet til Ansibles maskeringsliste via _SECRETS_INPUT_FILES før udførelse.
  3. Playbooken kører udrulningsscriptet med det rigtige token.
  4. Hvis scriptet inkluderer dette token i sit output, maskerer Ansible det i det viste resultat.

For eksempel kan et udløbet token producere denne meddelelse i opgaveloggen:

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

Vi kan se, hvilken udrulning der fejlede og hvorfor, uden at vise tokenet til alle, der læser loggen. Det samme flow vil gælde for et midlertidigt token indtastet via et hemmeligt Survey-felt.

Begrænsninger

Maskering fungerer med registrerede værdier. Udviklingsimplementeringen springer hemmeligheder over, der er kortere end fire tegn, og en kodet eller på anden måde transformeret værdi kan have brug for separat registrering.

Det beskytter heller ikke legitimationsoplysninger i procesargumenter, filer skrevet af en playbook eller logs produceret uden for Ansible. Bliv ved med at bruge no_log: true til opgaver, hvis samlede output skal forblive privat.

Med denne integration vil hemmeligheder markeret i Semaphore UI også være kendt af Ansibles maskeringssystem. Dette vil hjælpe med at holde legitimationsoplysninger ude af opgavelogs, mens der bevares nyttige oplysninger til fejlfinding.