Schlagwort-Archiv: Planet

Tag für den Ubuntuusers.de Planeten.

Ansible – Die Module copy und cron

In diesem Beitrag zu meiner kleinen Ansible-Reihe beschäftige ich mich mit den Modulen copy[1. Ansible: copy – Copies files to remote locations] und cron[2. Ansible: cron – Manage cron.d and crontab entries].

Hinweis: Die folgende Konfiguration ist nicht zur Nachahmung empfohlen. Es handelt sich dabei um meine ersten Schritte mit Ansible. Es ist daher wahrscheinlich, dass die Konfiguration noch Fehler enthält, nicht optimiert ist und ein großes Verbesserungspotenzial besitzt. Die Nachahmung erfolgt ausdrücklich auf eigene Gefahr. Über Hinweise, wie man es besser machen kann, freue ich mich jederzeit.

Anforderungen

In diesem Szenario sollen Shell-Skripte auf das Zielsystem kopiert werden. Anschließend sind Einträge in der crontab zu erstellen, um diese Shell-Skripte auszuführen. Beim Zielsystem handelt es sich um die Gruppe [i-stage], in der sich aktuell nur ein Host namens host-i1.example.com befindet.

Vorbereitungen

Die zu verteilenden Skripte werden auf der Ansible-Control-Machine im Verzeichnis /root/src/ gesammelt. Anschließend wurde eine Rolle für dieses Vorhaben erstellt. Die auf meiner Spielwiese verwendete Verzeichnisstruktur wurde bereits in den vergangenen Beiträgen[3. Linux-Benutzerkonten mit Ansible verwalten] zu dieser Reihe beschrieben.

Umsetzung

Zur Umsetzung der Anforderungen wird ein Playbook erstellt, welches die geforderten Tasks ausführt. Der folgende Code-Block listet die benötigten Dateien inkl. ihres kommentierten Inhalts auf:

# Begin of file: local_scripts_i-stage.yml
---
- hosts: i-stage
  roles:
    - local_scripts
# End of file ############################

# Begin of file: roles/local_scripts/tasks/main.yml
---
## Copy local script files to target hosts
- copy: src=/root/src/sript1.sh dest=/root/src/sript1.sh owner=root group=root mode=755
- copy: src=/root/src/sript2.sh dest=/root/src/sript2.sh owner=root group=root mode=755

## Create cron jobs for local script files
- cron: name="local script1" minute="10" hour="1" job="/root/src/sript1.sh"
- cron: name="local script2" minute="12" hour="1" job="/root/src/sript2.sh"
# End of file #############################

Nach der Ausführung des Playbooks liegen die Skripte auf dem oder den Zielsystemen im gewünschten Verzeichnis /root/bin/. Lässt man sich die Crontab des Benutzers root anzeigen, so erkennt man die von Ansible hinzugefügten Einträge:

# crontab -l
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/tmp/crontabaf5r8i installed on Mon Jul 18 11:52:09 2016)
# (Cronie version 4.2)
#Ansible: local script1
10 1 * * * /root/bin/script1.sh
#Ansible: local script2
12 1 * * * /root/bin/script2.sh

Fazit

Wieder konnte eine Anforderung schnell und einfach mit Ansible umgesetzt werden. Ob dies bereits der Königsweg ist bzw. ob dieser überhaupt existiert, steht jedoch noch nicht fest. Anstatt die Dateien zuerst auf das Ziel zu kopieren und dort Cron-Einträge für die Ausführung zu erstellen, könnte auch das Modul script[4. Ansible: script – Runs a local script on a remote node after transferring it] genutzt werden. Dieses Modul transferiert ein lokales Skript zum Zielsystem und führt es dort aus.

Bisher habe ich mich gegen den Einsatz des script-Moduls entschieden, da mir noch nicht klar ist, ob das Skript auf dem Zielsystem verbleibt oder bei jeder Ausführung erneut übertragen wird. Letzteres wäre bei einer großen Anzahl Zielsysteme nicht unbedingt wünschenswert.

Ansible – Das Modul yum_repository

Das Ansible Modul yum_repositoryist dazu geeignet, Repositories zu RPM-basierten Linux-Distributionen hinzuzufügen bzw. zu entfernen. Es findet z.B. in unserer Umgebung Anwendung, um Repositories von unserem lokalen Spiegelserver anzubinden. Der folgende Text gibt ein Beispiel zur Anwendung dieses Ansible-Moduls.

Auf meiner Spielwiese verwende ich folgende Konfiguration, um zwei Repositories hinzuzufügen.

Hinweis: Die folgende Konfiguration ist nicht zur Nachahmung empfohlen. Es handelt sich dabei um meine ersten Schritte mit Ansible. Es ist daher wahrscheinlich, dass die Konfiguration noch Fehler enthält, nicht optimiert ist und ein großes Verbesserungspotenzial besitzt. Die Nachahmung erfolgt ausdrücklich auf eigene Gefahr. Über Hinweise, wie man es besser machen kann, freue ich mich jederzeit.

Verzeichnisstruktur

Abgeleitet aus den „Best Practices“ von Ansible, verwende ich auf meiner Spielwiese folgende Verzeichnisstruktur:

ansible/
|-- group_vars
|   `-- e-stage               # variables for group e-stage
|-- hosts                     # inventory file
|-- host_vars                 # for system specific variables
|-- roles
|   |-- common                # this hierarchy represents a "role"
|   |   |-- defaults          
|   |   |-- files
|   |   |-- handlers
|   |   |   `-- main.yml      #  handlers file
|   |   |-- meta
|   |   |-- tasks
|   |   |   `-- main.yml      #  tasks file can include smaller files if wanted
|   |   `-- vars
|   `-- std-repos
|       |-- defaults
|       |-- files
|       |-- handlers
|       |-- meta
|       |-- tasks
|       |-- templates
|       `-- vars
|-- set_repos.yml             # playbook which sets the repos
|-- site.yml                  # master playbook file
`-- staging                   # inventory file for staging environment

Das Playbook

Das Playbook ist sehr kurz gehalten und gibt im Wesentlichen nur an, welche Hosts auf welche Rolle gemapped werden sollen.

# set_repos.yml
---
- hosts: all
  roles:
    - std-repos

Das obige Playbook definiert, dass die Tasks aus der Datei roles/e-stage/tasks/main.yml ausgeführt werden sollen, welche wie folgt aufgebaut ist:

---
- name: Add rhel-e-stage-repository
  yum_repository:
    name: "{{ repo_name1 }}"
    description: "{{ repo_description1 }}"
    baseurl: "{{ repo_baseurl1 }}"
    gpgcheck: yes
    gpgkey: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release

- name: Add my-own-repository
  yum_repository:
    name: "{{ repo_name2 }}"
    description: "{{ repo_description2 }}"
    baseurl: "{{ rebo_baseurl2 }}"
    gpgcheck: no

GroupVars

Nun existieren im Staging-Bereich häufig noch weitere Stages. So gibt es oftmals eine T-, E- und I-Stage. Dabei ist jeder Stage ein eigenes Stage-Repository zugeordnet. Um die Systeme in den unterschiedlichen Stages mit den dazugehörigen Stage-Repositories zu versorgen, werden diese mit Hilfe der group_vars den entsprechenden Gruppen zugewiesen.

Für die Server der Gruppe e-stage wird in der Datei group_vars/e-stage definiert:

# file: group_vars/e-stage
repo_name1: rhel-e-stage
repo_description1: Local RHEL-Repo for E-Stage
repo_baseurl1: http://repo.example.com/rhel-e-stage/

repo_name2: own-e-stage
repo_description2: Local OWN-Repo for E-Stage
repo_baseurl2: http://repo.example.com/own-e-stage/

Nach diesem Beispiel können nun weitere Variablen unter group_vars für andere Stages erstellt werden. Den Hosts in den entsprechenden Hostgruppen, werden auf diesem Wege die passenden Repositories hinzugefügt.

Linux-Benutzerkonten mit Ansible verwalten

Wie bereits in diesem Beitrag erwähnt, beschäftige ich mich aktuell mit der Evaluierung von Ansible.

In diesem Artikel dokumentiere ich ein Beispiel, wie das Modul user zur Administration von Linux-Benutzerkonten verwendet werden kann. Der Link zur offiziellen Dokumentation des user-Moduls befindet sich am Ende dieses Artikels.[1. Ansible Module: user – Manage user accounts {en}]

Hinweis: Die folgende Konfiguration ist nicht zur Nachahmung empfohlen. Es handelt sich dabei um meine ersten Schritte mit Ansible. Es ist daher wahrscheinlich, dass die Konfiguration noch Fehler enthält, nicht optimiert ist und ein großes Verbesserungspotenzial besitzt. Die Nachahmung erfolgt ausdrücklich auf eigene Gefahr. Über Hinweise, wie man es besser machen kann, freue ich mich jederzeit.

Anforderungen

  • Es soll ein lokales Benutzerkonto angelegt werden
  • Der Benutzer soll Mitglied der Gruppe „wheel“ werden
  • Es soll ein initiales Passwort für das Benutzerkonto gesetzt werden
  • Ein öffentlicher SSH-Schlüssel soll in die Datei authorized_keys des zu erstellenden Benutzers eingetragen werden
  • Konfiguration des SSH-Daemons

Vorbereitung

Abgeleitet aus den „Best Practices“[2. Ansible Best Practices – Directory Layout] verwende ich auf meiner Spielwiese folgende Verzeichnisstruktur:

ansible/
|-- autoupdate.txt            # ignore
|-- autoupdate.yml            # ignore
|-- check_reboot.             # playbook which sets the repos
|-- group_vars
|   `-- e-stage               # variables for group e-stage
|-- hosts                     # inventory file
|-- host_vars                 # for system specific variables
|-- roles
|   |-- common                # this hierarchy represents a "role"
|   |   |-- defaults          
|   |   |-- files
|   |   |-- handlers
|   |   |   `-- main.yml      # handlers file
|   |   |-- meta
|   |   |-- tasks
|   |   |   `-- main.yml      # tasks file can include smaller files if warranted
|   |   `-- vars
|   `-- e-stage
|       |-- defaults
|       |-- files
|       |-- handlers
|       |-- meta
|       |-- templates
|       `-- vars
|-- create_johnd.yml          # playbook which creates user johnd
|-- site.yml                  # master playbook file
`-- staging                   # inventory file for staging environment

17 directories, 11 files

Um das Passwort für den neuen Benutzer erstellen zu können, muss zuerst der passende Passwort-Hash generiert werden[3. How do I generate crypted passwords for the user module?]:

python -c "from passlib.hash import sha512_crypt; import getpass; print sha512_crypt.encrypt(getpass.getpass())"

Der generierte Hash wird auf der Standardausgabe ausgegeben. Dieser wird für das Playbook benötigt.

Playbook und Tasks

Das Playbook ist sehr kurz gehalten und gibt im Wesentlichen nur an, welche Hosts auf welche Rolle gemapped werden sollen.

# create_johnd.yml
---
- hosts: all
  roles:
    - common

Bei Verwendung dieses Playbooks werden die Tasks aus der Datei roles/common/tasks/main.yml ausgeführt, welche wie folgt aufgebaut wurde:

---
# Configure sshd_config on target system
- name: Enable Public-Key-Authentication
  lineinfile:
    dest: /etc/ssh/sshd_config
    regexp: "^PubkeyAuthentication"
    line: "PubkeyAuthentication yes"
    state: present
  notify:
    - reload sshd

- name: Set AuthorizedKeyFile
  lineinfile:
    dest: /etc/ssh/sshd_config
    regexp: "^AuthorizedKeysFile"
    line: "AuthorizedKeysFile      .ssh/authorized_keys"
    state: present
  notify:
    - reload sshd

- name: Disable PasswordAuthentication
  lineinfile:
    dest: /etc/ssh/sshd_config
    regexp: "^PasswordAuthentication"
    line: "PasswordAuthentication no"
    state: present
  notify:
    - reload sshd

# Add user johnd with specific uid in group 'wheel'
- user: name=johnd comment="John Doe" uid=100 groups=wheel password="PASSWORDHASH" shell=/bin/bash append=yes state=present
  notify:
    - deploy ssh-pub-keys

Die hier spezifizierten Tasks setzen die folgenden Aufgaben um:

  • Aktivierung der Public-Key-Authentication
  • Spezifikation des Standard-AuthorizedKeysFile
  • Deaktivierung der Password-Authentication

Was in dieser Datei noch nicht zu sehen ist, ist die Verteilung eines öffentlichen SSH-Schlüssels. Dies wird von dem Handler[4. Ansible Handlers – Running Operations On Change] deploy ssh-pub-keys übernommen.

Der Handler ist in der Datei roles/common/handlers/main.yml definiert. Es handelt sich dabei um einen Task, welcher nur ausgeführt wird, wenn der Benutzer erfolgreich erstellt wurde.

Fazit

Soweit zu meinen ersten Gehversuchen mit Ansible Playbooks. Meine Anforderungen können mit dem hier dokumentierten Playbook erfüllt werden.

In dem hier beschriebenen Beispiel habe ich angenommen, dass es sich bei dem zu erstellenden Benutzer um das erste lokale Benutzerkonto neben root handelt. Dieses soll über die Berechtigung verfügen, Kommandos mit sudo auszuführen und primär für die Arbeit auf dem System verwendet werden.

Die Verteilung des SSH-Schlüssels über einen Handler anzustoßen erscheint mir jedoch nicht optimal. Der Handler wird nur dann ausgeführt, wenn durch das user-Modul Änderungen am Zielsystem vorgenommen wurden. Weitere SSH-Schlüssel bzw. Änderungen an bereits vorhandenen SSH-Schlüsseln lassen sich auf diesem Weg nicht vornehmen.

Daher erscheint es mir sinnvoll, die Verteilung von SSH-Schlüsseln über das Modul authorized_key[5. Ansible Module: authorized_key – Adds or removes an SSH authorized key] in ein eigenes Playbook auszulagern.

Ansible – IT-Automation für Jedermann

Ansible[1. Ansible Homepage {en}] ist eine Open-Source-Plattform zur Orchestrierung und allgemeinen Konfiguration und Administration von Computern.[2. Ansible – Wikipedia] Ansible soll dabei helfen, Konfigurationsprozesse zu automatisieren und die Administration multipler Systeme zu vereinfachen. Damit verfolgt Ansible im Wesentlichen die gleichen Ziele wie z.B. Puppet[3. Puppet – Wikipedia], Chef[4. Chef – Wikipedia {en}] und Salt[5. Salt – Wikipedia {en}].

Ansible hat gegenüber den genannten Systemen das Alleinstellungsmerkmal, dass auf den verwalteten Rechnern kein Agent installiert werden muss. Der Zugriff erfolgt ausschließlich über das SSH-Protokoll. Dies ist ein Vorteil, da bei der Einführung von Ansible SSH-Key-Authentifizierungsverfahren genutzt werden können, die häufig schon existieren. Ein weiterer Vorteil ergibt sich in dem Fall, wenn man Ansible nicht mehr nutzen möchte. Es bleiben keine Softwarekomponenten auf den verwalteten Rechnern zurück, die wieder deinstalliert werden müssen.

Mir gefällt auf den ersten Blick, dass mir die Lösung zwei Wege bietet, um meine Systeme zu konfigurieren. Zum einen kann ich Playbooks[6. Ansible – Playbooks {en}] nutzen, welche gewissermaßen das Pendant der Puppet Manifeste darstellen. Zum anderen existiert ein Ad-hoc-Modus, welcher es erlaubt, die Konfiguration von Zielsystemen bei Bedarf anzupassen, ohne zuvor ein Rezept bzw. Playbook erstellt zu haben.

Die Playbooks selbst werden in YAML[7. YAML – Wikipedia]-Syntax verfasst. Dadurch wird eine gute Lesbarkeit sichergestellt. Zudem ist die Syntax recht einfach gehalten und daher schnell zu erlernen.

Für häufige Anwendungsfälle wie z.B. das Anlegen eines Benutzers, die Verteilung von SSH-Keys, die Installation verfügbarer Updates/Patches und noch vieles mehr, bringt Ansible vorgefertigte Module mit. Diese können direkt auf den Zielsystemen oder durch die Verwendung von Playbooks ausgeführt werden.[8. About Modules – Ansible {en}]

Die oben genannten Aspekte motivieren mich, zu evaluieren, ob Ansible für den Einsatz in meinem beruflichen Umfeld geeignet ist. In diesem Blog werden in unregelmäßigen Abständen weitere Artikel erscheinen, in denen ich Erkenntnisse aus meiner Evaluierung festhalte und einige kurze Beispiele zur Nutzung konkreter Module wiedergebe.

Wer dieser Reihe folgt und sich gern mit seinen Erfahrungen einbringen möchte, darf dies gerne tun. Ich freue mich jederzeit über Kommentare, Ideen und Anregungen.

Update vom 17.12.2016: Ich habe die Ansible-Artikel in diesem Blog in einer PDF-Datei zusammengefasst. Die Datei gibt es hier: Ansible-Kochbuch (PDF)

Changelog eines RPM-Pakets unter RHEL/CentOS anzeigen

Es kommt häufiger mal vor, dass ich mir das Changelog eines RPM-Pakets ansehen möchte, bevor ich dieses Paket auf meinem System installiere.

Dazu kann das Kommando repoquery aus dem Paket yum-utils verwendet werden. Der Aufruf erfolgt nach dem Muster:

repoquery --changelog PAKETNAME

Das folgende Listing zeigt beispielhaft das Changelog zum Paket open-vm-tools:

repoquery --changelog open-vm-tools.x86_64
* Fri Aug 14 2015 Richard W.M. Jones  - 9.10.2-4
- Enable PrivateTmp for additional hardening
  resolves: rhbz#1253698

* Wed Jul 29 2015 Richard W.M. Jones  - 9.10.2-3
- Enable deploypkg
  resolves: rhbz#1172335

* Mon Jul 27 2015 Richard W.M. Jones  - 9.10.2-2
- Disable vgauthd service in vmtoolsd.service file.
  resolves: rhbz#1172833

* Tue Jul 07 2015 Ravindra Kumar  - 9.10.2-1
- Package new upstream version open-vm-tools-9.10.2-2822639
- Removed the patches that are no longer needed
  resolves: rhbz#1172833

* Wed May 20 2015 Ravindra Kumar  - 9.10.0-2
- Claim ownership for /etc/vmware-tools directory
  resolves: rhbz#1223498

* Wed May 20 2015 Richard W.M. Jones  - 9.10.0-1
- Rebase to open-vm-tools 9.10.0 (synchronizing with F22)
  resolves: rhbz#1172833

* Fri Sep 19 2014 Richard W.M. Jones  - 9.4.0-6
- Really rebuild for updated procps
  resolves: rhbz#1140149

* Wed Sep 10 2014 Richard W.M. Jones  - 9.4.0-5
- Rebuild for updated procps
  resolves: rhbz#1140149

* Mon Aug 18 2014 Richard W.M. Jones  - 9.4.0-4
- Removed unnecessary package dependency on 'dbus'
- Moved 'vm-support' script to /usr/bin
- Added a call to 'tools.set.version' RPC to inform VMware
  platform when open-vm-tools has been uninstalled
- Add missing package dependency on 'which' (BZ#1045709)
- Add missing package dependencies (BZ#1045709, BZ#1077320)

* Tue Feb 11 2014 Richard W.M. Jones  - 9.4.0-3
- Only build on x86-64 for RHEL 7 (RHBZ#1054608).

Valides passwdfile für ldapsearch erstellen

Dieser Artikel beschreibt die Erstellung eines validen passwdfile für ldapsearch.

Die Man-Page zum LDAP search tool LDAPSEARCH(1) bietet die Möglichkeit, eine Passwortdatei zu nutzen:

-y passwdfile
              Use complete contents of passwdfile as the password  for  simple
              authentication.

Das passwdfile darf dabei ausschließlich das Passwort und keinerlei Newline-Zeichen („\n“) enthalten. Erstellt man diese Datei nun mit dem Editor vim oder vi, fügen diese Editoren automatisch ein Newline-Zeichen („\n“) an. Dies lässt sich überprüfen, indem man die Datei mit dem folgenden Kommando ausgibt:

od -c proxytest
0000000 S e c r e t P a s s w o r d 1 \n
0000020

Damit ist die Datei nicht mehr valide und kann nicht mit ldapsearch genutzt werden.

Um nun ein valides passwdfile zu erstellen, kann man folgendes Kommando verwenden:

echo -n SecretPassword1 > proxytest
od -c proxytest
0000000 S e c r e t P a s s w o r d 1
0000017

Die Ausgabe zeigt, dass in diesem Beispiel kein Newline-Zeichen mehr enthalten ist. Das passwdfile ist valide und kann mit dem Kommando ldapsearch verwendet werden.

Getestet wurde dies mit dem Kommando ldapsearch aus dem Paket openldap-clients-2.4.40-9.el7_2.x86_64 auf einem System mit RHEL 7.

Mein erstes RPM-Paket

Vorwort

Der Inhalt dieses Artikels ist nicht zur Nachahmung empfohlen. Ich halte an dieser Stelle fest, wie ich mein erstes RPM-Paket erstellt habe. Dieses funktioniert zwar und tut was es soll, doch ist es aus qualitativer Sicht noch ein weiter Weg, bis ich es selbst als gut bezeichnen würde. Der Artikel ist daher eher als ein Hilferuf zu verstehen. Ich freue mich, wenn mir geduldige, erfahrene Paketbauer in den Kommentaren Tipps geben, wie ich es besser machen kann.

Was habe ich getan?

Um die Installation des Tivoli TSM-Backup-Client 7.1.6 unter RHEL/CentOS/Fedora zu vereinfachen, habe ich für die Installation ein RPM-Paket erstellt. Der TSM-Backup-Client selbst wird vom Hersteller als TAR-Archiv bereitgestellt, welches die zur Installation benötigten RPM-Pakete enthält. Dazu gibt es eine Dokumentation, welche weitere z.T. optionale Abhängigkeiten aufführt. Darunter z.B. die Installation einiger Bibliotheken und eines Oracle JRE 1.7 oder höher.

All diese Dinge habe ich zusammen mit einem Skript, welches die initiale Installation und Konfiguration vornimmt, in ein RPM-Paket gepackt. Dieses Paket lässt sich auf dem Zielsystem installieren und durch die anschließende Ausführung des (selbst erstellten) Skripts tsm_init.sh werden die benötigten RPM-Pakete und Abhängigkeiten installiert.

Meine SPEC-Datei sieht wie folgt aus:

#---------------------------------------------------------------#
# version for using createRPM_* script
#---------------------------------------------------------------#
Name:      tsm-backup-client
Version:   7.1.6
Release:   1%{?dist}
Packager:  Tronde
Group:     Applications/System
Summary:   Tivoli TSM Backup Client for Linux

License:   non-free
URL:       http://example.com

BuildArch: x86_64
BuildRoot: %{_tmppath}/%{name}-%{version}

# $RPM_SOURCE_DIR : Variable of rpmbuild SOURCE dir
# $RPM_BUILD_DIR  : Variable of rpmbuild BUILD dir
# $RPM_BUILD_ROOT : Variable of rpmbuild BUILDROOT dir
#%define  

#BuildRequires:
Requires: libXrender
Requires: libXtst
Requires: libXp
Requires: xorg-x11-xauth

%description
This package installs the required packages and scripts for the
installation of the Tivoli TSM Backup Client for Linux.

The package contains:
 * bacli
 * tsm_init.sh
 * jre-8u91-linux-x64.tar.gz

#---------------------------------------------------------------#
# not used sections should be be set to comment
#---------------------------------------------------------------#
# The section '%prep' to extract the sourcefile 'Source0'
#%prep

# The section '%build' to build binaries from sources
#%build

# copy files to $RPM_BUILD_ROOT for using in the %files section
%install
cd $RPM_BUILD_ROOT
tar xvzf $RPM_SOURCE_DIR/%{name}.tgz
mv %{name}/* .
rmdir %{name}

# this files will be included in the rpm package
# with path on target host
%files
%defattr(-,root,root)
%doc
/root/bin/tsm_init.sh
/root/bin/start-tivoli-gui.sh
/data/bacli/gskcrypt64-8.0.50.66.linux.x86_64.rpm
/data/bacli/gskssl64-8.0.50.66.linux.x86_64.rpm
%doc /data/bacli/README_api_enu.htm
%doc /data/bacli/README_enu.htm
%doc /data/bacli/README
/data/bacli/cat_README.sh
/data/bacli/TIVsm-API64.x86_64.rpm
/data/bacli/TIVsm-APIcit.x86_64.rpm
/data/bacli/TIVsm-BAcit.x86_64.rpm
/data/bacli/TIVsm-BAhdw.x86_64.rpm
/data/bacli/TIVsm-BA.x86_64.rpm
/data/bacli/TIVsm-filepath-7.1.6-0-rhel59.x86_64.rpm
/data/bacli/TIVsm-filepath-7.1.6-0-rhel64.x86_64.rpm
/data/bacli/TIVsm-filepath-7.1.6-0-rhel7.x86_64.rpm
/data/bacli/TIVsm-filepath-7.1.6-0-sles11sp2.x86_64.rpm
/data/bacli/TIVsm-filepath-source.tar.gz
/data/bacli/TIVsm-JBB.x86_64.rpm
/data/jre-8u91-linux-x64.tar.gz

%clean
rm -rf %{buildroot}

# The section '%pre', for code to be executed prior to install
#%pre

# The section '%prerun' for code to be executed prior to uninstall
%preun

# the section '%post', for code to be executed after install
# normal sh script, prefs variables and macros can be used
%post

# The section '%postun' for code to be executed after uninstall
#%postun

%changelog
*Tue Jul 05 2016  Tronde 7.1.6-1
-- Initial Build.

Bisher erkannte Mängel

Mir sind bisher folgende Mängel aufgefallen:

  1. Nach der Installation des Pakets müssen die enthaltenen RPM-Pakete durch ein weiteres Skript installiert werden.
  2. Das Installationsskript muss manuell auf dem Zielsystem gestartet werden.
  3. Bei der Deinstallation werden die vom tsm_init.sh-Skript installierten RPM-Pakete nicht mit entfernt.

Meine Idee das tsm_init.sh-Skript in die Sektion %post zu packen hat leider nicht funktioniert, da ich die Paketverwaltung damit in einen Deadlock schicke. YUM ist noch durch den Installationsprozess blockiert, welcher mein RPM-Paket installiert und wartet darauf, dass der YUM-Aufruf aus meinem tsm_init.sh-Skript beendet werden kann. So geht es also nicht.

Was möchte ich eigentlich erreichen?

Erreichen möchte ich, dass durch die Installation eines RPM-Paktes die folgenden RPM-Pakete auf dem Zielsystem installiert werden:

  • gskcrypt64-8.0.50.66.linux.x86_64.rpm
  • gskssl64-8.0.50.66.linux.x86_64.rpm
  • TIVsm-API64.x86_64.rpm
  • TIVsm-BA.x86_64.rpm

Das Skript tsm_init.sh soll anschließend nur noch dazu verwendet werden, um den installierten TSM-Backup-Client mit einer initialen Konfiguration zu versehen. Ein zweites Skript soll an einem Ort abgelegt werden, von dem aus es ausgeführt werden kann.

Bisher ist meine einzige Idee, diese Aufgabe zu lösen, die vier genannten RPM-Pakete in ein YUM-Repository zu legen. In meiner SPEC-Datei kann ich sie dann als Abhängigkeiten definieren:

#BuildRequires:
Requires: gskcrypt64-8.0.50.66.linux.x86_64.rpm
Requires: gskssl64-8.0.50.66.linux.x86_64.rpm
Requires: TIVsm-API64.x86_64.rpm
Requires: TIVsm-BA.x86_64.rpm

Allerdings frage ich mich, ob es nicht auch eine Möglichkeit gibt, eine Art Meta-RPM zu erstellen, welches die benötigten RPMs enthält und diese Installiert. Ich könnte die Software auf diesem weg über ein einziges Paket bereitstellen.

Falls ihr Ideen oder Hinweise geben könnt, wie die Anforderung am besten umzusetzen ist, freue ich mich über eure Kommentare unter diesem Artikel.

SSH-Logins in RHEL/CentOS/Fedora auditieren

SSH-Logins werden unter RHEL, CentOS und Fedora in der Datei /var/log/secure protokolliert. Dieser Artikel beschreibt, wie man bei einem Audit den zum im Log protokollierten RSA-Fingerprint passenden SSH-Key identifiziert.

In dem hier beschriebenen Szenario wird angenommen, dass SSH-Logins ausschließlich über Public-Key-Authentifizierung zugelassen sind und die öffentlichen SSH-Schlüssel an zentraler Stelle im Dateisystem abgelegt sind. Darüber hinaus enthält jeder SSH-Schlüssel die E-Mail-Adresse des dazugehörigen Benutzers.

Authentifiziert sich ein Benutzer mit seinem öffentlichen SSH-Schlüssel an einem RHEL-, CentOS- oder Fedora-System, wird dies im Log /var/log/secure wie folgt dokumentiert:

Jun 18 15:34:55 hostname sshd[846]: Accepted publickey for tronde from X.X.X.X port 61362 ssh2: RSA cd:22:29:38:f7:e2:49:b1:a6:2f:8d:8f:cc:69:d7:c2

Neben Datum, Uhrzeit und dem verwendeten Benutzernamen wird hier der RSA-Fingerabdruck des verwendeten SSH-Publickey dokumentiert. Um nun herauszufinden, welcher SSH-Public-Key zu diesem Fingerabdruck gehört, nutze ich ein kleines Bash-Skript[1. Das Skript auf GitHub]:

#!/bin/bash
# Beschreibung:
# Dieses Skript gleicht einen RSA-Hash aus dem Log /var/log/secure mit den
# vorhandenen SSH-Public-Keys ab. Bei Uebereinstimmung wird der entsprechende
# Key ausgegeben.
#
# Der RSA-Hash wird dem Skript als Argument uebergeben.
#
# Autor: Joerg Kastning <joerg.kastning(aet)uni-bielefeld(punkt)de>

# Hauptteil #######################################################
rsa_fprint="$1"
printf "RSA-Fingerprint:\n${rsa_fprint}\n\n"
for key in *.pub
do
  tmp1=`/usr/bin/ssh-keygen -lf ${key}`
  set - $tmp1
  tmp2=`echo "$2"`
  if [[ "${rsa_fprint}" = "${tmp2}" ]]
  then
    printf "Der zugehoerige SSH-Key lautet:\n${tmp1}\n"
    exit 0
  fi
done
printf "Es wurde kein SSH-Key gefunden, welcher zu dem uebergebenen RSA-Fingerprint passt."
exit 0

Diesem Skript wird der RSA-Fingerabdruck als Argument übergeben. Das Skript generiert anschließend den RSA-Fingerabdruck aller SSH-Schlüssel in dem Verzeichnis, in dem das Skript aufgerufen wird und vergleicht diese mit dem übergebenen Fingerabdruck. Bei Übereinstimmung wird der zugehörige SSH-Schlüssel ausgegeben. Beispiel:

$ ./match_ssh-pubkey.sh cd:22:29:38:f7:e2:49:b1:a6:2f:8d:8f:cc:69:d7:c2
RSA-Fingerprint:
cd:22:29:38:f7:e2:49:b1:a6:2f:8d:8f:cc:69:d7:c2

Der zugehoerige SSH-Key lautet:
2048 cd:22:29:38:f7:e2:49:b1:a6:2f:8d:8f:cc:69:d7:c2  foo@example.com (RSA)
$

In diesem Beispiel gehört der verwendete SSH-Schlüssel dem Benutzer Foo. Auf diese Weise kann ein Audit mit einfachen Mitteln durchgeführt werden.

Ubuntu/Debian: PPA für PHP wechseln

In diesem Artikel dokumentiere ich den Wechsel eines PPA[1. „Personal Package Archive“] unter Ubuntu 14.04 LTS „Trusty Tahr“.

Achtung: Dies ist keine Schritt-für-Schritt-Anleitung. Die im Folgenden beschriebenen Schritte müssen auf einem anderen System nicht zwingend funktionieren. Fehler können euer System unbrauchbar machen. Also sagt nicht, ihr wurdet nicht gewarnt.

Warnung vor Fremdquellen: Die Benutzung fremder Quellen für Software sollte nach Möglichkeit auf das Notwendigste beschränkt werden, da sie einige gravierende Nachteile mit sich bringt.[2. ubuntuusers Wiki – Risiken von Fremdquellen]

Ich betreibe einen Server mit Ubuntu 14.04 LTS. In Trusty steht in den Originalquellen lediglich die PHP-Version 5.5.x zur Verfügung. Ich benötige jedoch PHP in Version 5.6.x und habe dazu das PPA ppa:ondrej/php5 in mein System eingebunden. Dieses PPA wurde nun von seinem Maintainer als deprecated markiert.

ppa:ondrej/php5 deprecated

ppa:ondrej/php5 deprecated

Der Maintainer stellt als Ersatz das PPA ppa:ondrej/php bereit. Dieses beinhaltet die PHP-Versionen 5.5, 5.6 und 7.0, welche auch nebeneinander installiert werden können.

Um dieses PPA meinem System hinzuzufügen, folge ich der PPA-Beschreibung[3. The main PPA for PHP (5.5, 5.6, 7.0) with many PECL[…]] und führe folgenden Befehl aus:

:~$ sudo LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php
 Co-installable PHP versions: PHP 5.5, 5.6, PHP 7.0 and batteries included.

You can get more information about the packages at https://deb.sury.org

For PHP 5.4 on Ubuntu 12.04 use: ppa:ondrej/php5-oldstable

BUGS&FEATURES: This PPA now has a issue tracker: https://deb.sury.org/#bug-reporting

PLEASE READ: If you like my work and want to give me a little motivation, please consider donating regularly: https://donate.sury.org/

WARNING: add-apt-repository is broken with non-UTF-8 locales, see https://github.com/oerdnj/deb.sury.org/issues/56 for workaround:

# LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php
 More info: https://launchpad.net/~ondrej/+archive/ubuntu/php
Press [ENTER] to continue or ctrl-c to cancel adding it

gpg: keyring `/tmp/tmptgkt4t8k/secring.gpg' created
gpg: keyring `/tmp/tmptgkt4t8k/pubring.gpg' created
gpg: requesting key E5267A6C from hkp server keyserver.ubuntu.com
gpg: /tmp/tmptgkt4t8k/trustdb.gpg: trustdb created
gpg: key E5267A6C: public key "Launchpad PPA for Ondřej Surý" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
OK
:~$

Analog zu dem oben ausgeführten Befehl wird das alte PPA aus dem System entfernt:

:~$ sudo add-apt-repository -r ppa:ondrej/php5
 This PPA is going to be DEPRECATED, please use ppa:ondrej/php

If you need other PHP versions use:
  PHP 5.4: ppa:ondrej/php5-oldstable (Ubuntu 12.04 LTS)
  PHP 5.5, PHP 5.6 and PHP 7.0: ppa:ondrej/php (Ubuntu 14.04 LTS - Ubuntu 16.04 LTS)

WARNING: add-apt-repository is broken with non-UTF-8 locales, see https://github.com/oerdnj/deb.sury.org/issues/56 for workaround:

# apt-get install -y language-pack-en-base
# LC_ALL=en_US.UTF-8 add-apt-repository ppa:ondrej/php5
 More info: https://launchpad.net/~ondrej/+archive/ubuntu/php5
Press [ENTER] to continue or ctrl-c to cancel removing it
:~$

Hinweis: Durch das Entfernen des PPA wird die aus diesem PPA installierte Software nicht vom System entfernt.

Um zukünftig die Software aus dem neuen PPA zu nutzen, werden die folgenden Befehle ausgeführt. Bei dieser Gelegenheit habe ich gleich meine PHP-Version auf 7.0 aktualisiert:

:~$ sudo apt-get update
:~$ sudo apt-get --reinstall install php-pear
Paketlisten werden gelesen... Fertig
Abhängigkeitsbaum wird aufgebaut.       
Statusinformationen werden eingelesen.... Fertig
Die folgenden zusätzlichen Pakete werden installiert:
  php-cli php-common php-xml php7.0-cli php7.0-common php7.0-json
  php7.0-opcache php7.0-readline php7.0-xml
Die folgenden NEUEN Pakete werden installiert:
  php-cli php-common php-xml php7.0-cli php7.0-common php7.0-json
  php7.0-opcache php7.0-readline php7.0-xml
Die folgenden Pakete werden aktualisiert (Upgrade):
  php-pear
1 aktualisiert, 9 neu installiert, 0 zu entfernen und 2 nicht aktualisiert.
Es müssen 2.284 kB an Archiven heruntergeladen werden.
Nach dieser Operation werden 9.839 kB Plattenplatz zusätzlich benutzt.
Möchten Sie fortfahren? [J/n] J

Operation beendet, Webanwendung funktioniert noch, Happy End.

Roundcube mit PGP-Unterstützung

Vor Kurzem wurde Roundcube Webmail[1. Roundcube Webmail] in Version 1.2.0 veröffentlicht. Zu einer der Neuerungen zählt die Unterstützung von PGP. Dabei hat man die Wahl zwischen der client-seitigen Verschlüsselung, basierend auf der Browser-Erweiterung Mailvelope und der server-seitigen Variante mittels Enigma-Plugins.

In diesem Artikel stelle ich beide Varianten kurz vor und zeige einige Punkte auf, die beim Einsatz zu beachten sind.

Zu Beginn noch einmal kurz zur Erinnerung: OpenPGP verwendet asymmetrische Verschlüsselung[2. Asymmetrische Verschlüsselung], bestehend aus einem privaten und einem öffentlichen Schlüssel. Dabei gilt, dass der private Schlüssel unbedingt vor unberechtigtem Zugriff zu schützen ist.

Enigma-Plugin

Das Enigma-Plugin ist bereits Bestandteil von Roundcube 1.2.0. Aleksander Machniak beschreibt in seinem englischsprachigen Blog die Installation und Nutzung des Plugins.[3. Enigma plugin (PGP encryption)]

Das Plugin befindet sich demnach bereits auf dem gleichen Server, auf dem auch die Roundcube-Installation läuft. Besitzt man selbst die vollständige Kontrolle über diesen Server, ist die Nutzung des Enigma-Plugins eine komfortable Lösung.

In meinem Fall läuft der Server, welcher die Roundcube-Installation hostet, jedoch bei einem Hosting-Provider. Zwar habe ich root-Zugriff auf diesen Host, doch besitze ich nicht die vollständige Kontrolle über diesen Server. Es besteht die Möglichkeit, dass beim Provider ein Zugriff auf meinen Server und damit auch auf meinen privaten Schlüssel erfolgen kann.

Mir persönlich ist das Risiko der Kompromittierung meines privaten Schlüssels bei dieser Variante zu groß. Daher scheidet sie für mich aus.

Mailvelope

Mailvelope[4. Mailvelope Webseite] stellt über eine Browser-Erweiterung eine client-seitige OpenPGP-Verschlüsselung für Webmailer bereit. Es existieren Erweiterungen für Chrome und Firefox. Die Schlüssel werden dabei im Benutzerverzeichnis von Chrome bzw. im Profilordner von Firefox gespeichert.[5. Mailvelope – Wo werden meine Schlüssel gespeichert?] Die Chrome-Einstellung „Nutzungsstatistiken und Absturzberichte automatisch an Google senden“, sollte man jedoch besser deaktivieren. Andernfalls könnten im Falle eines Absturzes Speicherinhalte mit privaten Schlüsseln an Google gesendet werden.

Verschlüsselt man die Festplatte mit der Installation, in der sich der private Schlüssel befindet, ist dieser zusätzlich bei Verlust oder Diebstahl des Endgeräts geschützt.

Der Vorteil dieser Variante liegt in jedem Fall darin, dass sich die Schlüssel auf einem Endgerät befinden, über das der Besitzer in der Regel die vollständige Kontrolle hat. Gerade wenn die Roundcube-Installation bei einem Hosting-Provider betrieben wird, ist diese Variante daher in meinen Augen vorzuziehen.

Fazit

Dass Roundcube nun zwei Varianten zur Nutzung von OpenPGP-Verschlüsselung unterstützt, finde ich grundsätzlich positiv. Für beide genannten Varianten gibt es sinnvolle Einsatzszenarien.

In jedem Fall sollte man für einen konkreten Anwendungsfall abwägen, bei welcher Variante der private Schlüssel besser geschützt ist.

Für mich persönlich habe ich beschlossen, dass keine der beiden beschriebenen Varianten für mich in Frage kommen. Die Variante mit dem Enigma-Plugin scheidet für mich aus, da mein Mailserver bei einem Hosting-Provider betrieben wird und ich nicht die vollständige Kontrolle über den Host habe.

Die Variante mit Mailvelope kommt für mich nicht in Frage, da es mir nicht gefällt, dass die Schlüssel im Webbrowser gespeichert und verwaltet werden. Ich besuche mit meinem Webbrowser täglich dutzende Webseiten und nutze verschiedenste Webdienste. Dabei besteht grundsätzlich das Risiko, dass mein Webbrowser durch Malware kompromittiert wird. Mir persönlich ist die Gefahr zu groß, dass dabei auch mein privater Schlüssel kompromittiert bzw. entwendet wird.

Meinen E-Mail-Client verwende ich hingegen ausschließlich zum Lesen und Schreiben von E-Mails. Die Angriffsfläche ist hier wesentlich kleiner und das Risiko geringer, dass mein privater Schlüssel kompromittiert wird.