HCL Connections Dateiupload über den IBM HTTP Server statt WebSphere mit mod_ibm_upload

Standardmäßig werden Dateiuploads in HCL Connections über den WebSphere-Anwendungsserver durchgeführt. Der vorgeschaltete IBM HTTP Server fungiert dabei als eine Art Reverse Proxy. Diese Konstellation ist – vor allem in größeren Umgebungen – aus mehreren Gründen suboptimal: WebSphere ist schlecht für das Hoch- und Herunterladen großerer Dateien ausgelegt. Und hierbei sprechen wir nicht einmal von 5GB aufwärts, die das offizielle Limit von nur 2GB bei weitem sprengen würden. Inoffiziell lässt sich diese nicht mehr wirklich zeitgemäße Limitierung auch nur über den IHS praktikabel umgehen. In diesem Artikel möcht ich mich jedoch darauf fokusieren, dies unter einer Connections 6.5.1 überhaupt erst einmal zum Laufen zu bekommen. Zumindest in der aktuellen Version war einiges an Rervese Engineering und ausprobieren notwendig.

Der Artikel gliedert sich in zwei Abschnitte: Der Erste ist eher eine praktische Anleitung, um den Dateiupload über den IHS zu realisieren. Teil 2 behandelt die Probleme, welche bei Anwendung der offiziellen Doku auftreten mit Details zu meinen Recherchen/Tests. Connections bietet auch die Möglichkeit, die Uploads aus den Aktivitäten per IHS auszuliefern. Das habe ich in diesem Artikel zur Vereinfachung nicht behandelt, sollte sich mit den hier dargestellten Lösungswegen aber auch umsetzen lassen. In meinen Augen ist es dort zu vernachlässigen, da größere Dateien eher in der Files-Anwendung hochgeladen werden.

So bekommt man den Dateiupload per ISH unter CNX 6.5 zum Laufen (Praktische Anleitung)

Konfiguration des IBM HTTP Servers

Wahrscheinlich habt ihr einen 64 Bit IHS und benötigt dementsprechend eines der 64 Bit Module – Wahlweise aus dem ihs.linux.x86_64 oder ihs.linux.ia32 Ordner. Die Dokumentation erwähnt nicht worin sich diese unterscheiden, in meinen Tests funktionieren beide.

cp /opt/HCL/Connections/ihs/mod_ibm_upload/ihs.linux.x86_64/mod_ibm_upload.so /opt/IBM/HTTPServer/modules/

In der httpd.conf des IHS beide Module laden. Auch das Rewrite-Modul wird benötigt, da im Falle des Uploads per IHS die URL umgeschrieben wird:

LoadModule rewrite_module modules/mod_rewrite.so
LoadModule ibm_upload_module modules/mod_ibm_upload.so

Damit der IHS die Uploads ins Dateisystem schreiben darf, benötigt er Schreibzugriff. Und zwar auf den files/upload Ordner im Shared Directory. Bei Bedarf kann man ihn in der ISC über die WAS-Variablen einsehen. In meinem Fall lautet er /opt/IBM/shared, woraus sich der Uploadpfad /opt/IBM/shared/files/upload/ ergibt. Per ACL gewähren wir nobody (dem Standard-IHS Benutzer) Zugriff und erstellen eine ACL für neue Daten:

chown nobody:nobody -R /opt/IBM/shared/files/upload
setfacl -R -d -m user:nobody:rwx /opt/IBM/shared/files/upload

Dies muss vom Dateisystem unterstützt werden – hier getestet auf einem CentOS 7.9 Server mit XFS. Gegebenfalls muss zusätzlich das Leserecht auf /opt/IBM/shared gewährt werden, je nach Mount/Dateisystem.

Der Upload kann nun im IHS aktiviert werden. Dazu muss der Konfigurationsblock aus der Doku in den VirtualHost eingefügt werden. Ich habe das mit einer Teilkonfiguration gelöst, die per Include eingebunden wird:

<VirtualHost *:443>
  SSLEnable
   RedirectMatch "^/$" "/homepage"
   Include conf/ihs-upload.conf
</VirtualHost>

In die Datei conf/ihs-upload.conf müssen folgende Direktiven:

<IfModule mod_rewrite.c>
RewriteEngine On

# Uncomment to create log messages.
RewriteLog logs/rewrite.log
RewriteLogLevel 9

RewriteCond %{ENV:ENV-SKIP-IBM-UPLOAD-HANDLER} !=true [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-METHOD} phases [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-TOKEN} [0-9a-zA-Z-] [NC]
RewriteCond %{REQUEST_METHOD} !=GET [NC]
RewriteCond %{REQUEST_METHOD} !=OPTION [NC]
RewriteCond %{REQUEST_METHOD} !=HEAD [NC]
RewriteCond %{REQUEST_METHOD} !=DELETE [NC]
RewriteRule ^/files/(basic|form|oauth)/api/myfilesync/feed(\?[^/]*)? /ihs/files/$1/api/myfilesync/feed$2 [PT,L]

RewriteCond %{ENV:ENV-SKIP-IBM-UPLOAD-HANDLER} !=true [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-METHOD} phases [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-TOKEN} [0-9a-zA-Z-] [NC]
RewriteCond %{REQUEST_METHOD} !=GET [NC]
RewriteCond %{REQUEST_METHOD} !=OPTION [NC]
RewriteCond %{REQUEST_METHOD} !=HEAD [NC]
RewriteCond %{REQUEST_METHOD} !=DELETE [NC]
RewriteRule ^/files/(basic|form|oauth)/api/userlibrary/([^/]+)/feed(\?[^/]*)? /ihs/files/$1/api/userlibrary/$2/feed$3 [PT,L]

RewriteCond %{ENV:ENV-SKIP-IBM-UPLOAD-HANDLER} !=true [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-METHOD} phases [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-TOKEN} [0-9a-zA-Z-] [NC]
RewriteCond %{REQUEST_METHOD} !=GET [NC]
RewriteCond %{REQUEST_METHOD} !=OPTION [NC]
RewriteCond %{REQUEST_METHOD} !=HEAD [NC]
RewriteCond %{REQUEST_METHOD} !=DELETE [NC]
RewriteRule ^/files/(basic|form|oauth)/api/communitylibrary/([^/]+)/feed(\?[^/]*)? /ihs/files/$1/api/communitylibrary/$2/feed$3 [PT,L]

RewriteCond %{ENV:ENV-SKIP-IBM-UPLOAD-HANDLER} !=true [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-METHOD} phases [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-TOKEN} [0-9a-zA-Z-] [NC]
RewriteCond %{REQUEST_METHOD} !=GET [NC]
RewriteCond %{REQUEST_METHOD} !=OPTION [NC]
RewriteCond %{REQUEST_METHOD} !=HEAD [NC]
RewriteCond %{REQUEST_METHOD} !=DELETE [NC]
RewriteRule ^/files/(basic|form|oauth)/api/myfilesync/document/([^/]+)/entry(\?[^/]*)? /ihs/files/$1/api/myfilesync/document/$2/entry$3 [PT,L]

RewriteCond %{ENV:ENV-SKIP-IBM-UPLOAD-HANDLER} !=true [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-METHOD} ^phases$ [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-TOKEN} ^[0-9a-zA-Z-]+$ [NC]
RewriteCond %{REQUEST_METHOD} !=GET [NC]
RewriteCond %{REQUEST_METHOD} !=OPTION [NC]
RewriteCond %{REQUEST_METHOD} !=HEAD [NC]
RewriteCond %{REQUEST_METHOD} !=DELETE [NC]
RewriteRule ^/files/(basic|form|oauth)/api/library/([^/]+)/document/([^/]+)/entry(\?[^/]*)? /ihs/files/$1/api/library/$2/document/$3/entry$4 [PT,L]

RewriteCond %{ENV:ENV-SKIP-IBM-UPLOAD-HANDLER} !=true [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-METHOD} phases [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-TOKEN} [0-9a-zA-Z-] [NC]
RewriteCond %{REQUEST_METHOD} !=GET [NC]
RewriteCond %{REQUEST_METHOD} !=OPTION [NC]
RewriteCond %{REQUEST_METHOD} !=HEAD [NC]
RewriteCond %{REQUEST_METHOD} !=DELETE [NC]
RewriteRule ^/files/(basic|form|oauth)/api/userlibrary/([^/]+)/document/([^/]+)/entry(\?[^/]*)? /ihs/files/$1/api/userlibrary/$2/document/$3/entry$4 [PT,L]

RewriteCond %{ENV:ENV-SKIP-IBM-UPLOAD-HANDLER} !=true [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-METHOD} phases [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-TOKEN} [0-9a-zA-Z-] [NC]
RewriteCond %{REQUEST_METHOD} !=GET [NC]
RewriteCond %{REQUEST_METHOD} !=OPTION [NC]
RewriteCond %{REQUEST_METHOD} !=HEAD [NC]
RewriteCond %{REQUEST_METHOD} !=DELETE [NC]
RewriteRule ^/files/(basic|form|oauth)/api/myuserlibrary/document/([^/]+)/entry(\?[^/]*)? /ihs/files/$1/api/myuserlibrary/document/$2/entry$3 [PT,L]

RewriteCond %{ENV:ENV-SKIP-IBM-UPLOAD-HANDLER} !=true [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-METHOD} phases [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-TOKEN} [0-9a-zA-Z-] [NC]
RewriteCond %{REQUEST_METHOD} !=GET [NC]
RewriteCond %{REQUEST_METHOD} !=OPTION [NC]
RewriteCond %{REQUEST_METHOD} !=HEAD [NC]
RewriteCond %{REQUEST_METHOD} !=DELETE [NC]
RewriteRule ^/files/(basic|form|oauth)/api/myuserlibrary/feed(\?[^/]*)? /ihs/files/$1/api/myuserlibrary/feed$2 [PT,L]

RewriteCond %{ENV:ENV-SKIP-IBM-UPLOAD-HANDLER} !=true [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-METHOD} phases [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-TOKEN} [0-9a-zA-Z-] [NC]
RewriteCond %{REQUEST_METHOD} !=GET [NC]
RewriteCond %{REQUEST_METHOD} !=OPTION [NC]
RewriteCond %{REQUEST_METHOD} !=HEAD [NC]
RewriteCond %{REQUEST_METHOD} !=DELETE [NC]
RewriteRule ^/files/(basic|form|oauth)/api/communitylibrary/([^/]+)/document/([^/]+)/entry(\?[^/]*)? /ihs/files/$1/api/communitylibrary/$2/document/$3/entry$4 [PT,L]

RewriteCond %{ENV:ENV-SKIP-IBM-UPLOAD-HANDLER} !=true [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-METHOD} phases [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-TOKEN} [0-9a-zA-Z-] [NC]
RewriteCond %{REQUEST_METHOD} !=GET [NC]
RewriteCond %{REQUEST_METHOD} !=OPTION [NC]
RewriteCond %{REQUEST_METHOD} !=HEAD [NC]
RewriteCond %{REQUEST_METHOD} !=DELETE [NC]
RewriteRule ^/files/(basic|form|oauth)/api/library/([^/]+)/feed(\?[^/]*)? /ihs/files/$1/api/library/$2/feed$3 [PT,L]

RewriteCond %{ENV:ENV-SKIP-IBM-UPLOAD-HANDLER} !=true [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-METHOD} phases [NC]
RewriteCond %{HTTP:X-IBM-UPLOAD-TOKEN} [0-9a-zA-Z-] [NC]
RewriteCond %{REQUEST_METHOD} !=GET [NC]
RewriteCond %{REQUEST_METHOD} !=OPTION [NC]
RewriteCond %{REQUEST_METHOD} !=HEAD [NC]
RewriteCond %{REQUEST_METHOD} !=DELETE [NC]
RewriteRule ^/files/(basic|form|oauth)/api/document/([^/]+)/entry(\?[^/]*)? /ihs/files/$1/api/document/$2/entry$3 [PT,L]

</IfModule>

<Location "/ihs/files">
        IBMUploadHandler On
        SetHandler ibm_upload_handler
        IBMUploadBaseStore "/opt/IBM/shared/files/upload/files"
        IBMUploadMethods POST,PUT
        IBMUploadURLPrefix /ihs
        IBMUploadActivateResumable On
</Location>

Neben dem ggf. anzupassenden Uploadpfad enthält der Block nur eine neue, aber wichtige Zeile im Gegensatz zu HCL Doku:

IBMUploadActivateResumable On

Fehlt diese Zeile, erhaltet ihr beim Upload von Dateien größer als 500MB eine Fehlermeldung. Damit ist der IHS abgeschlossen und muss lediglich noch neu gestartet werden.

Konfiguration von WebSphere (Files-Anwendung)

In der files-config.xml ist das Modul standardmäßig seit einiger Zeit aktiviert, sofern man es nicht explizit abgeschaltet hat (wirkt sich nicht negativ aus, so lange der IHS nicht wie oben beschrieben konfiguriert wurde):

<upload>
       <modIBMUpload enabled="true"/>
</upload>

Nun setzen wir ein Limt für die simpleUploadAPI, die über WebSphere läuft – also mit Overhead. Tragen wir hier z.B. 128MB ein, kommt bis 128MB der WAS zum Einsatz und erst darüber der IHS.

<api>
     <indent enabled="false"/>
     <simpleUploadAPI maximumSizeInKb="128000">
     ...

Wichtig noch das generelle Größenlimit, zu finden in file.media

<file>
     ...
     <media maximumSizeInKb="5000000"/>
     ...

Dieses Limit greift unabhängig von der Uploadart und erzeugt bei Überschreitung auch eine Fehlermeldung für den Benutzer. Laut HCL werden offiziell lediglich maximal 2GB unterstützt. In Kombination mit dem IHS-Upload ist in der Praxis mehr möglich.

Nach dem vollständigen Neu-Synchronisieren und einem Neustart der Files-Anwendung greifen die Änderungen. Man sollte nun Dateien bis zum files.media Limit hochladen können.

Probleme und Fallstricke bei der offiziellen Doku: Die Hintergründe

In diesem Abschnitt gehe ich ausführlicher auf die Probleme ein, die in meiner CNX 6.5.1 Umgebung bei Verwendung der offiziellen HCL-Dokumentation aufgetreten sind. Wer sich weniger für die Hintergründe interessiert und primär eine funktionierende Installation realisieren möchte, findet eine funktionierende Anleitung im oberen ersten Abschnitt.

Architektur: Es gibt auch einen (bzw. zwei) 64 Bit IHS!

Hier beginnt das erste Problem. In der Dokumentation wird darauf hingewiesen, der IBM HTTP Server sei immer nur eine 32-Bit Anwendung – dementsprechend würde auch das 32 Bit Modul benötigt werden.

These directories are valid whether you installed the IBM HTTP Server from the 32-bit or 64-bit supplemental package. The IBM HTTP Server process is 32-bits in both cases and requires 32-bit modules.

Offizielle HCL Connections 6.5 Dokumentation

Dies ist allerdings nicht korrekt. Über den Schalter -V (Groß, da -v lediglich die Version ausgibt) erhält man zahlreiche Builddetails – darunter auch die Architektur. Wie man sieht, handelt es sich um eine 64-Bit Instanz:

# /opt/IBM/HTTPServer/bin/apachectl -V
Server version: IBM_HTTP_Server/8.5.5.16 (Unix)
Apache version: 2.2.8 (with additional fixes)
Server built:   Jul 22 2019 14:19:35
Build level:    IHS85/webIHS1929.01
Server's Module Magic Number: 20051115:23
Server loaded:  APR 1.2.12, APR-Util 1.2.12
Compiled using: APR 1.2.12, APR-Util 1.2.12
Architecture:   64-bit
[...]

Verifizieren lässt sich dies auch über ps -oflags anhand der httpd-Prozesse:

# for pid in $(pgrep httpd); do echo $pid; echo $(ps -oflags=$pid | tail -n 1); echo ""; done
887
4

888
4
[...]

Das Flag 4 steht für LP64 und damit für einen 64 Bit Prozess. Dies ist bei sämtlichen 7 Prozessen der Fall, sodass es sich hier um eine vollständige 64-Bit Installation handelt. Dies macht auch Sinn – schließlich ist ein 32 Bit Prozess für heutige Verhältnisse doch stark im Arbeitsspeicher beschränkt. Gerade bei einem Apache-Fork (der bekanntlich nicht gerade am sparsamsten mit dem RAM ist), würde ich eine 64-Bit Installation bevorzugen.

Damit ist nun klar, dass wir ein 64 Bit Modul benötigen. Auf der Suche danach stellt sich die nächste Frage: Welches davon? Wir haben die Wahl zwischen amd64 und x86_64:

# ls -lh /opt/HCL/Connections/ihs/mod_ibm_upload/ | grep linux
drwxr-xr-x 2 root root   31 Feb 13 15:26 ihs.linux.amd64
drwxr-xr-x 2 root root   31 Feb 13 15:26 ihs.linux.ia32
drwxr-xr-x 2 root root   31 Feb 13 15:26 ihs.linux.ppc32
drwxr-xr-x 2 root root   31 Feb 13 15:26 ihs.linux.ppc64
drwxr-xr-x 2 root root   31 Feb 13 15:26 ihs.linux.s390
drwxr-xr-x 2 root root   31 Feb 13 15:26 ihs.linux.s390_64
drwxr-xr-x 2 root root   31 Feb 13 15:26 ihs.linux.x86_64

Beides sind geläufige Bezeichnungen für die 64 Bit Architektur. Es ist daher unklar, worin die beiden sich unterscheiden. Die Größe ist mit 36360 zu 36520 Bytes zwar ähnlich, aber nicht identisch. Somit handelt es sich um keine Kopie des gleichen Modules.

cp /opt/HCL/Connections/ihs/mod_ibm_upload/ihs.linux.x86_64/mod_ibm_upload.so /opt/IBM/HTTPServer/modules/

Grundsätzlich scheinen beide Module zu funktionieren. Mit entsprechender Konfiguration (siehe unten) konnte ich keine Probleme feststellen. Man kann daher wahlweise eines der beiden nehmen, zum Beispiel

cp /opt/HCL/Connections/ihs/mod_ibm_upload/ihs.linux.amd64/mod_ibm_upload.so /opt/IBM/HTTPServer/modules/

Mit der entsprechenden ACL kann WAS auch als root laufen

In der Dokumentation wird vor Konflikten gewarnt, die den Upload verhindern, falls WebSphere als root ausgeführt wird. Zunächst einmal ist natürlich aus sicherheitstechnischer Sicht davon abzuraten, einen Anwendungsserver mit vollen Privilegien zu starten. Zumal bei WebSphere aufgrund der verwendeten Ports ohnehin keinerlei Grund dazu besteht – einzig bei der Installation von Docs muss man die Standardports 80/443 anpassen. Gerade in Testinstallationen ist dies jedoch durchaus weniger kritisch und wird auch von HCL selbst so praktiziert.

An dieser Stelle geht es mir daher um den Einwand in der Dokumentation, dies würde nicht funktionieren. Auch das ist in meinen Augen falsch. Wichtig ist, dass die passenden Zugriffsrechte gesetzt werden. Standardmäßig läuft der IHS mit dem Benutzer nobody. Für den files Ordner im gemeinsam genutzten Verzeichnis sind daher folgende Rechte zu setzen:

setfacl -R -d -m user:nobody:rwx /opt/IBM/shared/files/

Dies natürlich unter der Voraussetzung, dass vom Dateisystem ACLs unterstützt werden. Hier anhand eines CentOS 7.9 mit XFS getestet, wo dies kein Problem darstellt.

Leave a Reply