Schnittstellen

SIP2 Response Handler

Einleitung

Diese Toolchain überwacht eine Protokolldatei auf SIP2-Antwortnachrichten und leitet diese an einen geschützten rocklog Endpunkt zur Verarbeitung weiter.

Skripte

  • post_sip2_response.sh: Sendet einzelne SIP2-Nachrichten an den Endpunkt
  • watch_sip2.sh: Überwacht die Protokolldatei und löst post_sip2_response.sh für neue Einträge aus

Kontrollfluss

+-------------------+         +------------------+        +-----------------+
|                   |  SIP2   |                  | writes |                 |
| Bibliotheca       |-------->| SIP2 Interceptor |------->| SIP2            |
| Sorter            | msgs    |                  | to file| output.log      |
+-------------------+         +------------------+        +-----------------+
                                                                |
                                                                | observes
                                                                v
+-------------------+         +------------------+         +-----------------+
|                   | Bearer  |                  |  reads  |                 |
| Keycloak          |-------->| post_sip2        |<--------| watch_sip2.sh   |
| Auth Server       | Token   | _response.sh     |  line   |                 |
+-------------------+         +------------------+         +-----------------+
                                     |
                                     | POST SIP2 msg
                                     v
+-------------------+           +------------------+
|                   | Stock     |                  |
| Rocklog           |<----------| Rocklog Backend  |
| Stock Management  | Transfer  |                  |
+-------------------+           +------------------+

Ablauf:
1. Sorter ----[SIP2 Nachrichten]----> Interceptor
2. Interceptor ----[schreibt]----> output.log
3. watch_sip2.sh ----[überwacht]----> output.log
4. watch_sip2.sh ----[triggert]----> post_sip2_response.sh
5. post_sip2_response.sh ----[fordert an]----> Keycloak
6. Keycloak ----[sendet Token]----> post_sip2_response.sh
7. post_sip2_response.sh ----[POSTs SIP2]----> Rocklog Backend
8. Rocklog Backend ----[transferiert Bestand]----> Rocklog Stock Management

Referenzimplementierung post_sip2_response.sh

Dieses Skript wird verwendet, um eine SIP2-Antwortnachricht an den geschützten Endpunkt zu senden. Zuerst wird das Skript ein gültiges Bearer-Token von Keycloak (rocklog Authentication Service) abgerufen. Dann wird eine POST-Anfrage an den geschützten Endpunkt mit der SIP2-Antwortnachricht gesendet.

#!/usr/bin/env bash

##
## Dieses Skript wird verwendet, um eine SIP2-Antwortnachricht an den geschützten Endpunkt zu senden
##

# Überprüfen, ob die erforderlichen Parameter vorhanden sind
if [ $# -ne 6 ]; then
  echo "Usage: $0 <keycloak_token_url> <client_id> <client_secret> <token_file> <protected_url> <body>"
  echo
  echo "Example:"
  echo "$0 http://<rocklog keycloak host>/realms/unibas/protocol/openid-connect/token <client_id> <client_secret> /tmp/.myapp-token http://<rocklog_host>/v1/protected/sip2/responses 'SIP2_MESSAGE_HERE'"
  exit 1
fi

KEYCLOAK_URL="$1"
CLIENT_ID="$2"
CLIENT_SECRET="$3"
TOKEN_FILE="$4"
PROTECTED_URL="$5"
BODY="$6"

get_new_token() {
  response=$(curl -s \
    -X POST \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "grant_type=client_credentials&client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}" \
    "$KEYCLOAK_URL")

  # Token und Ablaufzeit extrahieren
  access_token=$(echo "$response" | jq -r '.access_token')
  expires_in=$(echo "$response" | jq -r '.expires_in')

  if [ "$access_token" = "null" ]; then
    echo "Error retrieving access token: $response" >&2
    exit 1
  fi

  # Ablaufzeit berechnen
  current_time=$(date +%s)
  expires_at=$((current_time + expires_in))

  # Token und Ablaufzeit in TOKEN_FILE speichern
  echo "{\"access_token\": \"${access_token}\", \"expires_at\": ${expires_at}}" > "${TOKEN_FILE}"
}

get_valid_token() {
  if [ -f "${TOKEN_FILE}" ]; then
    access_token=$(jq -r '.access_token' "${TOKEN_FILE}")
    expires_at=$(jq -r '.expires_at' "${TOKEN_FILE}")
    current_time=$(date +%s)

    if [ "$current_time" -lt "$expires_at" ]; then
      # Token noch gültig
      echo "${access_token}"
      return
    fi
  fi

  # Wenn wir hier ankommen, wurde kein gültiges Token gefunden, also ein neues abrufen
  get_new_token
  jq -r '.access_token' "${TOKEN_FILE}"
}

# Ein gültiges Token abrufen
token=$(get_valid_token)

# Die POST-Anfrage mit der bereitgestellten Nachricht als text/plain senden
response=$(curl -s -v -X POST \
  -H "Authorization: Bearer $token" \
  -H "Content-Type: text/plain" \
  --data "$BODY" \
  "$PROTECTED_URL")

echo "$response"

Wichtige Implementierungsdetails

Protokollrotation und Dateihandhabung

Der Watcher verwendet tail --follow=name anstelle von nur tail -f, um die Protokollrotation korrekt zu handhaben. Dies stellt sicher:

  • Fortsetzung der Überwachung auch bei Protokollrotation
  • Automatischer Wechsel zur neuen Datei nach Rotation
  • Erstellung der Protokolldatei, falls diese nicht existiert

Beispielimplementierung in watch_sip2.sh:

der Parameter <log_file> ist die Protokolldatei, die überwacht wird. Diese Datei wird automatisch erstellt, falls sie nicht existiert.

Technische Details zur Verarbeitung von SIP2-Protokollnachrichten

Die Verarbeitung von SIP2-Nachrichten erfordert besondere Aufmerksamkeit bei der Behandlung von Zeilenumbrüchen, da diese je nach Quelle unterschiedlich sein können:

  • Windows-Systeme verwenden \r\n (Carriage Return + Line Feed)
  • Unix/Linux-Systeme verwenden \n (Line Feed)
  • Ältere Mac-Systeme verwenden \r (Carriage Return)

Unsere Implementierung verwendet eine Kombination aus stdbuf und tr, um diese unterschiedlichen Zeilenenden einheitlich zu behandeln:

  1. stdbuf -oL deaktiviert die Ausgabepufferung, sodass jede Zeile sofort verarbeitet wird
  2. tr '\r' '\n' wandelt alle Carriage Returns in Line Feeds um
  3. Die Pipe-Kombination ermöglicht eine robuste Verarbeitung aller SIP2-Nachrichten, unabhängig von ihrer Herkunft

Diese Lösung gewährleistet eine zuverlässige Verarbeitung von SIP2-Protokollnachrichten aus verschiedenen Quellsystemen.

Implementierung des Protokoll-Watchers

Das folgende Skript implementiert einen robusten Watcher für SIP2-Protokollnachrichten. Besondere Merkmale sind:

  • Zuverlässige Behandlung von Protokollrotation durch --follow=name
  • Automatische Erstellung der Protokolldatei falls nicht vorhanden
  • Echtzeitverarbeitung durch Deaktivierung der Pufferung
  • Universelle Behandlung von Zeilenumbrüchen für maximale Kompatibilität
  • Sichere Authentifizierung über Keycloak
  • Automatische Token-Erneuerung bei Ablauf

Das Skript ist so konzipiert, dass es als Systemdienst laufen kann und dabei alle wichtigen Aspekte der Protokollverarbeitung und Sicherheit berücksichtigt.

#!/usr/bin/env bash
# watch_sip2.sh

# Check for required parameters
if [ $# -ne 6 ]; then
  echo "Usage: $0 <keycloak_token_url> <client_id> <client_secret> <token_file> <protected_url> <log_file>"
  echo
  echo "Example:"
  echo "$0 http://localhost:81/keycloak/realms/unibas/protocol/openid-connect/token werner-backend supersecret /tmp/.myapp-token http://localhost:8080/v1/protected/sip2/responses /var/log/sip2_responses.log"
  exit 1
fi

KEYCLOAK_URL="$1"
CLIENT_ID="$2"
CLIENT_SECRET="$3"
TOKEN_FILE="$4"
PROTECTED_URL="$5"
LOG_FILE="$6"

# Create log file if it doesn't exist
touch "$LOG_FILE"

# Use tail --follow=name to handle log rotation
# Use tail with a custom delimiter
# Use stdbuf to disable buffering and handle \r as line endings
stdbuf -oL tail --follow=name -n 0 "$LOG_FILE" | stdbuf -oL tr '\r' '\n' | while read -r line; do
    ./post_sip2_response.sh \
        "$KEYCLOAK_URL" \
        "$CLIENT_ID" \
        "$CLIENT_SECRET" \
        "$TOKEN_FILE" \
        "$PROTECTED_URL" \
        "$line"
done

Skript-Berechtigungen

Beiden Skripten ausführbare Berechtigungen erteilen:

chmod +x post_sip2_response.sh
chmod +x watch_sip2.sh

Service-Konfiguration

Systemd Service

  1. Erstellen eines dedizierten Service-Benutzers:
sudo useradd -r -s /bin/false <specific_user>
  1. Erstellen einer systemd Service-Datei unter /etc/systemd/system/sip2-watcher.service:
[Unit]
Description=SIP2 Response Watcher Service
After=network.target

[Service]
Type=simple
User=<specific_user>
Group=<specific_user>
WorkingDirectory=/opt/werner/bin
ExecStart=/<path_to_watch_sip2.sh> <keycloak_token_url> <client_id> <client_secret> <token_file> <protected_url> <log_file>
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
  1. Installation und Aktivierung des Services:
sudo systemctl daemon-reload
sudo systemctl enable sip2-watcher.service
sudo systemctl start sip2-watcher.service

Service-Protokolle

Status und Protokolle des Services überprüfen:

sudo systemctl status sip2-watcher.service
sudo journalctl -u sip2-watcher.service
Previous
Automatisiertes Abholen/Bereitstellen von Dateien von/auf einem FTP Server