Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Refactoring eines Storage Layers am Beispiel von Keycloak

Refactoring eines Storage Layers am Beispiel von Keycloak

Keycloak ist eine Open Source Lösung für Identity und Access Management, die seit vielen Jahren weltweit in großen und kleinen Installationen eingesetzt wird.Von Anfang an unterstütze es relationalen Datenbanken via JPA/Hibernate. Über die Zeit kamen weitere Speichermöglichkeiten für Caching und ein In-Memory-Grid dazu, außerdem wurden Directory-Dienste wie LDAP integriert. Mit der Zeit verwoben sich die verschiedenen Bereiche, so dass neue Funktionen schwieriger umzusetzen waren.Dieser Vortrag zeichnet die Aktivitäten auf der Architektur- und Technik-Ebene nach, mit denen die Bereiche entflochten und eine neue, flexible Storage-Struktur erstellt wurde. Diese ermöglicht unter anderem Zero-Downtime-Upgrades und skalierbare Installationen.

Alexander Schwartz

October 11, 2022
Tweet

More Decks by Alexander Schwartz

Other Decks in Technology

Transcript

  1. Refactoring eines Storage Layers am Beispiel von Keycloak Software Architecture

    Alliance | 2022-10-11 Alexander Schwartz | Principal Software Engineer @ Red Hat
  2. Herausforderung: Uneinheitlichkeit und Komplexität • Daten verteilt auf Datenbank, externe

    Verzeichnisse und Infinispan • Daten als Kopie in der Datenbank oder als Cache in Infinispan • Zugriff auf User-Daten über users(), userLocalStorage(), userCache(), userStorageManager() und userFederatedStorage() • Setup von Keycloak benötigt immer Infinispan, da bestimmte Daten nur dort gespeichert werden • Keycloak-Upgrades erfordern eine Downtime, Rollback nur mit Datenbank-Restore
  3. Zero-Downtime • Schema-Migrationen ohne Stillstand • Zwei benachbarte Keycloak-Versionen können

    auf den gleichen Daten laufen, dadurch Test und Rollback möglich KC Version A: Schreibt Version N, liest Storage Version 1…N+1 KC Version B: schreibt Version N+1, liest Storage Version 1…N+2
  4. Datenbankformat für Zero-Downtime in JPA Primary Key UUID JPA Optimistic

    Locking Daten als JSONB PostgreSQL Generated Columns
  5. Implementieren eines neuen Providers Class Responsibilities Collaborators JpaMapStorageProviderFactory Stellt Verbindung

    zu Datenbank her über die JPA EntityManagerFactory JpaMapStorageProvider Eine Instanz pro Keycloak Session/Transaktion JpaMapStorageProviderFactory Jpa*MapKeycloakTransaction Eine Instanz pro Entity-Type in einer Session Map*Provider JpaModelCriteriaBuilder Mapping einer abstrakten Abfrage auf JPQL Jpa*MapKeycloakTransaction
  6. Bewertung des Ansatzes Vorteile: • Die Felder einer Entity sind

    dem MapStore erst einmal egal • Interface für eine *Transaction ist überschaubar (create / read / delete) • Fachlichkeit wird in *Model abgebildet Herausforderungen: • Felder nach denen gesucht wird müssen bekannt sein • Abfragen lassen sich je nach Store ggf. nur unvollständig abbilden • Nicht alles lässt sich auf das Interface abbilden, z. B. Authentifikaiton für Kerberos
  7. Testen eines neuen Providers • Testsuite mit Aufrufen auf der

    *Model-Ebene • Prüfen ob Abfragen funktionieren und Daten richtig gespeichert werden • Lasttests
  8. Zukunft: Tree Store • Manche Stores (z. B. LDAP) können

    nicht alle Attribute speichern (partial store) • Fehlende Attribute werden in in einem anderen Store (native store, z. B. JPA) abgelegt, andere Attribute werden dort ggf. als Cache abgelegt
  9. Erfahrungen • Keycloak 19 enthält MapStore für JPA/PostgreSQL, HotRod und

    ConcurrentHashMap • Keycloak 20* soll voraussichtlich JPA/CockroachDB, Tree Store und File Store unterstützen • Keycloak 21* soll voraussichtlich LDAP und Garbage Collection unterstützen * https://www.keycloak.org/2022/07/storage-map.html
  10. Architekturänderung • Alter Code setzt einen Cache voraus, dadurch sehr

    viele Zugriff auf den Store => Caching innerhalb einer Session implementieren • Viele Entitäten in der JPA Session machen den Zugriff langsam => Read-Only Entitäten in der Session, weniger Entitäten in der Session
  11. Erste Schemaänderung: Nutzername Beim Nutzernamen soll die Groß-/Kleinschreibung beachtet werden

    • Wie speichere ich die Daten und brauche ich eine Schema-Änderung? • Was passiert, wenn die neue Version alte Daten liest? • Was passiert, wenn die alte Version neue Daten liest und im alten Format schreibt?
  12. Zwischenfazit • Interface für den Physical Store erleichtert neue Store-Implementierungen

    • Stores für verschiedene Entitäten frei kombinierbar • Neue suchbare Felder im logischen Modell erfordern Änderungen an jedem physischen Store • Zero-Downtime ist eine optionale Eigenschaft des Physical Stores • Testsuite und Beispiele existieren • Dokumentation existiert zur Zeit nur als Javadoc und in Form der ursprünglichen Konzepte
  13. • Keycloak X - Storage - High-level architecture https://github.com/keycloak/keycloak- community/blob/main/design/keycloak.x/storage-architecture.md

    • Keycloak X - Storage / Persistence layer https://github.com/keycloak/keycloak- community/blob/main/design/keycloak.x/storage-persistence.md • „New storage for Keycloak” @ DevConf.cz https://devconfcz2022.sched.com/event/siGK/new-storage-for-keycloak Links