LDAPS mit SSL

Selbstsignierte Zertifikate

Das Problem mit den selbstsignierten Zertifikaten ist, dass man überall Probleme bekommt, wenn man SSL nutzen möchte. Hier ganz konkret die Nutzung eines Docker Containers mit Sonarqube. Es ist ohne viel Aufwand zu betreiben, nicht möglich Sonarqube zu überreden mit dem OpenLDAP Server mit SSL zu kommunizieren. Es müsste erst ein Truststore erstellt und dann in dem Container propagiert werden. Diese oder ähnliche Probleme bekommt man immer wieder.

LetsEncrypt Zertifikat

Wer sich ein Wildcard Zertifikat von LetsEncrypt für seine Domäne ausgestellt hat, der kann dieses auch nutzen um OpenLDAP per SSL abzusichern. Dieses hat dann den Vorteil, dass die oben beschriebenen Probleme nicht auftreten und das Leben viel einfacher wird.

Die Konfiguration von OpenLDAP

Die Verwendung der LetsEncrypt Zertifikate ist eigentlich nicht besonders schwierig. Es muss nur die Konfiguration angepasst werden. Editieren sie die Datei /etc/openldap/slapd.conf und passen sie die SSL Konfiguration an:

# Certificate/SSL Section
TLSCipherSuite DEFAULT
TLSCertificateFile /etc/openldap/ssl/cert.pem
TLSCertificateKeyFile /etc/openldap/ssl/privkey.pem
TLSCACertificateFile /etc/openldap/ssl/chain.pem
TLSCACertificatePath /usr/share/ca-certificates/trust-source

Damit das funktioniert, müssen aus dem LetsEncrypt live Verzeichnis die Dateien kopiert werden. Es muss für den User unter dem der OpenLDAP Server ausgeführt wird (meisten ldap) lesbar sein.

Konfiguration einlesen

Die Konfiguration muss nun in die Datenbank übernommen werden, da OpenLDAP die Konfigurationsdatei nicht mehr direkt einliest. Ich verwende immer ein kurzes Skript welches den Dreisatz für mich ausführt:

#!/bin/bash

# remove old config
rm -rf /etc/openldap/slapd.d/*

# create new files
slaptest -f /etc/openldap/slapd.conf -F /etc/openldap/slapd.d/

# chown to ldap:ldap
chown -R ldap:ldap /etc/openldap/slapd.d

Führen sie das Skript aus, damit die geänderte Konfiguration übernommen wird.

Server Test starten

Da bei Fehlern die Meldungen in Journal sehr dürftig sind, ist es besser wenn man den Server zum Testen auf der Konsole startet.

slapd -u ldap -g ldap -h ldaps://ldap.XXX.org:636 -d Config,Stats

Wichtig: Passt hier die Domain nicht, dann gibt es einen daemon: bind(8) failed errno=98 (Address already in use). Das Starten mit ldaps:/// reicht nicht !!!

Das Zertifikat von OpenLDAP überprüfen

Ist der Server gestartet, so bietet es sich an schnell mit openssl das Zertifikat zu überprüfen.

openssl s_client -connect ldap.XXX.org:636

Änderung Systemd

Zuletzt muss die override.conf von dem slapd.service muss nun angepasst werden. Danach starten sie per

systemctl start slapd.service

OpenLDAP neu.

KeyCloak

Der KeyClaok von JBoss ist ein IM (Identity Management) Tool. Mit KeyClaok lassen sich einfach SSO (Single Sign on) Lösungen mit verschiedenen Protokollen umsetzen. Dazu zählen das etwas ältere SAML2 genauso wie der aktuelle quasi Standard OpenID Connect alias OIDC.

Docker

Die Verwendung von KeyCloak mit Docker ist sehr einfach. Wie man es von Docker gewohnt ist, wird keine weitere Installation benötigt.

docker run -d -p 9001:8080 -e DB_VENDOR="h2" -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin --name keycloak jboss/keycloak    

Hier wird die interne in Memory Datenbank H2 explizit verwendet und die Anwendung auf dem Port 9001 exposed. Als Benutzername und Passwort wird admin festgelegt.

Docker mit Datenbank auf dem Host verwenden

KeyCloak kann mit verschiedenen Datenbanken betrieben werden. Diese können mit dem Docker Container in einem isolierten Netzwerk zusammen mit KeyCloak betrieben werden. Manchmal ist aber auch schon eine Datenbank auf dem Host vorhanden und diese soll auch benutzt werden. In diesem Beispiel möchte ich den KeyCloak mit einer auf dem Host laufenden MariaDB verwenden.

Vor dem ersten Start

Wichtig ist das beim Anlegen des Schemas auf latin2 geachtet wird. Muss vor dem Starten des Containers erfolgen, sonst erhält man beim Starten des Containers Fehlrermeldungen, dass die Rowsize nicht ausreiched sei. KeyCloak benötigt die 4096 Zeichen, weil hier die Key abgespeichert werden.

Den Host bekannt machen

Mit der –add-host Anweisung wird in dem Container ein Eintrag in der /etc/hosts Datei erzeugt. Hier also unser Hostname des Hosts und dessen statische IP Adresse. In diesem Fall hat der Host die statische Adresse 192.168.2.101. Sind Syntax ist hierbei Hostname:IP Adresse.

docker run --add-host=manjaro-server:192.168.2.101 --rm -d -p 9001:8080 -e DB_VENDOR=mariadb -e DB_ADDR=manjaro-server -e DB_DATABASE=keycloak -e DB_USER=root -e DB_PASSWORD=spfau -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin --name keycloak jboss/keycloak

Hinter NginX als Reverse Proxy mit SSL

Für die SSL Verschlüsselung kommt NginX als Reverse Proxy zum Einsatz. Die Konfiguration ist pretty straight forward.

Einstellungen in der NginX Konfiguration

# HTTP -> HTTPS
server {
    listen 80;
    server_name keycloak.xxx.org;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name keycloak.xxx.org;

    # SSL
    include /etc/nginx/ssl/*.xxx.org;

    # logging
    error_log /var/log/nginx/keycloak_error.log debug;
    access_log /var/log/nginx/keycloak_access.log;

    #
    # Serve KeyCloak
    #
    location / 
    {
        proxy_set_header        Host $host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        X-Forwarded-Proto $scheme;

        # static IP address of KeyCloak host
        proxy_pass              http://192.168.2.101:9001/;

        proxy_read_timeout      600s;
        proxy_send_timeout      600s;
    }
}

Anpassung des KeyCloak Docker Containers

Es muss das Proxy Address Forwarding aktiviert werden. Dazu wird in dem Container mit der JBoss-Cli die Einstellung geändert. Diese kann von außen mit Docker exec aufgerufen werden. Nun noch den Container neu starten, dann sollte der KeyCloak mit SSL über den Reverse Proxy abgesichert sein.

docker exec keycloak /opt/jboss/keycloak/bin/jboss-cli.sh --connect "/subsystem=undertow/server=default-server/http-listener=default:write-attribute(name=proxy-address-forwarding, value=true)"

FreshRSS

FreshRSS ist ein open Source RSS Feed Aggregator speziell für on premise Hosting.

Installation

Die Anwendung wird nach /usr/share/webapps/freshrss installiert. Hierzu muss man nur das Paket FreshRSS aus dem AUR installieren.

yaourt --noconfirm -S freshrss

Einrichtung NginX

# HTTP -> HTTPS
server {
    listen 80;
    server_name freshrss.xxx.org;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name freshrss.xxx.org;

    # SSL
    include /etc/nginx/ssl/*.xxx.org;

    # logging
    error_log /var/log/nginx/freshrss_error.log debug;
    access_log /var/log/nginx/freshrss_access.log;

    # the folder p of your FreshRSS installation
    root /usr/share/webapps/freshrss/p/;
    index index.php index.html index.htm;

    # php files handling
    # this regex is mandatory because of the API
    location ~ ^.+?\.php(/.*)?$ {
        fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        # By default, the variable PATH_INFO is not set under PHP-FPM
        # But FreshRSS API greader.php need it. If you have a “Bad Request” error, double check this var!
        fastcgi_param PATH_INFO $fastcgi_path_info;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

    location / {
        try_files $uri $uri/ index.php;
    }
}

Automatisches aktualisieren der Feed im Hintergrund

Leider bringt die Software keine Möglichkeit mit die abonnierten Feed automatisch im Hintergrund zu aktualisieren. Dieses ist aber nicht weiter dramatisch, da ein Systemd Timer schon das Problem lösen kann.

Timer Task bestimmen

Es muss nur das mitgelieferte Skript actualize_script.php mit den Benutzerrechten des WebServers ausgeführt werden. Unter Arch Linux ist das in der Regel der User http in der Gruppe http.

[Unit]
Description=auto refresh FreshRSS feeds

[Service]
Type=oneshot
User=http
Group=http
ExecStart=/usr/bin/php -f /usr/share/webapps/freshrss/app/actualize_script.php > /tmp/FreshRSS.log 2>&1

Interval einstellen

Eine Aktualisierung alle 10 Minuten anstoßen.

[Unit]
Description=refresh FreshRSS feeds every 10 minutes

[Timer]
OnCalendar=*:0/10
Persistent=true

[Install]
WantedBy=timers.target

Den Timer starten

Jetzt muss nur noch der Timer gestartet werden.

systemctl enable --now freshrss.timer

Git Credentials

Es ist auf Dauer müßig, immer und immer wieder die Credentials einzugeben. Daher gibt den internen Credentials Store von Git, aber dieser speichert nur SSH Credentials.

git config --global credentials.helper 'store --file ~/.git-credentials'

Lösung für HTTP(s) Verbindungen

Es gibt im AUR das Paket git-credential-gnome-keyring. Der Helper ermöglicht es auch für HTTP Verbindungen die Credentials zu speichern.

yaourt -S --noconfirm git-credential-gnome-keyring

Nun muss der Helper nur noch git bekannt gemacht werden:

git config --global credential.helper /usr/lib/git-core/git-credential-libsecret

Jetzt speichert Git die Credentials im Gnome-Keyring.

Wildcard Zertifikat

Der freie DNS Dienst DuckDNS bietet Unterstützung für TXT records an. Zudem werden beliebige SubDomains unterstützt, sodass das zusammen für die Validierung von Wildcard Zertifikaten von Let’s Encrypt zu gebrauchen ist. Mit den Wildcard Zertifikat kann man lokale Dienste auch über SSL verschlüsseln. Dazu kann man den NginX oder den Apache WebServer als Reverse Proxy einrichten.

Einrichtung mit Certbot

Unter Arch Linux verwende ich Certbot, um den Request anzufordern und die Challange zu lösen. Das lösen der Challange und somit die Validierung der Domain, geschiet in dem man ein Secret (Key) als TXT record Let’s Encrypt auf der Domain bereit stellt.

1. Schritt – Anforderung eines Wildcard Zertifikat

Als erstes müssen wir mit dem Certbot ein Wildcard Zertifikat anfordern. Das macht der Parameter -d. Tragen Sie hier ihre DuckDNS Domain ein für die sie ein Wildcard Zertifikat beantragen möchten. In diesem Beispiel also *.XXXXXXXXX.duckdns.org.

#request wildcard certificate
certbot --server https://acme-v02.api.letsencrypt.org/directory -d *.XXXXXXXXX.duckdns.org --manual --preferred-challenges dns-01 certonly

Beantworten Sie die Frage nach dem IP-Logging mit y.

certbot --server https://acme-v02.api.letsencrypt.org/directory -d *.XXXXXXXXX.duckdns.org --manual --preferred-challenges dns-01 certonly
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for XXXXXXXXX.duckdns.org

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NOTE: The IP of this machine will be publicly logged as having requested this
certificate. If you're running certbot in manual mode on a machine that is not
your server, please ensure you're okay with that.

Are you OK with your IP being logged?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.XXXXXXXXX.duckdns.org with the following value:

JAn7QDG3W4f-RqbztXnwkjET3DpU7GTImcysQfH60zE

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

Wichtig: Es muss nun zunächst der TXT record bei DuckDNS angelegt werden. Wechseln Sie zunächst in ein neues Terminal, bevor sie fortfahren.

2. Das Secret bereitstellen

Die Validierung, ob sie wirklich der Inhaber (oder berechtigter) sind, geschiet über ein Sekret welches sie in einem TXT record hinterlegen müssen. Wie sie der Ausgabe oben entnehmen können, ist das in diesem Fall der Key JAn7QDG3W4f-RqbztXnwkjET3DpU7GTImcysQfH60zE.

Die API von DuckDNS erlaubt es das setzen und löschen TXT records. Durch einen einfachen Aufruf mit curl sind wir in der Lage das Sekret zu setze.

 curl "https://www.duckdns.org/update?domains=XXXXXXXXX.duckdns.org&token=TTTTTTTT-TTTT-TTTT-TTTT-TTTTTTTTTTTT&txt=JAn7QDG3W4f-RqbztXnwkjET3DpU7GTImcysQfH60zE"

3. Überprüfen ob der TXT record gesetzt ist

In der UI von DuckDNS kann man leider die TXT records nicht erkennen. Daher können sie zum beispiel mit dig oder einem Online Dig Dienst dieses prüfen.

Ich nutze hier, wie von DuckDNS vorgeschlagen www.digwebinterface.com.

 https://www.digwebinterface.com/?hostnames=XXXXXXXXX.duckdns.org&type=TXT&ns=resolver&useresolver=8.8.4.4&nameservers=

Überprüfen sie mit dig, ob der TXT record verfügbar ist. Solange er nicht gesetzt ist, können sie mit dem nächsten Schritt nicht weiter machen.

4. Certbot Validierung fortsetzen

Nun kann die Validierung fortgesetzt werden und somit die Erstellung abgeschlossen werden.

Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/XXXXXXXXX.duckdns.org/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/XXXXXXXXX.duckdns.org/privkey.pem
   Your cert will expire on 2019-08-25. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Nun stehen die Dateien unter /etc/letsencrypt/live/XXXXXXXXX.duckdns.org/ bereit.

5. Cleanup – TXT record löschen

Die API von DuckDNS erlaubt, wie oben beschrieben, auch das löschen von TXT records. Der Aufruf ist identisch, bis auf das zusätzlich der Parameter clear=true mit angehangen wird.

curl "https://www.duckdns.org/update?domains=XXXXXXXXX.duckdns.org&token=TTTTTTTT-TTTT-TTTT-TTTT-TTTTTTTTTTTT&txt=JAn7QDG3W4f-RqbztXnwkjET3DpU7GTImcysQfH60zE&clear=true"

Installation

Docker besteht unter Arch Linux und Manjaro nur aus der Komponente docker. Damit man nicht als Root den Docker Daemon steuer muss, kann man einen benutzer in die Gruppe docker. Aufnehmen.

# Install Docker
yaourt --noconfirm -S docker
# add user to group docker
sudo usermod -aG docker $USER

Jetzt muss der User sich neu anmelden, damit die geänderten Gruppenrechte ziehen.

Hierbei muss sudo usermod -aG docker $USER als der User der Docker verwenden soll ausgeführt werden, da $USER auasgelesen wird. Danach muss der User sich neu einloggen, damit er die Gruppenrechte bekommt oder der User direkt angegeben werden.

Änderungen ohne Logout übernehmen

Mit su – BENUTZER kann eine Shell präsentieren die so aussieht, als wenn man sich auf der Virtuelle Konsole angemeldet hat.

su - $USER

Somit hat man die neu hinzugefügten Gruppenrechte und man kann mit Docker direkt loslegen.

Geringer Plattenplatz zur Verfügung?

Jeder kennt die Situation das schnell etwas mehr Plattenplatz her muss, weil zum Beispiel wichtige Updates anliegen. Wenn es schnell gehen muss, dann reicht oft eine Liste der Größten Dateien um zu entscheiden was gelöscht werden kann. Dazu reichen die Bordmittel von Linux aus. Ein bischen find, sort und head und schon bekommt man die größten Dateien auf dem Rootfilesystem angezeigt.

sudo find / -type f -ls | sort -k 7 -r -n | head -20

So lassen sich schnell die 20 größten Verbraucher an Plattenplatz bestimmen.

Aber Achtung: Es werden auch die virtuellen Dateisysteme (wenn eingehangen) mit untersucht und somit können auch bei viel Arbeitsspeicher Abbilder (/proc/kcore) oder VRAM der Grafikkarte mit in den Top 20 sein.

Spring Tool Suite mit Gradle unter JDK 11

Im allgemeinen funktioniert die Spring Tool Suite 4 (Version 4.0.2) unter dem aktuellen Java 11 LTS. Leider ist die Erkennung Java Versionen anscheinend sehr fragil, da zum Beispiel die aktuelle Version 11.0.1 nicht erkannt wird.

Dadurch funktioniert das Gradle Tooling (Eclipse Buildship Plugin) nicht und es wird das öffnen eines Gradle Projektes mit einer Fehlermeldung der Editoren quittiert.

An internal error occurred during: "Initializing Java Tooling".
Could not determine java version from '11.0.1'.

Bestimmung der JVM

Unter Arch Linux oder Manjaro werden die verschiedenen Java Versionen parallel unterhalb /usr/lib/jvm abgelegt. Mit dem kleinen Hilfsprogramm archlinux-java kann die Default JVM angezeigt und bestimmt werden. Ist diese nun zum Beispiel auf die aktuelle Version 11 eingestellt, dann läuft auch Eclipse bzw. die RCP und somit auch die Spring Tool Suite unter der JVM. Abhilfe schafft die .ini Datei im Root-Verzeichnis. Hier lässt sich u.a. die zu verwendende JVM angegeben.

[sp@Laptop ~]$ sudo archlinux-java status
Available Java environments:
  java-11-openjdk (default)
  java-8-graal
  java-8-openjdk

Der Parameter vm bestimmt den Pfad zur JVM. Dieser muss unbedingt vor dem Parameter vm-args angegeben werden!

-vm
/usr/lib/jvm/java-8-graal/bin/java
-vmargs
-Dosgi.requiredJavaVersion=1.8

In diesem Beispiel läuft Spring Tool Suite unter der GraalVM, obwohl die Default VM auf JDK 11 zeigt.

Makepkg

Das Tool makepkg gehört zur Toolsammlung von Arch Linux und deren Derivaten. Mit dem Bash Skript lassen sich die Pakete, die der Paketmanager Pacman verwaltet, bauen. Zum Bau der Pakete verwendet makepkg die BUILDSKRIPTS.

Das Temporäre Filesystem

Standardmäßig hängt Arch Linux oder dessen Derivat Manjaro das tmpfs auf /tmp ein, um eine dynamische RAM Disk für temporäre Dateien zur Verfügung zu stellen. Dieses bringt bei vielen Anwendungen Performanceverbesserung wie z.B. Firefox und Chrome die viele kleine Dateien zum Cachen ablegen.

Das Build

Beim Bau der Pakete werden zunächst die Quellen entpackt. Verwendet man yaourt, dann werden die Dateien nach /tmp/yaourt-user in ein eigenes Verzeichnis entpackt. Als nächstes folgt in der Regel die Kompilation der Quelltext und ein anschließendes Packen zu einem Archiv mit und auch ohne Kompression.

Das Problem

Da heute Softwaren nicht immer klein sind und nicht jedes Gerät mehr als 4 GB Arbeitsspeicher verfügt, kann es beim Bau der Pakete schnell zu dem Fehler “no space left on device” kommen, was nichts anderes bedeutet als das der Arbeitsspeicher verbraucht worden ist.

Lösungen

Zum einen kann man das automatische Mounten des temporären Dateisystems mit Systemd tmpfs maskieren und somit das einhängen beim Start verhindern. Das hat aber auch zur Folge das der gewüschte Performancezuwachs nicht mehr vorhanden ist.

Eine andere Lösung ist, dass man dem Programm makepkg den Pfad für die temporären Dateien vorgibt.

#-- Specify a directory for package building.
BUILDDIR=/home/sascha/PKGBUILDS/build

Ich habe immer ein lokales Verzeichnis, wo ich Änderungen an den Buildskripten vornehme. Dieses ist das Verzeichnis /home/sascha/PKGBUILDS und darin befindet sich der Ordner build. Wenn man jetzt ein großes Paket baut, so werden die Daten auf die Festplatte geschrieben und das Paket kann erfolgreich gebaut werden.