Bachelorarbeit FAKULTÄT INFORMATIK - Johannes Steinleitner Betreueung: Prof. Dr.-Ing. Johann Uhrmann, Hochschule Landshut - OPUS 4
←
→
Transkription von Seiteninhalten
Wenn Ihr Browser die Seite nicht korrekt rendert, bitte, lesen Sie den Inhalt der Seite unten
FAKULTÄT INFORMATIK Bachelorarbeit Verteilte Policy-basierte Autorisierung mit OAuth 2.0 und OpenID Connect Johannes Steinleitner Betreueung: Prof. Dr.-Ing. Johann Uhrmann, Hochschule Landshut Christian Fritz, QAware GmbH
ERKLÄRUNG ZUR BACHELORARBEIT Steinleitner, Johannes Hochschule Landshut Fakultät Informatik Hiermit erkläre ich, dass ich die Arbeit selbständig verfasst, noch nicht anderweitig für Prüfungszwecke vorgelegt, keine anderen als die angegebenen Quellen oder Hilfsmittel benützt, sowie wörtliche und sinngemäße Zitate als solche gekennzeichnet habe. .................... .................................................... (Datum) (Unterschrift des Studierenden)
Zusammenfassung/Abstract Durch den Open Policy Agent (OPA) soll es eine einheitliche Lösung geben, um Policy Entscheidungen für unterschiedlichste Anwendungen im Cloud-Native-Umfeld durchzu- setzen. [OPA20e] Es gibt schon viele Projekte, die OPA integriert haben. Hierzu zählen das AWS API Gateway, um den API Datenverkehr zu kontrollieren, Kubernetes um die Ressourcen Nutzung zu begrenzen. [OPA20d] Ein weiterer Anwendungsfall ist in Micro- services als Sidecar um eine verteilte Autorisierung zu ermöglichen. Durch OPA können die Policies von den Services getrennt werden. Somit müssen Services nicht neu deployt werden, falls sich die Policies ändern. [OPA20e] OPA hat jedoch keine eingebaute Funktion für die Authentifizierung und das Identitätsmanagement. [OPA20a] In dieser Arbeit soll aufgezeigt werden, wie die Authentifizierung mithilfe von Keycloak und die Autorisierung mit dem Open Policy Agent umgesetzt werden kann.
Inhaltsverzeichnis 1 Inhaltsverzeichnis 1 Einleitung 4 1.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.2 Ziele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.3 Aufbau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2 Grundlagen 6 2.1 Informationssicherheit . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2.1.1 Schutzziele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2.1.2 Authentifizierung und Autorisierung . . . . . . . . . . . . . . 7 2.2 Identity und Access Management . . . . . . . . . . . . . . . . . . . . . 8 2.3 Zugriffskontrolle (engl. Access Control) . . . . . . . . . . . . . . . . . 8 2.3.1 Role Based Access Control . . . . . . . . . . . . . . . . . . . . . 8 2.3.2 Attribute Based Access Control . . . . . . . . . . . . . . . . . . 10 2.3.3 Vergleich RBAC und ABAC . . . . . . . . . . . . . . . . . . . . 11 2.3.4 Kombination von RBAC und ABAC . . . . . . . . . . . . . . . 11 2.4 JSON Web Token . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.4.1 Aufbau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.5 OAuth 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.5.1 Grundbegriffe . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.5.2 Flows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 2.5.2.1 Authorization Code Flow . . . . . . . . . . . . . . . . 17 2.5.2.2 Authorization Code Flow with PKCE . . . . . . . . . 18 2.5.2.3 Client Credentials Flow . . . . . . . . . . . . . . . . . 20 2.5.2.4 Token Exchange Flow . . . . . . . . . . . . . . . . . . 21 2.6 OpenID Connect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.6.1 Authorization Code Flow . . . . . . . . . . . . . . . . . . . . . 23 2.7 Microservices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.7.1 Vorteile gegenüber eines Monolithen . . . . . . . . . . . . . . 24 2.7.2 Sidecar-Muster . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Inhaltsverzeichnis 2 2.8 CAP-Theorem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 3 Fachliche Anforderungen 27 3.1 Authentifizierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 3.1.1 Unterstützung von OpenID Connect . . . . . . . . . . . . . . . 27 3.2 Autorisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 3.2.1 Lesbarkeit der Policies . . . . . . . . . . . . . . . . . . . . . . . 27 3.2.2 Austauschbarkeit der Policies . . . . . . . . . . . . . . . . . . . 27 3.2.3 Testbarkeit der Policies . . . . . . . . . . . . . . . . . . . . . . . 28 3.2.4 Plattformunabhängigkeit . . . . . . . . . . . . . . . . . . . . . 28 3.2.5 Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 3.2.6 Verteilte Autorisierung . . . . . . . . . . . . . . . . . . . . . . . 28 4 Technisches Konzept 29 4.1 Verwendete Technologien . . . . . . . . . . . . . . . . . . . . . . . . . 29 4.1.1 Open Policy Agent . . . . . . . . . . . . . . . . . . . . . . . . . 29 4.1.1.1 Rego . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 4.1.1.2 Filtern von Daten . . . . . . . . . . . . . . . . . . . . 32 4.1.1.3 Bundles . . . . . . . . . . . . . . . . . . . . . . . . . . 34 4.1.2 Keycloak . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 4.1.3 Kubernetes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 4.1.4 Google Kubernetes Engine . . . . . . . . . . . . . . . . . . . . 35 4.1.5 Google Cloud Storage . . . . . . . . . . . . . . . . . . . . . . . 35 4.2 Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 5 Implementierung 38 5.1 Aufbau der Beispielanwendung . . . . . . . . . . . . . . . . . . . . . . 38 5.1.1 Regeln für die Autorisierung . . . . . . . . . . . . . . . . . . . 39 5.2 Microservices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 5.2.1 Autorisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 5.2.2 Datenfilterung . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 5.3 Keycloak . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 5.4 Open Policy Agent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 5.4.1 Policies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 5.4.2 Bundles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 5.5 Kubernetes Deployment . . . . . . . . . . . . . . . . . . . . . . . . . . 51 5.6 Frontend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Inhaltsverzeichnis 3 6 Ergebnis 53 6.1 Fazit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 6.2 Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Literaturverzeichnis 55 Anhang 59 Abbildungsverzeichnis 70 Tabellenverzeichnis 71 Listings 72 Akronyme 74
1 Einleitung 4 1 Einleitung In diesem Kapitel werden die Motivation, sowie der Aufbau und die Ziele von dieser Arbeit aufgezeigt. 1.1 Motivation Viele Unternehmen nutzen zur Sicherheit ihres Netzwerkes eine demilitarisierte Zone (DMZ). Es handelt sich um einen Bereich, der außerhalb des geschützten Unternehmensnetzwerkes liegt. Diese Zone stellt die Verbindung zwischen den internen Ressourcen, die im Internet verfügbar sein sollen, und dem öffentlichen Netzwerk dar. Typische Anwendungen, auf die von außerhalb des Netzwerkes zugegriffen werden soll, sind die E-Mail und VPN Server. Der Datenverkehr wird durch die DMZ gefiltert. Das soll gefährliche Anfragen z. B. durch eine Firewall herausfiltern. [Web14] In diesem Modell wird dem Datenverkehr innerhalb des Netzwerkes vertraut. Hat es ein Angreifer geschafft, die DMZ zu überwinden ist es für diesen relativ einfach auf vertrauliche Daten des Unternehmens zuzugreifen. Das Modell funktioniert, wenn alle innerhalb des Unternehmens arbeiten. Dies ist aber in der heutigen Zeit nicht mehr voraussetzbar. Mitarbeiter möchte auch von Zuhause oder von Unterwegs arbeiten können und auf die Daten, die sie benötigen zugreifen. Es werden im Unternehmen auch immer mehr Cloud Dienste eingesetzt, wodurch noch mehr Angriffsvektoren entstehen. [WB14] Deshalb wurde in 2010 von Forrester Research das Prinzip Zero Trust eingeführt. Dieses Prinzip besagt: Vertraue niemanden und verifiziere alles. Jeder Zugriff auf eine Ressource muss authentifiziert und autorisiert erfolgen. Setzt man das Prinzip von Zero Trust um, muss dies auch in den Microservices berücksichtigt werden. [Saw20] In dieser Arbeit soll ein Aspekt des Zero-Trust-Prinzips, der verlangt, dass jeder Microservice selbst eine Autorisierung vornimmt betrachtet werden.
1 Einleitung 5 1.2 Ziele Ziel dieser Arbeit ist es aufzuzeigen, wie eine verteilte Autorisierung und Authen- tifizierung mithilfe der Standards OAuth 2.0 und OpenID Connect in Microservices umgesetzt werden kann. Dazu soll der Open Policy Agent (OPA) genutzt werden, der viele der fachlichen Anforderungen, wie Plattformunabhängigkeit und Aus- tauschbarkeit der Policies erfüllt. Auf diese Anforderungen wird näher in Kapitel 3 eingegangen. OPA hat jedoch keine eingebaute Funktion für Identitätsmanage- ment und Authentifizierung. Hierfür soll Keycloak genutzt werden. Es soll nun gezeigt werden wie die ausgestellten JSON Web Token (JWT) von Keycloak für die Autorisierung in OPA genutzt werden können. Am Ende soll außerdem eine Beispielanwendung mit diesem Konzept implementiert werden. 1.3 Aufbau Die Bachelorarbeit ist in 6 Abschnitte aufgeteilt. Im zweiten Kapitel werden die grundlegenden Konzepte für die Authentifizierung und Autorisierung erklärt und Protokolle mit denen diese Umgesetzt werden kann vorgestellt. Weiterhin werden die wichtigsten Begriffe zu Microservices erläutert. Die fachlichen Anforderungen, die für die Authentifizierung und Autorisierung gelten sollen folgen im dritten Kapitel. Im vierten Teil werden die Technologien vorgestellt, die für die Umsetzung benötigt werden. Besonders wichtig sind hierbei Keycloak und der Open Policy Agent. Im fünften Kapitel wird ein Prototyp mit den Technologien aus dem vorherigen Kapitel erstellt und in der Google Cloud implementiert. Abschließend wird im letzten Kapitel noch ein Fazit gezogen und ein Ausblick auf weitere mögliche Arbeiten gezeigt.
2 Grundlagen 6 2 Grundlagen In diesem Kapitel geht es um die grundlegenden Begriffe in der Informationssi- cherheit und der Identitätsverwaltung. Weiterhin werden die Protokolle für Au- thentifizierung und Autorisierung OAuth und OpenID Connect erklärt. Am Ende werden noch Grundlagen zu den Microservices erläutert. 2.1 Informationssicherheit Informationen besitzen einen essenziellen Wert für Unternehmen und müssen des- halb geschützt werden. Wenn diese nicht ausreichend geschützt werden handelt es sich um ein Risiko, das die Existenz des Unternehmens bedrohen kann. [BSI20a] 2.1.1 Schutzziele Der Zugriff auf Informationen darf nur von autorisierten Subjekten vorgenom- men werden. Dies wird durch die Schutzziele Datenintegrität und Informations- vertraulichkeit ausgedrückt. Zusätzlich dazu sollte das System sicherstellen, dass der Zugriff auch möglich ist, wenn ein Benutzer autorisiert ist. Dies wird durch das Schutzziel Verfügbarkeit sichergestellt. [Eck18, S.7f] Im nachfolgenden wer- den diese 3 allgemeinen Schutzziele und die Authentizität, die zu den erweiterten Schutzzielen zählt, vorgestellt. Informationsvertraulichkeit: „Wir sagen, dass das System die Informationsvertraulichkeit (engl. confidentia- lity) gewährleistet, wenn es keine unautorisierte Informationsgewinnung ermög- licht.“ [Eck18, S.10] Dies bedeutet niemand hat Zugriff auf Information, für die er keine Berechtigungen hat. Ein Beispiel ist eine Banking-App. Es sollte keiner außer dem Benutzer und der Bank zugriff auf den Kontostand haben.
2 Grundlagen 7 Datenintegrität: „Wir sagen, dass das System die Datenintegrität (engl. integrity) gewährleistet, wenn es Subjekten nicht möglich ist, die zu schützenden Daten unautorisiert und unbemerkt zu manipulieren.“ [Eck18, S.9] Daten dürfen nur von Personen oder Programmen verändert, hinzugefügt oder gelöscht werden, wenn diese eine Berechtigung dafür haben. Ein negatives Beispiel wäre in diesem Fall eine Überweisung in einer Banking-App, bei der ein Angrei- fer den Betrag ändern könnte, wenn die Überweisung zur Bank übertragen wird. Hierfür muss nicht unbedingt auch die Informationsvertraulichkeit beeinträchtigt sein. Der Angreifer muss nur genau wissen, wo der Betrag steht. Verfügbarkeit: „Wir sagen, dass das System die Verfügbarkeit (engl. availability) gewährleistet, wenn authentifizierte und autorisierte Subjekte in der Wahrnehmung ihrer Berech- tigungen nicht unautorisiert beeinträchtigt werden können.“ [Eck18, S.12] Auf den ersten Blick hat Verfügbarkeit nicht viel mit IT-Sicherheit zu tun. Dabei handelt es sich jedoch um ein sehr wichtiges Schutzziel. Den würde man dieses weglassen, wäre ein sicheres System eines, das nicht mit dem Internet verbunden ist und auch keinen physischen Zugriff ermöglicht. Das ergibt aber meistens wenig Sinn. Zusätzlich zu den 3 allgemeinen Schutzzielen werden weitere Schutzziele defi- niert. Für diese Arbeit ist vor allem die Authentizität relevant. Authentizität „Unter der Authentizität eines Objekts bzw. Subjekts (engl. authenticity) verste- hen wir die Echtheit und Glaubwürdigkeit des Objekts bzw. Subjekts, die an- hand einer eindeutigen Identität und charakteristischen Eigenschaften überprüfbar ist.“ [Eck18, S.8] Damit die Authentizität sichergestellt werden kann, muss zuerst eine Authentifi- zierung stattfinden. Diese wird im nächsten Absatz beschrieben. 2.1.2 Authentifizierung und Autorisierung Durch die Authentifizierung wird die Authentizität eines Subjekts oder Objekts überprüft. Hierfür muss nachgewiesen werden, dass es sich um die Identität eines
2 Grundlagen 8 Objekts oder Subjekts handelt, die er vorgibt zu sein. In vielen Fällen erfolgt die Au- thentifizierung eines Nutzers durch einen Nutzernamen und ein Passwort. [Eck18, S.8] Bei der Autorisierung geht es hingegen darum, ob ein Subjekt berechtigt ist ei- ne bestimmte Aktion durchzuführen. [BSI20b] Das heißt bevor überhaupt eine Autorisierung durchgeführt werden kann, muss zuvor eine Authentifizierung erfolgt sein. 2.2 Identity und Access Management Identity und Access Management (IAM) ist in einem Unternehmen wichtig für das Verwalten von Identitäten und die Zugriffsrechte auf die einzelnen Systeme. Durch das IAM können einem Nutzer Berechtigungen zugewiesen werden, um eine Aktion an einem System durchzuführen. Die wichtigsten Funktionen, die ein IAM mit sich bringt, sind die Authentifizierung und die Autorisierung eines Nutzers. Es gibt darüber hinaus noch weitere wichtige Funktionen wie Single Sign-On, wodurch ein Nutzer mit einer Identität auf mehrere Systeme zugreifen kann. [LS17] 2.3 Zugriffskontrolle (engl. Access Control) Die Zugriffskontrolle regelt, wer Unternehmensdaten einsehen oder ändern darf. Durch die Zugriffskontrolle wird sichergestellt, dass vertrauliche Daten wie bei- spielsweise Kunden- oder Finanzdaten nur für autorisierte Personen zugänglich sind. Es gibt vier Hauptarten von Zugriffskontrollen. Diese lauten Discretionary Ac- cess Control, Mandatory Access Control, Role-based Access Control und Attribute- based Access Control. [Cit19] Vor allem die letzten beiden sind relevant für diese Arbeit und werden im Folgenden vorgestellt. 2.3.1 Role Based Access Control Role Based Access Control (RBAC) wurde 1992 von David Ferraiolo und Rick Kuhn vorgestellt. In RBAC definieren sich die Rechte eines Nutzers anhand der Rolle in dem Unternehmen. Rollen bleiben in einem Unternehmen über einen Zeitraum re- lativ konstant und die Zuweisung von Rechten kann deutlich vereinfacht werden. Dadurch können potenzielle Fehler vermieden werden, wo einem Nutzer zu viele
2 Grundlagen 9 Rechte zugewiesen wurden. Es gibt 4 Stufen von RBAC, in der die Komplexität stufenweise zunimmt. [SFK00] Das einfachste Modell ist das Flat RBAC Modell. In diesem Modell werden den Nutzer eine Rolle zugewiesen. Dadurch werden dem Nutzer bestimmte Berech- tigungen eingeräumt. Ein Nutzer kann mehrere Rollen gleichzeitig besitzen und eine Rolle kann auch mehrere Berechtigungen mit sich bringen. Ein Nutzer kann sich gleichzeitig in mehreren Rollen befinden. In diesem Modell muss eindeutig nachvollziehbar sein, welche Rollen einem Nutzer zugewiesen wurden. Das Flat RBAC Modell scheitert daran die hierarchische Struktur in einem Unternehmen darzustellen. In einem Unternehmen überschneiden sich Berechtigungen für be- stimmte Rollen. [SFK00] Dies wird in der 2. Stufe, dem hierachical RBAC Modell behoben. In diesem können Hierarchien von Rollen erstellt werden. Erbt ein Nutzer durch seine Rolle von einer anderen Rolle, hat dieser die vollen Rechte der geerbten Rolle. Dieses Modell kann weiter eingeschränkt werden zu dem Restricted Hierachical RBAC. In dem ist es er- laubt nur einfache Vererbungsstrukturen wie einen Baum darzustellen. [SFK00] Die nächste Stufe wird Constrained RBAC genannt. Wie der Name schon sagt wer- den hier gegenüber von Hierachical RBAC Einschränkungen eingeführt. Es soll dadurch Betrug und Fehler in der Rollenzuteilung verhindert werden. Um dies umzusetzen wird die sogenannte Funktionstrennung (engl. Seperation Of Duty) angewandt. Dafür werden Aufgaben auf verschiedene Rollen aufgeteilt um zu verhindern, dass ein Nutzer zu viel Autorität besitzt. Unterstützt wird die Funk- tionstrennung durch das Prinzip der Least Privileges. In diesem Prinzip geht es darum, dem Nutzer nur so viele Privilegien zu geben, wie er unbedingt benötigt, um seine Arbeit zu erledigen. Dadurch wird verhindert, dass ein Nutzer unnötige und möglicherweise gefährliche Aktionen durchführen kann. Die Funktionstren- nung kann von statischer Natur sein und es kann, wenn ein Nutzer eine bestimmte Rolle besitzt, eine andere durch Funktionstrennung in Konflikt stehende Rolle nicht zugewiesen werden. Die Funktionstrennung kann auch dynamisch erfolgen. Hier können einem Nutzer zwar mehrere Rollen zugewiesen werden, aber in einer Ses- sion kann er nur eine der beiden Rollen nutzen. Ein Beispiel hierfür ist ein Kassierer und ein Vorgesetzter eines Kassierers. Dem Vorgesetzten ist es erlaubt Änderungen an der Kasse des Kassierers zu bestätigen. Der Kassierer kann auch die Rolle des Vorgesetzten einnehmen. Hierfür wird er durch RBAC aber verpflichtet erst die Kas- se zu schließen und die Rolle des Kassierers für die Session aufzugeben. [SFK00] Die letzte Stufe wird Symmetric RBAC genannt. Hier muss nachvollziehbar sein,
2 Grundlagen 10 welche Berechtigungen durch eine Rolle gewährt wird. Darüber hinaus muss auch die Umkehrung erfüllt sein. Hat man eine bestimmte Berechtigung muss es mög- lich sein alle Rollen aufzulisten, die diese Berechtigung erteilt. Das Überprüfen der Berechtigungen eines Nutzers muss dann durchgeführt werden, wenn z. B. der Nutzer seinen Job in dem Unternehmen wechselt. Es sollte immer versucht werden das Prinzip der Least Privileges einzuhalten. In großen verteilten Systemen kann Symmetric RBAC schwer zu implementieren sein und wird deshalb erst in der 4. Stufe erwähnt. [SFK00] 2.3.2 Attribute Based Access Control Attribute Based Access Control (ABAC) benutzt Attribute um eine Zugriffsent- scheidung zu treffen. Weiterhin gibt es sogenannte Policies, die anhand der Attri- bute entscheiden, ob das Subjekt berechtigt ist die Aktion am Objekt durchzufüh- ren. [Okt20] Attribute können vielseitig sein: • Sie können sich auf den Benutzer, Subjekt beziehen, wie z.B. Name, Abteilung sein. • Sie können sich auf Aktionen beziehen, wie z.B. GET, POST, PUT, DELETE. • Sie können Attribute von Ressourcen sein, wie z.B. Arbeitszeit eintragen. • Sie können sich auf den Kontext von einer Interaktion beziehen, z.B. Zeit, Gerät [Okt20] Die Umsetzung in einem Unternehmen hängt von vielen Faktoren ab, wie der Größe des Unternehmens, der Verteilung der Ressourcen und der Bedürfnisse der Benutzer. Deshalb können die einzelnen Zugriffsmechanismen physisch und lo- gisch separiert werden. [HFK+ 14] Policy Decision Point (PDP): PDP wertet die Policies, die den Zugriff auf das geschützte Objekte regeln anhand der Attribute des Subjekts aus und gibt diese Entscheidung an den Policy Enforce- ment Point weiter. Hat der PDP nicht alle Informationen um eine Entscheidung zu treffen kann er beim Policy Information Point anfragen.
2 Grundlagen 11 Policy Enforcement Point (PEP): PEP setzt die Policy Entscheidung vom PDP um. Das heißt der PEP entscheidet, ob ein Subjekt das anfragt Zugriff auf das geschützte Objekt erhält. Policy Information Point (PIP): PIP dient als Quelle für den PDP, damit der PDP Attribute oder Information die zur Auswertung der Policies benötigt werden erhalten kann. Policy Administration Point (PAP): PAP ist zuständig für das Verwalten und Testen von Policies. [HFK+ 14] 2.3.3 Vergleich RBAC und ABAC In RBAC kann einfach nachvollzogen werden, welche Berechtigungen mit einer Rolle verknüpft sind. Außerdem können die Rollen bestimmt werden, die einem Nutzer zugewiesen wurden. Das macht es einfach zu überprüfen, welche Berech- tigungen ein Nutzer im System hat. Das Problem bei RBAC ist, dass die Rollen statisch sind und es keine dynamischen Attribute, wie die Zeit gibt. Dies lässt sich mit ABAC lösen. Hier können einfach dynamisch Attribute, wie der Standort in die Entscheidung, ob der Zugriff erlaubt werden soll mit einfließen. Bei ABAC müs- sen aber eine hohe Anzahl an Attributen verwaltet und auch verstanden werden, da je nachdem welche Attribute ein Nutzer hat der Zugriff erlaubt oder verboten wird. Es kann also nicht einfach nachvollzogen werden welche Berechtigungen ein Nutzer hat, wie es in RBAC möglich ist. [CW19] 2.3.4 Kombination von RBAC und ABAC Beide Ansätze haben ihre Vorteile und Nachteile. Um die Nachteile auszugleichen wurden Ansätze entwickelt, die beide Ansätze verbinden. Es gibt den Attribute-centric Ansatz, in dem Rollennamen einfach als Attribute des Nutzers betrachtet werden. Dieser Ansatz schöpft die Vorteile von ABAC voll aus, aber es geht die Einfachheit der Verwaltung durch RBAC verloren, nämlich die Beziehung zwischen Berechtigungen und Rollen. Ein anderer Ansatz ist der Role-centric Ansatz. Hierbei werden Attribute genutzt, um RBAC einzuschränken. Ein Attribut kann die Berechtigungen eines Nutzers nur einschränken und diese nicht erweitern. Durch diesen Ansatz wird einiges an der Flexibilität von ABAC eingebüßt, aber das System erhält die RBAC Möglich- keiten und es kann die maximale Anzahl der Berechtigungen eines Nutzers einfach
2 Grundlagen 12 nachvollzogen werden. [KCW10] Insgesamt bleibt festzuhalten, es gibt leider keine Einheitslösung, um die Zugriffs- kontrolle zu implementieren. Dies hängt von vielen Faktoren, wie der Struktur des Unternehmens und wie fein die Berechtigungen eines Nutzers sein sollen, ab. Es sollte der Ansatz gewählt werden, der am besten im Unternehmen umgesetzt werden kann. 2.4 JSON Web Token JSON Web Token (JWT) repräsentieren eine Menge von Claims in einem JSON Objekt, die zwischen zwei Parteien ausgetauscht werden können. Ein Claim ist ein Name/Wert Paar. Der Name ist immer ein String. Der Wert kann ein beliebiger JSON Wert sein. Es kann sich also zum Beispiel um ein Array, String, JSON Objekt handeln. Die Claims sind der Payload einer JSON Web Signature (JWS) oder einer JSON Web Encryption (JWE). Der Unterschied zwischen diesen beiden ist, dass eine JWS nur die Datenintegrität sicherstellt und eine JWE zusätzlich zur Datenintegrität auch die Informationsvertraulichkeit. [JBS15] 2.4.1 Aufbau Ein JWT ist in 3 Teile gegliedert Header, Payload und Signatur. In diesem Beispiel wird ein JWT mit einer JWS gezeigt, der Aufbau mit einer JWE ist sehr ähnlich. Ein Beispiel für einen Header wird in Listing 2.1 dargestellt. 1 { 2 "typ": "JWT", 3 "alg":" HS256 " 4 } Listing 2.1: JWT Header (Quelle: [JBS15]) Der Typ gibt an, dass es sich um einen JSON Web Token handelt. Alg ist der Algorithmus, der für die Signatur verwendet wurde. [JBS15]
2 Grundlagen 13 Die Claims des Payloads sind anwendungsspezifisch. Der JWT Standard gibt aber trotzdem standardisierte Claims an. Die wichtigsten werden nun anhand des Beispiels in Listing 2.2 erläutert. [JBS15] 1 { 2 "iss": "http :// www.jwt.de/ issuer ", 3 "iat": 1589306239, 4 "exp": 1589307440, 5 "aud": "www.aud.com", 6 "sub": "j. steinleitner " 7 } Listing 2.2: JWT Payload (Quelle: In Anlehnung an [JBS15]) iss (Issuer) Claim: Der Issuer Claim gibt den Service an, der den Token ausgestellt hat. Es handelt sich hierbei meistens um eine URL. [JBS15] iat (Issued At) Claim: Der Issued At Claim gibt den Zeitpunkt an, an dem der JWT ausgestellt wur- de. [JBS15] exp (Expiration Time): Der Expiration Time Claim ist wiederum ein Zeitpunkt, der dieses Mal angibt, bis wann der JWT gültig ist. Ist dieser abgelaufen, muss er abgewiesen werden. [JBS15] aud (Audience) Claim: Die Audience gibt den Empfänger des Tokens an. Es kann sich auch um mehre- re handeln. Diese werden dann in einem JSON Array angegeben. Es handelt sich meistens um eine URL, welche den Service, für den der Token bestimmt ist, ein- deutig identifiziert. [JBS15] sub (Subject) Claim: Der Subject Claim identifiziert den Benutzer oder die Anwendung, für den der Token ausgestellt wurde. [JBS15] Am Ende jedes Tokens erhält dieser noch eine JWS, um sicherzustellen, dass der Token nicht verändert werden kann. Für die Signatur wird in diesem Beispiel der HMAC-SHA256 Algorithmus genutzt. Um die Signatur zu berechnen werden der
2 Grundlagen 14 Header und Payload jeweils einzeln Base64URL kodiert und weiterhin mit einem " ." dazwischen zusammengefügt. Die Base64URL Kodierung ist eine Modifikation von Base64, die nur URL konforme Zeichen enthält. [JBS15] HMAC_SHA256(base64 URL(Header) + "." + base64 URL(Body), secret) In diesem Beispiel wird als Secret 123456 genutzt. Die Base64URL kodierte Signatur für den obigen Header und Payload lautet fol- gendermaßen: KzDbcXjxH_FhQnBe0Aliloqrt0KRovysDY43jt-gmcc Der Token wird nun aus den 3 einzelnen Teilen folgendermaßen zusammengebaut: base64 URL(Header) + "." + base64 URL(Body) + "." + base64 URL(Signatur) Aus dem obigen Beispiel folgt nun der komplette JSON Web Token. Die Zeilenum- brüche werden nur zur Veranschaulichung eingefügt. Dadurch kann man eindeutig die 3 Bestandteile des JSON Web Token erkennen. [JBS15] eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 .eyJpc3MiOiJodHRwOi8vd3d3Lmp3dC5kZS9pc3N1ZXIiLCJpYXQiOjE1ODkzMDYyMzks ImV4cCI6MTU4OTMwNzQ0MCwiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoiai5zd GVpbmxlaXRuZXIifQ .KzDbcXjxH_FhQnBe0Aliloqrt0KRovysDY43jt-gmcc 2.5 OAuth 2.0 OAuth 2.0 erlaubt einem Drittanbieter limitierten Zugriff auf einen HTTP-Service. Ein Beispiel hierfür ist eine eigene Kalender-App, die zugriff auf den Google Ka- lender haben möchte, um den Terminkalender zu lesen. Eine Möglichkeit wäre der Anwendung den Benutzernamen und das Passwort zu überlassen und darauf zu vertrauen, dass diese nur den Kalender abruft und nicht auch noch die E-Mails oder das Konto Passwort ändert. Für diesen Anwendungsfall wurde das Protokoll OAuth spezifiziert. Heutzutage ist OAuth ein wichtiger Standard im Internet.
2 Grundlagen 15 2.5.1 Grundbegriffe Um die OAuth Flows zu beschreiben werden zunächst die Grundbegriffe erklärt. In OAuth 2.0 werden 4 Rollen definiert. Es gibt den Resource Owner, der den Zugriff auf die geschützte Ressource erlaubt. Die zweite Rolle ist der Resource Server. Dieser hostet die geschützte Resource und kann bei Anfragen auf eine geschützte Ressource antworten. Weiterhin gibt es noch den Client, bei dem es sich um eine Anwendung handelt, die im Auftrag des Resource Owners auf eine geschützte Resource zugreifen möchte. Ein Client kann zum Beispiel ein Webbrowser sein. Als letztes gibt es noch den Authorization Server, der den Resource Owner authen- tifiziert und wenn dies Erfolgreich war ein Access Token ausstellt. [Har12] Die oben genannte Client Rolle kann in zwei Arten von Clients unterteilt werden, je nachdem, ob sie sich sicher beim Authorization Server authentifizieren kann. Das bedeutet, ob sie die Vertraulichkeit ihrer Credentials (z. B. Passwort, Zertifikat, ...) sicherstellen können. Ist das möglich werden sie confidential genannt. Es kann sich hierbei z. B. um einen sicheren Server handeln. Kann ein Client seine Credentials nicht geheim halten, handelt es sich um ein public Client. Beispiele für public Clients sind eine App oder eine Browseranwendung. Die Unterscheidung ist wichtig, da je nachdem ob es sich um ein public oder con- fidential Client handelt ein anderer OAuth Flow genutzt werden sollte. [Har12] Als letztes werden noch die 2 verschiedenen Arten von Token betrachtet. Es gibt Access Token, mithilfe dessen auf eine geschützte Ressource zugegriffen wer- den kann. In Access Tokens kann ein Scope festgelegt werden, der angibt auf welche geschützten Daten das Client zugriff erhält. Es erhält weiterhin einen Zeitstempel, der die Gültigkeit angibt. Das Access Token soll für das Client opaque sein. Refresh Token werden benutzt, um ein neues Access Token zu erhalten. Mithilfe des Refresh Token kann ein neues Access Token angefordert werden, wenn das alte abgelaufen oder ungültig geworden ist. Es kann theoretisch auch der Scope in dem Refresh Token für das neue Access Token eingeschränkt werden. Refresh Token sind deutlich länger gültig, als Access Token. Deren Gültigkeit beträgt zumeist nur mehrere Minuten. Die Dauer der Gültigkeit muss gegenüber der Sicherheit der Anwendung abgewogen werden. [Har12]
2 Grundlagen 16 2.5.2 Flows OAuth unterscheidet verschiedene Flows, die je nach Anwendung genutzt werden sollen. Bei dem Resource Owner Password Credentials Flow wird der Nutzerna- me und das Passwort an den Authorization Server geschickt. Dies soll aber genau durch OAuth verhindert werden. Der Flow ist nur für die Abwärtskompatibilität vorhanden und wird hier nicht erläutert. [Har12] Ein weiterer Flow, der heutzu- tage nicht mehr genutzt werden sollte, ist der Implicit Flow. Der Implicit Flow war für Single Page Web Application gedacht. Dieser Flow ist anfällig dafür das Access Token zu leaken und auch für Replay-Attacken. In diesem Flow wird das Access Token in der URL zurückgesendet. Dadurch kann es passieren, dass der Browser es in der Historie speichert. Hat ein Angreifer zugriff auf diese kann er es auslesen. Aufgrund dieser Sicherheitsrisiken wird der Implicit Flow nicht weiter erläutert. [LBLF20] Es bleiben noch der Authorization Code Flow und der Client Credentials Flow übrig, auf die im Folgenden weiter eingegangen wird. Es gibt auch noch vorgeschlagene Standards die schon Einzug in OAuth Implementierungen er- halten haben und auch genutzt werden sollten. Bei den vorgeschlagenen Standards werden der Authorization Code Flow with PXCE und der Token Exchange Flow vorgestellt. Es werden Sequenzdiagramme für die einzelnen Flows aufgezeigt. In diesen sind nur die in OAuth definierten Anfragen und Antworten aufgezeigt. Es werden dazwischen weitere Daten ausgetauscht, die aber außerhalb des Bereichs von OAuth liegen.
2 Grundlagen 17 2.5.2.1 Authorization Code Flow Der Authorization Code Flow, wie in Abb. 2.1 ist für confidential Clients gedacht. Abb. 2.1: OAuth Authorization Code Flow (Quelle: In Anlehnung an [Har12]) 1. Der Flow wird vom Client gestartet, indem er den User-Agent (z. B. Webbrowser) auf den Authorization Server umleitet. Der Client schickt in diesem Schritt Para- meter, wie seine Client-ID und die Umleitungs-URI mit, auf die der Nutzer später wieder auf den Client umgeleitet wird. 2. Der Authorization Server authentifiziert den Resource Owner und wartet nun, ob der Resource Owner den Zugriff erlaubt oder verbietet. 3. Wird der Zugriff erlaubt, wird der User-Agent vom Authorization Server auf den Client zurück umgeleitet. Die URI, auf die er umgeleitet wird, wurde im Schritt 1 angegeben. Diese URI enthält den Authorization Code. 4. Der Client fordert nun beim Authorization Server mithilfe des Authorization Code ein Access Token an. Der Client authentifiziert sich bei der Anfrage beim Authorization Server. 5. Im letzten Schritt authentifiziert der Authorization Server den Client, überprüft
2 Grundlagen 18 den Authorization Code. Ist alles korrekt, gibt der Server ein Access Token zurück und optional ein Refresh Token, das genutzt werden kann, um das kurzlebigere Access Token zu erneuern. [Har12] Es wird im Schritt 3 nicht direkt ein Access Token ausgestellt, sondern nur ein Authorization Code, da der Access Token sonst direkt an den Nutzer ginge. In diesem Fall geht es nur an den Client, bei dem es sich normalerweise um einen Backend-Server handelt. Das heißt, wenn ein Angreifer einen Authorization Code abgreift kann er immer noch nicht auf die geschützte Ressource zugreifen, da sich der Client in Schritt 4 beim Authorization Server zusätzlich authentifiziert, um ein Access Token zu bekommen. [Har12] 2.5.2.2 Authorization Code Flow with PKCE OAuth public Clients sind dort für Attacken anfällig, wo der Authorization Code abgefangen werden kann. Dies kann auf Transportwegen geschehen, die nicht mit TLS verschlüsselt sind, wie inter-applikation Kommunikation mit dem Betriebs- system des Clients. Hat der Angreifer Zugriff auf den Authorization Code, kann er diesen für ein Access Token umtauschen. Bei diesem Flow geht es um die Verhin- derung eines komplexen Angriffs, der in der Praxis vorgekommen ist. Bei diesem Angriff läuft eine bösartige Anwendung auf dem Client. Die bösartige Software registriert ein benutzerdefiniertes URI Schema auf die URI, die genutzt wird, um den Authorization Code an das Client zu senden. Das Betriebssystem muss es in diesem Fall erlauben, dass benutzerdefinierte URIs von mehreren Anwendungen gleichzeitig genutzt werden. Der Authorization Code wird in diesem Fall an die bösartige Applikation und an das valide OAuth Client gesendet und kann, da es sich um ein public Client handelt und dadurch keine Credentials geheim gehalten werden können, einfach gegen ein Access Token umgetauscht werden. [SBA15]
2 Grundlagen 19 Es werden in Abb. 2.2 die Unterschiede zu dem Standard Authorization Code Flow aufgezeigt. Abb. 2.2: OAuth Authorization Code Flow with PKCE (Quelle: In Anlehnung an [Har12, SBA15]) 1. Der Client leitet wie bei dem normale Authorization Code Flow den User-Agent mit den üblichen Parametern auf den Authorization Server um. Zusätzlich gene- riert der Client sich einen zufälligen String mit hoher Entropie. Dieser String wird Code-Verifier genannt. Aus diesem leitet er durch die Funktion t eine transformierte Version ab. Bei der Funktion t kann es sich um die Hash Funktion SHA-256 han- deln. Die transformierte Version wird Code-Challenge genannt. Er schickt diesen Parameter BASE64URL kodiert und mit dem Namen der Funktion, die genutzt wurde zusätzlich an den Authorization Server. 2. Der Authorization Server antwortet wie üblich, aber speichert die transformierte Code-Challenge und den Namer der Funktion, die für die Transformation genutzt
2 Grundlagen 20 wurde, ab. 3. Der Client sendet den Authorization Code an den Authorization Server, um ein Access Token zu erhalten. Zusätzlich sendet er den Code-Verifier mit. 4. Der Authorization Server transformiert den Code-Verifier und vergleicht es mit dem aus Schritt 2. Sind diese gleich, wird ein Access Token zurückgegeben. Wenn nicht wird der Zugriff verweigert. [SBA15] Fängt ein Angreifer den Authorization Code ab und möchte es für ein Access Token umtauschen ist das nicht möglich, da er den Code-Verifier nicht kennt. [SBA15] 2.5.2.3 Client Credentials Flow Möchte ein Client eine geschützte Ressource aufrufen kann es nur mit seinem Client Credentials am Authorization Server ein Access Token erhalten. [Har12] Abb. 2.3: OAuth Client Credentials Flow (Quelle: In Anlehnung an [Har12]) 1. Der Client authentifiziert sich bei dem Authorization Server und fordert ein Ac- cess Token an. 2. Der Authorization Server authentifiziert den Client. Ist die Anfrage valide, wird ein Access Token zurückgegeben. [Har12] Dieser Flow kann bei Microservices von Nutzen sein, um einen Microservice im
2 Grundlagen 21 Backend aufrufen zu können. Das Problem hierbei ist, dass der Nutzerkontext in dem Access Token verloren geht. Das heißt der Microservice hat volle Berechtigun- gen auf den Backend-Service, obwohl der Nutzer eine Aktion nicht durchführen darf. Dies verstoßt gegen das Least Privileg Prinzip. 2.5.2.4 Token Exchange Flow Der Token Exchange ist eine Verbesserung des Client Credentials Flows. Abb. 2.4: OAuth Token Exchange (Quelle: In Anlehnung an [Har12]) 1. Der Client authentifiziert sich beim Authorization Server und schickt das Ac- cess Token des Nutzers an den Token Endpunkt des Authorization Server. Bei der Anfrage kann auch die Audience, die für das neue Token gelten soll, angegeben werden. 2. Ist die Authentifizierung erfolgreich, wird ein Access Token zurückgegeben. Das neue Access Token erhält die Nutzerinformation. Somit kann das Backend selbst eine Autorisierung durchführen. [JNC+ 20]
2 Grundlagen 22 Die Spezifikation des Token Exchange Flow geht aber noch deutlich darüber hinaus. Es können, wenn vom Authorization Server akzeptiert, auch Saml Token oder die in OpenID Connect spezifizierten ID Token umgetauscht werden. [JNC+ 20] 2.6 OpenID Connect Bei OpenID Connect handelt es sich um ein Authentifizierungsprotokoll, das auf OAuth aufbaut. Es hilft den Endbenutzer durch den Authorization Server zu au- thentifizieren und hilft darüber hinaus Clients Informationen über den Nutzer zu erhalten. Es gibt das sogenannte ID Token, das die Informationen über den Nutzer als Claims in ein JWT gepackt zurückgibt. Es müssen die Claims, die in Kapitel 2.3.1 aufgezeigt wurden, vorhanden sein. Darüber hinaus gibt es noch weitere. Zusätz- lich zu dem ID Token gibt es noch den UserInfo Endpunkt, der mit einem Access Token aufgerufen werden kann und auch Claims über den Nutzer im JSON Format zurückgibt. OpenID Connect hat wie OAuth verschiedene Flows. Es gibt den Im- plicit, Authorization Code und Hybrid Flow. Bei dem Implicit und Authorization Code Flow gibt es kaum Unterschiede zu denen in OAuth. Der Hybrid Flow ist eine Mischung aus dem Authorization Code Flow und Implicit Flow. [SBJ+ 14] Es wird in dieser Arbeit nur der Authorization Code Flow weiter betrachtet.
2 Grundlagen 23 2.6.1 Authorization Code Flow Der Authorization Code Flow ist fast identisch zu dem in OAuth. Es werden die Unterschiede in Abb. 2.5 aufgezeigt. Abb. 2.5: OpenID Connect Authorization Code Flow (Quelle: In Anlehnung an [Har12]) 1. Der User-Agent wird wie in OAuth vom Client umgeleitet. Die Anfrage erhält im Scope aber zusätzlich den Parameter openid. Der Scope Parameter wird auch an den Authorization Server weitergeleitet. Nur durch diesen Parameter weiß er, dass es sich um eine OpenID Connect anfrage handelt. Die Schritt 2 bis 4 sind identisch zu denen im OAuth Flow. 5. Zusätzlich zu dem Access Token und dem optionalen Refresh Token wird auch ein ID Token zurückgegeben. 6. Dieser Schritt ist neu. Der Client validiert in diesem das erhaltene ID Token. [SBJ+ 14]
2 Grundlagen 24 Bei OpenID Connect kann natürlich auch der Authorization Code Flow with PXCE genutzt werden. Hierbei ändert sich nichts weiteres in OpenID Connect zu den oben genannten Änderungen. 2.7 Microservices Es gibt keine eindeutige Definition von Microservices. Häufig werden zwei Defini- tionen herangezogen. Die erste ist von Sam Newman. „Microservices are small, autonomous services that work together.“ [New15] Die zweite Defintion von Micrservices kommt von Martin Fowler: „Microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated de- ployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use diffe- rent data storage technologies.“ [Fow14] Beide Definitionen besagen, dass es sich um kleine Services handelt, die mitein- ander kommunizieren und selbständig sind. Die Definition von Fowler geht noch genauer darauf ein, wie die Kommunikation zwischen den Services oft geschieht. Nämlich über HTTP API Schnittstellen. 2.7.1 Vorteile gegenüber eines Monolithen Microservices haben im Gegensatz zu einem Monolithen viele Vorteile. Durch die Zerlegung des Monolithen in kleine Services können die einzelnen Microservices skaliert und dadurch einfacher auf Nachfragesteigerungen reagiert werden. Ein weiterer Vorteil ist die technologische Flexibilität. Jedes Entwicklerteam kann die Technologien für den Microservice nutzen, die am besten zum Lösen des Problems passen. Durch die verteilte Architektur erhöht sich die Ausfallsicherheit der Anwendung.
2 Grundlagen 25 Der Ausfall einer Komponente führt nicht zum Ausfall der ganzen Anwendung. Es wird hier lediglich eine Funktionalität beeinträchtigt. [AWS20] 2.7.2 Sidecar-Muster Zur Isolation und Kapselung werden Komponenten einer Software in einen eigenen Container ausgelagert. Dadurch kann eine technologische Unabhängigkeit von der Hauptanwendung erreicht werden. Dieses Muster wird Sidecar genannt. Es bietet unterstützende Funktionen für die Hauptanwendung . Anwendungen benötigen Funktionen wie Monitoring, Logging und Autorisierung. Diese Funktionen können alle als ein Sidecar implementiert werden und dadurch in allen Services genutzt werden. Das hat einige Vorteile. [olp19] • Das Sidecar kann in einer anderen Programmiersprache geschrieben werden, als die Primäranwendung. • Es gibt kaum eine Latenz bei der Kommunikation zwischen dem Sidecar und der Primäranwendung [olp19] Dieses Muster wird oft in containerisiserten Anwendungen und damit auch oft in Microservices genutzt. [olp19] 2.8 CAP-Theorem Das CAP-Theorem von Professor Eric A. Brewer besagt, dass in verteilten Systemen immer nur zwei der drei verlangten Charakteristiken (Konsistenz, Verfügbarkeit, Partitionstoleranz) erreicht werden können. [Edu19] Konsistenz: Konsistenz meint, dass alle Clients die gleichen Daten zur selben Zeit sehen. Es ist also nicht relevant zu welchen Knoten die Clients verbunden sind, sie sehen alle die gleichen Daten. Werden Daten an einen Knoten geschrieben, müssen diese sofort an die anderen Knoten weitergeleitet werden, bevor das Schreiben auf den initialen Knoten beendet wurde. [Edu19]
2 Grundlagen 26 Verfügbarkeit: Ein Client soll auch eine Antwort bekommen, wenn ein oder mehrere Knoten nicht mehr funktionieren. Die funktionierenden Knoten in einem verteilten System ge- ben eine korrekte Antwort zurück. [Edu19] Partitionstoleranz: Eine Partition ist eine Unterbrechung der Verbindung in einem verteilten System. Es kann sich um eine unterbrochene oder eine verspätete Verbindung zwischen zwei Knoten handeln. Partitionstoleranz bedeutet, dass auch wenn die Kommunikation zwischen zwei oder mehreren Knoten unterbrochen ist, das gesamte verteilte Sys- tem immer noch funktioniert. [Edu19] Ein falscher Schluss, der oft aus dem CAP-Theorem gezogen wird ist, dass im- mer nur exakt 2 der 3 Eigenschaften erfüllt werden können. Die drei Eigenschaften müssen als kontinuierlich und nicht als binäre Größen betrachtet werden. [Bre12] Folglich müssen in einer Eigenschaft Abstriche gemacht werden, um mehr von den anderen beiden zu erreichen. Zielt man zum Beispiel ein System, dass eine hohe Verfügbarkeit und Partitionstoleranz hat, heißt das nicht, dass das System kom- plett inkonsistent ist. Es gibt in der Konsistenz z. B. die Abstufung der eventuellen Konsistenz. Es wird hier sichergestellt, dass wenn keine Daten geupdatet werden, nach einer bestimmten Zeit der neueste Wert zurückgegeben wird. [Vog09]
3 Fachliche Anforderungen 27 3 Fachliche Anforderungen In diesem Kapitel geht es um die fachlichen Anforderungen für die Authentifizie- rung und Autorisierung. 3.1 Authentifizierung 3.1.1 Unterstützung von OpenID Connect Die Authentifizierung soll mit OpenID Connect vorgenommen werden, da es sich hier um einen Standard handelt, der sehr häufig für die Authentifizierung im Internet genutzt wird und sich auch bewährt hat. Weiterhin arbeitet dieser Standard mit JWTs, was für zustandslose Microservices vom Vorteil ist. 3.2 Autorisierung 3.2.1 Lesbarkeit der Policies Die Policies sollten so geschrieben werden, dass sie einfach lesbar und dadurch auch besser nachvollziehbar sind. Denn sonst kommt es leicht zu Fehlern, bei denen ein Nutzer Berechtigungen hat, die er nicht haben sollte. 3.2.2 Austauschbarkeit der Policies Die Policies sollten verändert werden können und ohne neues deployen des Ser- vices auch automatisch greifen. Es kann sein, dass sich Policies in einem Unterneh- men oft ändern. Brauchen Nutzer zum Beispiel für ein neues Projekt Zugriff auf geschützte Daten sollte es möglich sein, einfach die Policies zu ändern, damit die Nutzer Zugriff haben, ohne den Service neu zu deployen.
3 Fachliche Anforderungen 28 3.2.3 Testbarkeit der Policies Die Policies sollten einfach getestet werden können. Dies hilft den Entwickler Fehler zu erkennen. Zusätzlich werden Policies mit der Zeit geändert. Bei der ersten Entwicklung werden Fälle in Betracht gezogen, an die beim Update der Policies nicht mehr gedacht wird. Tritt dieser Fall ein, schlägt der Test fehl. 3.2.4 Plattformunabhängigkeit Die Autorisierung sollte unabhängig von der im Service verwendeten Program- miersprache funktionieren. Jeder Service soll in der Programmiersprache und mit dem Framework programmiert werden, welche am besten zu dem Anwendungsfall passt. Die Policies sollten aber immer in der gleichen Sprache geschrieben werden, da diese zentral verwaltet werden sollen. 3.2.5 Performance Damit das ganze System reaktionsfähig bleibt, sollte die Entscheidung über die Zu- griffserlaubnis sehr schnell getroffen werden. Dies ist deshalb so wichtig, da jeder Microservice selbst eine Autorisierung durchführen muss. Dadurch, dass ein Micro- service weitere Microservices aufrufen kann, summiert sich die Auswertungszeit der Policies. Deshalb sollte die Dauer möglichst minimal gehalten werden. Manch- mal kann die Authentifizierung nicht durch JWTs oder lokale Daten geschehen und es müssen andere Microservices oder Datenbanken aufgerufen werden, das einen negativen Einfluss auf die Auswertungszeit hat. 3.2.6 Verteilte Autorisierung Jeder Service muss aufgrund der Sicherheit selbst eine Autorisierung durchführen. Es kann aber auch einen eigenen Service geben, der als Policy Decision Point fun- giert und nur die Policy Enforcement lokal im Service durchgeführt wird. In dieser Arbeit soll jeder Service selbst die Autorisierung durchführen. Der PDP und der PEP laufen lokal im Service. Aus Sicht des CAP Theorems wirkt sich die durch die verteilte Autorisierung hohe Verfügbarkeit auf die Konsistenz aus. Denn die Policies sind alle lokal in den Services. Gibt es neue Policies kann es sein, dass ein Service diese früher lädt als ein anderer und es zu kurzzeitigen inkonsistenten Ergebnissen bei der Autorisierung kommen kann.
4 Technisches Konzept 29 4 Technisches Konzept Das technische Konzept handelt von den Technologien, die für die verteilte Au- torisierung und die Authentifizierung genutzt werden und der Architektur der Microservices, um die verteilte Autorisierung und die Authentifizierung umzuset- zen. 4.1 Verwendete Technologien 4.1.1 Open Policy Agent OPA ist eine Policy Engine die es erlaubt Policies im deklarativen Stil als Code zu spezifizieren und damit Policy Entscheidungen von der Anwendung zu trennen. OPA wird in vielen Anwendungsbereichen verwendet, beispielsweise in Microser- vices, Kubernetes, CI/CD Pipelines oder API Gateways. [OPA20b] OPA wird immer mehr im Cloud-Native-Umfeld genutzt. Denn durch die deklarative Sprache kön- nen die Policies leserlich und verständlich geschrieben werden. Deshalb wird OPA auch für diese Arbeit verwendet. OPA arbeitet als Policy Decision Point. Benötigt eine Software eine Entscheidung, fragt es bei OPA an und übergibt Daten, die für die Autorisierung relevant sind. Dies kann z. B. ein Access Token und der Name der aufgerufene API sein. Zusätz- lich hat OPA selbst noch einen Data-Store, wo zusätzlich Daten gespeichert werden können, die relevant für die Auswertung sind. In OPA werden zwei Arten von Daten unterschieden. Die einen werden über die Rest-API oder über den Bundle- Service, der weiter unten erklärt wird, in OPA geladen. Diese Daten werden als base documents bezeichnet. Auch die Regeln in den Policies können neue Dokumente erzeugen. Diese werden dann als virtual documents bezeichnet, da diese durch die Policies erzeugt wurden. [OPA20f]
4 Technisches Konzept 30 4.1.1.1 Rego Rego ist die Sprache die in OPA genutzt wird um zu Entscheiden, ob der Zugriff auf eine geschützte Ressource erlaubt oder verboten werden soll. Rego Queries sind im genaueren Sinn Behauptungen, die auf Basis von Policies und Daten, welche in OPA gespeichert sind auf die Wahrheit überprüft werden. Regeln in OPA können beliebige Werte zurückgeben. Eine Regel wird als wahr angenommen, wenn Sie einen Wert hat oder nicht explizit falsch ist. [OPA20g] Eine solche Regel wird in Listing 4.1 vorgestellt. 1 allow { 2 method := input . method 3 method == "GET" 4 input .path == [" contracts "] 5 isInsuranceAgent 6 } Listing 4.1: Einfache Regel in Rego Mit „input“ werden die Daten angesprochen, die mit der Anfrage an OPA mitge- schickt werden. In der zweiten Zeile erfolgt eine Zuweisung von „input.method“ an die lokale Variable „method“ durch den Zuweisungsoperator „:=“. Die lokale Variable muss äquivalent zu dem String „GET“ sein. Der Pfad muss äquivalent zu dem angegebenen Array sein. Im letzten Schritt wird eine andere Regel mit dem Namen „isInsuranceAgent“ referenziert, die auch in diesem Paket definiert ist. Gibt diese einen Wert zurück, der wahr ist und die obigen beiden Ausdrücke auch, wird die ganze Regel „allow“, wahr. Die einzelnen Ausdrücke werden alle und-verknüpft, d. h. ist ein Ausdruck in der Regel falsch, wird die ganze Regel falsch. Möchte man stattdessen eine oder-Verknüpfung erreichen schreibt man eine neue Regel mit dem gleichen Namen. Es muss dann nur eine der beiden Regeln wahr sein. Da es sich bei Rego um eine deklarative Sprache handelt, gibt es keine Schleifen. Um über Mengen oder Arrays zu iterieren wird einfach eine Variable, der noch kein Wert zugewiesen wurde, genutzt. Für diesen Fall gibt es auch das „_ “ Zeichen. Dieses Zeichen wird intern durch eine Variable ersetzt. [OPA20g]
4 Technisches Konzept 31 1 array := [" hallo ", "welt"] 2 3 allow { 4 array [_] == " hallo " 5 } Listing 4.2: Iteration in Rego (Quelle: In Anlehnung an [OPA20g]) Die in Listing 4.2 festgelegte „allow“ Regel kann in einer imperativen Program- miersprache folgendermaßen aussehen: 1 for ( String e: array ) { 2 if(e == " hallo ") return true; 3 } Listing 4.3: Iteration des Rego Beispiels in imperativer Sprache (Quelle: In Anlehnung an [OPA20g] Hier ist darauf zu achten, dass der Ausdruck nicht für alle Werte korrekt sein muss, falls über Elemente iteriert wird und diese mit einem konstanten Wert verglichen werden. Der Ausdruck muss nur ein einziges Mal wahr sein Möchte man aus Regeln nicht nur einen Wert, sondern eine Menge zurückgeben muss der Name der Regel nur mit einer Variable in viereckigen Klammern beendet und dieser Variable dann Werte zugewiesen werden. [OPA20g] 1 array := [" hallo ", "welt"] 2 3 set[s] { 4 s := array [_] 5 } 6 7 allow { 8 set[" hallo "] 9 } Listing 4.4: Erzeugen einer Menge In dem Beispiel Listing 4.4 wurde das Array in eine Menge umgewandelt. Es kann in einer Menge nur über alle Elemente iteriert oder überprüft werden, ob ein Element in der Menge existiert, wie in der „allow“ Regel geschehen. Möchte man hingegen ein Objekt erzeugen, funktioniert das sehr ähnlich.
4 Technisches Konzept 32 1 array := [" hallo ", "welt"] 2 3 toUpperCaseArray := str { 4 c := concat (" ",array ) 5 str := upper (c) 6 } Listing 4.5: Erzeugen eines Objekts In Listing 4.5 wird mithilfe der Regel „toUpperCaseArray“ das Array in einen String umgewandelt, der dann nur Großbuchstaben enthält. Das Ergebnis muss der im Kopf spezifizierten Variable „str“, wie in Zeile 5 geschehen, zugewiesen werden. Dieses Objekt ist sehr einfach, es können deutlich kompliziertere Objekte erstellt werden, die auch einen Schlüssel und nicht nur einen Wert haben. Ein weiteres interessantes Feature ist Unifikation. Mit Unifikation kann gefragt werden, ob es Werte für Variablen gibt, um den Ausdruck wahr zu machen. 1 [x ,"welt"] = [" hallo ", y] Listing 4.6: Unifikation in Rego (Quelle: [OPA20g] In dem Listing 4.6 wird in Rego gefragt, ob es eine Lösung gibt, dass diese Gleichung wahr wird. Die Lösung für diese Unifikation ist einfach. Die Variable x wird den Wert „hallo“ erhalten und die Variable y den Wert „welt“. Um die Policies in OPA zu testen, gibt es das „with“ Schlüsselwort. Mit diesem können Mocks erstellt werden. Es können Regeln, die Input Daten und auch lokale Daten gemockt werden. OPA hat darüber hinaus noch selbst eingebaute Funktionen. Es gibt zum Beispiel Funktionen, um Strings zu bearbeiten, JWTs zu validieren und auch ein HTTP- Client um HTTP-Aufrufe zu machen. [OPA20g] 4.1.1.2 Filtern von Daten Ein Problem, das oft auftritt ist, dass man zu wenig Daten hat, um eine Entschei- dung zu treffen, ob der Zugriff erlaubt werden soll oder nicht. Ein Beispiel wäre, dass ein Kunde einen Vertrag abrufen möchte. Der Kunde ruft dafür den Service mit der eindeutigen ID des Vertrages auf. Diese ID sagt aber nichts darüber aus, zu welchem Kunden der Vertrag gehört. Eine Möglichkeit ist es, das Vertrags- Kunden-Mapping lokal in OPA zu halten. Das bringt aber deutliche Probleme mit sich, da OPA die Daten im Arbeitsspeicher hält und bei einer großen Firma die
4 Technisches Konzept 33 Datenmenge schnell sehr groß wird. Außerdem müssen die Daten bei jedem neuen Vertrag, der hinzukommt, geupdatet werden. Ein anderer Ansatz ist es mithilfe des HTTP-Clients anzufragen, ob dieser Vertrag zu den Kunden gehört. Dies kann Funktionieren, wenn eine HTTP Schnittstelle für die Datenbank bereitgestellt wird. Hier zahlt man aber wieder mit einem deutlichen Performanceverlust. Das gleiche Problem tritt auf, wenn der Nutzer eine Liste von Verträgen haben möchte. Er darf aber nicht alle sehen, sondern nur seine eigenen. OPA bietet für dieses Problem den Compile-Endpunkt an, um Regeln nur Teilweise auszuwerten, so weit wie es möglich ist. Bei der Auswertung gibt OPA einen abstrakten Syntaxbaum zurück, der in einen SQL-Ausdruck umgewandelt werden kann. Dies kann nicht nur für SQL-Datenbanken genutzt werden, sondern auch für NoSQL-Datenbanken wie MongoDB, es muss aber hier der abstrakte Syntaxbaum anders übersetzt werden. Die teilweise Auswertung von Policies wird anhand eines Beispiels erläutert. filter { Policy data. contracts [_]. customerID == input . userID } { Input userID : "123456" } Unbekannten [data.contracts] Output data.contracts[_].customerID = 123456 Tab. 4.1: Beispiel für die Datenfilterung (Quelle: In Anlehnung an [San18]) OPA hat, wie in Tabelle 4.1 gezeigt, die folgende Policy gegeben. Als Input wird die ID des Nutzers übergeben. Die Unbekannten sind alle Verträge, da diese nicht lokal in OPA gespeichert werden. Die Unbekannten müssen beim Aufruf des Compile- Endpunkts mitgeschickt werden. Der Ausdruck „data.contracts“ kann in diesem Fall als eine Tabelle mit dem Namen „contracts“ in einer Datenbank gesehen wer- den. In dieser Tabelle gibt es ein Attribut mit dem Namen „customerID“. Dieses Attribut muss in diesem Fall also gleich „123456“ sein. Der SQL-Ausdruck könnte also folgendermaßen aussehen. 1 SELECT * FROM contracts WHERE customerId = ’123456 ’ Listing 4.7: Beispiel für einen durch die Datenfilterung erzeugten SQL-Ausdruck
Sie können auch lesen