Psono Passwortmanager installieren

Den kostenfreien OpenSource Passwortmanager Psono installieren

Diese Anleitung umfasst die Installation des Psono Passwortmanagers step-by-step ohne Fileserver. Leider ist die offizielle Anleitung nicht in allen Details vollständig, sodass ich hier auch Schritte und fehlende Einstellungen erwähne, die in der offiziellen Anleitung nicht auftauchen. Generell ist die Installation der Community Edition (CE) und er Enterprise Edition (EE) sehr ähnlich. Ich gehen an die Unterschiede an entsprechender Stelle ein.

Für Psono werden 2 Server benötigt. Für kleine installation wird für den Datenbankserver mindesten 1 CPU, 1,5GB RAM und 20GB HDD benötigt. Der zweite Server ist der eigentliche Applikationsserver, welcher 1 CPU, 1GB RAM und 10GB HDD benötigt. Für Installationen mit mehr als 100 Nutzern gelten andere Anforderungen. Siehe Installation Preparation | Psono Documentation.

Installation Datenbankserver

Voraussetzungen

  • Ein Debian oder Ubuntu Server in der aktuellsten Version inkl. aller Updates. Die Installation unter CentOS ist ebenfalls möglich. Darauf gehe ich hier aber nicht ein.
  • Eine Internetverbindung des Servers während der Installation.

Installation

Der Datenbankserver betreibt eine PostreSQL Datenbank. Um diese in der Version 13 (Mindestanforderung) zu installieren und für Psono vorzubereiten sind folgende Befehle nötig:

sudo apt -y install vim bash-completion wget gnupg lsb-release
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" | sudo tee  /etc/apt/sources.list.d/pgdg.list
sudo apt -y update
sudo apt -y install postgresql-13 postgresql-client-13

Wechseln zum postgres user

sudo -iu postgres

Eine neue Datenbank erstellen

createdb psono

Zum postgres Shell wechseln

psql psono

Den psono Datenbankbenutzer erstellen und die Berechtigungen vergeben. Ersetze das Passwort mit einem geheimen und sicheren Passwort.

CREATE USER psono WITH PASSWORD 'password';
GRANT ALL PRIVILEGES ON DATABASE "psono" to psono;

Die benötigen Postgres Erweiterungen installieren:

CREATE EXTENSION IF NOT EXISTS ltree;
CREATE EXTENSION IF NOT EXISTS "pgcrypto";

Die Postgres Shell verlassen:

\q (or Ctrl+D)

Den postgres Benutzerkontext verlassen und zurück zum originalen Benutzerkontext wechseln

exit

Nun muss die pg_hba.conf konfiguriert werden. Diese Datei enthält welche hosts, mit welchem Benutzer auf welche Datenbanken zugreifen dürfen. Standardmäßig darf nur der lokale Host auf Datenbanken zugreifen. Daher müssen wir nun konfigurieren, dass der Psono Applicationserver auf die psono Datenbank zugreifen darf. Dies fehlt in der offiziellen Dokumentation. Öffne die pg_hba.conf mit folgendem Befehl:

sudo nano /etc/postgresql/13/main/pg_hba.conf

Am Ende der Datei folgende Zeilen einfügen. Ersetze dabei <IP> mit der IP des Psono Applicationservers:

host    psono     psono     127.0.0.1/32      md5
host    psono     psono     ::1/128           md5
host    psono     psono     <IP>/32           md5

Auch in der postresql.conf wird eingeschränkt welche Server verbinden dürfen. Um dies zu ändern öffnen wir die postgresql.conf:

sudo nano /etc/postgresql/13/main/postgresql.conf

Drücke Strg + W um nach dem Wort listen zu suchen. Das erste oder zweite Ergebniss sollte eine Zeile sein, die nicht auskommentiert ist. Ersetze die Zeile mit dem folgenden um allen Hosts zu erlauben Verbindungen herzustellen: listen_addresses = '*'

Nun noch den Datenbankdienst neustarten und die Konfiguration ist erledigt:

sudo systemctl restart postgresql

Psono Application Server installieren

Voraussetzungen

  • Ein Debian oder Ubuntu Server in der aktuellsten Version inkl. aller Updates. Die Installation unter CentOS ist ebenfalls möglich. Darauf gehe ich hier aber nicht ein.
  • Eine Internetverbindung des Servers während der Installation.

Installation

Als erstes Docker installieren:

sudo apt install docker.io -y

Führe nun die folgenden Befehle aus und Kopiere die Ausgabe in ein Notepad oder ähnliches auf dem lokalen System. Wir benötigen diese später für die Konfiguration der settings.yaml.

docker run --rm -ti psono/psono-combo:latest python3 ./psono/manage.py generateserverkeys

Erstelle und öffne die settings.yaml Datei unter /opt/docker/psono:

sudo mkdir /opt/docker
sudo mkdir /opt/docker/psono
sudo nano /opt/docker/psono/settings.yaml

Settings file für Psono Community Edition (CE)

Dies stammt aus der offiziellen Doku: Install Psono’s combo CE image | Psono Documentation Füge folgenden Inhalt in die settings.yaml für die Psono Community Edition (CE) ein. Für die Enterprise Edition (EE) diesen Schritt überspringen.

# generate the following six parameters with the following command
# docker run --rm -ti psono/psono-combo:latest python3 ./psono/manage.py generateserverkeys
SECRET_KEY: 'SOME SUPER SECRET KEY THAT SHOULD BE RANDOM AND 32 OR MORE DIGITS LONG'
ACTIVATION_LINK_SECRET: 'SOME SUPER SECRET ACTIVATION LINK SECRET THAT SHOULD BE RANDOM AND 32 OR MORE DIGITS LONG'
DB_SECRET: 'SOME SUPER SECRET DB SECRET THAT SHOULD BE RANDOM AND 32 OR MORE DIGITS LONG'
EMAIL_SECRET_SALT: '$2b$12$XUG.sKxC2jmkUvWQjg53.e'
PRIVATE_KEY: '02...0b'
PUBLIC_KEY: '02...0b'

# The URL of the web client (path to e.g activate.html without the trailing slash)
# WEB_CLIENT_URL: 'https://psono.example.com'

# Switch DEBUG to false if you go into production
DEBUG: False

# Adjust this according to Django Documentation https://docs.djangoproject.com/en/2.2/ref/settings/
ALLOWED_HOSTS: ['*']

# Should be your domain without "www.". Will be the last part of the username
ALLOWED_DOMAINS: ['example.com']

# If you want to disable registration, you can comment in the following line
# ALLOW_REGISTRATION: False

# If you want to disable the lost password functionality, you can comment in the following line
# ALLOW_LOST_PASSWORD: False

# If you want to enforce that the email address and username needs to match upon registration
# ENFORCE_MATCHING_USERNAME_AND_EMAIL: False

# If you want to restrict registration to some email addresses you can specify here a list of domains to filter
# REGISTRATION_EMAIL_FILTER: ['company1.com', 'company2.com']

# Should be the URL of the host under which the host is reachable
# If you open the url and append /info/ to it you should have a text similar to {"info":"{\"version\": \"....}
HOST_URL: 'https://psono.example.com/server'

# The email used to send emails, e.g. for activation
# ATTENTION: If executed in a docker container, then "localhost" will resolve to the docker container, so
# "localhost" will not work as host. Use the public IP or DNS record of the server.
EMAIL_FROM: 'the-mail-for-for-example-useraccount-activations@test.com'
EMAIL_HOST: 'smtp.example.com'
EMAIL_HOST_USER: ''
EMAIL_HOST_PASSWORD : ''
EMAIL_PORT: 25
EMAIL_SUBJECT_PREFIX: ''
EMAIL_USE_TLS: False
EMAIL_USE_SSL: False
EMAIL_SSL_CERTFILE:
EMAIL_SSL_KEYFILE:
EMAIL_TIMEOUT: 10

# In case one wants to use mailgun, comment in below lines and provide the mailgun access key and server name
# EMAIL_BACKEND: 'anymail.backends.mailgun.EmailBackend'
# MAILGUN_ACCESS_KEY: ''
# MAILGUN_SERVER_NAME: ''

# In case you want to offer Yubikey support, create a pair of credentials here https://upgrade.yubico.com/getapikey/
# and update the following two lines before commenting them in
# YUBIKEY_CLIENT_ID: '123456'
# YUBIKEY_SECRET_KEY: '8I65IA6ASDFIUHGIH5021FKJA='

# If you have your own Yubico servers, you can specify here the urls as a list
# YUBICO_API_URLS: ['https://api.yubico.com/wsapi/2.0/verify']

# Cache enabled without belows Redis may lead to unexpected behaviour

# Cache with Redis
# By default you should use something different than database 0 or 1, e.g. 13 (default max is 16, can be configured in
# redis.conf) possible URLS are:
#    redis://[:password]@localhost:6379/0
#    rediss://[:password]@localhost:6379/0
#    unix://[:password]@/path/to/socket.sock?db=0
# CACHE_ENABLE: False
# CACHE_REDIS: False
# CACHE_REDIS_LOCATION: 'redis://127.0.0.1:6379/13'

# Enables the management API, required for the psono-admin-client / admin portal (Default is set to False)
MANAGEMENT_ENABLED: True

# Enables the fileserver API, required for the psono-fileserver
# FILESERVER_HANDLER_ENABLED: False

# Enables files for the client
# FILES_ENABLED: False

# Allows that users can search for partial usernames
# ALLOW_USER_SEARCH_BY_USERNAME_PARTIAL: True

# Allows that users can search for email addresses too
# ALLOW_USER_SEARCH_BY_EMAIL: True

# Disables central security reports
# DISABLE_CENTRAL_SECURITY_REPORTS: True

# Configures a system wide DUO connection for all clients
# DUO_INTEGRATION_KEY: ''
# DUO_SECRET_KEY: ''
# DUO_API_HOSTNAME: ''

# If you are using the DUO proxy, you can configure here the necessary HTTP proxy
# DUO_PROXY_HOST: 'the-ip-or-dns-name-goes-here'
# DUO_PROXY_PORT: 80
# DUO_PROXY_TYPE: 'CONNECT'
# If your proxy requires specific headers you can also configure these here
# DUO_PROXY_HEADERS: ''

# Normally only one of the configured second factors needs to be solved. Setting this to True forces the client to solve all
# MULTIFACTOR_ENABLED: True

# Allows admins to limit the offered second factors in the client
# ALLOWED_SECOND_FACTORS: ['yubikey_otp', 'google_authenticator', 'duo', 'webauthn']

# Your Postgres Database credentials
# ATTENTION: If executed in a docker container, then "localhost" will resolve to the docker container, so
# "localhost" will not work as host. Use the public IP or DNS record of the server.
DATABASES:
    default:
        'ENGINE': 'django.db.backends.postgresql_psycopg2'
        'NAME': 'psono'
        'USER': 'psono'
        'PASSWORD': 'password'
        'HOST': 'localhost'
        'PORT': '5432'
# for master / slave replication setup comment in the following (all reads will be redirected to the slave
#    slave:
#        'ENGINE': 'django.db.backends.postgresql_psycopg2'
#        'NAME': 'YourPostgresDatabase'
#        'USER': 'YourPostgresUser'
#        'PASSWORD': 'YourPostgresPassword'
#        'HOST': 'YourPostgresHost'
#        'PORT': 'YourPostgresPort'

# The path to the template folder can be "shadowed" if required later
TEMPLATES: [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['/root/psono/templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

Folgende Dinge müssen an der settings.yaml geändert werden:

  • Die ersten 6 Zeilen mit den secrets und keys müssen mit den Werten ersetzt werden, welche zuvor generiert wurden.*
  • Setze ALLOWED_DOMAINS zu der künftigen Domäne. Dies kann eine interne Domäne sein oder eine externe öffentliche Domäne, falls das System aus dem Internet erreichbar sein soll.
  • Setze die HOST_URL zu der URL, die genutzt wird um auf den Server zuzugreifen. Das “/server” Suffix am Ende muss bestehen bleiben.
  • Als nächstes müssen die E-Mail-Settings konfiguriert werden. Dies kann eine sehr herausfordernde Prozedur sein. Für den Fall, dass Microsoft 365 eingesetzt wird: Siehe das folgende Kapitel “Mail-Einstellungen für M365 Domänen”.
    • Setze EMAIL_FROM auf die E-Mail-Addresse, die als Absender der E-Mails von Psono angezeigt werden soll.
    • Setze EMAIL_HOST zur SMTP-Server Addresse.
    • Setze EMAIL_HOST_USER auf den Benutzer, der für die Authentifizierung am SMTP-Server erforderlich ist.
    • Setze EMAIL_HOST_PASSWORD auf das Passwort des Users
    • Setze EMAIL_PORT auf den zu nutzenden Port. Port 25 ist der unverschlüsselte SMTP Port. Port 587 ist Standard für StartTLS, 465 ist Standard für SSL verschlüsselte Verbindungen.
    • Setze EMAIL_SUBJECT_PREFIX zu einem Prefix, wenn gewünscht, der bei jeder E-Mail vor dem Titel steht, die Psono sendet.
    • Setze EMAIL_USE_TLS auf True, wenn StartTLS verschlüsselte SMTP-Verbindungen verwendet werden sollen. Ansonsten auf False.
    • Setze EMAIL_USE_SSL auf True, wenn SSL verschlüsselte SMTP-Verbindungen verwendet werden sollen. Ansonsten auf False.
    • Wen ein SSL Zeritifkat für SSL verschlüsselte Verbindungen vorhanden ist, muss der Pfad zum Zeritifikat hier angegeben werden. z.B. /opt/docker/psono/cert.pem und /opt/docker/psono/cert.key. Dies muss in dein Einstellungen EMAIL_SSL_CERTFILE und EMAIL_SSL_KEYFILE geschehen.
    • Lasse EMAIL_TIMEOUT auf dem Standardwert von 10 (Sekunden). Wenn eine wirklich langsame Internetverbindung besteht oder es andere berechtigte Gründe für eine Anpassung gibt, passe den Wert an.
  • Bei den DATABASES Einstellungen, setze den Wert für PASSWORD auf das Passwort, dass für den Psono-Datenbankuser bei der Datenbankserverinstallation gesetzt wurde.
  • Außerdem ebenfalls bei DATABASES den Wert HOST auf die IP des Datenbankservers.
  • Wenn das Auditing aktiviert werden soll:

Drücke Strg+O um die Änderungen zu speichern und Strg+X um nano zu schließen.

Settings.yaml für Psono Enterprise Edition (EE)

Die Inhalte der settings.yaml stammen aus der offiziellen Psono Dokumentation Install Psono’s combo EE | Psono Documentation. Füge den folgenden Inhalt in die neue settings.yaml ein. Überspringe diesen Schritt, wenn die Psono Community Edition genutzt werden soll.

# generate the following six parameters with the following command
# docker run --rm -ti psono/psono-combo:latest python3 ./psono/manage.py generateserverkeys
SECRET_KEY: 'SOME SUPER SECRET KEY THAT SHOULD BE RANDOM AND 32 OR MORE DIGITS LONG'
ACTIVATION_LINK_SECRET: 'SOME SUPER SECRET ACTIVATION LINK SECRET THAT SHOULD BE RANDOM AND 32 OR MORE DIGITS LONG'
DB_SECRET: 'SOME SUPER SECRET DB SECRET THAT SHOULD BE RANDOM AND 32 OR MORE DIGITS LONG'
EMAIL_SECRET_SALT: '$2b$12$XUG.sKxC2jmkUvWQjg53.e'
PRIVATE_KEY: '02...0b'
PUBLIC_KEY: '02...0b'

# The URL of the web client (path to e.g activate.html without the trailing slash)
# WEB_CLIENT_URL: 'https://psono.example.com'

# Switch DEBUG to false if you go into production
DEBUG: False

# Adjust this according to Django Documentation https://docs.djangoproject.com/en/2.2/ref/settings/
ALLOWED_HOSTS: ['*']

# Should be your domain without "www.". Will be the last part of the username
ALLOWED_DOMAINS: ['example.com']

# If you want to disable registration, you can comment in the following line
# ALLOW_REGISTRATION: False

# If you want to disable the lost password functionality, you can comment in the following line
# ALLOW_LOST_PASSWORD: False

# If you want to enforce that the email address and username needs to match upon registration
# ENFORCE_MATCHING_USERNAME_AND_EMAIL: False

# If you want to restrict registration to some email addresses you can specify here a list of domains to filter
# REGISTRATION_EMAIL_FILTER: ['company1.com', 'company2.com']

# Should be the URL of the host under which the host is reachable
# If you open the url and append /info/ to it you should have a text similar to {"info":"{\"version\": \"....}
HOST_URL: 'https://psono.example.com/server'

# The email used to send emails, e.g. for activation
# ATTENTION: If executed in a docker container, then "localhost" will resolve to the docker container, so
# "localhost" will not work as host. Use the public IP or DNS record of the server.
EMAIL_FROM: 'the-mail-for-for-example-useraccount-activations@test.com'
EMAIL_HOST: 'smtp.example.com'
EMAIL_HOST_USER: ''
EMAIL_HOST_PASSWORD : ''
EMAIL_PORT: 25
EMAIL_SUBJECT_PREFIX: ''
EMAIL_USE_TLS: False
EMAIL_USE_SSL: False
EMAIL_SSL_CERTFILE:
EMAIL_SSL_KEYFILE:
EMAIL_TIMEOUT: 10

# In case one wants to use mailgun, comment in below lines and provide the mailgun access key and server name
# EMAIL_BACKEND: 'anymail.backends.mailgun.EmailBackend'
# MAILGUN_ACCESS_KEY: ''
# MAILGUN_SERVER_NAME: ''

# In case you want to offer Yubikey support, create a pair of credentials here https://upgrade.yubico.com/getapikey/
# and update the following two lines before commenting them in
# YUBIKEY_CLIENT_ID: '123456'
# YUBIKEY_SECRET_KEY: '8I65IA6ASDFIUHGIH5021FKJA='

# If you have your own Yubico servers, you can specify here the urls as a list
# YUBICO_API_URLS: ['https://api.yubico.com/wsapi/2.0/verify']

# Cache enabled without belows Redis may lead to unexpected behaviour

# Cache with Redis
# By default you should use something different than database 0 or 1, e.g. 13 (default max is 16, can be configured in
# redis.conf) possible URLS are:
#    redis://[:password]@localhost:6379/0
#    rediss://[:password]@localhost:6379/0
#    unix://[:password]@/path/to/socket.sock?db=0
# CACHE_ENABLE: False
# CACHE_REDIS: False
# CACHE_REDIS_LOCATION: 'redis://127.0.0.1:6379/13'

# The server will automatically connect to the license server to get a license for 10 users.
# For paying customers we offer the opportunity to get an offline license code.
#
# LICENSE_CODE: |
#   0abcdefg...
#   1abcdefg...
#   2abcdefg...
#   3abcdefg...
#   4abcdefg...
#   5abcdefg...
#   6abcdefg...
#   7abcdefg...
#   8abcdefg...

# Enables the management API, required for the psono-admin-client / admin portal (Default is set to False)
MANAGEMENT_ENABLED: True

# Enables the fileserver API, required for the psono-fileserver
# FILESERVER_HANDLER_ENABLED: False

# Enables files for the client
# FILES_ENABLED: False

# Allows that users can search for partial usernames
# ALLOW_USER_SEARCH_BY_USERNAME_PARTIAL: True

# Allows that users can search for email addresses too
# ALLOW_USER_SEARCH_BY_EMAIL: True

# Disables central security reports
# DISABLE_CENTRAL_SECURITY_REPORTS: True

# Configures a system wide DUO connection for all clients
# DUO_INTEGRATION_KEY: ''
# DUO_SECRET_KEY: ''
# DUO_API_HOSTNAME: ''

# If you are using the DUO proxy, you can configure here the necessary HTTP proxy
# DUO_PROXY_HOST: 'the-ip-or-dns-name-goes-here'
# DUO_PROXY_PORT: 80
# DUO_PROXY_TYPE: 'CONNECT'
# If your proxy requires specific headers you can also configure these here
# DUO_PROXY_HEADERS: ''

# Normally only one of the configured second factors needs to be solved. Setting this to True forces the client to solve all
# MULTIFACTOR_ENABLED: True

# Allows admins to limit the offered second factors in the client
# ALLOWED_SECOND_FACTORS: ['yubikey_otp', 'google_authenticator', 'duo', 'webauthn']

# If you want to use LDAP, then you can configure it like this
#
# 		LDAP_URL: Any valid LDAP string, preferable with ldaps. usual urls are 'ldaps://example.com:636' or 'ldap://192.168.0.1:389'
#		LDAP_DOMAIN: Your LDAP domain, is added at the end of the username to form the full username
#		LDAP_BIND_DN: One User that can be used to search your LDAP
#		LDAP_BIND_PASS: The password of the user specified in LDAP_BIND_DN
#		LDAP_ATTR_GUID: The uuid attribute. e.g. on Windows 'objectGUID', but common are 'GUID' or 'entryUUID', default 'objectGUID'
#		LDAP_OBJECT_CLASS_USER: The objectClass value to filter user objects e.g. on Windows 'user', default 'user'
#		LDAP_OBJECT_CLASS_GROUP: The objectClass value to filter group objects e.g. on Windows 'group', default 'group'
#		LDAP_SEARCH_USER_DN: The "root" from which downwards we search for the users
#		LDAP_SEARCH_GROUP_DN: The "root" from which downwards we search for the groups
#		LDAP_ATTR_USERNAME: The username attribute to try to match against. e.g. on Windows 'sAMAccountName', default 'sAMAccountName'
#		LDAP_ATTR_EMAIL: The attribute of the user objects that holds the mail address e.g. on Windows 'mail', default 'mail'
#		LDAP_ATTR_GROUPS: The attribute of the user objects that holds the groups e.g. on Windows 'memberOf', default 'memberOf'
#		LDAP_REQUIRED_GROUP : The attribute to restrict access / usage. Only members of these groups can connect e.g. ['CN=groupname,OU=something,DC=example,DC=com'], default []
#		LDAP_CA_CERT_FILE: If you want to use ldaps and don't have a publicly trusted and signed certificate you can specify here the path to your ca certificate
#
#		LDAP_MEMBER_OF_OVERLAY: If your server has not this memberOf overlay, you can switch modes with this flag.
#                               Users will be mapped (based on their LDAP_ATTR_GROUP_MEMBER_ATTRIBUTE attribute) to groups (based on their LDAP_ATTR_MEMBERS attribute), default True
#		LDAP_ATTR_GROUP_MEMBER_ATTRIBUTE: The user attribute that will be used to map the group memberships, default 'uid'
#		LDAP_ATTR_MEMBERS: The group attribute that will be used to map the to the users LDAP_ATTR_GROUP_MEMBER_ATTRIBUTE attribute, default 'memberUid'
#
# To help you setup LDAP, we have created a small "testldap" command that should make things a lot easier. You can execute it like:
# docker run --rm \
#  -v /opt/docker/psono/settings.yaml:/root/.psono_server/settings.yaml \
#  -ti psono/psono-combo-enterprise:latest python3 psono/manage.py testldap username@something.com thePassWord
#
# For Windows AD it could look like this:
#
# LDAP : [
#     {
#         'LDAP_URL': 'ldaps://192.168.0.1:636',
#         'LDAP_DOMAIN': 'example.com',
#         'LDAP_BIND_DN': 'CN=LDAPPsono,OU=UsersTech,OU=example.com,DC=example,DC=com',
#         'LDAP_BIND_PASS': 'hopefully_not_123456',
#         'LDAP_SEARCH_USER_DN': 'OU=Users,OU=example.com,DC=example,DC=com',
#         'LDAP_SEARCH_GROUP_DN': 'OU=Groups,OU=example.com,DC=example,DC=com',
#     },
# ]
#
# If your server does not have the memberOf overlay, then you can also do something like this
#
# LDAP : [
#     {
#         'LDAP_URL': 'ldaps://192.168.0.1:636',
#         'LDAP_DOMAIN': 'example.com',
#         'LDAP_BIND_DN': 'CN=LDAPPsono,OU=UsersTech,OU=example.com,DC=example,DC=com',
#         'LDAP_BIND_PASS': 'hopefully_not_123456',
#         'LDAP_SEARCH_USER_DN': 'OU=Users,OU=example.com,DC=example,DC=com',
#         'LDAP_SEARCH_GROUP_DN': 'OU=Groups,OU=example.com,DC=example,DC=com',
#         'LDAP_OBJECT_CLASS_USER': 'posixAccount',
#         'LDAP_OBJECT_CLASS_GROUP': 'posixGroup',
#         'LDAP_ATTR_USERNAME': 'uid',
#         'LDAP_ATTR_GUID': 'entryUUID',
#         'LDAP_MEMBER_OF_OVERLAY': False,
#         'LDAP_ATTR_GROUP_MEMBER_ATTRIBUTE': 'uid',
#         'LDAP_ATTR_MEMBERS': 'memberUid',
#     },
# ]
#
# ATTENTION: API kays currently bypass LDAP authentication, that means API keys can still access secrets even if the
# user was disabled in LDAP. API keys can be disabled with COMPLIANCE_DISABLE_API_KEYS

# You also have to comment in the line below if you want to use LDAP (default: ['AUTHKEY'])
# For SAML authentication, you also have to add 'SAML' to the array.
# AUTHENTICATION_METHODS: ['AUTHKEY', 'LDAP']

# Enable Audit logging
# LOGGING_AUDIT: True

# To log to another destination you can specify this here, default '/var/log/psono'
# Never really necessary, as we will run the Psono server in a docker container and can mount /var/log/psono to any
# location on the underlying docker host.
# LOGGING_AUDIT_FOLDER: '/var/log/psono'

# If you prefer server time over utc, you can do that like below (default 'time_utc')
# LOGGING_AUDIT_TIME: 'time_server'

# If the server logs too much for you can either whitelist or blacklist events by their event code. (default: [])
# LOGGING_AUDIT_WHITELIST: []
# LOGGING_AUDIT_BLACKLIST: []

# If you are having Splunk and don't have a Splunk forwarder that can ship the logs, you can use Psono's native Splunk
# implementation to ship the logs for you. In order for that to work you need a Splunk HTTP EVent Collector to be
# configured as explained here https://dev.splunk.com/enterprise/docs/devtools/httpeventcollector/
# Afterwards configure the following variables:
# 
# SPLUNK_HOST The host, e.g. an ip or a domain
# SPLUNK_PORT The port, e.g. 8088 that you configured in the splunk http event collector
# SPLUNK_TOKEN The token of your splunk http event collector
# SPLUNK_INDEX The splunk index that you want the events to end up in By default 'main'
# SPLUNK_PROTOCOL 'http' or 'https' to indicate the protocol. By default 'https'
# SPLUNK_VERIFY True or False to indicate whether to verify certificates. By default True
# SPLUNK_SOURCETYPE The source type. By default 'psono:auditLog' (that one is compatible with the provided splunk addons)
#
# More infos can be found here https://github.com/zach-taylor/splunk_handler

# If you are having Logstash running and no way to ship logs with an external agent, you can use Psono's native Logstash
# implementation to ship the logs for you. In order for that to work you need a Splunk HTTP EVent Collector to be
# configured as explained here https://dev.splunk.com/enterprise/docs/devtools/httpeventcollector/
# Afterwards configure the following variables:
# 
# LOGSTASH_HANDLER Shipping logs either async (logstash_async.handler.AsynchronousLogstashHandler) or in sync (logstash_async.handler.SynchronousLogstashHandler). By default 'logstash_async.handler.SynchronousLogstashHandler'
# LOGSTASH_TRANSPORT The transport to use. TCP: logstash_async.transport.TcpTransport or UDP: logstash_async.transport.UdpTransport or Beats logstash_async.transport.BeatsTransport or HTTP logstash_async.transport.HttpTransport. Defaults to 'logstash_async.transport.TcpTransport'
# LOGSTASH_HOST The host, e.g. an ip or a domain
# LOGSTASH_PORT The port, e.g. 5959 that you configured the. By default 5959
# LOGSTASH_SSL_ENABLED Wether you want to use SSL or not. By default True
# LOGSTASH_SSL_VERIFY True or False whether to verify certificates. By default True
# LOGSTASH_CA_CERTS If you want a custom CA, you can specify here a path to the file with the certs
# LOGSTASH_CERFILE The path to the cert file
# LOGSTASH_KEYFILE The path to the key file
#
# More infos can be found here https://python-logstash-async.readthedocs.io/en/stable/index.html

# If you want to use SAML, then you can configure it like this as a dictionary.
#
# About the parameters:
#   idp->entityId: Thats the url to the metadata of your IDP
#   idp->singleLogoutService->url: Thats the url to the logout service of your IDP
#   idp->singleSignOnService->url: Thats the url to the single sign-on service of your IDP
#   idp->x509cert: Thats the certificate of your IDP
#   idp->groups_attribute: The attribute in the SAML response that holds your groups
#   idp->username_attribute: The attribute in the SAML response that holds the username. If you put here null, then it will use the NameID
#   idp->email_attribute: The attribute in the SAML response that holds the email address.
#   idp->username_domain: The domain that is appended to the provided username, if the provided username is not already in email format.
#   idp->required_group: A list of group names (casesensitive) in order to restrict who can use SAML login with this installation. Leave empty for no restriction.
#   idp->is_adfs: If you are using ADFS.
#   idp->honor_multifactors: Multifactor authentication can be bypassed with this flag for all SAML users (e.g. when you already enforce multifactor on the SAML provider).
#   idp->max_session_lifetime: The time in seconds that a session created throught SAML will live
#
#   sp->NameIDFormat: The normal nameformat parameter. (should only be set to transient if you have set a username attribute with username_attribute)
#   sp->attributeConsumingService: Only necessary if the IDP needs to be told to send some specific attributes
#   sp->x509cert: The X.509 cert
#   sp->privateKey: The corresponding private key of the X.509 cert
#
# There are a couple of more options next to those required ones below.
# More information can be found here https://github.com/onelogin/python3-saml
#
# A self-signed certificate can be generated with:
# openssl req -new -newkey rsa:2048 -x509 -days 3650 -nodes -sha256 -out sp_x509cert.crt -keyout sp_private_key.key
#
# To help you setup SAML, we have created a small "testsaml" command that should make things easier. You can execute it like:
# docker run --rm \
#  -v /opt/docker/psono/settings.yaml:/root/.psono_server/settings.yaml \
#  -ti psono/psono-combo-enterprise:latest python3 psono/manage.py testsaml
#
# The number 1 in line 2 is the provider id. Users are matched by the constructed username.
#
# SAML_CONFIGURATIONS:
#     1:
#         idp:
#             entityId: "https://idp.exampple.com/metadata.php"
#             singleLogoutService:
#                 binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
#                 url: "https://idp.exampple.com/SingleLogoutService.php"
#             singleSignOnService:
#                 binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
#                 url: "https://idp.exampple.com/SingleSignOnService.php"
#             x509cert: "ABC...=="
#             groups_attribute: "groups"
#             username_attribute: 'username'
#             email_attribute: 'email'
#             username_domain: 'example.com'
#             required_group: []
#             is_adfs: false
#             honor_multifactors: true
#             max_session_lifetime: 86400
#         sp:
#             NameIDFormat: "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
#             assertionConsumerService:
#                 binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
#             attributeConsumingService:
#                 serviceName: "Psono"
#                 serviceDescription: "Psono password manager"
#                 requestedAttributes:
#                     -
#                         attributeValue: []
#                         friendlyName: ""
#                         isRequired: false
#                         name: "attribute-that-has-to-be-requested-explicitely"
#                         nameFormat: ""
#             privateKey: "ABC...=="
#             singleLogoutService:
#                 binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
#             x509cert: "ABC...=="
#         strict: true
#
# You need a couple of urls to configure the IDP correctly. If the server is accessible under https://example.com/server
# (e.g. https://example.com/server/healthcheck/ shows some json output) and the provider id is 1 as in the example
# above the folling urls are valid:
#
# for metadata :                   https://example.com/server/saml/1/metadata/
# for assertion consumer service : https://example.com/server/saml/1/acs/
# for single logout service :      https://example.com/server/saml/1/sls/
#
#
# ATTENTION: API kays currently bypass SAML authentication, that means API keys can still access secrets even if the
# user was disabled in SAML. API keys can be disabled with COMPLIANCE_DISABLE_API_KEYS

# If you want to use OIDC, then you can configure it like this as a dictionary.
# OIDC_CONFIGURATIONS:
#     1:
#         OIDC_RP_SIGN_ALGO: 'RS256'
#         OIDC_RP_CLIENT_ID: 'whatever client id was provided'
#         OIDC_RP_CLIENT_SECRET: 'whatever secret was provided'
#         OIDC_OP_JWKS_ENDPOINT: 'https://example.com/jwks'
#         OIDC_OP_AUTHORIZATION_ENDPOINT: 'https://example.com/authorize'
#         OIDC_OP_TOKEN_ENDPOINT: 'https://example.com/token'
#         OIDC_OP_USER_ENDPOINT: 'https://example.com/userinfo'
#
# Standard parameters explained:
# OIDC_RP_SIGN_ALGO defaults to HS256 and needs to match the algo of your IDP
# OIDC_RP_CLIENT_ID the client id that is provided by your IDP
# OIDC_RP_CLIENT_SECRET the secret that is provided by your IDP
# OIDC_OP_JWKS_ENDPOINT The JWKS endpoint of your IDP
# OIDC_OP_AUTHORIZATION_ENDPOINT The authorization endpoint of your IDP
# OIDC_OP_TOKEN_ENDPOINT The token endpoint of your IDP
# 
# other parameters are:
# OIDC_VERIFY_JWT defaults to true, Controls whether Psono verifies the signature of the JWT tokens
# OIDC_USE_NONCE defaults to true, Controls whether Psono uses nonce verification
# OIDC_VERIFY_SSL defaults to true, Controls whether Psono verifies the SSL certificate of the IDP responses
# OIDC_TIMEOUT defaults to 10, Defines a timeout for all requests in seconds to the IDP (fetch JWS, retrieve JWT tokens, userinfo endpoint))
# OIDC_PROXY defaults to None, Defines a proxy for all requests to the IDP (fetch JWS, retrieve JWT tokens, Userinfo Endpoint). More infos can be found here https://requests.readthedocs.io/en/master/user/advanced/#proxies
# OIDC_RP_SCOPES defaults to 'openid email', The OpenID Connect scopes to request during login.
# OIDC_AUTH_REQUEST_EXTRA_PARAMS defaults to {}, Additional parameters to include in the initial authorization request.
# OIDC_RP_IDP_SIGN_KEY defaults to None, Sets the key the IDP uses to sign ID tokens in the case of an RSA sign algorithm. Should be the signing key in PEM or DER format.
# OIDC_ALLOW_UNSECURED_JWT defaults to False, Controls whether the Psono is going to allow unsecured JWT tokens (tokens with header {"alg":"none"}). This needs to be set to True if the IDP is returning unsecured JWT tokens and you want to accept them. See also https://tools.ietf.org/html/rfc7519#section-6
# OIDC_TOKEN_USE_BASIC_AUTH defaults to False, Use HTTP Basic Authentication instead of sending the client secret in token request POST body.

# Your Postgres Database credentials
# ATTENTION: If executed in a docker container, then "localhost" will resolve to the docker container, so
# "localhost" will not work as host. Use the public IP or DNS record of the server.
DATABASES:
    default:
        'ENGINE': 'django.db.backends.postgresql_psycopg2'
        'NAME': 'psono'
        'USER': 'psono'
        'PASSWORD': 'password'
        'HOST': 'localhost'
        'PORT': '5432'
# for master / slave replication setup comment in the following (all reads will be redirected to the slave
#    slave:
#        'ENGINE': 'django.db.backends.postgresql_psycopg2'
#        'NAME': 'YourPostgresDatabase'
#        'USER': 'YourPostgresUser'
#        'PASSWORD': 'YourPostgresPassword'
#        'HOST': 'YourPostgresHost'
#        'PORT': 'YourPostgresPort'

# The path to the template folder can be "shadowed" if required later
TEMPLATES: [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['/root/psono/templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

Folgende Dinge müssen an der settings.yaml geändert werden:

  • Die ersten 6 Zeilen mit den secrets und keys müssen mit den Werten ersetzt werden, welche zuvor generiert wurden.*
  • Setze ALLOWED_DOMAINS zu der künftigen Domäne. Dies kann eine interne Domäne sein oder eine externe öffentliche Domäne, falls das System aus dem Internet erreichbar sein soll.
  • Setze die HOST_URL zu der URL, die genutzt wird um auf den Server zuzugreifen. Das “/server” Suffix am Ende muss bestehen bleiben.
  • Als nächstes müssen die E-Mail-Settings konfiguriert werden. Dies kann eine sehr herausfordernde Prozedur sein. Für den Fall, dass Microsoft 365 eingesetzt wird: Siehe das folgende Kapitel “Mail-Einstellungen für M365 Domänen”.
    • Setze EMAIL_FROM auf die E-Mail-Addresse, die als Absender der E-Mails von Psono angezeigt werden soll.
    • Setze EMAIL_HOST zur SMTP-Server Addresse.
    • Setze EMAIL_HOST_USER auf den Benutzer, der für die Authentifizierung am SMTP-Server erforderlich ist.
    • Setze EMAIL_HOST_PASSWORD auf das Passwort des Users
    • Setze EMAIL_PORT auf den zu nutzenden Port. Port 25 ist der unverschlüsselte SMTP Port. Port 587 ist Standard für StartTLS, 465 ist Standard für SSL verschlüsselte Verbindungen.
    • Setze EMAIL_SUBJECT_PREFIX zu einem Prefix, wenn gewünscht, der bei jeder E-Mail vor dem Titel steht, die Psono sendet.
    • Setze EMAIL_USE_TLS auf True, wenn StartTLS verschlüsselte SMTP-Verbindungen verwendet werden sollen. Ansonsten auf False.
    • Setze EMAIL_USE_SSL auf True, wenn SSL verschlüsselte SMTP-Verbindungen verwendet werden sollen. Ansonsten auf False.
    • Wen ein SSL Zeritifkat für SSL verschlüsselte Verbindungen vorhanden ist, muss der Pfad zum Zeritifikat hier angegeben werden. z.B. /opt/docker/psono/cert.pem und /opt/docker/psono/cert.key. Dies muss in dein Einstellungen EMAIL_SSL_CERTFILE und EMAIL_SSL_KEYFILE geschehen.
    • Lasse EMAIL_TIMEOUT auf dem Standardwert von 10 (Sekunden). Wenn eine wirklich langsame Internetverbindung besteht oder es andere berechtigte Gründe für eine Anpassung gibt, passe den Wert an.
  • Bei den DATABASES Einstellungen, setze den Wert für PASSWORD auf das Passwort, dass für den Psono-Datenbankuser bei der Datenbankserverinstallation gesetzt wurde.
  • Außerdem ebenfalls bei DATABASES den Wert HOST auf die IP des Datenbankservers.
  • Wenn das Auditing aktiviert werden soll: Ersetze die Zeile # LOGGING_AUDIT: True mit LOGGING_AUDIT: True (Das # entfernen)
  • Später, wenn alles läuft, können noch weitere Einstellungen genauer geprüft und ggf. eingerichtet werden. z.B. für LDAP, Multifactor, Auditing Einstellungen etc.

Drücke Strg+O um die Änderungen zu speichern und Strg+X um nano zu schließen.

Nach der Einrichtung der settings.yaml, erstelle ein Verzeichniss für die audit logs:

sudo mkdir -p /var/log/psono

Mail-Einstellungen für M365 Domänen

Wenn Microsoft 365 (ehemals Office 365) genutzt wird um E-Mails zu verwalten, kann die folgende Anleitung (Option 2) dabei helfen dies einzurichten: Einrichten eines Multifunktionsgeräts oder einer Anwendung zum Senden von E-Mails mit Microsoft 365 oder Office 365 | Microsoft Learn Zusammengefasst müssen die E-Mail-Einstellung in der settings.yaml wie folgt gesetzt werden (Ersetze die Platzhalter entsprechend mit den Werten der zu nutzenden M365 Instanz):

EMAIL_FROM: '<anything>@<yourdomain>.<tld>'
EMAIL_HOST: '<your MX-Endpoint>' # i.e. contoso-com.mail.protection.outlook.com
# EMAIL_HOST_USER: ''        # No authentication
# EMAIL_HOST_PASSWORD : ''   # No authentication
EMAIL_PORT: 25               # Port 25 used for SMTP and StartTLS
EMAIL_USE_TLS: True
EMAIL_USE_SSL: False

Um zu verhindern, dass die E-Mails als Spam deklariert werden, kann ein SPF-Eintrag in den DNS-Einstellungen der Domäne gesetzt werden, wenn eine statische IP für den Internetanschluss genutzt wird. Dazu folgenden TXT-DNS-Eintrag der SPF-Settings mit folgendem Wert ergänzen: v=spf1 ip4:<Static IP Address> include:spf.protection.outlook.com ~all Da es vom DNS Anbieter abhängig ist wie genau dies konfiguriert wird, kann an dieser Stelle nicht im Detail darauf eingegangen werden, wie dies geschieht. Ggf. bitte den DNS-Anbieter kontaktieren.

E-Mail-Einstellungen testen

Nun muss getestet werden, ob die E-Mail-Einstellungen ohne Probleme funktionieren. Dies ist zwingend erforderlich. Ansonsten kann nichteinmal mit dem Testen von Psono begonnen werden. Ersetze testuser@testdomain.com mit einer validen Emfpänger-Adresse und führe folgenden Befehl aus:

sudo docker run --rm -v /opt/docker/psono/settings.yaml:/root/.psono_server/settings.yaml -ti psono/psono-combo-enterprise:latest python3 ./psono/manage.py sendtestmail testuser@testdomain.com

Datenbank vorbereiten

Um die Datenbank zu initalisieren, führe folgende Befehl aus:

Psono CE
sudo docker run --rm -v /opt/docker/psono/settings.yaml:/root/.psono_server/settings.yaml -ti psono/psono-combo:latest python3 ./psono/manage.py migrate
Psono EE
sudo docker run --rm -v /opt/docker/psono/settings.yaml:/root/.psono_server/settings.yaml -ti psono/psono-combo-enterprise:latest python3 ./psono/manage.py migrate

Client Konfiguration erstellen

Erstelle einen Ordner für den Psono Client (die Webseite) und erstelle eine neue Konfigurationsdatei:

sudo mkdir /opt/docker/psono-client/
sudo nano /opt/docker/psono-client/config.json

Füge folgenden Inhalt in die Datei ein:

{
  "backend_servers": [{
    "title": "Psono.pw",
    "url": "https://psono.example.com/server"
  }],
  "base_url": "https://psono.example.com/",
  "allow_custom_server": true,
  "allow_registration": true,
  "allow_lost_password": true,
  "disable_download_bar": false,
  "authentication_methods": ["AUTHKEY", "LDAP"],
  "saml_provider": []
}

Ändere den Inhalt wie folgt:

  • title zu dem Text, der angezeigt wird, wenn Benutzer die Psono Webseite besuchen.
  • url zum gleichen Wert wie HOST_URL in der settings.yaml
  • base_url zu dem gleichen Wert wie url aber ohne /server

Drücke Strg+O um die Änderungen zu speichern und Strg+X um nano zu schließen.

Psono starten

Folgenden Befehl ausführen um den Psono Dockercontainer zu starten

sudo docker run --name psono-combo-enterprise \
    --sysctl net.core.somaxconn=65535 \
    -v /opt/docker/psono/settings.yaml:/root/.psono_server/settings.yaml \
    -v /opt/docker/psono-client/config.json:/usr/share/nginx/html/config.json \
    -v /opt/docker/psono-client/config.json:/usr/share/nginx/html/portal/config.json \
    -v /path/to/log/folder:/var/log/psono \
    -d --restart=unless-stopped -p 10200:80 psono/psono-combo-enterprise:latest

Anschließend versuche folgende URL im Browser zu öffnen: http://<your server IP>:10200/server/info/. Wenn alles geklappt hat, wird eine Ausgabe angezeigt, die wie folgt beginnt: {"info":"{\"version\": .... Falls dies nicht der Fall ist, prüfe zunächst deine Firewall-Einstellungen.

Wartungsaufgaben

Um die Psono-Datenbank von Zeit zu Zeit aufzuräumen, wird ein cronjob benötigt. Konfigurieren diesen wie folgt:

sudo crontab -e

Wenn nach einem Editor gefragt wird, wähle nano aus. Füge folgendes ans Ende der Datei hinzu:

30 2 * * * docker run --rm -v /opt/docker/psono/settings.yaml:/root/.psono_server/settings.yaml -ti psono/psono-combo-enterprise:latest python3 ./psono/manage.py cleartoken >> /var/log/cron.log 2>&1

Drücke Strg+O um die Änderungen zu speichern und Strg+X um nano zu schließen.

Reverse Proxy einrichten

Nun läuft Psono, aber nur auf Port 80 (unverschlüsselt). Dies ist nicht gut. Wir werden nun einen Reverse Proxy einrichten, der den Endpunkt für die Benutzer dastellt und ein SSL-Zertifikat in die Verbindung zur Verschlüsselung einfügt. Dies kann mit jedem Reverse Proxy im Netzwerk erledigt werden (falls schon einer existiert). Falls nicht, kann auf dem Psono Application Server wie folgt einer eingerichtet werden.

Voraussetzungen

Es wird ein valides öffentliches Zertifikat benötigt (.pem), dem alle Clients, die zu Psono verbinden sollen, vertrauen. Ebenso der dazugehördende private Schlüssel (.key). Wenn von einer Windows Zertifikatsstelle eine .pfx-Datei erzeugt wurde, welche sowohl das öffentliche Zertifikat als auch den privaten Schlüssel enthält, so können wie folgt die .pem- und .key-Dateien daraus erzeugt werden:

Das öffentliche Zertifikat extrahieren (.pem):

openssl pkcs12 -in cert.pfx -out cert.pem -nokeys -clcerts`

Den privaten Schlüssel extrahieren (.key):

openssl pkcs12 -in cert.pfx -out cert.key -nocerts -nodes

Wenn die .pem nicht die vollständige Zertifizierungskette enthält, z.B. weil diese aus der .pfx-Datei extrahiert wurde, dann muss das öffentlichen Stammzertifizierungsstellenzertifikat der .pem-Datei noch angefügt werden (z.B. mit nano). Die .pem-Datei sieht dann am Ende wie folgt aus (ggf. sind am Begin noch einige Attribute enthalten):

-----BEGIN CERTIFICATE-----
MIIF9zCCBN+gAwIBAgITGwAAAAjgOR0bKF2AlwAAAAAACDANBgkqhkiG9w0BAQsF
...
inNyFgDzqdN8Y182+Da3iyQ4fz7pjySjyJlwk9GCJAwZLQtaudyKGInBKg==
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----
MIIDZzCCAk+gAwIBAgIQbwVSTbcyOrhIUgWXRTgKvDANBgkqhkiG9w0BAQsFADBF
...
38qV3rsb6mxhdgQ=
-----END CERTIFICATE-----

Das erste Zertifkat ist das öffentliche Zertifikat des Psono-Servers. Das zweite Zertifikat ist das Zertifikat der Stammzertifizierungsstelle.

Kopiere diese beiden Dateien nach /etc/ssl/ mit den Befehlen sudo cp cert.pem /etc/ssl und sudo cp cert.key /etc/ssl.

nginx installieren

sudo apt-get install nginx

site configuration erstellen

Erstelle eine neue Konfigurationsdatei (Dateinamen entsprechend anpassen) und füge den folgenden Text ein:

sudo nano /etc/nginx/sites-available/psono.example.com.conf
server {
    listen 80;
    server_name psono.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name psono.example.com;

    ssl_protocols TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_session_timeout 1d;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';

    # Comment this in if you know what you are doing
    # add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";

    add_header Referrer-Policy same-origin;
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";

    # If you have the fileserver too, then you have to add your fileserver URL e.g. https://fs01.example.com as connect-src too:
    add_header Content-Security-Policy "default-src 'none';  manifest-src 'self'; connect-src 'self' https://static.psono.com https://api.pwnedpasswords.com https://storage.googleapis.com https://*.digitaloceanspaces.com https://*.blob.core.windows.net https://*.s3.amazonaws.com; font-src 'self'; img-src 'self' data:; script-src 'self'; style-src 'self' 'unsafe-inline'; object-src 'self'; child-src 'self'";

    ssl_certificate /etc/ssl/fullchain.pem;
    ssl_certificate_key /etc/ssl/privkey.key;

    client_max_body_size 256m;

    gzip on;
    gzip_disable "msie6";

    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_min_length 256;
    gzip_types text/plain text/css application/json application/x-javascript application/javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;

    root /var/www/html;

    location ~* \.(?:ico|css|js|gif|jpe?g|png|eot|woff|woff2|ttf|svg|otf)$ {
        expires 30d;
        add_header Pragma public;
        add_header Cache-Control "public";

        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;
        proxy_hide_header Content-Security-Policy;
        
        proxy_pass          http://localhost:10200;
        proxy_redirect      http://localhost:10200 https://psono.example.com;
    }


    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;
        proxy_hide_header Content-Security-Policy;
	
        proxy_pass          http://localhost:10200;
        proxy_read_timeout  90;
	
        proxy_redirect      http://localhost:10200 https://psono.example.com;
    }
}

Ändere folgendes an dem Inhalt:

  • Setze die beiden Einstellungen ssl_certificate und ssl_certificate_key auf den Pfad, wo die beiden Zertifikatsdateien liegen. z.B.
      ssl_certificate /etc/ssl/cert.pem;
      ssl_certificate_key /etc/ssl/cert.key;
    
  • Ersetze psono.example.com mit der Domäne, die genutzt wird um den Psono server aufzurufen ÜBERALL in der Datei. Wenn der Server ausschließlich aus dem internen Netzwerk aufgerufen wird, setze hier den FQDN des Servers im Netzwerk.
  • Wenn der Server nur intern erreichbar sein soll, dann gibt es ggf. einen DNS-Alias für den Server (z.B. “psono”), den die Benutzer eingeben können um über den Browser Psono direkt öffnen zu können. Wenn dies so geschieht, werden diese jedoch beim Login oder bei der Registrierung stehts Server offline als Meldung erhalten. Um dies zu verhindern bauen wir eine automatische Weiterleitung auf den FQDN, wenn der Server nur mit dem Hostname/Alias aufgerufen wurde. Dazu fügen wir an den Anfang der nginx-Konfigurationsdatei folgendes ein. Ersetze dabei psono bei server_name mit dem Alias/Hostname, der genutzt wird und FQDN mit dem FQDN des servers. Außerdem müssen die Pfade zu den Zertifikatsdateien entsprechend der Speicherorte angepasst werden. ```nginx server { listen 80; server_name psono; return 301 https://FQDN; }

server { listen 443 ssl http2; server_name psono; return 301 https://FQDN;

ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
ssl_session_timeout 1d;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';

ssl_certificate /etc/ssl/cert.pem;
ssl_certificate_key /etc/ssl/cert.key; } ```

site configuration aktivieren

Erstelle einen Symlink zu der site configuration (Dateinamen anpassen):

sudo ln -s /etc/nginx/sites-available/psono.example.com.conf /etc/nginx/sites-enabled/

Konfiguration testen

Führe folgenden Befehl aus um zu testen, ob die erstellte nginx-Konfiguration fehlerfrei ist:

sudo nginx -t

Die Ausgabe sollte zeigen, dass der Test erfolgreich war. Wenn nicht wird in der Regel erwähnt was genau nicht korrekt ist.

Konfiguration anwenden

Um die Konfiguration anzuwenden, muss der nginx-Dienst neu gestartet werden:

sudo service nginx restart

Nun kann wieder getestet werden, ob Psono erreichbar ist. Dazu folgende URL in die Addresszeile des Browsers eingeben: https://YourDomainOrFqdnOrHostname/server/info/. Die Ausgabe sollte wieder mit {"info":"{\"version\":... starten.

Ersten User und Administrator einrichten

User registrieren

Gehe per Browser auf https://yourDomainOrFqdnOrHostname. Klicke dort auf “Registrieren” und führe die reguläre Registrierung durch - für einen User, der gleich Administrator werden soll. Nach der Verifizierung durch einen Klick auf den Link in der Verifizierungs-E-Mail, bei Psono anmelden. Wenn die Anmeldung erfolgreich war, erscheint die Startseite von Psono.

User zum Administrator machen

Der erste Administrator muss per Konsole zu einem solchen gemacht werden, da es diesem zum aktuellen Zeitpunkt noch nicht gibt. Hierzu folgenden Befehl auf dem Psono Applicationserver ausführen (die E-Mail-Adresse entsprechend ersetzten):

sudo docker run --rm \
  -v /opt/docker/psono/settings.yaml:/root/.psono_server/settings.yaml \
  -ti psono/psono-combo:latest python3 ./psono/manage.py promoteuser username@example.com superuser

Nun auf die Seite https://yourDomainOrFqdnOrHostname/portal gehen. Dies ist die Admin-Seite. Hier mit den gleichen Benutzerdaten anmelden, wie auf der Standard-Psono-Seite.

Neuste Blogposts

Install Mattermost behind OPNsense Reverse Proxy

This article is about installing mattermost behind a OPNsense reverse proxy using Ubuntu and the official Omnibus deployment method of Mattermost.

Mattermost hinter einem OPNsense Reverse Proxy installieren

Dieser Artikel beschreibt die Installation von Mattermost hinter einem OPNsense Reverse Proxy mit Ubuntu und der offiziellen Omnibus Deployment Methode von Mattermost.

Cluster Shared Volume (CSV) has redirected access

Troubleshooting guide for cluster shared volumes (CSV). From easy to hard.