Puppet: Virtuelle Ressourcen fuer Benutzer und SSH-Keys

Puppet kann Ressourcen nur einfach definieren. Hat man eine Klasse einmal eingebunden, kann man dieses an einer zweiten Stelle nicht erneut tun. Folgendes Beispiel:

Ich deploye eine selbst entwickelte Software und moechte sie unter einem bestimmten Nutzeraccount laufen lassen. Mit Puppet stelle ich sicher, dass der Nutzeraccount existiert. Spaeter moechte ich auf dem gleichen Server eine zweite Software deployen die ebenfalls unter diesem Benutzeraccount laeuft. Ich erzeuge dafuer ein weiteres Modul das die Abhaengigkeiten abbildet. Laesst sich wunderbar alles konfigurieren, aber spaetestens auf dem Server gibt es dann einen Fehler:

err: Could not retrieve catalog from remote server: Error 400 on SERVER: Duplicate declaration: Class[FOO] is already declared; cannot redeclare at /etc/puppet/manifests/site.pp:20 on node node01.example.org

Die Loesung fuer das Problem sind virtuelle Ressourcen. Im folgenden Beispiel moechte ich aufzeigen, wie man Benutzeraccounts als virtuelle Ressourcen definiert und auf den Nodes einbindet. Die Loesung die ich hier aufzeige habe ich mir nicht selbst ausgedacht, sondern bei meinem Kollegen abgeguckt.

Eigentlich kommt man bei mehreren Benutzeraccounts auf mehreren Servern nicht um einen LDAP Server herum. Bei kleineren Setups kann man es aber auch noch auf die klassische Art- und Weise mit lokalen Konten machen.

Viele Anleitungen die man im Internet liesst zeigen Wege, bei denen man die Benutzerinformationen als Parameter an die Klasse uebergibt. Ich habe mich bewusst dagegen entschieden und alle Infos in dem Modul. Spaeter werde ich mich wohl noch mal mit Hiera beschaeftigen, dann werde ich die Informationen dort ablegen.

Die Verzeichnisstruktur meines Moduls „users“ sieht wie folgt aus:

└── manifests
    ├── init.pp
    ├── mmuster.pp
    └── virtual.pp

Die init.pp ist sehr simpel:

class users () {
  include users::virtual
}

Spannender wird es dann, wenn man die virtual.pp anschaut:

class users::virtual {
 
  @user { 'mmuster':
    ensure      => 'present',
    comment     => 'Max Mustermann,,,',
    shell       => '/bin/bash',
    managehome  => true,
    groups      => ['sudo', 'wheel' ],
    }
 
  @ssh_authorized_key { 'mmuster-privat':
    ensure      => 'present',
    type        => 'ssh-rsa',
    user        => 'mmuster',
    key         => 'AAA [...] ZZZ='
  }
}

Virtuelle Ressourcen definiert man mit einem vorgestellten @. In dem Beispiel werden zwei virtuelle Ressourcen definiert:

  1. Den Nutzeraccount mmuster
  2. Den oeffentlichen SSH-Key mmuster-privat

Die Parameter fuer den Nutzeraccount mmuster bedeuten folgendes:

  • ensure => ‚present‘: Stellt sicher, dass der Benutzeraccount existiert. Wenn nicht wird er angelegt.
  • comment => ‚Max Mustermann,,,‘: Kommentar zum Benutzeraccountt in der /etc/passwd
  • shell => ‚/bin/bash‘: Die Shell die der Benutzeraccount haben soll.
  • managehome => true: Stellt sicher das das Homeverzeichnis existiert.
  • groups => [’sudo‘, ‚wheel‘ ]: Stellt sicher, dass der Benutzeraccount Mitglied in den Gruppen sudo und wheel ist. Die Gruppen muessen im System existieren. Sie werden nicht automatisch angelegt!

Die Einstellungen fuer den SSH-Key mmuster-privat bedeuten folgendes:

  • ensure => ‚present‘: Stellt sicher, dass der SSH-Key existiert
  • type => ’ssh-rsa‘: Definiert den Verschluesselungsalgorithmus
  • user => ‚mmuster‘: Der Benutzeraccount zu dem dieser oeffentliche SSH Schlussel gehoert
  • key => ‚AAA […] ZZZ=‘:Der eigentliche public key

Fertig ist die Definition der virtuellen Ressourcen. Damit diese spaeter auch auf dem Node ausgefuehrt werden, muessen sie mit der realize Funktion markiert werden. Das passiert in der dritten Datei: mmuster.pp

class users::mmuster inherits users::virtual {
 
  realize(
    User['mmuster'],
    Ssh_authorized_key['mmuster-privat']
  )
}

Das schoene an dieser Loesung ist, dass der Nutzer nun mit einer einzigen Zeile zu dem Node hinzugefuegt werden kann:

include users::mmuster

Zum Schluss: Das Passwort wird nicht gesetzt. Man kann den Hash bei dem Nutzer mit dem Parameter password => “ mitgeben. Das finde ich aber nicht gut, weil die Nutzer dann die Passwoerter nicht selbst aendern koennen. Man findet im Netz auch Infos zu Kruecken mit denen man das Passwort nur beim Nutzer anlegen setzen kann, sollte man an diesem Punkt angelangt sein ist definitiv wieder der Zeitpunkt erreicht sich erneut Gedanken ueber einen LDAP Server zur Benutzerverwaltung zu machen 8-)

Ein Versuch #Heartbleed fuer nicht-Techniker verstaendlich zu machen

heartbleed

Eigentlich sollte ich keine Zeit haben zu schreiben, aber das ist die mit Abstand krasseste Sicherheitsluecke die es seit langem gegeben hat. Das Ausmass kann man nur erahnen, im Prinzip muessen alle persoenlichen Daten auf einem System das den Fehler hatte als unsicher erachtet werden. Es reicht nicht die gepatchte Version von OpenSSL einzuspielen und die betroffenen Prozesse wie Apache, Postfix, Dovecot oder OpenVPN neu zu starten. Es muessen private Schluessel und Zertifikate erneuert werden und wer den Konsequenzen der Luecke klar ins Gesicht schaut wird auch ueberall Passwoerter neu setzen muessen.

Heute beim Kaffee und Kuchen fragte unsere Nachbarin wie man sich das vorstellen koennte und ich habe versucht es wie folgt zu erklaeren:

Stell Dir vor auf dieser Welt gibt es einen Hersteller fuer Haustuerschloesser. Dieser Hersteller baut sehr sichere Schloesser und man kann sich darauf verlassen, dass wenn man seine Haustuer mit einem Schloss dieser Marke schuetzt, dass dort nicht eingebrochen werden kann. Das Schloss ist in diesen Fall OpenSSL, und das Haus der Server selbst.

Vor ein paar Jahren gab es dann den Trend zu sogenannter Perfect Forward Secrecy. Im uebertragenen Sinne kann man sich das so vorstellen, dass das Schloss kontinuierlich neue Schluessel generiert die jedes mal anders sind. Gelangt also mal ein Haustuerschluessel in die falschen Haende, dann kann man damit trotzdem nichts mehr anfangen, weil das Schloss sich geaendert hat.

Die Sicherheitsluecke in OpenSSL erlaubt es, das man von extern, ohne, dass man auf den Server einbrechen muss, an sehr sehr private Daten gelangen kann. Das koennen Zugangsdaten sein oder auch der private Key, mit dem man sich dann fuer den Server ausgeben kann ohne eben dieser zu sein.

Wenn man das wieder auf den Schlosshersteller und das Haus zurueckbringt, dann stelle man sich vor, das man zu jedem Haus mit einem Schloss von diesem Schlosshersteller hingehen kann, und ohne einzubrechen bekommt man die Information wie das Schloss jetzt Schluessel generiert. Man muss nichts stehlen, man muss nichts kaputt machen, man geht einfach hin und fragt und das Schloss sagt es einem.

Auch wenn in dem Beispiel viele Dinge vielleicht als Vergleich hinken, es zeigt ziemlich einfach welche Tragweite die Sicherheitsluecke hat. Man kann ja von aussen nicht sehen „ob jemand vorbeigekommen ist und gefragt hat wie sich das Schloss aendert oder nicht“. Aus diesem Grund muss man alle Server auf denen OpenSSL in der betroffenen Version eingesetzt wurde als unsicher betrachten. Der Fehler existiert seit dem 14. Maerz 2012 und man muss also davon ausgehen, dass es Menschen / Organisationen gibt, die seit zwei Jahren in alles rein gucken konnten was man irgendwie sichern wollte.

Fuer Sysadmins ist das der Supergau…

Eine ganz gute Zusammenfassung zu dem Thema gibt es bei Golem:

Weitere Infos:

Wer seine eigene Infrastruktur testen moechte (Router, NAS, Drucket etc) kann mit dem heartbleeder lokale IP Adressen probieren und findet dann auf einschlaegigen Seiten wie Packetstormsecurity die entsprechenden Exploits…

HowTo: Export and Import GnuPG Keys

Exportieren:

  1. Vorhandene Keys auflisten um Schluessel ID herauszufinden:
    gpg --list-keys
  2. Public Key abspeichern:
    gpg -ao mynamefor-public.key --export KEY_ID
  3. Private Key abspeichern:
    gpg -ao mynamefor-private.key --export-secret-keys KEY_ID
  4. Wiederrufszertifikat erzeugen:
    gpg --gen-revoke KEY_ID

Importieren:

gpg --import _something_-public.key
gpg --import _something_-private.key