Passwörter mit eYAML-GPG in Hiera speichern

simonhoenscheid

Simon Hönscheid

Posted on April 10, 2022

Passwörter mit eYAML-GPG in Hiera speichern

Manchmal ist es notwendig, Zugangsdaten wie Passwörter, Tokens oder Benutzernamen in Hiera zu speichern. Puppet bringt die Implementation Hiera e(ncryted)YAML auf Basis von PKCS7 mit um dies zu ermöglichen,

Vor- und Nachteile der beiden eYAML Implementierungen

eYAML

eYAML basiert auf einem öffentlichen/privatem Schlüsselpaar. Der öffentliche Schlüssel wird an die Benutzer verteilt und ermöglicht Ihnen das verschlüsseln von Inhalten. Der private Schlüssel wird an einem sicheren Ort und auf den Puppetservern abgelegt. Dieser Schlüssel ist in der Lage Inhalte zu entschlüsseln.

Die Konfiguration ist einfach, kann aber zum Problem werden wenn Teammitglieder die Firma verlassen. In vielen Teams, in denen kein zusätzlicher Passwortmanager existiert, wird häufig das komplette Schlüsselpaar an die User herausgegeben um Hiera als Passwort Datenbank zu benutzen. Dies erhöht das Risiko das Schlüsselpaar zu kompromittieren.

+ mitgeliefert

+ einfach zu konfigurieren

- kann zu Sicherheitsproblemen führen

eYAML-GPG

eYAML-GPG verwendet ebenfalls ein öffentliches/privates Schlüsselpaar, jedoch nutzt jeder Server und jeder Benutzer sein eigenes. Es ist ziemlich einfach Benutzer zur Liste der Empfänger hinzuzufügen oder zu entfernen. Häufig ist GPG bereits im Einsatz und Nutzer haben bereits ein Schlüsselpaar.

+ jeder Benutzer/Server hat sein eigenes Schlüsselpaar

+ hinzufügen oder löschen von Benutzern nach Bedarf

+ neuverschlüsseln von Inhalten sodass dieser für ehemalige Benutzer unlesbar wird, selbst wenn Sie Daten und Schlüssel mitnehmen.

- nicht mitgeliefert

- muss eingerichtet werden

Das Projekt auf Github: https://github.com/voxpupuli/hiera-eyaml-gpg

Die Installation

Voraussetzungen

Eine laufende Installation des Puppet Servers 6 oder neuer ist eine Grundvoraussetzung, genau wie eine Workstation mit einer Ruby Installation. Dies sollte nicht das Ruby sein, das im Puppet Agent mitgeliefert wird. Warum das wichtig ist, dazu später mehr.

Installation der benötigten Gems

Für Ruby existieren zwei GPG Implementierungen, ruby_gpg ist die native Implementierung aber soweit mir bekannt nur in der Lage Inhalte zu entschlüsseln. Gpgme ist die Implementierung mit allen Funktionen, das sowohl verschlüsseln als auch entschlüsseln kann.
Es muss kompiliert werden, sodass es weder mit dem JRuby des Puppet Servers, noch mit dem Agent Ruby funktioniert, da diese keine Quellen für die Kompilierung mitbringen. Wir installieren das Ruby der Linux Distribution.

sudo /opt/puppetlabs/bin/puppetserver gem install ruby_gpg
sudo /opt/puppetlabs/bin/puppetserver gem install hiera-eyaml hiera-eyaml-gpg
sudo /opt/puppetlabs/puppet/bin/gem install ruby_gpg
sudo opt/puppetlabs/bin/puppetserver gem install ruby_gpg
sudo apt-get install ruby ruby-dev
sudo gem install hiera-eyaml-gpg gpgme puppet
Enter fullscreen mode Exit fullscreen mode

Die benötigten Pakete sind nun installiert..

GPG Schlüsselpaare erstellen

Puppet Server Schlüsselpaar

gpg --full-generate-key

Folge dem Dialog und schütze den Key NICHT mit einem Passwort

Schlüsselpaar für den Benutzer generieren

gpg --full-generate-key

Folge dem Dialog und schütze den Key mit einem Passwort

Die Schlüsselpaare exportieren

Die Schlüsselpaare prüfen

gpg -K 

sec   rsa4096 2020-05-29 [SC]
      DD186A9AE323294BA99A124977DC5816AD58E28E
uid        [ ultimativ ] Puppet Server (the gpg key of the puppetserver) <puppetserver@betadots.de>
ssb   rsa4096 2020-05-29 [E]

sec   rsa4096 2020-05-29 [SC]
      23872B1059DD0AF63EDC8CA4E24907C2260F6FA7
uid        [ ultimativ ] Puppet User (the puppet users gpg key) <puppetuser@betadots.de>
ssb   rsa4096 2020-05-29 [E]
Enter fullscreen mode Exit fullscreen mode

Export der privaten Schlüssel

gpg --export-secret-key -a "puppetuser@betadots.de" > puppetuser.gpg.sec
gpg --export-secret-key -a "puppetserver@betadots.de" > puppetserver.gpg.sec
Enter fullscreen mode Exit fullscreen mode

Export der öffentlichen Schlüssel

gpg --export -a "puppetuser@betadots.de" > puppetuser.gpg.pub
gpg --export -a "puppetserver@betadots.de" > puppetserver.gpg.pub
Enter fullscreen mode Exit fullscreen mode

Vorbereiten der Hiera Struktur

vim hiera.yaml
---
version: 5
defaults:
hierarchy:
  - name: "my hierachy structure"
    lookup_key: eyaml_lookup_key
    options:
      gpg_gnupghome: /opt/puppetlabs/server/data/puppetserver/.gnupg
    paths:
      - "common.yaml"
Enter fullscreen mode Exit fullscreen mode

Verschlüsselung des ersten Werts

Import der Schlüssel(paare)
Zuerst importieren wir die Schlüssel auf dem Puppet Server.
Da es sich hier um ein demo System handelt, importieren wir den Privaten Schlüssel des Puppet Users bei einem Systembenutzer.
Normalerweise verbleibt dieser auf der Workstation oder dem Entwickungsserver

sudo cp puppetserver.gpg.sec /opt/puppetlabs/server/data/puppetserver/key
sudo chown puppet:puppet /opt/puppetlabs/server/data/puppetserver/key
sudo su puppet -s /bin/bash -c '/usr/bin/gpg --import /opt/puppetlabs/server/data/puppetserver/key' 
gpg --import puppetuser.gpg.sec
Enter fullscreen mode Exit fullscreen mode

Abschließend starten wir den Puppet server neu

systemctl restart puppetserver.service

Füge die Scripte und öffentlichen Schlüssel zum data directory des control-repositories hinzu

Es gibt zwei scripte die es sehr einfach machen mit Hiera eYAML-GPG zu arbeiten

edit.sh

Dieses script erlaubt es eine Datei mit verschlüsselten Werten zu editieren oder neue Werte hinzuzufügen. Anpassen des puppetserver_keys nach Bedarf

#!/bin/bash

puppetserver_key='puppetserver@betadots.de'
recipient_file='gpg_recipients'

if [ $# -ne 1 ]; then
    echo "[-] Please specify a file to edit.."
    exit 1
fi

grep $puppetserver_key $recipient_file > /dev/null || { echo "ERROR: ${puppetserver_key} not in recipient file ${recipient_file}. This may NEVER happen!"; exit 1; }

if [ ! -e $1 ]; then
    echo "[*] Specified file argument $1 does not exist, creating it for you..."
    touch $1
fi

echo -e "[*] Importing new public keys..."
gpg --import gpg_pubkeys/*

echo -e "[*] Editing the following file: $1"
echo -e "[*] Recipients are:"
cat $recipient_file
echo ""

eyaml edit --gpg-always-trust --gpg-recipients-file $recipient_file $1
Enter fullscreen mode Exit fullscreen mode

recrypt_all.sh

Mit diesem Script lassen sich alle Dateien mit verschlüsseltem Inhalt neu verschlüsseln, wenn Mitarbeiter das Unternehmen verlassen oder neu hinzu kommen.
Anpassen des puppetserver_keys nach Bedarf

#!/bin/bash

if [ $# -eq 0 ]; then
    encrypted_files=`grep -Rl "ENC\[GPG" *`
else
    encrypted_files=$*
fi
puppetserver_key='puppetserver@betadots.de'
recipient_file='gpg_recipients'

grep $puppetserver_key $recipient_file > /dev/null || { echo "ERROR: ${puppetserver_key} not in recipient file ${recipient_file}. This must NEVER happen!"; exit 1; }

echo -e "[*] Reencrypting the following files:\n $encrypted_files\n"
echo -e "[*] Recipients are:"
cat $recipient_file
echo ""

for item in $encrypted_files ; do
    echo "[*] Reencrypting $item"
    eyaml recrypt --gpg-always-trust --gpg-recipients-file $recipient_file $item
    if [ $? -eq 0 ] ; then
        echo -e "[+] Successfully reencrypted $item\n"
    else
        echo "[-] Reencryption of $item failed, this is bad!"
        echo "[-] Please investigate what went wrong and DO NOT PUSH THIS!!"
        exit 1
    fi
done
echo "[+] Reencryption of all files was successful"
Enter fullscreen mode Exit fullscreen mode

Füllen der gpg_recipients Datei

Diese Datei enthält alle Mailadressen oder KeyIDs der Puppetserver und aller Teammitglieder.
Wenn ein Teammitglied geht oder dazu kommt, füge den Schlüssel hinzu und entferne diesen.

puppetserver@betadots.de
puppetuser@betadots.de
Enter fullscreen mode Exit fullscreen mode

GPG public Keys ins gpg_pubkeys Verzeichnis legen

cp puppetserver.gpg.pub gpg_pubkeys/
cp puppetuser.gpg.pub gpg_pubkeys/
Enter fullscreen mode Exit fullscreen mode

Wenn ein Teammitglied geht oder dazu kommt, füge den Schlüssel hinzu und entferne diesen.

Abschließende Arbeiten

Kopieren der Scripte und Dateien in Hiera Daten Verzeichnis.

cp -r edit.sh recrypt_all.sh gpg_recipients gpg_pubkeys/ data/
Enter fullscreen mode Exit fullscreen mode

Das erste Secret verschlüsseln

Das Script wird den bevorzugten Editor öffnen, im Zweifelsfall wird gefragt:

./edit.sh common.yaml
[*] Importing new public keys...
gpg: key 77DC5816AD58E28E: "Puppet Server (the gpg key of the puppetserver) <puppetserver@betadots.de>" not changed
gpg: key E24907C2260F6FA7: "Puppet User (the puppet users gpg key) <puppetuser@betadots.de>" not changed
gpg: Total number processed: 2
gpg:              unchanged: 2
[*] Editing the following file: common.yaml
[*] Recipients are:
puppetserver@betadots.de
puppetuser@betadots.de

# | This is eyaml edit mode. This text (lines starting with # | at the top of
# | the file) will be removed when you save and exit.
# |  - To edit encrypted values, change the content of the DEC(<num>)::PKCS7[]!
# |    block (or DEC(<num>)::GPG[]!).
# |    WARNING: DO NOT change the number in the parentheses.
# |  - To add a new encrypted value copy and paste a new block from the
# |    appropriate example below. Note that:
# |     * the text to encrypt goes in the square brackets
# |     * ensure you include the exclamation mark when you copy and paste
# |     * you must not include a number when adding a new block
# |    e.g. DEC::PKCS7[]! -or- DEC::GPG[]!
---
super_secret_test: 'DEC::GPG[super secret string]!'
Enter fullscreen mode Exit fullscreen mode

Speichern. Die Ausgabe mit cat sieht so aus:

---
super_secret_test: 'ENC[GPG,hQIMA0HLK7hFkXxnAQ//RqmeCG1vG7QVpTaaQ3NXJ7sb4/kd8PYtc9jL/P10z76KAuuid2CR1rlGczmCsDLasHGcQDLQuXpfcIOdKN1CxK3M2fJUDWsOn+oK+LK21W+0YsTHLmSUm6k/2pp36q03QlIaNcWL2BFzSs/fGskM6V57p97a3Fm27i32dGJRVyZ071G9f2lgismTK09sk50+xtIS3OCT8S4uWZkCst7TBnon3RQvfr80xKFOBYfJoo4NJob/XQi5/j00IMmF7KmrX76LZBeJV4X5PqRvOWTmlRGFT9JpDLi1fWR6hGvzSDNaL5JL6e1Wl/EsCMZgaTL7VxYwvRCvD0sAkyESD2LLMGULVT9MRO5mwhmoR1E5AMVt0FwFXwL9kQnfWS7us/TJfSPgovrZmMAav+oIZOzAv/Q1c6381urpdHtfbP17iz1jfggfDgmowcCH1UJ7R8kZ7C5RcZa/j+Uv+ll8SqbAQo/yX8mXe627OOD/WfzXP++UF7nsvdxCHpk2me+hUjo6XUWt0h2bkZKc2GinY29oojd/2FoI4EZBpTow6TgpFhw0hK2tiU1PWaAU5v6oi2BSrpIqFaZ0Fowd1fNT+86NjvArb6JY8vOWbqbh2Y6DKoTqWtZV/pxB42iXe1I59h7CsGHMtp71S37XwXDcie51EZOpEfiTmBuR4xFg7eEEiwOFAgwD+3NwktMooowBD/wNxeOWG2fH9raBl1G671JdyzNhWZq/3wyK8As7nC2P8dqK9OBT4GXfSif1ssLwvabix4C9SAiET1+JJVPPnhh3tGOCye4TUjkpdMjWNf8NXIkUXd7qwbtNNqu1TTpuSfTNpGc9cgaonuvr8SLiwGpKm57kdcuPVfrTVkeRns6h6ahTsgy4kbAXSD8b+FMApMCnJFyjEu2ne+IKfCmYbnhExj5S2qeedW0509XhVLR4cPAMQ6tefYmzRrrgm+3P3mHkNULtbrXmZWmpt0HhrVyT0axDVvuvcz+g3poByDBPsrHdhMTjkOqY6ikyS9a+H85OM9HECxQD/X1oseMrnaoCr9Ds+In9aFV2gmXHoraSEfVecHNhHyU470lx5X0CI8clICYsZzCKFea2IjG34myb2xNwQSQyg6pX7iUR4zafOsUImOacc30HX+XUoaOLn/GEcHiiBucRnso57CLICN474TXIEqEqBpaJEHnwxozxyQI7mlf2mfpdGt1X+ECjQth7lzKDJeapcK6uxy7g+9GALhjGC+dKXWY+MvM/7fvj+yUls798a4f05PivMDXmwysxYr3W/CCxzKOwSJNZ3SZkSRcpMg0zeIrk617jHsKI6ehJ1ADr8on3wfLjlD9Yg+4YqGxQxcTHN+IDexAZVO9erZR1C+02kTsqMmdyxjaTBdJOARxyzTCNeUDweVLIwXKPT8Bq5IX7CGEsySRDmqYxZpACzbvP0xIlZskuJ0ybKJUCLEmRDikJBIx0n/DcQEK2jthFidOgy6nnVv2Bc2LO]'
Enter fullscreen mode Exit fullscreen mode

Herzlichen Glückwunsch!

Prüfen des lookup:

Wenn alles passt sollten wir mit puppet lookup den Wert abfragen können und den Klartext als Antwort bekommen:

 HIERA_EYAML_GPG_GNUPGHOME=~/.gnupg puppet lookup 'super_secret_test'
--- super secret string
Enter fullscreen mode Exit fullscreen mode

Das Setup ist damit abgeschlossen

Hinzufügen oder entfernen von Team Mitgliedern

  1. editieren der gpg_recipients datei
  2. hinzufügen/entfernen des öffentlichen Schlüssels zum/aus dem gpg_pubkeys Verzeichnis
  3. recrypt.sh laufen lassen
  4. commit
  5. merge
  6. fertig

Bekannte Stolpersteine

Daten Strukturen

YAML Blöcke funktionieren nicht.

key: |
  content
  more content
Enter fullscreen mode Exit fullscreen mode

Es ist gut möglich das weitere komplexe Strukturen ebenfalls nicht funktionieren

Anführungszeichen

Wenn ein String mit Anführungszeichen begrenzt wird, schließen diese den Verschlüsselungs-Block ein

'DEC(1)::GPG[super secret string]!'
Enter fullscreen mode Exit fullscreen mode

Der Index und das kopieren von Werten

Das kopieren und einfügen von Werten im Editier-Modus ist ohne Probleme möglich, wenn man folgendes beachtet:

Die Indexnummer werden pro Datei hochgezählt und sind immer ungerade. Beim kopieren ist darauf zu achten den Index zu entfernen, dieser wird automatisch wieder hinzugefügt.

---
super_secret_test: 'DEC(1)::GPG[super secret string]!'
super_secret_test_two: 'DEC::GPG[super secret string too]!'
Enter fullscreen mode Exit fullscreen mode

Beim erneuten editieren:

---
super_secret_test: 'DEC(1)::GPG[super secret string]!'
super_secret_test_two: 'DEC(3)::GPG[super secret string too]!'
Enter fullscreen mode Exit fullscreen mode

Viel Spass beim benutzen von Hiera eYAML-GPG!

💖 💪 🙅 🚩
simonhoenscheid
Simon Hönscheid

Posted on April 10, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related