haupia

Betriebsdokumentation

e-Spirit AG

06.08.2020
Inhaltsverzeichnis

1. Neuigkeiten und Migrationsleitfäden

Version 2.0.62

Mit der Version 2.0.62 wurde intern von Spring Boot 1 auf Spring Boot 2 aktualisiert. Durch dieses Update kann zukünftig der Betrieb von haupia erleichtert werden. Dazu wurde exemplarisch in dieser Version ein Prometheus-Endpoint aktiviert, um ein Monitoring des Servers zu ermöglichen.

Durch dieses Major-Version-Upgrade müssen einige Konfigurationen in der application.yml angepasst werden. Hintergründe dazu sind auf dem Spring Boot 2 Migrationsguide zu finden. Es wurde bei dieser Gelegenheit die application.yml überarbietet und weiter verbessert.

Entfernen der cache-period:

spring:
   resources:
      cache-period: 3600

Der key definiert den 'cache control max age'-Wert für statische Dateien (zum Beispiel JS oder CSS). Dieser wird allerdings nicht benötigt und wurde entfernt.

Entfernen der MongoDB Excludes:

spring:
   autoconfigure:
      exclude:
      - org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration
      - org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration
      - org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration
      - org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfigura tion

Durch die Änderungen am Umgang mit MongoDB-Treibern innerhalb des Spring-Kontexts wurde das MongoDB-Modul vorerst deaktiviert. Damit müssen auch entsprechende Excludes nicht mehr verwendet werden.

Hinzufügen von:

spring:
   mandatory-file-encoding: UTF-8

Erzwingt die Verwendung von UTF-8 auf Dateiebene.

Hinzufügen von:

spring:
   http:
      encoding:
         charset: UTF-8
         enabled: true
         force: true

Erzwingt die Verwendung von UTF-8 bei der Kommunikation mit dem Server.

Ändern von:

spring:
   session:
      store-type: hash-map

auf:

spring:
   session:
      store-type: none

Deaktiviert die Verwendung von Spring Session, was der Standard ist.

Entfernen von:

management:
   contextPath: /api/boot

Ein geänderter Pfad wird nicht benötigt, da es nicht zu einem Namenskonflikt kommt. Die Verwendung der Actuatoren haben sich stark geändert. Es wird empfohlen diesen Teil der Konfiguration neu aufzusetzen. Die Konfiguration wird in einem eigenen Abschnitt beschrieben.

2. Serverlandschaft

Benötigt zum Betrieb von haupia wird neben der haupia-Instanz:

  • Eine oder mehrere Solr-Cloud-Instanz(en)
  • Eine oder mehrere ZooKeeper-Instanz(en)

Empfohlene Versionen

  • Solr: 8.4.1
  • ZooKeeper: 3.5.5

2.1. Solr-Cloud

haupia liefert ein eigenes Schema mit, das im Solr-Server installiert wird. Dafür müssen in der Solr-Installation folgende Jar-Dateien zusätzlich im Classpath vorhanden sein (Diese werden im contrib-Verzeichnis von Solr mitgeliefert):

  • morfologik-stemming-X.Y.Z.jar
  • morfologik-fsa-X.Y.Z.jar
  • morfologik-polish-X.Y.Z.jar
  • lucene-analyzers-morfologik-X.Y.Z.jar
  • lucene-analyzers-smartcn-X.Y.Z.jar

3. Update

Zu jedem Update wird ein umfangreiches Changelog mitgeliefert, das auch Informationen zu optionalen und benötigten Updates der Serverlandschaft enthält. In der Regel sind Updates abwärtskompatibel (auch zur Serverlandschaft) und können rollierend ausgeführt werden. Wenn möglich werden Features, die ein Update der Systemlandschaft benötigen mit einem Feature-Toggle implementiert, um diese Verwendung optional zu machen.

4. Lizenz

Die Lizenz für haupia wird auf dem Server in einer Textdatei hinterlegt. In der Datei application.yml wird mit folgendem key auf diese Datei verwiesen:

haupia:
   licence:
      path: ./license.txt

Der Name des ersten Mandanten entspricht dem Company-Name aus der Lizenz.

4.1. Benötigte Infrastruktur

ZooKeeper

Die Konfigurationen die im Backend vorgenommen werden, werden in einem ZooKeeper gespeichert. Es wird empfohlen dazu die gleiche ZooKeeper-Instanz zu verwenden, die bereits für die Solr-Cloud benötigt wird.

Als root-Knoten wird per default "haupia" verwendet, so ist eine Trennung zu den Daten von Solr gewährleistet. Die Konfigurationsdaten werden lesbar innerhalb dieses Ordners gespeichert. Dabei werden die vergebenen Namen der Konfiguration als Knotennamen verwendet und die Daten an sich im JSON-Format gespeichert. Diese Struktur kann mit einer externen GUI eingesehen werden, es wird aber empfohlen, diese nicht direkt zu ändern.

Der erste Knoten unterhalb von "haupia" ist der Name des Mandanten. In einem Multi- Mandantenumfeld sind hier entsprechend viele Ordner. Unterhalb davon sind Konfigurationen, die keine Abhängigkeit haben, zum Beispiel die PreparedSearches oder die Datengeneratoren. Es können sich unter diesen wiederum weitere Konfigurationen befinden, wenn diese Abhängigkeiten haben. Zum Beispiel befinden sich die AdaptableResults unterhalb der zugehörigen PreparedSearch. So kann anhand der Struktur bereits die Abhängigkeiten erkannt werden.

5. Tiefergehende Konfiguration

haupia basiert auf Spring-Boot. Zur Konfiguration wird die Datei application.yml verwendet, die im haupia-Verzeichnis nebem dem haupia-Jar liegt. Für eine Liste aller möglichen Konfigurationen wird auf die Spring-Boot-Dokumentation verwiesen.

Beispiel: SSL

haupia verwendet per default SSL, um eine sichere Übertragung der Daten zu ermöglichen. Dabei wird der Spring-Boot-Jetty im default verwendet. Dies sollte in den meisten Fällen funktionieren. Es kann aber bei der Wahl des Protokolls oder der Verschlüsselung zu Problemen kommen. In der Spring-Boot-Dokumentation werden dazu die Konfigurationskeys "server.ssl.enabled-protocols" und "server.ssl.ciphers" beschrieben. Um zunächst eine Liste von möglichen Parametern zu bekommen muss zunächst das Logging für Jetty für die richtige Stelle auf DEBUG gesetzt werden. Dazu wird im application.yml folgende Konfiguration aufgenommen:

logging:
   level:
      org:
         eclipse:
            jetty:
               util:
                  ssl: DEBUG

Danach wird am Ende des Startvorgangs eine Logausgabe ausgegeben, die ungefähr so aussieht:

May 22 11:14:50 haupia-cluster-1 server.jar[1208]: 2017-05-22 11:14:50.621 DEBUG 1230 --- [ main] o.e.jetty.util.ssl.SslContextFactory : Selected Protocols [TLSv1, TLSv1.1, TLSv1.2] of [SSLv2Hello, SSLv3, TLSv1, TLSv1.1, TLSv1.2]
May 22 11:14:50 haupia-cluster-1 server.jar[1208]: 2017-05-22 11:14:50.622 DEBUG 1230 --- [ main] o.e.jetty.util.ssl.SslContextFactory : Selected Ciphers [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_EMPTY_RENEGOTIATION_INFO_SCSV] of [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV, TLS_DH_anon_WITH_AES_128_GCM_SHA256, TLS_DH_anon_WITH_AES_128_CBC_SHA256, TLS_ECDH_anon_WITH_AES_128_CBC_SHA, TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SH
May 22 11:14:50 haupia-cluster-1 server.jar[1208]: A, SSL_DH_anon_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA, TLS_RSA_WITH_NULL_SHA256, TLS_ECDHE_ECDSA_WITH_NULL_SHA, TLS_ECDHE_RSA_WITH_NULL_SHA, SSL_RSA_WITH_NULL_SHA, TLS_ECDH_ECDSA_WITH_NULL_SHA, TLS_ECDH_RSA_WITH_NULL_SHA, TLS_ECDH_anon_WITH_NULL_SHA, SSL_RSA_WITH_NULL_MD5, TLS_KRB5_WITH_3DES_EDE_CBC_SHA, TLS_KRB5_WITH_3DES_EDE_CBC_MD5, TLS_KRB5_WITH_DES_CBC_SHA, TLS_KRB5_WITH_DES_CBC_MD5, TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA, TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5]

Bei diesen zwei Logausgaben werden die aktuellen Werte für Protokoll und Verschlüsselung, sowie die möglichen Werte ausgegeben. Soll nun zum Beispiel die Verschlüsselung auf zwei begrenz werden, kann dies wie folgt in der application.yml eingetragen werden:

server:
   ssl:
      ciphers:
         TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
         TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256

Gleiches gilt für das verwendete Protokoll. Beim Neustart kann dann im Log geprüft werden, ob die Konfiguration auch übernommen wurde.

6. Proxy-Konfiguration

Sollte ein http(s)-Proxy nötig sein damit die (Web/XML)-Crawler Zugriff auf ihre Crawlziele haben, so lässt dieser sich per JAVA_OPTS konfigurieren. Die relevanten Parameter zur Konfiguration sind die folgenden:

   

http.proxyHost

Host für den http-Proxy

12.13.14.15

http.proxyPort

Port für den http-Proxy

8080

https.proxyHost

Host für den https-Proxy

12.13.14.15

https.proxyPort

https.proxyPort

8080

http.nonProxyHosts

Ausnahmen bei denen der Proxy nicht berücksichtigt werden soll.

localhost

Exemplarischer Eintrag in die server.conf:

JAVA_OPTS="-server
-Dhaupia.master.profile=STANDALONE
-Dfile.encoding=UTF-8
-Dhttp.proxyHost=12.13.14.15
-Dhttp.proxyPort=8080
-Dhttps.proxyHost=12.13.14.15
-Dhttps.proxyPort=8080
-Dhttp.nonProxyHosts=localhost|127.0.0.1"

7. Troubleshooting

Vereinzeltes Synchronisieren von Teildokumenten

Bei der Verwendung eines lokalen Storage auf einer Netzwerkfestplatte kann es dazu kommen, dass bei Dokumente die letzte Änderung noch nicht komplett persistiert ist, bevor synchronisiert wird. Dadurch werden bei einem Dokument zum Beispiel die i18n-Felder nicht gesetzt. Um dies zu verhindern kann ein cool down für den Storage in der application.yml gesetzt werden. Dadurch wird dem Storage die konfigurierte Zeit in ms mitgegeben um alle Daten vollständig zu persistieren.

haupia:
   storage:
      cooldown: 500 #Example cooldown for the storage in ms
Aktivieren von Spring-Boot-Actuatoren

Spring Boot liefert eine Reihe von Actuatoren mit, die in der default Konfiguration von haupia aktiviert sind. Mit diesen ist es möglich zur Laufzeit einen Einblick in den Server zu bekommen. Es werden zum Beispiel Informationen zum aktuellen Environment oder Einstellungen der Logmeldungen geliefert. Für mehr Hintergrundinformationen zu den Actuatoren wird auf die Spring Boot Actuator Dokumentation verwiesen.

Die Actuatoren stellen Ihre Informationen über REST Services zur Verfügung. Dieses sind über HTTP Basic authentication gesichert und benötigen valide Zugangsdaten eines Users der Admin Gruppe.

management:
   endpoint:
      health:
         show-details: when-authorized
      metrics:
         enabled: true
      prometheus:
         enabled: true
   endpoints:
      web:
         exposure:
            include: "*"
            exclude:
               - "heapdump"
   metrics:
      export:
         prometheus:
            enabled: false
            descriptions: false

Diese Konfiguration aktiviert die default Endpunkte, deaktiviert allerdings explizit den heap dump Endpunkt. Der heap dump Endpunkt ermöglicht potentiell einen Download in GB Größe was evtl. in einer Produktionsumgebung nicht unbedingt gewünscht ist.

Um einen Überblick über die aktuellen Actuatoren zu bekommen kann folgende URL verwendet werden:

  • Method: GET
  • URL: /actuator

    Beim Aufruf wird eine Basic Authentifizierung mit einem Benutzer der Admin Gruppe durchgeführt. Der Nutzer aus der application.yml, kann zu diesem Zweck verwendet werden.

    Eine mögliche Antwort:

    {
       "_links": {
          "self": {
             "href": "https://haupia-server:8181/actuator",
             "templated": false
          },
          "auditevents": {
             "href": "https://haupia-server:8181/actuator/auditevents",
             "templated": false
          },
          "beans": {
             "href": "https://haupia-server:8181/actuator/beans",
             "templated": false
          },
          "health": {
             "href": "https://haupia-server:8181/actuator/health",
             "templated": false
          },
          "conditions": {
             "href": "https://haupia-server:8181/actuator/conditions",
             "templated": false
          },
          "configprops": {
             "href": "https://haupia-server:8181/actuator/configprops",
             "templated": false
          },
          "env": {
             "href": "https://haupia-server:8181/actuator/env",
             "templated": false
          },
          "env-toMatch": {
             "href": "https://haupia-server:8181/actuator/env/{toMatch}",
             "templated": true
          },
          "info": {
             "href": "https://haupia-server:8181/actuator/info",
             "templated": false
          },
          "loggers": {
             "href": "https://haupia-server:8181/actuator/loggers",
             "templated": false
          },
          "loggers-name": {
             "href": "https://haupia-server:8181/actuator/loggers/{name}",
             "templated": true
          },
          "threaddump": {
             "href": "https://haupia-server:8181/actuator/threaddump",
             "templated": false
          },
          "metrics": {
             "href": "https://haupia-server:8181/actuator/metrics",
             "templated": false
          },
          "metrics-requiredMetricName": {
             "href": "https://haupia-server:8181/actuator/metrics/{requiredMetricName}",
             "templated": true
          },
          "scheduledtasks": {
             "href": "https://haupia-server:8181/actuator/scheduledtasks",
             "templated": false
          },
          "httptrace": {
             "href": "https://haupia-server:8181/actuator/httptrace",
             "templated": false
          },
          "mappings": {
             "href": "https://haupia-server:8181/actuator/mappings",
             "templated": false
          }
       }
    }
Verwenden der Logging-API zur Anpassung der Log-Level

Die Aktivierung der Actuatoren wurde weiter oben erläutert.

Es existiert ein spezieller Spring-Boot-Actutator zum Umgang mit den Logging Einstellungen. Dieser ermöglicht das Ändern der Log-Level zur Laufzeit. Öffnet man auf einer haupia-Instanz die unten stehende relative URL, so werden zunächst alle derzeit konfigurierten Log-Level ausgegeben:

  • Method: GET
  • URL: /actuator/loggers

    Es können auch Informationen zu einem speziellen Logger ausgegeben werden:

  • Method: GET
  • URL: /actuator/loggers/<Logger>

    Beispiel URL zum Abruf vom Logger "de.arithnea.haupia.Server"

  • URL: /actuator/loggers/de.arithnea.haupia.Server

    Eine mögliche Antwort:

    {
       "configuredLevel": "INFO",
       "effectiveLevel": "INFO"
    }

    Zum Anpassen eines Log-Levels wird ein POST-Request gegen eine konkrete Logger-URL ausgeführt, in dem im JSON-Format das neue Log-Level übermittelt wird:

  • Method: POST
  • URL: /actuator/loggers/<Logger>

    Der Body ist ein JSON Object mit dem key "configuredLevel" und als Wert den gewünschten log Level. Beispiel:

    $ curl 'https://haupia-server:8181/actuator/loggers/de.arithnea.haupia.Server'
    -i -u 'user:password' -X POST \
       -H 'Content-Type: application/json' \
       -d '{
          "configuredLevel" : "DEBUG"
       }'

    Im Erfolgsfall wird der Code 204 zurück gegeben.

Prometheus Endpoint

Prometheus ist ein Tool zum Monitoring von Prozessen. Dieses Tool erfasst in Regelmäßigen Abständen den Zustand eines Prozesses und ermöglicht eine Zeitliche Auswertung der Daten. So kann zum Beispiel der Speicherverbrauch im Verhältnis zu den Anfragen an die REST Services beobachtet werden. haupia liefert bereits vorkonfiguriert einen Prometheus Endpunkt mit, der über die application.yml noch aktiviert werden muss. Zum Aktivieren muss folgender key auf true gesetzt werden:

management:
   metrics:
      export:
         prometheus:
            enabled: true

Danach ist ein Endpoint unter der URL:

  • URL: /actuator/prometheus

    verfügbar.

    In Prometheus kann nun der Endpoint zum Beispiel wie folgt eingebunden werden:

    scrape_configs:
       - job_name: 'haupia'
       metrics_path: '/actuator/prometheus'
       scheme: https
       basic_auth:
          username: admin@localhost.de
          password: admin
       static_configs:
          - targets: ['haupia-server:8181']

8. Unsignierte SSL-Zertifikate

Bei folgendem Fehler im Log gilt es das Zertifkat des HTTPS-Servers welcher gecrawlt wird (XML/Web-Crawler) in den keystore des haupia-Servers einzubinden:

Caused by: sun.security.validator.ValidatorException:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Dies wird erreicht, indem die Zertifikatsdatei heruntergeladen wird, und mit dem "keytool"- Befehl zur JRE hinzugefügt wird.

Exemplarisch ein Aufruf für MacOS:

sudo keytool -import -alias BELIEBIGER_ALIAS -keystore /PFAD_ZUR_JAVA_JRE/lib/security/cacerts -file /PFAD/ZUM/ZERTIFIKAT/zertifikats.datei

9. Rechtliche Hinweise

haupia ist ein Produkt der e-Spirit AG, Dortmund, Germany.
Für die Verwendung des Produkts gilt gegenüber dem Anwender nur die mit der e-Spirit AG vereinbarte Lizenz.