In einem Beitrag haben wir SimpleSAMLphp vorgestellt, um zum Beispiel Singe-sign-on umzusetzen. Jetzt erweitern wir dieses Szenario und sichern das ganze mit einem 2. Faktor ab. Dazu verwenden wir die Open Source Software Privacyidea.
Auf der Projektseite heißt es:
privacyIDEA is a modular authentication server that can be used to enhance the security of your existing applications like local login, VPN, remote access, SSH connections, access to web sites or web portals with two factor authentication. Originally it was used for OTP (One Time Password) authentication devices – being an OTP server. But other “devices” like challenge response, U2F, Yubikeys, SSH keys and x509 certificates are also available.
Genau das brauchen wir.
Die Installation ist relativ einfach, wobei die Onlinedokumentation an manchen Stellen ein paar Lücken aufweist. Diese wird aber gut gefüllt mit der sehr aktiven Community, die auf Fragen rasch antwortet.
Die Installation wurde auf Debian (10/11) durchgeführt. Folgende Schritte sind notwendig.
Nachdem Privacyidea mit Python umgesetzt wurde, brauchen wir einige Python Pakete.
apt install python3 python3-venv virtualenv python3-virtualenv python3-wheel python3-all-dev
Und Falls nicht vorhanden braucht es auch noch einen Datenbankserver und ein paar andere Kleinigkeiten:
apt install mariadb-server mariadb-client libmariadbclient-dev libapache2-mod-wsgi-py3 gcc
Dann kann es schon los gehen. Wir legen ein Verzeichnis in /opt an und legen uns dort eine virtuelle Pythonumgebung an
mkdir /opt/privacyidea
python3 -m venv /opt/privacyidea/
Für die nächsten Schritte aktivieren wir diese Umgebung.
cd /opt/privacyidea
source bin/activate
Jetzt installieren wir mit Hilfe von pip3 alle notwendigen Pythonmodule. Nachdem privacyidea 3.6 die aktuelle Release ist, geben wir das auch entsprechend an. Andernfalls würden wir eine aktuellere nicht stabile Version installieren.
pip3 install wheel
pip3 install -r https://raw.githubusercontent.com/privacyidea/privacyidea/v3.6/requirements.txt
pip3 install privacyidea==3.6
pip3 install mysqlclient
Jetzt erstellen wir noch einen Benutzer, und das Verzeichnis für die Konfiguration – dieser Schritt fehlt in der Onlinedokumentation, im PDF-Dokument ist das jedoch enthalten. Unter diesem Benutzer laufen die Pythonskripte.
/sbin/useradd -r -m privacyidea -d /opt/privacyIDEA -s /bin/false
mkdir /etc/privacyidea
Wir erstellen die MySQL-Datenbank und führen dazu folgende SQL-Befehle aus.
CREATE DATABASE pi;
CREATE USER "pi"@"localhost" IDENTIFIED BY "PASSWORD";
GRANT ALL PRIVILEGES ON pi.* TO "pi"@"localhost";
flush privileges;
Die Installation ist soweit abgeschlossen. Jetzt geht es darum das ganze entsprechend zu konfigurieren.
Ein Schlüssel zum verschlüsseln diverser Infos in der Datenbank und zum Signieren des Auditlogs ist notwendig.
PEPPER="$(tr -dc A-Za-z0-9_ </dev/urandom | head -c24)" echo "PI_PEPPER = '$PEPPER'" >> /etc/privacyidea/pi.cfg SECRET="$(tr -dc A-Za-z0-9_ </dev/urandom | head -c24)" echo "SECRET_KEY = '$SECRET'" >> /etc/privacyidea/pi.cfg pi-manage create_enckey # encryption key for the database pi-manage create_audit_keys # key for verification of audit log entries
Die fertige pi.cfg sieht so aus. Die Datenbank-URI etc. müssen eventuell noch angepasst werden.
import logging
# The realm, where users are allowed to login as administrators
SUPERUSER_REALM = ['MYREALM']
# Your database
SQLALCHEMY_DATABASE_URI = 'mysql://pi:PASSWORD@localhost/pi'
PI_PEPPER = ''
SECRET_KEY = ''
PI_ENCFILE = '/etc/privacyidea/enckey'
# This is used to sign the audit log
PI_AUDIT_KEY_PRIVATE = '/etc/privacyidea/private.pem'
PI_AUDIT_KEY_PUBLIC = '/etc/privacyidea/public.pem'
PI_AUDIT_SQL_TRUNCATE = True
# The Class for managing the SQL connection pool
PI_ENGINE_REGISTRY_CLASS = "shared"
PI_AUDIT_POOL_SIZE = 20
PI_LOGFILE = '/var/log/privacyidea/privacyidea.log'
PI_LOGLEVEL = logging.INFO
Jetzt erstellen wir die Tabellen in der Datenbank
pi-manage createdb
Das Markieren der Datenbank auf die aktuelle Datenbankschemaversion ist für den späteren Aktualisierungsprozess wichtig:
pi-manage db stamp head -d /opt/privacyidea/lib/privacyidea/migrations/
Jetzt müssen wir noch einen Administrator anlegen.
pi-manage admin add ADMINLOGIN
Abschließend müssen wir noch den Webserver konfigurieren. Hier eine privacyidea.conf die am besten im Verzeichnis /etc/apache2/sites-enabled gespeichert wird.
<VirtualHost _default_:443>
ServerAdmin webmaster@localhost
# You might want to change this
ServerName MEINSERVER
DocumentRoot "/var/www/"
<Directory />
# For Apache 2.4 you need to set this:
Require all granted
Options FollowSymLinks
AllowOverride None
</Directory>
# Yubico servers use /wsapi/2.0/verify as the path in the
# validation URL. Some tools (e.g. Kolab 2fa) let the
# user/admin change the api host, but not the rest of
# the URL. Uncomment the following two lines to reroute
# the api URL internally to privacyideas /ttype/yubikey.
#RewriteEngine on
#RewriteRule "^/wsapi/2.0/verify" "/ttype/yubikey" [PT]
# We can run several instances on different paths with different configurations
WSGIScriptAlias /priv /opt/privacyidea/etc/privacyidea/privacyideaapp.wsgi
#WSGIScriptAlias /instance1 /home/privacyidea/deploy/privacyideaapp1.wsgi
#WSGIScriptAlias /instance2 /home/privacyidea/deploy/privacyideaapp2.wsgi
#WSGIScriptAlias /instance3 /home/privacyidea/deploy/privacyideaapp3.wsgi
#
# The daemon is running as user 'privacyidea'
# This user should have access to the encKey database encryption file
WSGIDaemonProcess privacyidea processes=1 threads=15 display-name=%{GROUP} user=privacyidea
WSGIProcessGroup privacyidea
WSGIPassAuthorization On
ErrorLog /var/log/apache2/error.log
LogLevel warn
# Do not use %q! This will reveal all parameters, including setting PINs and Keys!
# Using SSL_CLINET_S_DN_CN will show you, which administrator did what task
LogFormat "%h %l %u %t %>s \"%m %U %H\" %b \"%{Referer}i\" \"%{User-agent}i\"" privacyIDEA
CustomLog /var/log/apache2/ssl_access.log privacyIDEA
# SSL Engine Switch:
# Enable/Disable SSL for this virtual host.
SSLCertificateFile /etc/ssl/private/sslcert.crt
SSLCertificateKeyFile /etc/ssl/private/sslcert.key
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory /usr/lib/cgi-bin>
SSLOptions +StdEnvVars
</Directory>
</VirtualHost>
Den Webserver neu starten und dann kann der erste Login erfolgen. Wenn sich der Administrator anmeldet und kein useridresolver und kein Realm definiert ist, erscheint ein Popup, in dem Sie aufgefordert werden, einen Standard-Realm zu erstellen.
Für unser Szenario brauchen wir einen eigenen Realm und einen Resolver dazu. Wir erstellen zuerst einen Resolver unter Konfiguration => Benutzer.
Man kann aus verschiedenen Typen wählen (z.B. Ldap, SQL,…) wir wählen den SQL-Resolver
Die Zuordnung ist wichtig, wobei der erste Parameter immer der von Privacyidea ist und der zweite ein Feld in der angegebenen Datenbank. Achtung die WHERE-Klausel Syntax ist nicht ganz SQL-konform und hat 3 Parameter. Feld, Vergleichsoperator, Wert. z.B.: twoFactorUser == yes in SQL würde das dann so aussehen: twoFactorUser=“yes“
Vor dem Speichern testen wir den Resolver. Dabei sehen wir sofort ob und wie viele Datensätze er liefert.
Unter Konfiguration ==> Realms erstellen wir noch einen neuen Realm und ordnen diesem den soeben erstellten Resolver zu. Anschließend findet man unter Benutzer die entsprechenden Daten.
Wählt man dort einen Benutzer aus, kann diesem ein Token zugeordnet werden. Benutzer können sich auch selber einen Token zuordnen. Wie das mit Privacyidea umgesetzt wird, werde ich in einem späteren Beitrag erklären.
Jetzt geht es darum, SimpleSAMLphp so zu erweitern, dass der 2. Faktor auch verwendet werden muss.
SimpleSAMLphp
Das privacyidea-Modul für SimpleSAMLphp kann auf zwei Arten installiert werden.
Man verwendet composer und ruft folgenden Befehl auf:
php composer.phar require privacyidea/simplesamlphp-module-privacyidea:v1.6
Oder man lädt den Quellcode von Github herunter und kopiert ihn in des Modulverzeichnis von simpleSAMLphp – also in simpleSAMLphp/modules/privacyidea.
Jetzt müssen wir noch unseren SAML-Serviceprovider anpassen und einen authproc-Filter hinzufügen. Authproc-Filter werden in der config.php konfiguriert (um sie jedes Mal zu verwenden) oder in den Metadaten (um sie nur zu verwenden, wenn der Benutzer beispielsweise von einem bestimmten Dienstanbieter kommt). Jeder authproc-Filter wird in einem Array mit einer Nummer aufgelistet, die die Priorität anzeigt. Die niedrigste Zahl startet den Login-Vorgang.
20 => array(
'class' => 'privacyidea:serverconfig',
'privacyideaserver' => 'https://MYWEBSITE.AT/privacyidea',
'realm' => 'MYREALM',
'uidKey' => 'uid',
'sslverifyhost' => true,
'sslverifypeer' => true,
'serviceAccount' => '',
'servicePass' => '',
'tryFirstAuthPass' => 'simpleSAMLphp',
'enabledPath' => 'use_pi',
'enabledKey' => 'key',
),
24 => array(
'class' => 'core:PHP',
'code' => '
if ($state["Attributes"]["use2fa"][0]==0) {
$state["use_pi"] = ["key" => "0"];
}',
),
25 => array(
'class' => 'privacyidea:privacyidea',
),
Der Abschnitt 20 enthält die Serverkonfiguration und muss natürlichen entsprechend angepasst werden.
Abschnitt 24 deaktiviert privacyidea, falls das Attribut use2fa gleich 0 ist. Das Hilft bei einer langsamen Migration Richtung 2FA. Dadurch müssen nicht alle auf einmal einen 2. Faktor verwenden.
Abschnitt 25 aktiviert privacyIdea und nach dem 1. Login wir dann auch der 2. Faktor obligatorisch.
Man kann den 2. Faktor auch abhängig von der IP-Adresse deaktivieren. Damit wäre es möglich, die 2FA im schulinternen Netz abzudrehen.
21 => array (
'class' => 'privacyidea:checkClientIP',
'excludeClientIPs' => array("10.0.0.0-10.2.0.0", "192.168.178.10"),
),
Welchen 2. Faktor man unterstützt kann beim Erstellen des Tokens festgelegt werden.
Für einen Fido2 USB-Stick kann man zum Beispiel U2F auswählen. Gute Sticks gibt es zum Beispiel von https://www.nitrokey.com/de.
Auch TOTP klappt. Als Handy-App kann ich dazu FreeOTP empfehlen. Dies findest sich auch im f-droid-store.
Weitere Infos gibts unter https://www.privacyidea.org/
Für privacyidea gibt es auch Support von den https://netknights.it/
Image by Omar González from Pixabay
0 Kommentare