0%

I’m looking forward to Engage 2023 where we have a session on Wednesday on KeyCloak, Authentication & Authorisation, SSO and more. Feel free to come along, we look forward to seeing you!

  • Title: “Utilizing Keycloak for SSO with Domino and Nomad Web (and others)”
  • When: Wednesday, April 26 - 16:00 - 16:45
  • Where: Husly Lounge

Read more:
https://engage.ug/Engage2.nsf/Pages/session2023

There are news about the adapter situation at KeyCloak: the previous adapters can still be used, since the development in this area did not progress as fast as hoped. Read more about this in the KeyCloak blog:

Update on deprecation of Keycloak adapters

Oh, and not to forget: KeyCloak has become a CNCF (Cloud Native Computing Foundation) project (this announcement says so) and has incubation status now! It is not yet listed in the CNCF’s projects list though.

Bei einem Kunden existiert eine Webanwendung, die auf Tomcat 10.0.27 läuft und im wesentlichen Servlets enthält, die verschiedene Services anbieten. Genannte Webanwendung läuft jedoch nicht zu 100% stabil und gelegentlich kommt es vor, dass der Tomcat in der Prozessüberwachung zwar als active angezeigt wird, jedoch auf Requests nicht mehr reagiert.
Im Log catalina.out tauchen mehrmals Meldungen auf wie

The web application xyz appears to have started a thread named [Log4j2-TF-5-Scheduled-1] but has failed to stop it.

Zum Logging wird hier das gute, alte (aber aktuelle) Log4J2 benutzt und da es hier im Kontext mit Servlets verwendet wird, steht als dependency im pom.xml korrekterweise auch log4j-jakarta-web (ab Servlet 5.0) und nicht bloß log4j-api und log4j-core:

1
2
3
4
5
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jakarta-web</artifactId>
<version>2.19.0</version>
</dependency>

Wie erwähnt ist ein aktueller Tomcat 10.0.27 im Einsatz, der in der Vergangenheit jedoch bereits mehrmals aktualisiert wurde bzw. es wurde anscheinend jeweils eine neue Version installiert und dann die Konfig- und Properties Files von der vorherigen Installation ganz oder in Teilen übernommen. In der Log4J-Dokumentation steht u.a. folgender Hinweis:

Important Note! For performance reasons, containers often ignore certain JARs known not to contain TLDs or ServletContainerInitializers and do not scan them for web-fragments and initializers. Importantly, Tomcat 7 <7.0.43 ignores all JAR files named log4j*.jar, which prevents this feature from working. This has been fixed in Tomcat 7.0.43, Tomcat 8, and later. In Tomcat 7 <7.0.43 you will need to change catalina.properties and remove log4j*.jar from the jarsToSkip property. You may need to do something similar on other containers if they skip scanning Log4j JAR files.

Und tatsächlich: obwohl es sich um einen aktuellen Tomcat handelt, war in der catalina.properties bei der Property jarsToSkip tatsächlich der Wert log4j*.jar eingetragen. Nachdem dieser entfernt und Tomcat neu gestartet wurde, tauchte auch die oben genannte Meldung nicht mehr auf.
Fazit: wenn die Anwendung soweit okay aussieht und das Problem trotzdem auftritt, sollte man seine Prämissen (hier: “der Server ist korrekt konfiguriert, schließlich ist er seit Jahren im Einsatz”) überprüfen. Nur weil man eine aktuelle Software vor sich hat, heißt das nicht, dass auch die Konfiguration aktuell ist.

Once the appdevpack is installed on the Domino server and you have not noted which version of the appdevpack you have installed, there is unfortunately no easy official way to view the version of the installed appdevpack. When you start the Proton task (part of appdevpack), the console displays the version of Proton:

load proton

Unfortunately this information is not unique, because there are several appdevpack versions that contain the same Proton version. Fortunately, from appdevpack version 1.0.8 to 1.0.15, there is one component of appdevpack that can be used as an indicator of the installed appdevpack version: the version of the domino-db JAR file.

appdev-pack Version Proton-addin domino-db.jar domino-db iam-service node-iam-client domino-richtext min. req. Node.js Version
1.0.8 0.10.0 1.2.0 1.9.0 2.0.0 2.0.0 0.5.0 14.0
1.0.9 0.11.0 1.4.0 1.10.0 2.1.2 2.1.0 0.5.1 no information available in changelog
1.0.10 0.12.0 1.5.0 1.11.0 2.2.0 2.2.0 0.5.2 no information available in changelog
1.0.11 0.14.0 1.6.0 1.11.1 2.2.0 2.2.0 0.5.2 no information available in changelog
1.0.12 0.14.0 1.6.1 1.11.1 2.2.0 2.2.0 0.5.2 no information available in changelog
1.0.13 0.15.1 1.6.3 1.11.3 2.2.3 2.2.1 0.5.3 no information available in changelog
1.0.14 0.15.4 1.6.5 1.11.4 2.2.4 2.2.2 0.5.4 no information available in changelog
1.0.15 0.15.5 1.6.6 1.11.5 2.2.5 2.2.3 0.5.4 no information available in changelog

On a Linux server, you can use locate to search for the file - if a result is returned, you can use the version of the domino-db file to determine which appdevpack is installed using the table above.

1
locate -ir domino-db-.*jar

Auf dem Server eines Kunden ist mir bei der Einrichtung der Reverse-Proxy Konfiguration für eine Rest-API bei der Konfigurationsprüfung von Nginx folgende Warnung aufgefallen:

foldingAtHome Screenshot

In der Nginx-Konfiguration ist ssl_stapling aktiv - hierdurch wird OCSP (Online Certificate Status Protocol) Stapling verwendet. OCSP Stapling dient dazu in Echtzeit die Gültigkeit eines Zertifikats zu überprüfen und stellt damit eine Alternative zu Certificate Revocation Lists (CRL) dar. Beim OCSP Stapling fragt der Webserver (Zertifikatsinhaber) den OCSP-Server der Zertifikat-Ausstellers (CA) regelmäßig ab und erhält eine signierte OCSP-Antwort (Token) mit Zeitstempel. Wenn ein Browser versucht, sich mit der Website zu verbinden, wird diese OCSP-Antwort in den TLS-Handshake eingefügt und der Browser kann prüfen, ob das TLS-Zertifikat der Website gültig ist. Ist es gültig, baut der Browser die Verbindung zur Website auf, ansonsten wird die Verbindung verweigert. Da das Token von der CA signiert sein muss, kann der Zertifikatsinhaber das Token nicht fälschen. Sofern der Browser vom WebServer kein OCSP-Token erhält um die Gültigkeit des Zertifikats prüfen zu können, kontakiert dieser selbst den OCSP-Server.

Nginx testet beim Aufruf via nginx -t unter anderem, ob der OCSP-Server erreichbar ist und gibt eine Warnung aus, wenn dies nicht der Fall ist. Anscheinend nutzt Nginx für den Aufruf des OCSP_Servers jedoch anscheinend https und nicht http, denn via http ist die genannte URL problemlos erreichbar:

foldingAtHome Screenshot

Wie zu sehen ist, ist das Zertifikat des Servers abgelaufen, weshalb ich vermute, dass dies die Ursache für das Problem ist - etwas peinlich für eine CA einen Server mit einem seit Monaten abgelaufenen Zertifikat zu betreiben. Der Vorgänger von OCSP Stapling hieß OCSP (ohne Stapling) - hierbei war es generell die Aufgabe des Browsers den OCSP Server zu kontaktieren. Problematisch war dies u.a. da es für eine CA theoretisch möglich war, das Surfverhalten von Websitebesuchern zu tracken. Mir stellt sich nun die Frage, ob aufgrund der Warnung im Nginx-Log der Client das OCSP Request ausführen muss - das wäre auch mit Hinblick auf die DSGVO interessant.
Leider werden in den Entwicklertools der Browser keine OCSP-Requests im Kontext des TLS-Handshakes aufgezeichnet.

Mit folgendem Befehl lässt sich prüfen, ob eine Website OCSP Stapling verwendet oder nicht:

openssl s_client -connect [ihre.webseite.de]:443 -status

Wenn in der Ausgabe ein OCSP-Abschnitt auftaucht, dann verwendet der Server OCSP Stapling:

OCSP Response Data:
OCSP Response Status: successful (0x0)

Da bei der betroffenen Website mit der Warnung durch OpenSSL der OCSP Response Status ‘successful’ ist, gehe ich davon aus, dass der Browser während des Handshake selbst den OCSP-Server kontaktiert. Ich werde prüfen, ob die CA einen alternativen Resolver anbietet, dieser lässt sich in Nginx-Konfiguration entsprechend hinterlegen.

Für einen kommerziellen Anbieter wie RapidSSL als CA finde ich es nicht akzeptabel, dass ein OCSP-Server ein seit Monaten abgelaufenes Zertifikat hat - hier bietet sich Let’s encrypt als gute Alternative an.

Weiterführende Links:

Since version 19 KeyCloak has among other things a new admin console (see the keycloak changelog for further information on this) The appearance is much more modern, but you need some time to get used to it, especially since some functions are no longer where you expect them. In the old Admin Console, realm and resource roles were assigned directly via a selection:

foldingAtHome Screenshot

Initially, only the realm roles are displayed in the new Admin Console. Only after activating the filter “Filter by clients”, the resource roles are also displayed. I find this a bit misleading, because with a filter I normally expect that it filters a result set according to a criterion and the result set becomes smaller and not larger.

New admin console:
foldingAtHome Screenshot
foldingAtHome Screenshot

Also the download of the KeyCloak OIDC Json is now in a different place: in the old admin console there was a separate tab ‘Installation’ for this, this has been removed in the new admin console. The function is now in the new action menu instead:

Old admin console:
foldingAtHome Screenshot

New admin console:
foldingAtHome Screenshot

Regarding the adapter situation, the information is a bit contradictory about the keycloak-connect adapter for Node.js: according to the documentation it is recommended to use it, but according to this blogpost from early 2022 it is classified as deprecated, which unfortunately is not reflected in the documentation. Even for KeyCloak 20, released in early November 2022, there is an updated adapter version available with the same version number. Keep this in mind if you use the keycloak-connect adapter.

If you are using HCL’s appdevpack you might probably use the function bulkReadDocuments in your code. If this is the case and you are using this function with the parameter count you should check whether your application really displays all data. The count parameter is optional and is used to define the maximum number of results returned:

count {number}: An optional count of the maximum number of documents to read.
Note: If you don’t specify the optional count, the default value is 100. The “DOCUMENT LIMITS” configuration setting determines the maximum number of documents that can be read, up to 1000.

Source: appdevpack documentation

In one of our rest services, which are using appdevpack, the function bulkReadDocuments is used and a value of 1000 is set using the count parameter - paging is not used, because the expected result set will never exceed the set value. The problem now was that the count parameter is ignored under certain circumstances since appdevpack v1.0.9 at the latest, because with this version the value maximum note count was introduced in the central Proton configuration, whose default value is 200:

Controls the maximum number of documents Proton processes in a query found set. By default, Proton processes a maximum of 200 documents per request. A domino-db application may request more than the limit, but Proton caps the result size to this limit.

Source: appdevpack documentation

If the value of the count parameter of bulkReadDocuments is greater than the maximum note count parameter in the Proton configuration, you will still only get a maximum of 200 results delivered by bulkReadDocuments - there will be no warning in the log and no other hint. As a solution you can either increase the value of maximum note count or you always use paging when using bulkReadDocuments (this is imo the best solution).

Wenn man eine Node.js Anwendung schreibt, möchte man nicht immer eine Loglösung wie Morgan oder Winston verwenden, sondern einfach ein paar Ausgaben auf der Konsole, angereicht um die Informationen Datum und Uhrzeit. Dies kann man mit wenigen Zeilen Code erreichen:

console.logCopy = console.log.bind(console);
console.log = function(data){
var tt = ‘[‘ + new Date().toLocaleDateString(‘de-DE’) + “_” +new Date().toISOString().slice(11,-5) + ‘] ‘;
this.logCopy(tt, data);
};

Anschließend produziert console.log("Text 123") eine Ausgabe mit vorangestellter Uhrzeit und Datum.

Wenn die Anwendung über einen längeren Zeitraum läuft, ist eine Logrotation außerdem sinnvoll. Anstatt dies in jeder Anwendung einzeln zu implementieren, die auf dem Server läuft, kann man auch einfach das pm2-Modul pm2-logrotate verwenden. PM2 ist ein schlankes Tool aus der Kategorie Prozess-Monitoring: leichtgewichtig, schnell eingerichtet und insgesamt sehr zu empfehlen, insbesondere wenn man mehrere nodebasierte Anwendungen in Betrieb hat. Die Einrichtung ist hier beschrieben: https://www.npmjs.com/package/pm2
PM2 schreibt pro überwachter Node-Anwendung zwei Logdateien, err.log und out.log. Diese sind unter Linux unter /home/username/.pm2/logs zu finden. Wenn eine andere Lokation gewünscht ist, kann dies PM2 bei Start der Anwendung über den --log Parameter entsprechend mitgeteilt werden: pm2 start anwendung.js --log /lokation/meiner/wahl/logs
Das Modul pm2-logrotate wird wie folgt installiert und startet nach der Installation automatisch: pm2 install pm2-logrotate (Achtung: pm2 install nicht npm install!)
Nach einer Eingabe von pm2 status wird das Modul in der Modulübersicht gesondert aufgeführt, inkl. Statusinformation. Als Default verwendet pm2-logrotate für Logdateien bzgl. der Dateigröße ein Limit von 10MB und rotiert täglich 30 Tage lang. Die Konfiguration lässt sich beliebig anpassen und auf Wunsch können ältere Logs auch komprimiert werden - wie das geht ist auf der Projektseite dokumentiert: https://github.com/keymetrics/pm2-logrotate

Ein Kunde verwendet für die Suchfunktion seines Webportals Apache Nutch zur Indizierung der Inhalte. Es fiel auf, dass plötzlich keine neuen Inhalte mehr erfasst wurden und im Log des entsprechenden Cores /apache-nutch/coreconf/core-xy/log/hadoop.log fand sich folgende Meldung:

2021-02-20 00:11:54,923 INFO api.HttpRobotRulesParser - Couldn’t get robots.txt for https://domainDesKunden/: java.net.SocketException: Socket is closed
2021-02-22 00:11:54,930 ERROR http.Http - Failed to get protocol output

Als Ursache des Problems stellte sich heraus, dass nach einer Aktualisierung der Webserver-Konfiguration der Webserver andere Ciphers für TLS Verbindungen verwendete. Apache Nutch konnte beim Crawlen das Webportal nicht mehr erreichen, weil keine Einigung auf einen gemeinsamen Cipher mehr möglich war. Eine Anpassung der Cipher in der Webserver-Konfiguration beseitigte das Problem. Die Fehlermeldung von Nutch ist an dieser Stelle etwas irreführend, ich hätte hier eine TLSException oder zumindest etwas aussagekräftigeres erwartet.

An dieser Stelle möchte ich den SSL-Konfigurator von Mozilla empfehlen, der oft eine große Hilfe ist: https://ssl-config.mozilla.org