IsyFact Architekturregeln
1. Einleitung
Dieses Dokument gibt einen Überblick über alle in der IsyFact verwendeten Architekturregeln.
2. Architekturregeln
Beim Loggen der Nachrichten sind grundsätzlich die Vorgaben der Datenschutzgrundverordnung (DSGVO) einzuhalten. Eine besondere Rolle spielen dabei personenbezogene Daten und insbesondere Daten gemäß Artikel 9 DSGVO. Ebenso dürfen grundsätzlich keine sicherheitsrelevanten Daten (z.B. Passwörter) geloggt werden.
Logback wird durch eine Anwendung niemals direkt, sondern ausschließlich über die Bibliothek isy-logging aufgerufen.
Dadurch wird die einheitliche Nutzung von logback sichergestellt.
Ausnahmen sind hierbei externe Bibliotheken (siehe Logging externer Bibliotheken).
Persistente Entitäten dürfen nicht über den Anwendungskern hinaus herausgegeben werden. Sie haben im Anwendungskern zu verbleiben.
Für alle Frontends im Geltungsbereich dieser Referenzarchitektur MUSS der Architekturstil Single-Page Application (SPA) verwendet werden.
Für alle Frontends im Geltungsbereich dieser Referenzarchitektur, bei denen eine Laufzeit-Modularisierung erforderlich ist (z. B. mehrere Teams/Lieferanten und getrennte Release-Zyklen), MUSS Native Federation (ES-Module-basierte Integration über eine Shell-Anwendung) verwendet werden. Bundler- bzw. Webpack-gebundene Federation-Mechanismen (insbesondere Module Federation) DÜRFEN hierfür nicht eingesetzt werden.
Für Anwendungen mit erhöhtem Schutzbedarf SOLL ein Backend-for-Frontend (BFF, siehe [software-technisch-frontend-bff]) als bevorzugtes Zielbild gewählt werden.
In dieser Variante MÜSSEN Access Tokens und Refresh Tokens ausschließlich serverseitig im BFF gehalten werden und DÜRFEN NICHT an den Browser ausgeliefert werden.
Die Kommunikation zwischen Frontend und BFF MUSS über ein sicheres Session-Cookie (HttpOnly, Secure, SameSite) erfolgen.
Eine direkte SPA-zu-API-Kommunikation mit Token-Haltung im Browser MUSS eine bewusste und dokumentierte Architekturentscheidung sein und SOLL nur gewählt werden, wenn ein BFF nachweislich nicht erforderlich oder nicht umsetzbar ist.
Frontends MÜSSEN den OAuth 2.0 Authorization Code Flow mit PKCE (Proof Key for Code Exchange) zur Authentifizierung verwenden. Der Implicit Flow DARF NICHT eingesetzt werden (gemäß OAuth 2.0 Security Best Current Practice).
Die Vorgaben unterscheiden sich nach Architekturvariante:
BFF-Architektur:
Access Tokens und Refresh Tokens MÜSSEN ausschließlich serverseitig im BFF gehalten werden.
Tokens DÜRFEN NICHT an den Browser ausgeliefert werden.
Der Browser erhält ausschließlich ein Session-Cookie (HttpOnly, Secure, SameSite).
Direkte SPA-zu-API-Architektur:
Access Tokens MÜSSEN ausschließlich im Arbeitsspeicher (JavaScript-Variable / In-Memory) gehalten werden.
Refresh Tokens DÜRFEN NICHT im localStorage oder sessionStorage abgelegt werden.
Sofern eine persistente Haltung des Refresh Tokens technisch erforderlich ist (z. B. für Silent Renewal), MUSS dieser ausschließlich in einem HttpOnly-Cookie gespeichert werden.
Eine reine In-Memory-Haltung von Access Tokens schützt nicht vollständig vor XSS-Angriffen: Bei erfolgreichem XSS-Angriff kann ein In-Memory-Token im laufenden Kontext missbraucht werden. In-Memory ist gegenüber localStorage/sessionStorage zu bevorzugen, ersetzt jedoch keine wirksame XSS-Prävention (siehe [xss_pravention_im_code]).
|
Übergreifend: Client Secrets DÜRFEN NICHT im Frontend-Code oder in Build-Artefakten enthalten sein.
Die Lebensdauer von Access Tokens SOLL so kurz wie möglich gewählt werden (empfohlen: 5–15 Minuten, abhängig vom Schutzbedarf).
Refresh Tokens SOLLEN eine begrenzte Lebensdauer besitzen (empfohlen: wenige Stunden bis maximal 24 Stunden, abhängig vom Schutzbedarf) und nach jeder Nutzung rotiert werden (Refresh Token Rotation).
Frontends MÜSSEN mindestens die folgenden HTTP-Response-Header setzen:
| Header | Ziel |
|---|---|
|
Einschränkung erlaubter Ressourcenquellen; Schutz vor XSS und Injection |
|
Erzwingung von HTTPS |
|
Explizite Deklaration des MIME-Typs zur Vermeidung von Content-Sniffing |
|
Unterbindung von MIME-Type-Sniffing durch den Browser |
|
Steuerung der Browser-Cachebarkeit; sensible Seiten MÜSSEN mit |
Zusätzlich SOLLTEN folgende Header gesetzt werden:
| Header | Ziel |
|---|---|
|
Erweiterter HTTPS-Zwang für gesamte Domainstruktur |
|
Schutz vor Clickjacking (CSP bevorzugt, Header als Fallback) |
|
Kontrolle über Weitergabe von Referrer-Informationen |
|
Einschränkung von Browser-APIs (z. B. Kamera, Mikrofon, Geolocation) |
HTTP-Sicherheits-Header MÜSSEN auf die konkrete Webanwendung abgestimmt und so restriktiv wie möglich konfiguriert werden (Prinzip der minimalen Berechtigungen / Whitelisting).
Wildcard-Werte (z. B. Content-Security-Policy: default-src *) DÜRFEN NICHT verwendet werden.
Erlaubte Quellen MÜSSEN explizit definiert werden.
Die Content Security Policy MUSS mindestens die folgenden Direktiven enthalten:
| Direktive | Vorgabe |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
Explizite Liste der erlaubten Backend-/API-Endpunkte |
Bei Verwendung von Native Federation MUSS script-src zusätzlich die zulässigen Remote-Origins enumerieren (siehe [native_federation_security]).
Verstöße SOLLEN über report-to / report-uri an einen kontrollierten Endpunkt gemeldet werden.
Alle Cookies, die im Kontext der Webanwendung verwendet oder vom Backend gesetzt werden, MÜSSEN mit den folgenden Sicherheitsattributen versehen sein:
-
Secure— Übertragung MUSS ausschließlich über HTTPS erfolgen -
HttpOnly— ein Zugriff durch JavaScript DARF NICHT möglich sein (Schutz vor XSS-basiertem Cookie-Diebstahl) -
SameSite=StrictoderSameSite=Lax— Cross-Site Request Forgery (CSRF) SOLL verhindert werden
SameSite=None DARF nur in begründeten Ausnahmefällen (z. B. Cross-Origin-Einbettung) verwendet werden und MUSS immer zusammen mit Secure gesetzt werden.
Cookies SOLLTEN auf den kleinsten erforderlichen Scope (Domain und Path) eingeschränkt werden.
Session- und Refresh-Token-Cookies MÜSSEN eindeutig identifizierbar sein und DÜRFEN KEINE sensiblen Daten im Klartext enthalten.
Requests an Backend-APIs DÜRFEN NICHT mit Wildcard-Origins (Access-Control-Allow-Origin: *)
für authentifizierte Endpunkte konfiguriert werden.
Erlaubte Origins MÜSSEN explizit, vollständig und präzise auf API-Gateway- oder BFF-Ebene definiert sein.
Bei Verwendung von Credentials (z. B. Cookies oder Authorization Headern)
MUSS Access-Control-Allow-Credentials: true korrekt gesetzt werden,
und es DARF keine Wildcard-Origin verwendet werden.
Origins SOLLTEN auf konkrete Hostnamen eingeschränkt werden
(Wildcards wie *.example.com SOLLTEN nicht verwendet werden).
CSRF-Schutz MUSS als Defense-in-Depth-Strategie umgesetzt werden und DARF NICHT allein auf einer einzelnen Maßnahme beruhen.
Folgende Maßnahmen MÜSSEN bzw. SOLLEN kombiniert werden:
-
SameSite-Cookie-Attribute (StrictoderLax) MÜSSEN gesetzt werden (siehe [http_sicherheits_header_cookies]). -
Bei cookie-basierter Authentifizierung MUSS zusätzlich ein expliziter CSRF-Schutzmechanismus eingesetzt werden, z. B. ein serverseitiges CSRF-Token-Verfahren (Synchronizer Token Pattern) oder das Double-Submit-Cookie-Pattern.
-
Für sicherheitskritische, zustandsverändernde Anfragen SOLL serverseitig zusätzlich
Origin- und/oderReferer-Header geprüft werden. -
Sicherheitsrelevante Endpunkte SOLLEN ausschließlich über sichere HTTP-Methoden mit explizitem Content-Type (z. B.
application/json) angesprochen werden, um CSRF über einfache Formularsubmissions zu erschweren.
Bei BFF-Architektur MUSS der CSRF-Schutz auf der Frontend↔BFF-Verbindung implementiert werden, da hier cookie-basierte Sessions verwendet werden.
Frontends MÜSSEN ausschließlich über HTTPS ausgeliefert werden.
TLS 1.2 ist das Minimum; TLS 1.3 SOLL eingesetzt werden.
TLS 1.0 und TLS 1.1 DÜRFEN NICHT verwendet werden.
Mixed Content (Einbindung von HTTP-Ressourcen in einer HTTPS-Seite) ist VERBOTEN.
Strict-Transport-Security (HSTS) MUSS gesetzt werden.
Frontends SOLLEN über HTTP/2 ausgeliefert werden, um Ladeperformance und Multiplexing zu verbessern. HTTP/1.1 ist das erlaubte Minimum. HTTP/3 (QUIC) KANN eingesetzt werden, sofern Infrastruktur und Betriebsvorgaben dies unterstützen.
Dependency Scanning (z. B. mittels npm audit, OWASP Dependency-Check oder äquivalenter Tooling) MUSS als Pflichtschritt in der CI/CD-Pipeline automatisiert ausgeführt werden.
Builds mit bekannten kritischen Schwachstellen (CVSS ≥ 9.0) DÜRFEN NICHT in Produktivumgebungen deployt werden.
Schwachstellen mit hohem Risiko (CVSS ≥ 7.0) SOLLTEN bewertet und zeitnah behoben oder durch geeignete Maßnahmen mitigiert werden.
Ergebnisse des Dependency Scannings MÜSSEN dokumentiert und für Audits nachvollziehbar sein.
Repositories und Build-Artefakte MÜSSEN durch automatisiertes Secret Scanning auf versehentlich eingecheckte Zugangsdaten, API-Keys oder Zertifikate geprüft werden.
Secret Scanning MUSS als Pflichtschritt in der CI/CD-Pipeline automatisiert ausgeführt werden.
Gefundene Secrets MÜSSEN unverzüglich entfernt, rotiert oder widerrufen werden.
Builds mit enthaltenen Secrets DÜRFEN NICHT weiterverarbeitet oder in Produktivumgebungen deployt werden.
Für jedes produktiv deployte Frontend-Build-Artefakt MUSS eine SBOM im Format CycloneDX erstellt werden.
Die SBOM MUSS versioniert und revisionssicher archiviert werden.
Die SBOM MUSS für Vulnerability-Management-Prozesse genutzt werden, insbesondere zur Identifikation betroffener Abhängigkeiten bei bekannt werdenden Schwachstellen (CVEs).
Die Generierung und Auswertung der SBOM SOLL automatisiert in der CI/CD-Pipeline erfolgen.
Externe Abhängigkeiten DÜRFEN NICHT als ungebundene latest-Referenzen eingebunden werden.
Alle Abhängigkeiten MÜSSEN auf eine konkrete, fest definierte Version festgelegt sein (→ [AG-11]).
Ein Lockfile (z. B. package-lock.json, yarn.lock, pnpm-lock.yaml) MUSS eingecheckt und versioniert sein, um eine reproduzierbare Auflösung von Abhängigkeiten sicherzustellen.
Auch transitive Abhängigkeiten MÜSSEN über das Lockfile nachvollziehbar versioniert und kontrollierbar sein.
CI/CD-Pipelines MÜSSEN die Installation von Abhängigkeiten ausschließlich anhand des Lockfiles durchführen (z. B. npm ci, yarn install --frozen-lockfile, pnpm install --frozen-lockfile).
Eine Auflösung neuer Versionen während des CI-Builds DARF NICHT erfolgen.
Abhängigkeiten MÜSSEN ausschließlich aus organisationsweit freigegebenen Registries oder einem internen Proxy/Mirror bezogen werden. Direkte Bezugsquellen außerhalb dieser Registries (z. B. Git-URLs, beliebige HTTP-Quellen) DÜRFEN NICHT verwendet werden.
Direkte Einbindungen von JavaScript-, CSS- oder Schriften-Ressourcen aus öffentlichen CDNs zur Laufzeit DÜRFEN NICHT ohne explizite Freigabe erfolgen. Erforderliche externe Ressourcen SOLLEN als Build-Abhängigkeit eingebunden und selbst ausgeliefert werden.
Kritische Abhängigkeiten (insbesondere Framework, Build-Toolchain und sicherheitsrelevante Bibliotheken) MÜSSEN regelmäßig und nachvollziehbar auf aktuelle, vom Hersteller unterstützte Versionen aktualisiert werden.
Es MUSS ein definierter Prozess existieren, der Updates auf Basis von Schwachstellen- und Lifecycle-Informationen anstößt.
End-of-Life-Versionen kritischer Abhängigkeiten DÜRFEN NICHT in Produktivumgebungen verwendet werden.
Die direkte Verwendung der folgenden DOM-APIs mit nicht-vertrauenswürdigen oder nicht nachweislich bereinigten Daten DARF NICHT erfolgen:
-
innerHTML,outerHTML -
document.write,document.writeln -
insertAdjacentHTML -
eval,Function-Konstruktor,setTimeout/setIntervalmit String-Argument
Inhalte MÜSSEN bevorzugt über die framework-eigenen, kontext-sensitiven Binding-Mechanismen ausgegeben werden (z. B. Angular-Interpolation, React JSX-Textbindings), die eine automatische Ausgabe-Encodierung vornehmen.
Wo dynamisches HTML zwingend erforderlich ist, MUSS eine etablierte Sanitizer-Bibliothek (z. B. DOMPurify, framework-eigener Sanitizer) verwendet werden.
Framework-spezifische Bypass-Mechanismen für die Ausgabesicherung (z. B. Angular DomSanitizer.bypassSecurityTrust*, React dangerouslySetInnerHTML, Vue v-html) DÜRFEN nur in begründeten Ausnahmefällen verwendet werden.
Jede Verwendung MUSS:
-
dokumentiert und im Code-Review explizit freigegeben werden,
-
auf eine konkrete, vertrauenswürdige Datenquelle eingeschränkt sein,
-
mit einer vorgeschalteten Sanitisierung kombiniert sein, sofern die Datenquelle nicht vollständig kontrolliert ist.
Remote-Module DÜRFEN ausschließlich aus einer expliziten, organisationsweit gepflegten Allowlist von Origins geladen werden.
Die erlaubten Origins MÜSSEN in der script-src- und connect-src-Direktive der CSP enumeriert sein (siehe [http_sicherheits_header_cookies]).
Das Nachladen von Remote-Modulen aus beliebigen, vom Benutzer oder von externen Eingaben beeinflussbaren Origins DARF NICHT möglich sein.
Remote-Module MÜSSEN über fest definierte, unveränderliche Versionen referenziert werden (Immutable Artifacts).
latest-Referenzen oder andere wandernde Versions-URLs DÜRFEN NICHT verwendet werden.
Die Integrität geladener Remote-Module SOLL über Subresource Integrity (SRI) oder einen vergleichbaren Mechanismus geprüft werden, sofern technisch unterstützt.
Es MUSS ein dokumentierter Prozess existieren, mit dem ein einzelnes kompromittiertes oder fehlerhaftes Remote-Modul kurzfristig deaktiviert oder auf eine vorherige Version zurückgerollt werden kann, ohne dass ein vollständiges Re-Deployment der Shell-Anwendung erforderlich ist.
Die zentrale Konfiguration der Remote-Module (z. B. Federation Manifest) MUSS unter Versionskontrolle stehen und über einen kontrollierten Freigabeprozess änderbar sein.
Beim Logout MÜSSEN alle sicherheitsrelevanten Zustände invalidiert werden:
-
Der Frontend-State (insbesondere In-Memory-Tokens, Benutzerinformationen und zwischengespeicherte fachliche Daten) MUSS vollständig verworfen werden.
-
Serverseitige Sessions sowie ggf. Refresh Tokens MÜSSEN serverseitig invalidiert werden (z. B. über den Logout-Endpunkt des IAM-Service bzw. des BFF).
-
Auth-Cookies (Session, Refresh) MÜSSEN serverseitig invalidiert und gelöscht werden.
-
Persistente Browser-Caches mit sensiblen Inhalten (siehe unten) MÜSSEN bereinigt werden.
Ein clientseitiges Logout ohne serverseitige Invalidierung DARF NICHT als ausreichend betrachtet werden.
Antworten von Backend-APIs, die personenbezogene oder sicherheitsrelevante Daten enthalten, DÜRFEN NICHT persistent im Browser- oder Zwischen-Cache abgelegt werden.
Solche Antworten MÜSSEN serverseitig mit Cache-Control: no-store (und ergänzend Pragma: no-cache für Legacy-Clients) ausgeliefert werden.
Die clientseitige Wiederverwendung sensibler Antworten SOLL auf den Arbeitsspeicher und die Dauer der aktiven Nutzersitzung beschränkt sein.
Service Worker DÜRFEN keine personenbezogenen oder sicherheitsrelevanten Daten (z. B. Tokens, Session-Informationen, fachliche Bewegungsdaten) persistent speichern, es sei denn, dies wurde im Datenschutz- und Sicherheitskonzept der Anwendung explizit geprüft und freigegeben.
Der Cache eines Service Workers SOLL ausschließlich nicht-sensible, öffentlich auslieferbare Ressourcen (Applikations-Shell, statische Assets) enthalten.
Beim Logout MÜSSEN durch den Service Worker gehaltene Caches, die sensible Daten enthalten könnten, bereinigt werden.
Der Lebenszyklus von Service Workern (Registrierung, Aktualisierung, Deregistrierung) MUSS dokumentiert und kontrolliert sein; ein Update-Mechanismus MUSS sicherstellen, dass kompromittierte oder fehlerhafte Worker zeitnah ersetzt werden können.
Personenbezogene und sicherheitsrelevante Daten (z. B. Tokens oder Session-Informationen) DÜRFEN NICHT persistent im Browser-Speicher (localStorage, sessionStorage, IndexedDB) abgelegt werden, sofern dies nicht fachlich zwingend erforderlich ist und im Datenschutzkonzept der Anwendung begründet wurde.
Temporär verarbeitete Daten MÜSSEN nach Abschluss der fachlichen Operation aus dem Arbeitsspeicher entfernt werden.
Persistente Speicherung im Browser SOLLTE grundsätzlich vermieden werden und ist auf das notwendige Minimum zu beschränken.
Personenbezogene Daten DÜRFEN NICHT in clientseitige Logs, Browser-Konsole oder Telemetrie-Dienste geschrieben werden.
Sicherheitsrelevante Daten (z. B. Tokens, Session-IDs oder Authentifizierungsinformationen) DÜRFEN NICHT protokolliert werden.
Sofern Telemetriedaten erhoben werden, MÜSSEN diese vor der Übermittlung anonymisiert oder pseudonymisiert werden.
Die Übermittlung von Telemetriedaten an externe Dienste SOLLTE auf das notwendige Minimum beschränkt werden und MUSS den datenschutzrechtlichen Anforderungen entsprechen.
Debug- und Entwicklungslogs DÜRFEN in Produktivumgebungen nicht aktiv sein.
Im Frontend erhobene oder zwischengespeicherte Daten DÜRFEN ausschließlich für den definierten fachlichen Zweck verwendet werden, für den sie erhoben wurden.
Personenbezogene Daten DÜRFEN NICHT für andere als die vorgesehenen Zwecke verarbeitet werden.
Eine Weitergabe an Drittdienste (z. B. externe Analyse- oder Tracking-Dienste) MUSS datenschutzrechtlich geprüft und im Datenschutzkonzept dokumentiert sein.
Die Weitergabe von Daten an Drittdienste SOLLTE auf das notwendige Minimum beschränkt werden.
Metadaten sind, egal über welches Protokoll sie übertragen werden, einheitlich benannt. Gibt es eine durch einen Standard vorgegebene Benennung, ist diese zu verwenden.
Aufrufe nach dem Request-Response-Muster finden über das Protokoll HTTP statt und werden sowohl zur internen als auch externen Servicekommunikation genutzt. HTTP-Anfragen bzw. HTTP-Antworten erlauben es an drei Stellen, anwendungsspezifische Daten zu übertragen: in der URL, in den Headern sowie im Body.
Header enthalten Metadaten.
Der Body enthält Nutzdaten.
Bei Anfragen mittels GET und DELETE, die keinen Body erwarten, enthalten URL-Parameter Nutzdaten.
Datensätze werden nicht automatisch historisiert. Eine Historisierung wird, fachlich begründet, für betroffene Datensätze explizit realisiert.
Spring Beans nutzen Konstruktor-basierte Dependency Injection für zwingende Abhängigkeiten und Setter-basierte Dependency Injection für optionale Abhängigkeiten.
IT-Systeme verwenden kein Spring AOP zur Implementierung von Fachkomponenten.
Es dürfen nur nicht datenschutzrelevante Informationen in Query Parametern verwendet werden, um das Loggen von datenschutzrelevanten Daten zu verhindern.
POST wird auch für fachliche Operationen genutzt, die keiner der anderen HTTP-Methoden zugeordnet werden können (z. B. Verifikation eines Antrags).
PATCH ist nur zu verwenden, wenn PUT aus triftigen Gründen nicht funktioniert.
Alle REST-Services innerhalb einer Systemlandschaft nutzen eine einheitliche, textbasierte Repräsentationsform. Binäre Daten werden über direkte Anfragen binär ohne Transformation zurückgeliefert.
IT-Systeme müssen ihre REST-Services mindestens anhand Stufe 2 des [image-richard-maturity-model] umsetzen.
Sinnvoll ist der Einsatz eines Second-Level-Caches nur, wenn die darin enthaltenen Daten sehr häufig gelesen, aber nur selten geändert werden.
Wenn das fachliche Datenmodell variable Sichtbarkeitsregeln in größerem Umfang benötigt, sollten diese mit Hibernate Filtern umgesetzt werden.
Vererbungshierarchien zur Abbildung in relationalen Datenbanken sollten nur verwendet werden, wenn das fachliche Datenmodell dadurch optimal wiedergegeben wird. Sie sollten nur eine Oberklasse mit einigen Subklassen und höchstens zwei Vererbungsebenen umfassen.
Die Single Table per Class Hierarchy Strategie sollte die Default-Strategie sein, weil sie performante Abfragen erlaubt.
Wenn Not-Nullable-Constraints zwingend erforderlich sind und polymorphe Queries benötigt werden, ist die Joined Subclass Strategie eine gute Wahl. Ein weiteres Argument für diese Strategie sind Subklassen mit vielen Attributen.
Die Table per Concrete Class Strategie sollte, wenn überhaupt, nur gewählt werden, wenn die anderen Strategien nicht passen und auf die Oberklasse keine oder nur wenig polymorphe Zugriffe zu erwarten sind.
Diese Art der Vererbung von einer Java-Oberklasse auf Entitäten-Subklassen kann eingesetzt werden, wenn nur auf die Subklassen zugegriffen werden muss.
REST-Services verwenden ausschließlich Transferobjekte (Data Transfer Objects, DTOs).