Spezifikation der Semantik einer generischen

Transcrição

Spezifikation der Semantik einer generischen
T ECHNISCHE U NIVERSITÄT M ÜNCHEN
FAKULTÄT FÜR I NFORMATIK
Diplomarbeit
Spezifikation der Semantik einer generischen
Autorisierungskomponente als Basis für eine
verbesserte Implementierung
Thomas Nietsch
Abgabedatum: 31. August 2004
Aufgabensteller: Prof. Dr. Florian Matthes
Betreuer: Dipl.-Ing. Kathrin Lehmann
Prof. Dr. Johannes Siedersleben∗
∗
sd&m AG, München
Ich versichere, dass ich diese Diplomarbeit selbständig verfasst und nur die angegebenen Quellen und Hilfsmittel verwendet habe.
München, den 31. August 2004
...................................
Kurzfassung
Autorisierungskomponenten erbringen Basisdienste für die Kontrolle von Zugriffen
auf schützenswerte Ressourcen. Ausgehend von einem fertigen Produkt entwirft und
spezifiziert die vorliegende Arbeit eine generische Autorisierungskomponente anhand
ihrer Schnittstellen. Die Komponente bietet Dienste zur Authentifizierung und Sitzungsverwaltung an, zur Administration von Benutzerdaten und Zugriffsrechten und
zur Abfrage der festgelegten Rechte.
Lehrstuhl für Software Engineering
betrieblicher Informationssysteme
Inhaltsverzeichnis
1. Einführung
1.1. Thematische Einordnung .
1.1.1. IT-Sicherheit . . .
1.1.2. Design by Contract
1.2. Motivation und Ziel . . . .
1.3. Fahrplan . . . . . . . . . .
1
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2. Softwaretechnische Grundlagen
2.1. Quasar . . . . . . . . . . . . . . . .
2.2. Spezifikation von Schnittstellen . .
2.2.1. Die Schnittstelle als Vertrag
2.2.2. Spezifikationselemente . . .
2.2.3. Spezifikationstechniken . .
2.2.4. QSL . . . . . . . . . . . . .
1
1
2
2
3
5
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3. Grundlagen einer Sicherheitsarchitektur
3.1. Authentifizierung . . . . . . . . . . . . . . . . . . .
3.2. Autorisierung und Zugriffskontrolle . . . . . . . . .
3.2.1. Grundlegende Autorisierungsmechanismen
3.2.2. Implizite Rechte . . . . . . . . . . . . . . .
3.2.3. Negative Rechte und Konsistenz . . . . . . .
3.2.4. Zugriffskontrollstrategien . . . . . . . . . .
3.3. Vertrauens(un)würdige Software . . . . . . . . . .
3.4. JAAS – Informationssicherheit in der Java-Welt . .
3.4.1. Sandkastenspiele . . . . . . . . . . . . . . .
3.4.2. Codezentrierte Autorisierung . . . . . . . .
3.4.3. Know your principals . . . . . . . . . . . . .
5
7
7
8
10
11
15
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15
16
17
18
19
20
22
25
25
26
27
v
Inhaltsverzeichnis
4. QuasarAuthorization
29
4.1. Beschreibung der Komponente . . . . . .
4.1.1. Funktionsumfang . . . . . . . . . .
4.1.2. Datenmodell und Außensicht . . .
4.1.3. Berechtigungs-Cache . . . . . . . .
4.2. Verbesserungspotential . . . . . . . . . . .
4.2.1. Architektur und Implementierung .
4.2.2. Spezifikation . . . . . . . . . . . .
4.3. Fazit . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5. BasicAuthorization
5.1. Funktionsumfang . . . . .
5.2. Datenmodell . . . . . . .
5.3. Schnittstellen . . . . . . .
5.3.1. Operativer Betrieb
5.3.2. Instrumentierung .
5.3.3. Administration . .
29
29
30
35
36
36
38
39
41
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
6. AdvancedAuthorization
6.1. Funktionsumfang . . . . . . .
6.2. Datenmodell . . . . . . . . .
6.3. Schnittstellen . . . . . . . . .
6.3.1. Technische Umgebung
6.3.2. Operativer Betrieb . .
6.3.3. Instrumentierung . . .
6.3.4. Administration . . . .
6.4. Potential und Grenzen . . . .
41
41
42
44
45
46
49
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
49
49
52
52
53
54
62
64
7. Zusammenfassung und Ausblick
67
A. Glossar
69
B. QSL-Spezifikationen
73
B.1. Entitätstypen der Basic-/AdvancedAuthorization . . . . . . . . . . . . .
B.2. Schnittstellen der BasicAuthorization . . . . . . . . . . . . . . . . . . .
B.3. Schnittstellen der AdvancedAuthorization . . . . . . . . . . . . . . . .
73
75
81
Literaturverzeichnis
95
Index
99
vi
Abbildungen und Tabellen
Abbildungsverzeichnis
3.1. Ordnung auf Zugriffsarten . . . . . . . . . . . . . . . . . . . . . . . . .
3.2. Fundamentale Zugriffskontrollfunktionen . . . . . . . . . . . . . . . .
3.3. Sicherheitsarchitektur . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
23
24
4.1. QuasarAuthorization: Datenmodell (Teil 1) . . . . . . . . . . . . . . . . . .
4.2. QuasarAuthorization: Datenmodell (Teil 2) . . . . . . . . . . . . . . . . . .
4.3. QuasarAuthorization: Außensicht . . . . . . . . . . . . . . . . . . . . . . .
31
31
34
5.1. BasicAuthorization: Datenmodell . . . . . . . . . . . . . . . . . . . . . . .
5.2. BasicAuthorization: Außensicht . . . . . . . . . . . . . . . . . . . . . . . .
5.3. BasicAuthorization: Beispielkomposition . . . . . . . . . . . . . . . . . . .
42
43
43
6.1.
6.2.
6.3.
6.4.
6.5.
6.6.
6.7.
.
.
.
.
.
.
.
50
52
55
55
57
57
60
3.1. Zugriffsmatrix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
A.1. Gegenüberstellung der Synonyme . . . . . . . . . . . . . . . . . . . . .
72
Datenmodell . . . . . . . . . . . . . .
Außensicht . . . . . . . . . . . . . . .
Login-Sequenz (allgemein) . . . . . . . . . . . . . . . . .
Konfiguration für klassische Passwort-Authentifizierung . .
Login-Sequenz mit klassischer Passwort-Authentifizierung
Konfiguration für JAAS-basierte Authentifizierung . . . . .
Beispiel zur Linearisierung . . . . . . . . . . . . . . . . . .
AdvancedAuthorization:
AdvancedAuthorization:
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Tabellenverzeichnis
vii
Verzeichnis der Quelltexte
2.1.
2.2.
2.3.
2.4.
5.1.
5.2.
5.3.
5.4.
5.5.
6.1.
6.2.
6.3.
6.4.
6.5.
6.6.
6.7.
B.1.
B.2.
B.3.
B.4.
B.5.
B.6.
B.7.
B.8.
B.9.
B.10.
B.11.
B.12.
B.13.
B.14.
Grundgerüst einer QSL-Schnittstellenspezifikation . . . . . .
Allgemeine QSL-Methodenspezifikation . . . . . . . . . . . .
QSL-Methodenspezifikation (Beispiel) . . . . . . . . . . . . .
QSL-Testfall (Beispiel) . . . . . . . . . . . . . . . . . . . . . .
BasicAuthorization: Authentication.authenticate . . . . . .
BasicAuthorization: AuthorizationCheck.mayPerform . . . . .
BasicAuthorization: Auszug aus ResourceDefinition . . . . . .
BasicAuthorization: Implementierung von ResourceDefinition
BasicAuthorization: Auszug aus UserAdmin . . . . . . . . . . . .
AdvancedAuthorization: Auszug aus Assignment . . . . . . . . .
AdvancedAuthorization: Auszug aus SessionManagement . . . .
AdvancedAuthorization: Auszug aus Authentication . . . . . .
AdvancedAuthorization: Auszug aus ResourceDefinition . . . .
AdvancedAuthorization: Auszug aus Policy . . . . . . . . . . . .
AdvancedAuthorization: Auszug aus PositiveOverridePolicy .
AdvancedAuthorization: Auszug aus UserAdmin . . . . . . . . . .
AuthorizationEntity . . . . . . . . . . . . . . . . . . . . .
AbstractUser . . . . . . . . . . . . . . . . . . . . . . . . . .
User . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Group . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
AbstractRight . . . . . . . . . . . . . . . . . . . . . . . . .
Right . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Role . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Resource . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Operation . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . .
SessionTicket . . . . . . . . . . . . . . . . . . . . . . . . .
BasicAuthorization: Authentication . . . . . . . . . . . . . . .
BasicAuthorization: AuthorizationCheck . . . . . . . . . . . .
BasicAuthorization: ResourceDefinition . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
11
13
13
14
44
45
45
47
48
50
53
55
58
59
61
63
73
73
73
73
74
74
74
74
74
74
75
75
75
76
ix
Verzeichnis der Quelltexte
B.15.
B.16.
B.17.
B.18.
B.19.
B.20.
B.21.
B.22.
B.23.
B.24.
B.25.
B.26.
x
UserAdmin . . . . . . . . . .
AuthorizationAdmin . . . .
AdvancedAuthorization: Repository . . . . . . . .
AdvancedAuthorization: Logging . . . . . . . . . .
AdvancedAuthorization: SessionManagement . . .
AdvancedAuthorization: AuthorizationCheck . .
AdvancedAuthorization: Authentication . . . . .
AdvancedAuthorization: ResourceDefinition . .
AdvancedAuthorization: Policy . . . . . . . . . .
AdvancedAuthorization: PositiveOverridePolicy
AdvancedAuthorization: UserAdmin . . . . . . . .
AdvancedAuthorization: AuthorizationAdmin . .
BasicAuthorization:
BasicAuthorization:
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
76
79
81
82
83
83
84
84
86
86
87
91
»Hey, I don’t believe that any
system is totally secure!«
WarGames (Metro-Goldwyn-Mayer, 1983)
1. Einführung
Betriebliche Informationssysteme bilden das Kerngeschäft von sd&m (software design & management). Das Software- und Beratungshaus entwickelt und überarbeitet
solche Systeme im Projektgeschäft für Unternehmen und Behörden.
Bei jedem größeren System gibt es Teile, die man für den Kunden maßschneidert,
und andere, für die man besser auf (fast) fertige Software zurückgreift. Wer Programmcode wiederverwendet, bringt ein Projekt (zumindest theoretisch) schneller
und günstiger ans Ziel. sd&m Research – die Forschungs- und Entwicklungsabteilung
von sd&m – hat mehrere wiederverwendbare Standardkomponenten für Informationssysteme entwickelt. Eine davon – die Autorisierungskomponente QuasarAuthorization – ist der Ausgangspunkt dieser Arbeit.
1.1. Thematische Einordnung
IT-Sicherheit ist nicht nur in der Informatik ein Schlüsselbegriff, und wer verlässliche
Software bauen will, ist gut beraten, Design by Contract zu betreiben. Beides sind
Schlagworte, die den Inhalt der vorliegenden Arbeit betreffen.
1.1.1. IT-Sicherheit
Sicherheit in der Informationstechnik, kurz IT-Sicherheit, ist auf den ersten Blick ein
unübersichtliches Thema. Eine grundlegende Unterscheidung (nach [Eck03]) ist jene
zwischen Funktionssicherheit (safety) und Informationssicherheit (security).
Ein System arbeitet funktionssicher, wenn es jederzeit tut, was es soll. Wenn die
Bordelektronik eines Autos ohne Anlass den Airbag auslöst, so ist das ein Beispiel für
ein System, das seine Benutzer in Gefahr bringt, weil es nicht tut, was es soll.
Ein System arbeitet informationssicher, wenn es keine unerlaubten Zugriffe auf
schützenswerte Informationen zulässt. Systematische Zugriffskontrolle ist ein Weg zu
diesem Ziel. In umfangreichen Systemen ist es sinnvoll, die dafür notwendigen Vorkehrungen in einer eigenen Komponente zusammenzufassen. Man spricht dann von
einer Autorisierungskomponente.
1
1. Einführung
1.1.2. Design by Contract
Ein IT-System, das undefinierte Zustände annehmen kann, ist potentiell anfällig für
unerlaubte Zugriffe. Funktionssicherheit ist daher eine Voraussetzung für Informationssicherheit.
Wenn Funktionssicherheit heißt, dass Software tut, was sie soll, dann stellt sich
die Frage, wie man den Soll-Zustand festlegt. Idealerweise verfasst man dazu ein
Dokument mit einer präzisen Leistungsbeschreibung: die Spezifikation.
Design by Contract bedeutet, Software auf der Grundlage von Spezifikationen zu
entwerfen. Analog zu einem Vertrag (contract) regelt die Spezifikation das Verhältnis
zwischen zwei Vertragspartnern: Der eine erbringt eine (Rechen-)Leistung, der andere nimmt diese Leistung in Anspruch. Ein guter Vertrag lässt möglichst wenig Raum
für Missverständnisse.
1.2. Motivation und Ziel
Die QuasarAuthorization ist eine mächtige, vielseitig einsetzbare Autorisierungskomponente. Allerdings ist sie kompliziert in der Handhabung: Das mitgelieferte HelloWorld-Beispiel erstreckt sich über rund 500 Codezeilen. Der Einsatz der Komponente
fordert von den beteiligten Entwicklern einen hohen Einarbeitungsaufwand, der sich
nur bei großen Projekten mit langer Laufzeit lohnt.
Verbesserungswürdig ist auch die Spezifikation der QuasarAuthorization. Sie besteht nur aus informellen Beschreibungen und ist unvollständig. So erlaubt die Komponente die Definition beliebig komplizierter (auch widersprüchlicher) Zugriffsrechte; die Auswertungslogik ist jedoch nicht spezifiziert, sondern allein von der Implementierung abhängig.
Die wenigsten Informationssysteme entstehen heute auf der grünen Wiese; in der
Regel integriert man neue Systeme in eine bestehende (Sicherheits-)Infrastruktur. Die
QuasarAuthorization verfügt jedoch nur über rudimentäre Möglichkeiten der Integration mit anderen Produkten.
Das Ziel dieser Arbeit ist der Entwurf einer neuen Autorisierungskomponente mit
der QuasarAuthorization als Ausgangspunkt; dabei soll die Handhabung gegenüber
der existierenden Komponente vereinfacht werden. Der Entwurf beschränkt sich auf
die von außen sichtbaren Schnittstellen (die Außensicht) der Komponente.
Die Schnittstellen sind präzise zu spezifizieren. Die Auswertungslogik ist als Bestandteil der Schnittstellensemantik in der Spezifikation zu berücksichtigen.
Außerdem sollen Integrationsmöglichkeiten des Entwurfs erörtert werden. Er ist
hierzu mit dem Produkt JAAS (Java Authentication and Authorization Service) in Bezug zu bringen.
2
1.3. Fahrplan
1.3. Fahrplan
Es folgen zwei Grundlagenkapitel: In Softwaretechnische Grundlagen klären wir den
Begriff Quasar und stellen die verwendete Spezifikationstechnik vor. In Grundlagen
einer Sicherheitsarchitektur geht es um den Einsatzzweck von Autorisierungskomponenten: Authentifizierung und Autorisierung als Fundamente der Zugriffskontrolle und
damit für sichere Systeme. Hier wird auch JAAS vorgestellt.
Kapitel 4 ist der QuasarAuthorization gewidmet. Kapitel 5 enthält den Entwurf einer Autorisierungskomponente mit eingeschränktem Funktionsumfang, die wir BasicAuthorization nennen. Das ist ein Etappenziel auf dem Weg zum eigentlichen Entwurf,
den wir im darauf folgenden Kapitel vorstellen: AdvancedAuthorization.
Anhang A ist ein Glossar der zentralen Begriffe und aller verwendeten Abkürzungen. Anhang B enthält die Schnittstellenspezifikationen der Komponentenentwürfe.
3
»A verbal contract isn’t worth
the paper it’s written on.«
(Samuel Goldwyn)
2. Softwaretechnische Grundlagen
Die vorliegende Arbeit basiert auf einer Komponente namens QuasarAuthorization.
Doch was ist eigentlich Quasar? Der folgende Abschnitt fasst das kurz zusammen.
Danach führen wir in das Thema Spezifikation ein und stellen die für unsere Komponentenentwürfe verwendete Spezifikationssprache vor.
2.1. Quasar
Quasar steht für Qualitätssoftwarearchitektur und definiert den gedanklichen und
begrifflichen Rahmen für die Architektur der sd&m-Softwaresysteme. Quasar formuliert universell gültige Regeln und Baumuster für Software im Allgemeinen und für
betriebliche Informationssysteme im Besonderen. Letztere sind meistens groß, teuer und langlebig.1 Vor allem aus der Langlebigkeit der Systeme (oft misst man die
Lebensdauer in Jahrzehnten) ergeben sich hohe Anforderungen an ihre Wartbarkeit
und Erweiterbarkeit – und damit an ihre Architektur.
Das Referenzwerk zu Quasar ist [Sie04]. Die darin aufgestellten Regeln basieren
auf zwei Prinzipien, die seit langem zu den Tugenden des Software-Engineering zählen, in der Praxis aber selten konsequent umgesetzt werden:
• Trennung von Zuständigkeiten (separation of concerns): Jeder Baustein des Gesamtsystems hat einen definierten Aufgabenbereich.2
• Denken in Komponenten und Schnittstellen: Man untergliedert das Gesamtsystem in überschaubare Bausteine (Komponenten), die ausschließlich über wohldefinierte Kanäle (Schnittstellen) kommunizieren. Komponenten eignen sich zur
Komposition, dem Zusammenfügen mehrerer Komponenten zu einer größeren
Komponente.
David Parnas beschreibt bereits in [Par72] die Anwendung dieser Entwurfsprinzipien anhand eines Beispielsystems und fasst zusammen:
1
2
vgl. [DMT04, Teil 1]
Aus der UNIX-Welt stammt die ähnliche Philosophie one job, one tool: Jedes Werkzeug erledigt nur
eine Aufgabe, aber die sehr gut.
5
2. Softwaretechnische Grundlagen
„Every module [...] is characterized by its knowledge of a design decision which it hides from all others. Its interface [...] was chosen to reveal
as little as possible about its inner workings.“
Die Trennung von Zuständigkeiten bestimmt die Aufgabenverteilung zwischen den
Komponenten (Parnas nennt sie modules), und Schnittstellen (interfaces) abstrahieren
von deren Implementierung.
Wie legt man die Zuständigkeiten der Komponenten fest? Man bringt Software,
die unterschiedlichen Zwecken dient und sich voraussichtlich unterschiedlich schnell
ändern wird, in verschiedenen Komponenten unter. Jeder Entwickler sollte seine
Komponente möglichst unabhängig von anderen Komponenten entwickeln können,
und die nachträgliche Änderung einer Entwurfsentscheidung sollte Veränderungen an
möglichst wenigen Komponenten nach sich ziehen (knowledge of a design decision).
Das ist das Ziel. Als Weg dorthin schlägt Quasar die Bestimmung von Softwarekategorien vor, die die verschiedenen Aufgabenbereiche des Systems benennen.
Nach welchen Kriterien unterscheidet man Softwarekategorien? Ein Kriterium, das
sich bei jedem System anwenden lässt, ist die Abhängigkeit der Software von der
Anwendungslogik und von den technischen Mitteln, mit denen die Anwendung implementiert wird. Daraus ergeben sich die Standardkategorien (oder Blutgruppen):
A-Software ist allein durch die Anwendung bestimmt, T-Software allein durch die
Technik. 0-Software ist unabhängig von Anwendung und Technik (z. B. String- oder
Behälterklassen). AT-Software vermischt Anwendung und Technik und ist deshalb unerwünscht – doch ganz ohne AT geht es nicht: Software, die Objekte zwischen der
A- und T-Welt transformiert, ist zwangsläufig AT-Software. Quasar ordnet Software
in die Kategorie R (für Repräsentation) ein, wenn sie nur solchen Transformationen
dient.
Einer A-Komponente (Komponente, die ausschließlich aus A-Software besteht) ist
es egal, ob eine Oracle- oder eine IBM-Datenbank die Datenhaltung besorgt; einer
T-Komponente ist die Mehrwertsteuer gleichgültig.
Die Einteilung in A und T ist grobkörnig, deshalb schlägt Quasar vor, anwendungsspezifische Softwarekategorien einzuführen: Lagerhaltung und Personalverwaltung
fallen beide in die Kategorie A, doch es wäre nicht sinnvoll, sie in einer Komponente zu vereinen. Besser ist es, die Kategorien Lager und Personal zu definieren und
dafür getrennte Komponenten vorzusehen. Aus Kategorien lässt sich eine Hierarchie
aufbauen: Spezifischere Kategorien verfeinern allgemeinere. Die Kategorie 0 ist die
allgemeinste und damit die Basis jeder Kategorienhierarchie.
Bei einfachen Komponenten (das sind Komponenten, die nicht durch Komposition
entstanden sind) strebt man an, dass sie nur aus Software einer einzigen Kategorie
bestehen. Zusammengesetzte Komponenten dürfen zwar Software verschiedener Ka-
6
2.2. Spezifikation von Schnittstellen
tegorien enthalten (schließlich kann man auch das Gesamtsystem wiederum als Komponente auffassen) doch man sortiert die verschiedenartige Software in getrennten
Subkomponenten.
Neben den Grundprinzipien beschreibt Quasar eine Standardarchitektur für Informationssysteme, die detaillierter ist als das Drei-Schichten-Modell aus Datenhaltung,
Anwendungs- und Präsentationsschicht. Auch hier gibt es eine A-Architektur aus AKomponenten und eine T-Architektur, die von der technischen Infrastruktur (Hardware, Betriebssystem, Middleware) abstrahiert. Manche Elemente der T-Architektur eignen sich gut zur Wiederverwendung, weil sie in jedem Informationssystem vorkommen, z. B. Datenhaltung (Persistenz), Transaktionsverwaltung, grafische Benutzeroberfläche (GUI3 ). Quasar definiert für diese Elemente Standardschnittstellen. sd&m
Research hat einige Standardkomponenten entwickelt, die diese Schnittstellen implementieren. Eine davon ist die Persistenzkomponente QuasarPersistence – sie wird auf
der Webseite [OQ] als open source vertrieben – eine andere ist die Autorisierungskomponente QuasarAuthorization. Sie ist Gegenstand von Kapitel 4.
2.2. Spezifikation von Schnittstellen
Das Denken in Komponenten und Schnittstellen ist ein Fundament von Quasar.
Schnittstellen definieren Dienste, die von Komponenten erbracht oder in Anspruch
genommen werden. Beim Entwurf eines Softwaresystems kommt den Schnittstellen
eine bedeutende Rolle zu: Sie sind die tragenden Wände des Gebäudes. Komponenten
unterliegen einem Lebenszyklus, Veränderungen der Implementierung sind nicht ungewöhnlich. Dagegen wird eine Schnittstelle im Idealfall einmal definiert und danach
nicht mehr geändert. Die Spezifikation des Systems stützt sich deshalb überwiegend
auf seine Schnittstellen.
Die folgenden Unterabschnitte orientieren sich am Schnittstellenkonzept von Quasar, insbesondere an der in [Sie04, Kapitel 6] vorgestellten Methode zur Schnittstellenspezifikation.
2.2.1. Die Schnittstelle als Vertrag
Schnittstellen verbinden Komponenten mit Komponenten, Systeme mit Systemen
oder – im Fall von Benutzerschnittstellen – Systeme mit Menschen. Im Folgenden beschränken wir uns auf Programmschnittstellen. Sie bestehen aus maschinenlesbaren
Methoden- bzw. Funktionsdeklarationen.
3
Graphical User Interface
7
2. Softwaretechnische Grundlagen
Verbindet eine Schnittstelle zwei Komponenten, treten beide in verschiedenen Rollen auf:
• Der Exporteur erbringt den Dienst, er exportiert die Schnittstelle und implementiert ihre Methoden.
• Der Importeur nimmt den Dienst in Anspruch, er importiert die Schnittstelle und
ruft ihre Methoden auf.
Jede Komponente erbringt irgendeinen Dienst und exportiert deshalb mindestens
eine Schnittstelle. Die Gesamtheit der von einer Komponente exportierten und importierten Schnittstellen bildet die Außensicht der Komponente. Die Konfiguration
legt fest, welche Importeure durch welche Schnittstellen mit welchen Exporteuren
zu einer Komposition verbunden werden.
Wenn zwei Menschen eine Ware oder Dienstleistung austauschen, schließen sie
einen Vertrag, der die Rechte und Pflichten der Vertragspartner festschreibt. Wenn
zwei Softwarekomponenten verbunden werden (um eine Dienstleistung auszutauschen), übernimmt die Schnittstelle die Rolle des Vertrages. Diese Sichtweise liegt
der Entwurfstechnik Design by Contract zugrunde (siehe [Mey97]). Man beschreibt
dabei Komponenten nur anhand der Außensicht. Die Schnittstellenspezifikation ist
ein verbindlicher Vertrag (contract), und weder Importeur noch Exporteur dürfen Annahmen machen, die über den Vertrag hinausgehen. Damit weiß der Exporteur, was
er zu tun hat, und der Importeur weiß, worauf er sich verlassen kann. Die Abhängigkeiten zwischen Komponenten beschränken sich auf die Schnittstellen und bleiben
damit überschaubar. Design by Contract ist ein Schlüsselkonzept zur Entwicklung verlässlicher Software.
2.2.2. Spezifikationselemente
Die Spezifikation einer Schnittstelle macht Aussagen über deren Syntax und Semantik. Die Syntax ist einfach zu beschreiben: Sie besteht aus den Signaturen4 aller
Methoden der Schnittstelle, formuliert in der jeweiligen Programmiersprache. Interessanter ist die Semantik: Was bewirken Methodenaufrufe, welche Aufrufe sind unter
welchen Umständen erlaubt? Was bedeuten die Rückgabewerte? Die Semantik von
Schnittstellen kann man mit verschiedenen Ausdrucksmitteln erfassen:
• Vor- und Nachbedingungen für Methoden: Vorbedingungen (preconditions) bilden die Gebrauchsanleitung für den Importeur. Er darf die Methode nur aufrufen, wenn all ihre Vorbedingungen erfüllt sind. Nachbedingungen (postcondi4
8
Methodenname, Parametertypen und Rückgabetyp
2.2. Spezifikation von Schnittstellen
tions) beschreiben, was ein Methodenaufruf bewirkt. Der Exporteur sorgt dafür,
dass am Ende des Aufrufs alle Nachbedingungen der Methode erfüllt sind.
• Invarianten sind Bedingungen, die immer gelten. Jede Invariante ist zugleich
Vor- und Nachbedingung jeder Methode der Schnittstelle.
• Ein Zustandsmodell teilt den Zustandsraum einer Schnittstelle in wenige Äquivalenzklassen auf. Das erleichtert die Formulierung von Vor- und Nachbedingungen und Invarianten. Beispiel Liste: Der Zustandsraum einer Liste ist unendlich
groß, doch ein Zustandsmodell, das nur zwischen leeren und gefüllten Listen
unterscheidet, kommt mit zwei Zuständen aus.
• Testfälle sind beispielhafte Abfolgen von Methodenaufrufen mitsamt den erwarteten Ergebnissen.
• Fehler, die bei einem Methodenaufruf auftreten können, sind Bestandteil der
Spezifikation. Quasar unterscheidet zwischen Fehlern und Ausnahmen. Ein Fehler ist auf der Abstraktionsebene der Schnittstelle ein sinnvolles Ergebnis, eine
Ausnahme nicht. Beispiel Bankkonto: Wenn ein Überweisungsvorgang scheitert, weil der Kontostand zu niedrig ist, dann ist das ein Fehler. Scheitert die
Überweisung, weil der Zentralcomputer der Bank unerreichbar ist, handelt es
sich um eine Ausnahme. Im Gegensatz zu Fehlern sind Ausnahmen implementierungsabhängig, und der Aufrufer hat normalerweise keine Möglichkeit, sie
zu verhindern. Quasar propagiert die Spezifikation in einer heilen Welt – Ausnahmen zählen nicht dazu.
• Angaben zur Konstanz: Wenn der Aufruf einer Methode den Zustand5 der Komponente nicht verändert, schreibt man das in die Spezifikation dieser Methode.
Das Gleiche gilt für Methodenparameter, die beim Aufruf konstant bleiben.
Methoden, die den Komponentenzustand unverändert lassen, heißen Abfragen,
zustandsändernde Methoden heißen Kommandos.
• Angaben zur Wiederholbarkeit tragen ebenfalls zum besseren Verständnis der
Schnittstellensemantik bei. Dabei geht es um die Frage: Führen wiederholte
Methodenaufrufe mit unveränderten Parametern zu unveränderten Resultaten?
Quasar unterscheidet hier drei Fälle:
URR (unrestricted repeatable read) garantiert uneingeschränkte Wiederholbar-
keit: Die Methode liefert mit denselben Parametern immer dasselbe Ergebnis, verhält sich also wie eine mathematische Funktion.
5
Hier ist der an den Schnittstellen der Komponente beobachtbare Zustand gemeint. Nur ein Aufruf, der
das Ergebnis irgendeines nachfolgenden Aufrufs beeinflusst, ändert den beobachtbaren Zustand.
9
2. Softwaretechnische Grundlagen
RRR (restricted repeatable read) schränkt die Wiederholbarkeit ein: Zwei Me-
thodenaufrufe mit denselben Parametern liefern nur dann dasselbe Ergebnis, wenn niemand zwischenzeitlich den Zustand der Komponente ändert
(durch Aufruf eines Kommandos). Dies ist der häufigste Fall.
NRR (non-repeatable read) bedeutet, dass die Methode keine Wiederholbarkeit
garantiert: Jeder Aufruf kann ein anderes Ergebnis liefern (Beispiel: Zufallsgenerator).
2.2.3. Spezifikationstechniken
Wir haben aufgezählt, was in die Spezifikation einer Schnittstelle gehört, welche Vertragspunkte zu berücksichtigen sind. Es bleibt die Frage, wie man den Vertrag aufschreibt. Es gibt drei verschiedene Techniken:
• Weit verbreitet sind informelle Beschreibungen, wie man sie z. B. aus Java-Programmdokumentationen (Javadoc) kennt. Dabei erläutert man die Semantik
einer Schnittstelle oder Klasse ausschließlich in natürlicher Sprache. Die Qualität einer solchen Spezifikation hängt ganz von der Disziplin des Verfassers ab.
Ein genereller Nachteil besteht in der Mehrdeutigkeit natürlicher Sprache.
• Formale Spezifikationsmethoden bedienen sich präziser Spezifikationssprachen
mit Ausdrucksmitteln aus der Logik und Mengenlehre. Beispiele sind die ZNotation (siehe [Z]) und die Vienna Development Method (VDM) mit ihrer VDM
Specification Language (siehe [VDM]). Formale Spezifikationen sind maschinell
verifizierbar. Sie sind jedoch aufwendig zu erstellen und für den menschlichen
Leser nur schwer verständlich.
• Programmiernahe Beschreibungssprachen verwenden ähnliche Konstrukte und
Datenstrukturen wie Programmiersprachen. Sie kommen damit dem Programmierer entgegen, der die Spezifikation umsetzen soll. Als Beispiele seien hier
die Sprachen JML6 , OCL7 und Eiffel8 genannt. JML ist eine Erweiterung der
Programmiersprache Java, JML-Spezifikationen werden in Java-Quelltext eingebettet. OCL lehnt sich an keine bestimmte Programmiersprache an. Ein Sonderfall ist Eiffel: Das ist eine Programmiersprache, die von Haus aus Spezifikationselemente (Vor- und Nachbedingungen, Invarianten) enthält, also zugleich
Spezifikationssprache ist.
6
Java Modeling Language; siehe [JML]
Object Constraint Language; Teil des UML-Standards (Unified Modeling Language)
8
siehe [Mey97]
7
10
2.2. Spezifikation von Schnittstellen
2.2.4. QSL
In dieser Arbeit spezifizieren wir Schnittstellen mit Hilfe der programmiernahen
Beschreibungssprache Quasar Specification Language (QSL). Die Notation wird in
[Sie04] eingeführt, wir fassen an dieser Stelle die wichtigsten Merkmale zusammen. QSL-Spezifikationen enthalten Elemente der Zielsprache, in unseren Komponentenentwürfen ist das Java.
Jede QSL-Spezifikation hat den in Quelltext 2.1 dargestellten Aufbau (die meisten
Quelltextbeispiele dieses Abschnitts stammen aus [Sie04, Abschnitt 6.5]).
Quelltext 2.1: Grundgerüst einer Schnittstellenspezifikation in QSL
interface MyInterface extends YourInterface , HerInterface
uses H i s I n t e r f a c e , OurInterface
variables . . .
states . . .
basicQueries
firstBasicQuery
secondBasicQuery
...
derivedQueries
firstDerivedQuery
secondDerivedQuery
...
commands
firstCommand
secondCommand
...
invariants
firstInvariant
secondInvariant
...
testcases
firstTestCase
secondTestCase
...
11
2. Softwaretechnische Grundlagen
Die erste Zeile gleicht dem Beginn einer Java-Interface-Definition: Nach dem interface-Schlüsselwort folgt der Name der Schnittstelle; falls andere Schnittstellen
erweitert werden, zählt man deren Namen nach extends auf.
In der uses-Klausel stehen alle Klassen und Schnittstellen, die als Parameter- und
Resultattypen der Methoden vorkommen, mit Ausnahme von 0-Software (in Java sind
das die Typen aus den Paketen java.lang und java.util).
In der variables-Klausel deklariert man globale Variablen, auf die man in Vor- und
Nachbedingungen, Invarianten und Testfällen zurückgreift. Sie stehen in der gesamten Spezifikation mit einem impliziten Allquantor zur Verfügung, d. h. ohne explizite
Einschränkung bezieht sich jede Aussage über eine solche Variable auf alle Variablen
desselben Typs. Die Notation orientiert sich an Java:
variables L i s t r s maybenull , xs ; I t e r a t o r i t ; Object x , y , z ;
Variablen dürfen nur den Wert null annehmen, wenn dies durch Angabe des Schlüsselworts maybenull ausdrücklich gestattet ist.
In der states-Klausel definiert man ein oder mehrere Zustandsmodelle. Ein Beispiel mit zwei Zustandsmodellen:
states switch = { undefined , on , o f f }
l e v e l = { undefined , low , high }
Der Zugriff auf die Zustandsmodelle erfolgt durch Ausdrücke nach dem Muster
switch(x) == on (hier ist x die Variable, deren Zustand abgefragt wird). Existiert
nur ein Zustandsmodell, bekommt es keinen Namen, die Abfrage des Zustands erfolgt in diesem Fall mit state(x).
Die Klauseln basicQueries, derivedQueries und commands enthalten die Spezifikationen der Methoden, wobei man jede Methode genau einer der drei Klauseln
zuordnet. Kommandos ordnet man unter commands ein, Abfragen listet man unter
basicQueries (einfache Abfragen) bzw. derivedQueries (abgeleitete Abfragen) auf.
Die Unterscheidung zwischen einfachen und abgeleiteten Abfragen erfolgt gemäß
[MM02]: Abgeleitete Abfragen lassen sich auf einfache Abfragen zurückführen. Man
spezifiziert also das Resultat einer abgeleiteten Abfrage, indem man sich auf die Resultate einfacher Abfragen bezieht. Der Grund ist Arbeitserleichterung: Wenn man
die Semantik eines Kommandos spezifiziert, genügt es, seine Auswirkungen auf die
einfachen Abfragen zu beschreiben. Damit sind implizit die Auswirkungen auf die
abgeleiteten Abfragen ebenfalls erfasst.
Quelltext 2.2 zeigt den allgemeinen Aufbau von Methodenbeschreibungen in QSL.
Vorbedingungen leitet man mit pre ein, Nachbedingungen mit post. error-Klauseln
beschreiben, welche Fehler (keine Ausnahmen) unter welchen Bedingungen auftreten
können. repeatability bezieht sich auf die Wiederholbarkeit der Methode. Hier
steht entweder URR, NRR oder gar nichts (dann gilt RRR). Informelle Beschreibungen
12
2.2. Spezifikation von Schnittstellen
Quelltext 2.2: Allgemeiner Aufbau einer Methodenspezifikation in QSL
pre
firstPrecondition
pre
secondPrecondition
someType someMethod( firstParameter , secondParameter) r e pe a t ab i l it y
// i n f o r m e l l e Beschreibung
post
firstPostcondition
post
secondPostcondition
error someErrorCondition => f i r s t E r r o r
error secondError // i n f o r m e l l e F e h l e r b e s c h r e i b u n g
bringt man in Zeilenkommentaren unter (von // bis zum Zeilenende; QSL sieht keine
Blockkommentare vor). Die Methodensignatur notiert man in der Zielsprache, wobei
man die formalen Parameter zusätzlich mit maybenull markiert, falls sie den Wert
null annehmen dürfen. Parameter, die durch den Methodenaufruf nicht verändert
werden, kennzeichnet man mit const. Quelltext 2.3 zeigt die QSL-Beschreibung einer
konkreten Methode.
Quelltext 2.3: Beispiel einer QSL-Methodenspezifikation
pre
range > 0
i n t random( i n t range) NRR
// l i e f e r t e i n e Z u f a l l s z a h l .
post 0 <= r e s u l t < range
Zurück zum Grundgerüst (Quelltext 2.1): In der invariants-Klausel beschreibt
man die Invarianten der Schnittstelle. Die Angabe von Invariantennamen ist optional:
invariants
schulden () <= dispo ()
symmetry x . equals ( x )
// unbenannte I n v a r i a n t e
// I n v a r i a n t e namens ' symmetry '
Unter testcases beschreibt man Testfälle. Jeder Testfall hat einen Namen, optional
definiert man lokale Variablen, Vorbedingungen (pre) und Nachbedingungen (post).
Quelltext 2.4 zeigt einen Beispiel-Testfall aus der Spezifikation einer Liste.
Vor- und Nachbedingungen (von Methoden und Testfällen) sowie Invarianten formuliert man grundsätzlich in der Zielsprache. Zur Verbesserung der Ausdrucksstärke
bzw. Lesbarkeit sieht QSL zusätzlich folgende Konstrukte und Schlüsselwörter vor:
• Allquantor und Existenzquantor: forall, exists
• ∈-Relation der Mengenlehre (anwendbar auf Behälter, Arrays): in
• Logische Operatoren für UND, ODER und Negation: and, or, not
13
2. Softwaretechnische Grundlagen
Quelltext 2.4: Beispiel eines QSL-Testfalls
addAndRemove
L i s t<Object> xs ;
pre
xs . s i z e ()
xs . add( x )
xs . s i z e ()
xs . add( x )
xs . s i z e ()
xs . remove( y )
xs . s i z e ()
xs . indexOf ( x )
xs . indexOf ( y )
xs . contains ( x )
xs . contains ( y )
xs . remove( x )
xs . s i z e ()
xs . indexOf ( x )
xs . remove( x )
post xs . s i z e ()
// l o k a l e V a r i a b l e
== 0
−> 1
−>
−>
−>
−>
−>
−>
−>
−>
−>
−>
−>
==
2
false
2
0
−1
true
false
true
1
0
true
0
• Implikation und Äquivalenz: =>, <=>
• Zugriff auf den Wert von x vor Durchführung der Methode (in post- und errorKlauseln): ’x
• Zugriff auf das Methodenresultat (in post-Klauseln): result
• Typisierte Behälter: List<String> ls (Die Liste ls enthält nur Strings.)
14
3. Grundlagen einer
Sicherheitsarchitektur
»You can’t even travel around
your own microcircuits without
permission from that Master
Control creep.«
Tron (Walt Disney Pictures, 1982)
In jedem IT-System gibt es Subjekte (Prozesse, menschliche Benutzer etc.), die etwas tun, und Objekte (Bits, Datenbanktabellen, Dateien etc.), mit denen etwas getan
wird. Informationssicherheit ist dann hergestellt, wenn die Subjekte nur das tun können, was sie dürfen. Die Begriffe Authentifizierung, Autorisierung und Zugriffskontrolle
fassen die hierfür notwendigen Maßnahmen zusammen. Wir erörtern diese Begriffe
in den folgenden Abschnitten.
Desweiteren gehen wir in diesem Kapitel der Frage nach, was es mit vertrauenswürdiger Software auf sich hat, und stellen mit JAAS1 ein etabliertes Produkt vor, das
Softwareingenieuren Hilfsmittel für die Java-basierte Implementierung einer Sicherheitsarchitektur an die Hand gibt.
3.1. Authentifizierung
Jedes Subjekt hat eine Identität. Es ist die Aufgabe der Authentifizierung2 , die Identität eines Subjekts nachzuweisen.
Manchmal ist das trivial – das Betriebssystem erkennt einen lokal laufenden Prozess
einfach anhand seiner fest zugeordneten Nummer. Läuft der Prozess jedoch auf einem
entfernten Rechner, oder handelt es sich beim Subjekt um einen Menschen, der vor
einem Terminal sitzt, liegt der Fall komplizierter.
Authentifizierung basiert auf charakterisierenden Eigenschaften der Subjekte. Zu
diesen Eigenschaften zählt neben einer eindeutigen Kennung (Prozessnummer, Benutzername etc.) in den meisten Fällen ein Geheimnis, das nur dem echten Subjekt
bekannt ist, also ein Passwort – oder allgemeiner: ein Schlüssel in Form einer möglichst langen Zeichenkette.
Die Authentifizierung mittels Passwort läuft im einfachsten Fall so ab, dass das
zu authentifizierende Subjekt (nachfolgend Prüfling genannt) dem Authentifizierenden (Prüfer) sein Passwort mitteilt, woraufhin dieser es mit einer hinterlegten Kopie
1
2
Java Authentication and Authorization Service
alternative Begriffe: Authentifikation, Authentisierung
15
3. Grundlagen einer Sicherheitsarchitektur
vergleicht. Fortgeschrittenere Methoden erlauben es, einen Prüfling zu authentifizieren, ohne dass dieser sein Geheimnis vollständig preisgibt. Sogenannte ChallengeResponse-Verfahren basieren auf einer Art Frage-Antwort-Spiel, bei dem der Prüfer
dem Prüfling Aufgaben stellt, die dieser nur mit Kenntnis des Geheimnisses korrekt
lösen kann. Bei kryptographischen Verfahren (z. B. Fiat-Shamir-Authentifizierung, siehe [FS87, FFS87]) bestehen diese Aufgaben in der Regel darin, Zufallszahlen unter
Einbeziehung einer geheimen Zeichenkette zu verschlüsseln.
Neben Geheimnissen kann man bei menschlichen Benutzern auch biometrische
Merkmale wie z. B. Fingerabdrücke als charakterisierende Eigenschaften für die Authentifizierung verwenden. Ein Fingerabdruckscanner errechnet aus Messdaten eine
Zeichenkette, die ebenso wie ein geheimer Schlüssel nur sehr schwer zu fälschen ist.
Ein IT-System kann die Identität von Subjekten selbst prüfen, es kann diese Aufgabe aber auch an andere Systeme delegieren, indem es sich versichern lässt, dass ein
bestimmtes Subjekt bereits authentifiziert ist. Das setzt natürlich voraus, dass die beteiligten Systeme einander vertrauen, und ist die Grundlage für Single-Sign-On: Ein
Benutzer eines verteilten Systems authentifiziert sich nur an einem der vernetzten
Systeme, kann aber auch auf andere Systeme zugreifen, ohne sich dort erneut anzumelden. Die Delegation der Authentifizierung geschieht im Hintergrund, der Benutzer sieht davon nichts. Kerberos (siehe [Ker]) ist ein Authentifizierungsprotokoll, das
Single-Sign-On auf der Ebene lokaler bzw. unternehmensweiter Netzwerke ermöglicht. Microsoft Passport (siehe [MSP]) und das Liberty-Alliance-Project (siehe [Lib])
definieren Protokolle für Single-Sign-On-Verfahren zwischen verschiedenen Diensteanbietern im World Wide Web.
3.2. Autorisierung und Zugriffskontrolle
Durch Authentifizierung kann man sich auf die Identität der Subjekte verlassen –
das allein reicht aber nicht aus für eine wirksame Kontrolle der Objektzugriffe. Man
braucht Regeln, die festlegen, was welche Subjekte mit welchen Objekten tun dürfen.
Alles, was mit dem Formulieren und Abfragen solcher Regeln zu tun hat, fassen wir
unter Autorisierung3 zusammen. Die eigentliche Zugriffskontrolle besteht darin, die
Einhaltung der Regeln durchzusetzen.
Auch hier gibt es triviale Fälle. So kennt ein Betriebssystem für den Einbenutzerbetrieb (z. B. MS-DOS) nur eine Regel: Jeder hat die gleichen Rechte. Das macht
Authentifizierung überflüssig, denn es findet überhaupt keine Zugriffskontrolle statt.
3
Der Begriff Autorisierung wird in der Literatur nicht einheitlich verwendet. Manche meinen damit nur
die Vergabe, andere nur die Prüfung von Zugriffsrechten. Oft bezeichnet man auch ein einzelnes
Zugriffsrecht als Autorisierung oder Autorisation.
16
3.2. Autorisierung und Zugriffskontrolle
3.2.1. Grundlegende Autorisierungsmechanismen
Wir haben es in einem IT-System mit einer Menge von Subjekten (S) und einer Menge
von Objekten (O) zu tun.4 Subjekte können in vielfältiger Weise auf Objekte zugreifen,
womit als dritte Menge die Zugriffsarten (A) im Spiel sind. Typische Zugriffsarten
sind z. B. lesen, schreiben oder ausführen. [RBKW91] definiert auf diesen Mengen eine
Funktion
f : S × O × A → {True, False}
die jedes Tripel (s, o, a) mit s ∈ S, o ∈ O und a ∈ A auf einen Wahrheitswert abbildet.
Ein solches Tripel repräsentiert einen Zugriff, und die Funktion f stellt fest, ob dieser
Zugriff erlaubt ist. f liefert also die Antwort auf die Frage „Darf der das?“ Beispielsweise wäre f (Heidi, file1.txt, lesen) = True so zu interpretieren: „Heidi darf die Datei
file1.txt lesen“.
Es gibt verschiedene Möglichkeiten, diese Funktion zu implementieren. Ein offensichtlicher Ansatz wäre, alle Tripel zu speichern, für die f zu True auswerten soll.
So arbeitet das Modell der Zugriffsmatrix5 . Für jede mögliche Kombination aus Subjekt und Objekt existiert in der Matrix eine Zelle, in der die erlaubten Zugriffsarten
abgelegt sind. Tabelle 3.1 zeigt dafür ein Beispiel.
Tabelle 3.1.: Ausschnitt einer Zugriffsmatrix
Heidi
Otto
Uwe
..
.
file1.txt
file2.exe
lesen, schreiben
ausführen
ausführen
lesen
file3.txt
···
lesen
lesen, schreiben
Zugriffsmatrizen sind meist dünn besetzt, daher realisiert man sie gemeinhin durch
Listen, die einzelne Zeilen oder Spalten der Matrix repräsentieren – je nachdem, ob
man subjekt- oder objektbezogen vorgeht:
• Beim subjektbezogenen Ansatz verknüpft man je eine Liste mit einem Subjekt.
Diese Liste heißt Zugriffsausweis oder capability. Der Zugriffsausweis von Otto
enthält – bezogen auf das Beispielszenario – die Einträge (file2.exe, ausführen)
und (file3.txt, lesen).
• Beim objektbezogenen Ansatz verknüpft man je eine Liste mit einem Objekt.
Man spricht dann von einer Zugriffskontrollliste oder ACL (Access Control List).
4
5
S und O sind nicht zwangsläufig disjunkt.
auch bekannt als Lampson-Matrix (nach Butler Lampson, [Lam71])
17
3. Grundlagen einer Sicherheitsarchitektur
Die ACL der Datei file1.txt enthält die Einträge (Heidi, (lesen, schreiben)) und
(Uwe, lesen).
3.2.2. Implizite Rechte
Die Zugriffsmatrix und davon abgeleitete Modelle machen alle Rechtezuordnungen
explizit. Das ermöglicht eine sehr effiziente Auswertung, setzt in der Praxis aber überschaubare und möglichst statische Mengen von Subjekten und Objekten voraus, damit die Administration der Zugriffsrechte handhabbar bleibt. Man umgeht diese Einschränkung, indem man Rechte auch implizit vergibt, d. h. man speichert nur wenige
(s, o, a)-Tripel explizit und leitet weitere Rechte durch Anwendung von Regeln ab.
Sind Subjekte bzw. Objekte hierarchisch organisiert, ergeben sich Implikationsregeln oft ganz natürlich. Benutzer organisiert man normalerweise in Gruppen. Eine
Gruppe besteht aus einer Menge von Benutzern und eventuell weiteren Gruppen.
Beispiele für Implikationsregeln:
• Ein Benutzer erlangt bestimmte Rechte durch Mitgliedschaft in einer Gruppe.
• In einem Verzeichnisbaum schließt das Zugriffsrecht auf ein Verzeichnis entsprechende Rechte bezüglich aller enthaltenen Dateien und Unterverzeichnisse
ein.
Auch die Menge der Zugriffsarten kann geordnet sein. „Wer schreiben darf, darf
auch lesen“ kommt häufig vor, gilt aber nicht immer: Auf ein Bankkonto darf jeder
schreiben, indem er Geld einzahlt, deswegen darf er aber noch lange nicht den Kontostand abfragen.6 Abbildung 3.1 zeigt ein Beispiel mit vier Zugriffsarten.
6
Dieser Widerspruch lässt sich lösen, indem man neben der Zugriffsart schreiben die Zugriffsart einzahlen definiert.
W
G
Abbildung 3.1.: Darstellung einer (partiellen) Ordnung auf Zugriffsarten
write
read
generate
read definition
(entnommen aus [RBKW91]). Das Beispiel bezieht sich
auf eine objektorientierte Datenbank. Wer schreiben darf
(W), darf auch lesen (R) und – falls das Schreibrecht für
eine Klasse gilt – neue Objekte erzeugen (G). Aus allen
drei Zugriffsarten folgt das Recht zum Lesen der Klassendefinition (RD).
R
RD
W :
R :
G :
RD :
18
3.2. Autorisierung und Zugriffskontrolle
3.2.3. Negative Rechte und Konsistenz
In den bisherigen Beispielen nahmen wir stillschweigend an, dass das Erlaubnisprinzip gilt: Alles ist verboten, was nicht (explizit oder implizit) erlaubt ist. Dieses lässt
sich auch umkehren: Beim Verbotsprinzip formuliert man nur negative Zugriffsrechte
(Verbote) und erlaubt alles andere (vgl. [Die03, Teil 3]).
In Kombination mit impliziter Rechtevergabe ist es manchmal wünschenswert, sowohl positive als auch negative Zugriffsrechte parallel vergeben zu können. Man denke an ein Verzeichnis, das 100 Dateien enthält, von denen Otto 99 lesen darf. Statt 99
explizite Leserechte zu erteilen, ist es für den Administrator komfortabler, ein positives Recht für das Verzeichnis und ein negatives Recht für jene Datei darin zu erteilen,
die Otto nicht lesen darf.
Sobald positive und negative Rechte im Spiel sind, stellt sich die Frage, ob die Rechtefestlegungen widerspruchsfrei (konsistent) sind. Angenommen, Heidi ist Mitglied
in Gruppe1 und Gruppe2 . Gruppe1 hat ein positives Leserecht für file4.txt, Gruppe2
dagegen ein negatives. Darf Heidi die Datei nun lesen oder nicht?
Abhängig von den Implikationsregeln und den Beziehungsgeflechten bei Subjekten, Objekten und Zugriffsarten besteht unter Umständen ein beträchtliches Konfliktpotential. Damit die Funktion f von Seite 17 deterministisch bleibt, sorgt man entweder dafür, dass erst gar keine inkonsistenten Zugriffsrechte auftreten, oder man
gibt Regeln für die Auflösung aller möglichen Widersprüche an. Im ersten Fall ist die
Einhaltung der Konsistenz bei jeder neuen Rechtevergabe zu überwachen, im zweiten Fall sind alle Rechtezuordnungen per Definition konsistent (die Autorisierungskomponente QuasarAuthorization und unser Entwurf AdvancedAuthorization folgen
diesem Ansatz).
Im vorletzten Beispiel (Ottos 99 Dateien) haben wir bereits eine einfache Konfliktlösungsregel angewandt: Explizite Rechte überschreiben implizite. Das erscheint hier
vernünftig, ist aber nicht verallgemeinerbar – und ob Heidi file4.txt lesen darf, beantwortet diese Regel auch nicht: Heidis widersprüchliche Rechte ergeben sich beide
implizit durch Gruppenzugehörigkeit.7
Eine minimalistische Kombination aus positiver, negativer und impliziter Rechtevergabe kann Autorisierungsaufgaben vereinfachen, wohingegen das Ausschöpfen aller Freiheitsgrade den Rechtezustand eines Systems unüberschaubar macht. Das optimale Autorisierungsmodell gibt es (noch) nicht. Wie [Mar03] feststellt, „wird dem
Problem der Konsistenz der [...] vergebenen Rechte in der Literatur bisher wenig
Aufmerksamkeit geschenkt“.
7
Eine mögliche Lösung für das Heidi-Szenario wäre, Prioritäten auf Gruppenzugehörigkeiten zu definieren. Eine andere Lösung bietet die Regel: Negative Rechte überschreiben positive (oder umgekehrt).
19
3. Grundlagen einer Sicherheitsarchitektur
3.2.4. Zugriffskontrollstrategien
[Eck03] unterscheidet drei Strategien der Zugriffskontrolle:
DAC
DAC steht für Discretionary Access Control, auf deutsch benutzerbestimmbare Zugriffskontrolle. Bei dieser Strategie hat jedes Objekt einen Eigentümer, der festlegt, wer auf
welche Weise darauf zugreifen darf. Die Autorisierung erfolgt also dezentral.
Im Falle der ACL-basierten Rechtefestlegung hat allein der Eigentümer die Hoheit
über die ACLs seiner Objekte. SQL8 bietet Benutzern mit dem GRANT-Befehl die Möglichkeit, anderen Benutzern Zugriffsrechte auf ihre Datenbanktabellen zu gewähren.
MAC
Bei der systembestimmten Zugriffskontrolle oder MAC (Mandatory Access Control) bestimmen systemweite Vorgaben, wem was erlaubt ist.
Das bekannteste Modell, das dieser Strategie folgt, ist das Bell-LaPadula-Modell
(ausführlich beschrieben in [Eck03, S. 204ff]). Es basiert auf Sicherheitsklassen bzw.
Vertraulichkeitsstufen, wie sie vor allem in militärischen Einrichtungen Anwendung
finden. Jedes Objekt wird dabei entweder als unklassifiziert, vertraulich, geheim oder
streng geheim eingestuft. Die Subjekte sind analog klassifiziert. Jedes Subjekt darf nur
Objekte lesen, die seiner eigenen oder einer niedrigeren Vertraulichkeitsstufe angehören. Für den Schreibzugriff gilt die inverse Regel: Das Subjekt darf nur auf Objekte
zugreifen, die der gleichen oder einer höheren Vertraulichkeitsstufe angehören. Auf
diese Weise findet vertikaler Informationsfluss (also zwischen verschiedenen Sicherheitsklassen) nur von unten nach oben statt.
MAC ist von Haus aus eine zentralistische Strategie, allerdings ist eine Kombination
mit DAC möglich, wobei im Konfliktfall die restriktivere Regel Vorrang hat.
RBAC
Mit dem Anspruch, eine vollwertige Alternative zu den traditionellen DAC- und MACAnsätzen zu schaffen, wurde die rollenbasierte Zugriffskontrollstrategie in den neunziger Jahren unter dem Namen RBAC (Role-Based Access Control) formalisiert. Die Autorisierungskomponenten(entwürfe), die wir in den folgenden Kapiteln behandeln,
verfolgen einen rollenbasierten Ansatz, weshalb wir RBAC an dieser Stelle etwas ausführlicher vorstellen.
8
Structured Query Language (eine Abfragesprache für relationale Datenbanken)
20
3.2. Autorisierung und Zugriffskontrolle
Rollenkonzepte im weiteren Sinne gibt es schon lange – man denke z. B. an das
Gruppenkonzept in UNIX-Betriebssystemen – doch erst mit RBAC setzte sich eine
einheitliche Terminologie durch. Die US-amerikanische Normungsbehörde NIST (National Institute of Standards and Technology) schlägt RBAC als offiziellen Standard vor
(siehe [FSG+ 01]).
Wir führen zwei neue Begriffe ein:
• Eine Berechtigung ist ein Tupel (o, a) mit o ∈ O und a ∈ A. Sie verknüpft ein
Objekt mit einer Zugriffsart. Im Unterschied zum (s, o, a)-Tripel aus Abschnitt
3.2.1 beschreibt eine Berechtigung einen allgemeinen Zugriff unabhängig vom
Subjekt.
• Eine Rolle umfasst eine Menge von Berechtigungen. Beim hierarchischen RBACModell können Rollen auch ineinander verschachtelt sein, wodurch sich eine
Ordnung auf der Menge der Rollen ergibt. Eine Rolle enthält dann mindestens
alle Berechtigungen der ihr untergeordneten Rollen.
Der so definierte Rollenbegriff (als Menge von Rechten) unterscheidet sich deutlich
vom Begriff der Gruppe (als Menge von Subjekten).9
Bei RBAC ordnet man einem Subjekt eine oder mehrere Rollen zu, anstatt ihm direkte Zugriffsrechte auf Objekte zu erteilen. Unter der Voraussetzung, dass die Menge
der Rollen kleiner ist und sich seltener ändert als die Mengen der Subjekte und Objekte, ermöglicht RBAC damit eine vereinfachte und übersichtliche Administration
von Zugriffsrechten. Durch die Zuordnung einer Rolle zu einem Subjekt werden die
Berechtigungen der Rolle zu (positiven) Zugriffsrechten des Subjekts – eine Vergabe
negativer Rechte sieht das Modell nicht vor.
Gemäß dem Prinzip der minimalen Rechte – auch need-to-know- oder least-privilegePrinzip genannt – darf ein Subjekt nur über jene Zugriffsrechte verfügen, die es zur
Erfüllung seiner Aufgaben braucht. So minimiert man die Gefahr, dass jemand – absichtlich oder versehentlich – Unsinn anstellt. Bei der Definition von Rollen orientiert
man sich an diesem Prinzip, indem man nur Berechtigungen eines begrenzten Aufgabengebiets zusammenfasst. Einen Schritt weiter geht das Konzept der Sitzung (session). Eine Sitzung existiert nur begrenzte Zeit – normalerweise von der Anmeldung
eines Subjekts am System bis zu seiner Abmeldung – und enthält die während der Sitzungsdauer aktiven Rollen. Diese bilden eine Teilmenge aller Rollen, die dem Subjekt
zugeordnet wurden. Wenn man diese Teilmenge genau auf jene Aufgabe zuschneidet, die während der Sitzung zu erledigen ist, erfüllt man das Prinzip der minimalen
Rechte optimal.
9
Manche Autoren verwenden Gruppe und Rolle synonym, vgl. [SST97, S. 409].
21
3. Grundlagen einer Sicherheitsarchitektur
RBAC formuliert auch Randbedingungen (constraints) für eine statische und dynamische Aufgabentrennung (static/dynamic separation of duty). Diese Randbedingungen
sind Relationen auf der Rollenmenge, die besagen, welche Rollen sich gegenseitig
ausschließen. Statische Aufgabentrennung bedeutet, dass einander ausschließende
Rollen generell nicht demselben Subjekt zugeordnet werden dürfen. Bei dynamischer
Aufgabentrennung ist zwar die Zuordnung solcher Rollen erlaubt, das Subjekt darf
aber während einer Sitzung nur in der einen oder der anderen Rolle aktiv sein.
Als Beispiel stelle man sich eine studentische Hilfskraft vor, die an einem Lehrstuhl
Klausuren korrigiert. Sie darf natürlich keine Klausuren korrigieren, die sie selbst
mitgeschrieben hat, und deshalb nicht gleichzeitig in den Rollen Prüfungskandidat
und Korrektor auftreten.
3.3. Vertrauens(un)würdige Software
Authentifizierung und Autorisierung sind das Fundament einer Sicherheitsarchitektur. In Analogie zum Staatsapparat bilden sie die Legislative, die gesetzgebende Gewalt. Wir wissen damit, wer in einem System auf welche Weise agieren darf. Da wir
uns nicht darauf verlassen, dass alle Subjekte sich freiwillig an die Regeln halten,
fehlt noch ein entscheidender Schritt zur wirksamen Zugriffskontrolle: die Durchsetzung der festgelegten Rechte. Beim Staat ist dafür die Exekutive (ausführende Gewalt)
verantwortlich.
In der ISO-Norm 10181-3 (Security frameworks for open systems: Access control framework, [ISO]) findet sich eine einfache grafische Darstellung dieses Sachverhalts
(siehe Abbildung 3.2). Die Norm benennt zwei getrennte Funktionen:
• Die Access Control Decision Function (ADF) entscheidet, ob ein bestimmter Zugriff erlaubt ist, entspricht also unserer Funktion f von Seite 17.
• Die Access Control Enforcement Function (AEF) nimmt Zugriffswünsche entgegen
und konsultiert die ADF. Je nachdem, ob die Entscheidung der ADF positiv
oder negativ ausfällt, ist es die Aufgabe der AEF, Zugriffe zu gestatten oder zu
unterbinden.
Die Implementierung der AEF ist eine anspruchsvolle Aufgabe (die wir in dieser
Arbeit nur am Rande behandeln), und es leuchtet ein, dass man nicht sämtliche Zugriffe, die irgendwo im System stattfinden, durch eine AEF schleusen kann. Hier hilft
die Unterscheidung zwischen Teilsystemen, denen man vertraut, und solchen, denen
man misstraut. Bei einem vertrauenswürdigen System verlässt man sich darauf, dass
es vor sicherheitskritischen Zugriffen die ADF von sich aus um Erlaubnis fragt. Die
22
3.3. Vertrauens(un)würdige Software
Initiator
Submit
Access
Request
Present
Access
Request
AEF
Decision
Request
Target
Decision
ADF
Abbildung 3.2.: Illustration fundamentaler Zugriffskontrollfunktionen aus [ISO]. Der Initiator
ist das anfragende Subjekt, das Target ist das Objekt, auf das der Initiator
zugreifen will.
Zugriffe aus nicht vertrauenswürdigen Systemen sind streng zu überwachen. Man
konzentriert sie nach Möglichkeit auf eine oder wenige Schnittstellen.
[Dre02] stellt eine Sicherheitsarchitektur vor, die auf dem eben skizzierten Prinzip
basiert. Abbildung 3.3 vermittelt einen Überblick dieser Architektur. Die Kernaussagen sind:
• Der Vertrauensbereich (das trusted system, bestehend aus trusted software) ist
abgegrenzt vom Misstrauensbereich der non-trusted software.
• Ein zentraler Baustein wickelt alle Objektzugriffe ab. Im Bild ist das der Zugriffsmanager.
• Nur trusted software darf den Zugriffsmanager direkt aufrufen.
• Die trusted software sorgt selbst dafür, dass ihre Zugriffe mit den Rechtefestlegungen übereinstimmen. Sie konsultiert dazu die ADF (im Bild repräsentiert
durch den Baustein Rechteprüfung).
• Eine Prüfkomponente implementiert die AEF. Sie benutzt ihrerseits die ADF. Alle
Zugriffe durch non-trusted software laufen über die Prüfkomponente.
Das Architekturbild zeigt auch, welche Funktionen sich zur Auslagerung in eine
Autorisierungskomponente eignen, nämlich
• die Authentifizierung und
• die Autorisierung, welche unterteilt ist in
– die Administration der Zugriffsrechte und
– die Rechteprüfung (ADF).
23
3. Grundlagen einer Sicherheitsarchitektur
TRUSTED SYSTEM
Login am System
evtl. Ticket
TRUSTED
SOFTWARE
evtl.
Zugriffsausweis
einmalig
Ist der das? (Kennung, Schlüssel)
Prüfschnittstelle
Darf der das? (wer, wo, was, Ticket)
ZugriffsManager
Ja: Ticket, Nein: Ja, nein
NON-TRUSTED
SOFTWARE
Prüfkomponente
Ist der das?
(Kennung, Schlüssel)
Darf der das?
(wer, wo, was)
Authentifizierung
Rechteprüfung
Schnittstelle
Administration
Aufruf Autorisierungskomponente
Administrator
Autorisierungskomponente
Abbildung 3.3.: Sicherheitsarchitektur aus [Dre02]. Die Prüfkomponente implementiert die
AEF, die Rechteprüfung implementiert die ADF. Am Zugriffsmanager laufen
alle Zugriffe auf Objekte zusammen.
24
3.4. JAAS – Informationssicherheit in der Java-Welt
3.4. JAAS – Informationssicherheit in der Java-Welt
Der Java Authentication and Authorization Service (JAAS) ist seit der Version 1.4 in
der J2SE10 enthalten. JAAS erweitert die ursprünglich codezentrierte Sicherheitsarchitektur von Java um benutzerbezogene Zugriffsrechte. Was das genau bedeutet,
erläutern die folgenden Unterabschnitte.
[Oak01] vermittelt einen umfassenden Einblick in die Sicherheitsarchitekur der
Java-Plattform. Für Referenzdokumente und Programmieranleitungen zu JAAS ist die
Webseite [JAAa] ein guter Einstiegspunkt.
3.4.1. Sandkastenspiele
Java-Anwendungen laufen nicht direkt auf dem Prozessor, sondern in einem Interpreter – der Java Virtual Machine (JVM). Das ermöglicht in erster Linie die Entwicklung
plattformunabhängiger Software, hat aber auch eine sicherheitsrelevante Dimension: Da die JVM selbst ein Softwaresystem ist, kann man sie mit Zugriffskontrollmechanismen ausstatten, die leistungsfähiger sind als jene, die die darunterliegende
Hardware (Prozessor, Speicherverwaltung) von sich aus anbietet. Die Designer der
Java-Plattform haben genau das getan.
Die zentrale Metapher der Java-Sicherheitsarchitektur ist die Sandbox (Sandkasten). Das ist ein abgegrenzter Bereich, in dem sich non-trusted software austoben
kann, ohne Schaden anzurichten.11
Der Prüfkomponente aus Abbildung 3.3 entspricht bei der JVM der Security Manager12 . Er wacht über die Zugriffe der Software, die in der Sandbox läuft. Der Security Manager der ersten Java-Version war recht einfach gestrickt, das entsprechende Sicherheitsmodell war schwarz-weiß: Anwendungen durften entweder alles, oder
sie wurden in die Sandbox gesperrt, wo sie pauschal mit sehr restriktiven Zugriffsrechten auf Systemressourcen (Dateisystem, Netwerkverbindungen etc.) ausgestattet
wurden. In der Standardeinstellung kamen alle Applets13 in die Sandbox, während
lokaler Code keinen Einschränkungen unterlag.
10
Java 2 Platform, Standard Edition
Eine treffendere Metapher wäre Gummizelle.
12
In neueren Java-Versionen delegiert der Security Manager seine Aufgaben an eine weitere Komponente, den Access Controller. Wir unterlassen im Folgenden diese Unterscheidung.
13
Ein Applet ist ein Java-Programm, das man üblicherweise aus dem Internet lädt und direkt im WebBrowser ausführt.
11
25
3. Grundlagen einer Sicherheitsarchitektur
3.4.2. Codezentrierte Autorisierung
In jüngeren Java-Versionen wurde die Sandbox durchlässiger. Ab Java 1.2 kann man
differenzierte Zugriffsrechte vergeben – doch an wen und wofür?
Das Subjekt der Autorisierung ist hier der auszuführende Code, man vergibt also
Rechte an Klassendateien (Dateien mit der Endung .class, die Java-Bytecode enthalten). Für die Rechtevergabe sind dabei nur zwei Eigenschaften relevant:
• der Herkunftsort des Codes: Diesen benennt ein URL14 , zum Beispiel
http://www.sdm.de/sample/ oder file:/C:/sample.jar.
• der Unterzeichner des Codes: Das ist eine Person oder Institution, die durch
Anbringen ihrer digitalen Signatur (Unterschrift) bezeugt, dass der Code vertrauenswürdig ist. Die Aussagekraft steht und fällt natürlich mit der Vertrauenswürdigkeit des Unterzeichners.
Die Objekte der Autorisierung sind Permission-Objekte. Eine Permission ist charakterisiert durch ihren Typ (eine Unterklasse von java.security.Permission) und
evtl. einen Namen. Der Security Manager gibt mittels der Methode checkPermission
Auskunft, ob der laufende Code bestimmte Permissions hat; so benutzt man ihn als
ADF. Er wirkt auch als AEF und setzt Zugriffsrechte durch – das gilt aber nicht für
alle Permissions, es gibt nämlich zwei Arten:
• Einige Permission-Klassen sind fester Bestandteil der Java-API. Wir nennen sie
im Folgenden technische Permissions. Sie haben für den Security Manager eine definierte Semantik. Code, der in der Sandbox läuft, braucht diese Permissions, wenn er auf Systemressourcen zugreift. Der Security Manager wirkt hier
als AEF. Beispiel: Der Zugriff auf eine Datei erfordert eine Permission vom Typ
java.io.FilePermission, die den gleichen Namen trägt wie die Datei.
• Anwendungsentwickler können beliebige Permission-Typen definieren. Permissions dieser Art nennen wir fachliche Permissions. Der Security Manager wirkt
hier nur als ADF. Man kann ihn also fragen, ob ein bestimmtes Codestück die
KundenPermission mit dem Namen Eva Meier besitzt. Die Verknüpfung mit
dem zu schützenden Objekt (Frau Meiers Kundendaten) programmiert der Entwickler selbst.
Die Zugriffsarten der Autorisierung heißen bei Java Actions. Die Menge der möglichen Actions hängt vom Permission-Typ ab und kann auch leer sein. Zu der erwähnten
FilePermission gehören die Actions read, write, delete und execute.
14
Uniform Resource Locator
26
3.4. JAAS – Informationssicherheit in der Java-Welt
Actions sind als Attribute von Permissions realisiert. Ein Permission-Objekt mit genau
einer Action entspricht einer Berechtigung im Sinne von Abschnitt 3.2.4.
Die Administration der Zugriffsrechte erfolgt durch Anlegen bzw. Ändern eines Policy-Objekts – in der Standardimplementierung ist das eine Textdatei, in die man die
Zugriffsrechte in einer vorgegebenen Syntax einträgt.
3.4.3. Know your principals
Bei der codezentrierten Autorisierung hängen die Zugriffsrechte ab von der Herkunft
und dem Unterzeichner des auszuführenden Codes. Das hat den Zweck, das System
vor bösartigen Programmen aus nicht vertrauenswürdigen Quellen zu schützen. Wer
aber schützt das System vor seinen Benutzern? Wer schützt die Benutzer voreinander?
JAAS erweitert die beschriebenen Autorisierungsmöglichkeiten um den Benutzerkontext: Die Zugriffsrechte hängen nicht nur davon ab, welcher Code ausgeführt
wird, sondern auch davon, wer ihn ausführt. Benutzer heißen bei JAAS Principals.
Ein Principal ist charakterisiert durch seinen Typ (eine Implementierung des Interface
java.security.Principal) und einen Namen. Damit ist das Subjekt im Sinne der
Frage „Darf der das?“ die Kombination aus Herkunftsort, Unterzeichner und Principal
– also ein recht komplexes Gebilde. Wenn man nur mit vertrauenswürdigem Code
arbeitet, spricht aber nichts dagegen, codebezogene Eigenschaften zu ignorieren und
Zugriffsrechte allein an Principals zu vergeben. Das Ergebnis wäre eine benutzerzentrierte Autorisierung.
Objekte und Zugriffsarten sind die gleichen wie ohne JAAS. An der Autorisierung
ändert JAAS also nur wenig. Eine Frage ist allerdings noch offen: Wie kommen die
Principals in das System?
JAAS stellt für diesen Zweck Authentifizierungsschnittstellen bereit. Wie in Abschnitt 3.1 dargelegt, sind die Möglichkeiten, einen Benutzer zu authentifizieren,
nicht auf die Anmeldung mit Name und Passwort beschränkt. JAAS greift daher auf
Pluggable Authentication Modules (PAM) zurück. Das PAM-Konzept ist von der Open
Software Foundation standardisiert (siehe [PAM95]) und in vielen UNIX-artigen Betriebssystemen implementiert. Die Idee besteht darin, dass die Anwendung die Authentifizierung an separate Komponenten delegiert, so dass es ihr egal sein kann,
ob Benutzer sich per Passwort, Kerberos oder Fingerabdruckscanner anmelden. Die
Authentifizierungskomponenten sind per Konfiguration austauschbar, ohne dass ein
Neukompilieren der Anwendung nötig wäre.
Bei JAAS heißen diese Komponenten Login Modules. Jedes Login Module ist selbst
dafür verantwortlich, sich die für die Authentifizierung notwendigen Informationen
zu besorgen. Dazu kann es z. B. einen Bildschirmdialog zum Abfragen von Name und
27
3. Grundlagen einer Sicherheitsarchitektur
Passwort starten. Ein anderes Beispiel: Das Login Module delegiert die eigentliche
Authentifizierung an das Betriebssystem, indem es auf die Kennung des angemeldeten
Benutzers zurückgreift.15
Jedes Login Module liefert pro Authentifizierungsvorgang einen oder mehrere Principals. Die Semantik der Principals bestimmt das Login Module. Beispiel: Ein Principal
steht für den Benutzernamen, weitere Principals stehen für die Gruppen, denen der
Benutzer angehört.
Der Security Manager verlässt sich darauf, dass Login Modules nur korrekt authentifizierte Principals liefern. Login Modules sind also trusted software.
15
Die Firma Sun bietet lauffähige Login Modules dieser Art für die Betriebssysteme Solaris und Windows
NT kostenlos zum Download an (siehe [JAAb]).
28
»I’m what you guys call a User.«
Tron (Walt Disney Pictures, 1982)
4. QuasarAuthorization
Ein Ziel dieser Diplomarbeit ist der Entwurf einer Autorisierungskomponente, die
vielseitig einsetzbar und dabei einfach zu bedienen ist. Als Ausgangspunkt dient die
QuasarAuthorization, eine Eigenentwicklung von sd&m. Sie ist in Java programmiert.
Wir beschreiben im Folgenden den Ist-Zustand der Komponente und zählen verbesserungswürdige Merkmale auf.
4.1. Beschreibung der Komponente
Die QuasarAuthorization ist eine generische Autorisierungskomponente; generisch
deshalb, weil sie keine Annahmen über die Autorisierungsobjekte macht und deshalb
mit verschiedensten Anwendungen zusammenarbeiten kann.
Die Subjekte der Autorisierung nennen wir von nun an generell Benutzer, egal ob es
sich um Personen handelt oder um non-trusted software. (Logische) Objekte der Autorisierung nennen wir Ressourcen, um sie von (technischen) Java-Objekten zu unterscheiden, und Zugriffsarten bezeichnen wir als Operationen. Die QuasarAuthorization
referenziert ihre Entitäten (Benutzer, Ressourcen etc.) anhand eindeutiger Namen.
4.1.1. Funktionsumfang
Die Komponente bietet folgende Dienste an:
• Benutzeradministration: Pflege der Benutzerdaten (Login-Name, Vor- und Nachname etc.) und Einordnung der Benutzer in eine Gruppenhierarchie
• Administration von Zugriffsrechten: Definieren von Berechtigungen und Rollen
und ihre Zuordnung zu Benutzern und Gruppen
• Authentifizierung der Benutzer anhand von Name und Passwort
• Rechteprüfung: Realisierung der ADF (siehe Abschnitt 3.3)
Die QuasarAuthorization unterstützt positive und negative Rechtevergabe. Die Berechtigungen kann man mit Randbedingungen versehen, die im Zuge der Rechteprüfung ausgewertet werden.
29
4. QuasarAuthorization
4.1.2. Datenmodell und Außensicht
Wir stellen das Datenmodell der QuasarAuthorization vor, sowie die Schnittstellen,
die sie exportiert und importiert.
Die Abbildungen 4.1 und 4.2 zeigen das Datenmodell in Form von UML-Klassendiagrammen (Attribute und Methoden sind nicht aufgeführt). Das erste Diagramm
zeigt den administrierbaren Teil des Modells; er besteht aus den Entitätstypen und
Beziehungen, deren Ausprägungen man zur Laufzeit anlegen, ändern und löschen
kann. Das zweite Diagramm ergänzt das erste; es stellt den Bezug zu den wichtigsten
Initialisierungs- und Konfigurationsschnittstellen her.
In den Diagrammen sind die einzelnen Elemente so benannt wie im Programmcode und der Dokumentation der Komponente (siehe [JH03a, JH03b]). Beim Gebrauch
deutscher Fachbegriffe weichen wir zum Teil von der Dokumentation ab1 , um für die
drei Komponenten(entwürfe) dieser Arbeit eine einheitliche Terminologie zu schaffen. Im Anhang findet sich mit Tabelle A.1 eine Gegenüberstellung der Begriffe, die in
verschiedenen Kontexten mit gleicher oder ähnlicher Bedeutung verwendet werden.
Die Entitätstypen und Schnittstellen im Einzelnen:
• Users repräsentieren Benutzer des Systems. Die wichtigsten Attribute eines Benutzers sind der eindeutige (Login-)Name und das Passwort; daneben gibt es
typische Benutzerattribute wie Vor- und Nachname und Locale-Informationen
(Sprache, Nationalität). Zusätzlich kann man anwendungsspezifische Eigenschaften definieren.
• UserGroups repräsentieren benannte Gruppen von Benutzern. Durch Schachtelung erhält man eine Gruppenhierarchie; so lässt sich z. B. die Organisationsstruktur eines Unternehmens abbilden. Jeder Benutzer kann beliebig vielen
Gruppen angehören, jede Gruppe kann höchstens einer anderen Gruppe untergeordnet sein.
• Sowohl Benutzern als auch Gruppen kann man Zugriffsrechte zuordnen; der
abstrakte Typ Accessor repräsentiert diese gemeinsame Eigenschaft.
• Permissions entsprechen Berechtigungen im Sinne von Abschnitt 3.2.4, erweitert um Randbedingungen. Jede Permission hat einen eindeutigen Namen. Sie
verknüpft eine Ressource mit einer Operation und beliebig vielen Randbedingungen.
• PermissionGroups sind benannte Mengen von Berechtigungen, sie repräsentieren also Rollen. PermissionGroups sind nicht schachtelbar.
1
Beispiel: Die Dokumentation der QuasarAuthorization bezeichnet Ressourcen als Schutzobjekte.
30
4.1. Beschreibung der Komponente
granted
«i nterface»
*
Accessor
revoked
*
«interface»
*
PermissionGroup
*
*
contai ns
*
«i nterface»
«interface»
«interface»
UserGroup
User
Permission
*
*
0..1
*
*
*
depends on
0..1
*
*
contai ns
contai ns
1
Operation
1
*
«interface»
«i nterface»
AccessibleObject
AccessRestriction
1
*
RestrictionParameter
Abbildung 4.1.: Datenmodell der QuasarAuthorization (administrierbarer Teil)
«i nterface»
«i nterface»
AccessibleObject
AccessRestriction
Operation
*
1..*
*
1
*
RestrictionParameter
appli es to
*
1
1
*
«i nterface»
«i nterface»
AccessibleObjectType
AccessRestrictionType
1
1
*
defaul t param eter(s)
*
1
«i nterface»
«i nterface»
AccessController
AccessRestrictionController
Abbildung 4.2.: Datenmodell, erweitert um die anwendungsseitig zu implementierenden
Schnittstellen
31
4. QuasarAuthorization
• AccessibleObjects repräsentieren die durch die QuasarAuthorization zu überwachenden Ressourcen. Sie bestehen nur aus einem symbolischen Namen.
• Operations stehen für die Operationen (Zugriffsarten) der Autorisierung. Operationsnamen sind anwendungsspezifisch definierbar; typische Grundoperationen wie READ, WRITE und EXECUTE sind vordefiniert.
• AccessRestrictions sind Randbedingungen, die man Berechtigungen zuordnet, um deren Gültigkeit einzuschränken. Eine gewährte Berechtigung ist nur
dann tatsächlich wirksam, wenn die Rechteprüfung alle zugeordneten Randbedingungen als erfüllt erachtet.
• Wenn Randbedingungen Parameter haben, speichert man diese in Instanzen der
Klasse RestrictionParameter; sie enthält Parametername, -typ und -wert als
Attribute. Besteht z. B. eine Randbedingung darin, dass das Recht, eine Überweisung zu tätigen, nur bis zu einem bestimmten Geldbetrag gilt, dann ist dieser
Höchstbetrag der Parameter.
Die im Diagramm mit depends on bezeichnete Beziehung des Permission-Typs zu sich
selbst ist ein Spezialfall einer Randbedingung: Man kann damit die Wirksamkeit einer
gewährten Berechtigung davon abhängig machen, ob dem Benutzer eine bestimmte
andere Berechtigung ebenfalls gewährt wurde.
So weit die administrierbaren Elemente; Abbildung 4.2 zeigt daneben vier angeforderte Schnittstellen2 : Die Autorisierungskomponente definiert und importiert diese Schnittstellen, und sie fordert von demjenigen, der die Komponente benutzen
will, dass er die Implementierungen liefert. Angeforderte Schnittstellen implementiert man im Allgemeinen durch Adapter; ein Adapter bildet vorhandene Software
auf die (maßgeschneiderte) Schnittstelle ab.3
Die folgenden vier angeforderten Schnittstellen entkoppeln die QuasarAuthorization von der Anwendung:
• Jede Ressource ist einem AccessibleObjectType zugeordnet. Der Name ist etwas irreführend; die Schnittstelle birgt weit mehr Funktionalität als ein Entitätstyp oder Datentyp. Der AccessibleObjectType kapselt die Semantik seiner
Ressourcen; er erfüllt folgende Aufgaben:
– Er bildet technische Objekte auf Ressourcen ab. Diese Funktion kommt
bei der Rechteprüfung zum Einsatz, denn geprüft werden immer technische Objekte, während die Autorisierungskomponente nur Ressourcen
2
3
Synonyme: Stützschnittstellen, Anforderungsschnittstellen
Quasar empfiehlt die Verwendung von angeforderten Schnittstellen und Adaptern beim SoftwareEntwurf, um Importeure und Exporteure optimal zu entkoppeln.
32
4.1. Beschreibung der Komponente
(logische Objekte) verwaltet. Im Allgemeinen bilden verschiedene AccessibleObjectTypes ein und dasselbe technische Objekt auf verschiedene
Ressourcen ab.
– Er definiert, welche Operationen auf seine Ressourcen grundsätzlich angewandt werden können.
– Er definiert, welche Operationen sich untereinander implizieren (vgl. Abschnitt 3.2.2 über implizite Rechte) und realisiert damit einen Teil der Auswertungslogik.
– Er verknüpft seine Ressourcen mit einem AccessController.
• Die Schnittstelle AccessController kapselt den größten Teil der Auswertungslogik; die Implementierung (die von der Anwendung beizusteuern ist) bestimmt
maßgeblich das Ergebnis der Rechteprüfung. Im Lieferumfang der QuasarAuthorization ist eine Standardimplementierung namens SimpleAccessController enthalten, die als Ausgangspunkt für anwendungsspezifische Implementierungen dienen kann.
• Jede Randbedingung ist einem AccessRestrictionType zugeordnet. Er definiert Anzahl und Typen der Parameter seiner Randbedingungen, und er führt
auf gegebenen Parametermengen Konformitätsprüfungen durch. Außerdem
verknüpft er seine Randbedingungen mit einem AccessRestrictionController.
• Die Schnittstelle AccessRestrictionController übernimmt jenen Teil der
Rechteprüfung, der feststellt, ob eine gegebene Randbedingung erfüllt ist. Auch
hierfür sind einige Standardimplementierungen im Lieferumfang der Komponente enthalten; eine davon – der UpperLimitRestrictionController – ist
auf das obige Beispiel anwendbar (Überweisung mit beschränktem Geldbetrag).
Das Ergebnis, das ein AccessController ermittelt, kann von einem oder mehreren
Objekten des Typs AccessRestrictionController abhängen (das ist in Abbildung
4.2 durch einen Abhängigkeitspfeil angedeutet).
Die QuasarAuthorization importiert noch weitere Schnittstellen, und sie exportiert
natürlich auch welche. Das Komponentendiagramm in Abbildung 4.3 vermittelt einen
Überblick der Außensicht.
Über die beiden exportierten Schnittstellen links im Bild bietet die Komponente
ihre Kerndienste an:
• Die Schnittstelle AuthenticationManager ist der Zugang zum Authentifizierungsdienst. Die Methode authenticate erwartet den Login-Namen und das
33
4. QuasarAuthorization
Accessi bl eObj ectT ype
AccessControll er
AccessRestrictionT ype
AccessRestri cti onControll er
Authenticati onM anager
Authorizati onM anager
QuasarAuthorization
Authenti cati onAdm i ni strati onM anager
Authori zati onAdm i nistrati onM anager
Authenticati onStorage
Authorizati onStorage
UpdateEnvi ronm ent
UserDataSource
UserAuthenti cati on
Abbildung 4.3.: Außensicht der QuasarAuthorization (UML-2.0-Notation)
Passwort des Benutzers als Argumente; im Erfolgsfall liefert sie ein UserTicket
– eine Art Ausweis, der bei Rechteprüfungen vorzulegen ist. Auch Passwortänderungen nimmt man über diese Schnittstelle vor.
• Der AuthorizationManager ist der Zugang zur Rechteprüfung. Seine zentrale
Methode ist:
boolean isAccessPermitted ( S t r i n g accessibleObjectTypeName ,
Operation operation , Object object ,
UserTicket t i c k e t , Object parameter )
Die Aufrufparameter beschreiben detailliert den Zugriffswunsch: Man gibt an,
gemäß welchem AccessibleObjectType die Auswertung erfolgen soll und welche Operation auf welches (technische) Objekt durch welchen Benutzer (repräsentiert durch ticket) auszuführen ist. Das parameter-Argument ist optional,
es wird ggf. für die Bewertung von Randbedingungen herangezogen.
Weitere Methoden dienen zur Registrierung von Implementierungen der angeforderten Schnittstellen AccessibleObjectType, AccessRestrictionType,
AccessController und AccessRestrictionController. Die Registrierung erfolgt im Zuge der Initialisierung der QuasarAuthorization.
Die Komponente exportiert zwei weitere Schnittstellen (rechts im Bild):
• Über den AuthenticationAdministrationManager administriert man Benutzerdaten und einen Teil der Zugriffsrechte. Es gibt Methoden zum Anlegen,
Ändern und Löschen von User- und UserGroup-Objekten. Außerdem definiert
34
4.1. Beschreibung der Komponente
man hier die Mitgliedschaft von Benutzern in Gruppen bzw. von Gruppen in
anderen Gruppen (Gruppenhierarchie). Die Zugriffsrechte legt man fest, indem man vordefinierte Rollen mit Benutzern und Gruppen verknüpft, wobei die
granted-Beziehung (siehe Abbildung 4.1) in positiven Rechten resultiert und die
revoked-Beziehung in negativen.
• Über den AuthorizationAdministrationManager definiert man Rollen und
Berechtigungen sowie Randbedingungen und deren Parameter.
Im oberen und unteren Teil der Abbildung 4.3 sind die angeforderten Schnittstellen
der Komponente dargestellt. Die oberen Schnittstellen wurden bereits im Zusammenhang mit dem Datenmodell erläutert, jetzt widmen wir uns den verbleibenden:
• AuthenticationStorage, AuthorizationStorage und UpdateEnvironment
betreffen die Datenhaltung der QuasarAuthorization. Man implementiert diese Schnittstellen durch einen Persistenz-Adapter, der die Anbindung an ein Datenbanksystem (oder einen sonstigen Datenspeicher) realisiert. Über AuthenticationStorage speichert und lädt die Autorisierungskomponente ihre Userund UserGroup-Objekte, über AuthorizationStorage alle anderen Entitäten
des Datenmodells. Die QuasarAuthorization hält ihre Daten für den laufenden
Betrieb in einem Hauptspeicher-Cache. UpdateEnvironment kommt bei der Aktualisierung dieses Caches zum Einsatz.
• UserDataSource und UserAuthentication ermöglichen die Anbindung externer Systeme. UserDataSource dient dem Import von Benutzern und Gruppen
aus einer externen Datenquelle (z. B. einem LDAP4 -Verzeichnis). Falls die QuasarAuthorization Authentifizierungen nicht selbst durchführen soll, stellt UserAuthentication die Verbindung zu einem externen Authentifizierungsdienst
her. Die Methoden entsprechen denen des AuthenticationManagers; wenn
sich ein Benutzer dort anmeldet, werden Login-Name und Passwort einfach an
UserAuthentication weitergereicht.
4.1.3. Berechtigungs-Cache
Die vorliegende Arbeit konzentriert sich auf die Außensicht von Autorisierungskomponenten. Die Architektur der QuasarAuthorization trennt aber nicht strikt zwischen
Außen- und Innensicht und macht es notwendig, sich auch mit einem Implementierungsaspekt zu befassen: dem Berechtigungs-Cache5 .
4
5
Lightweight Directory Access Protocol (ein Protokoll für den Zugriff auf Verzeichnisdienste)
com.sdm.quasar.authorization.implementation.PermissionEvaluationCache
35
4. QuasarAuthorization
Dieser Cache ist zunächst einmal ein Zwischenspeicher für Benutzer- und Berechtigungsdaten. Er reduziert die Zugriffe der Komponente auf die Persistenz. Darüber
hinaus kommt beim Befüllen des Berechtigungs-Caches bereits Auswertungslogik
zum Einsatz: Beziehungen zwischen Benutzern und Berechtigungen, die eigentlich
nur indirekt auf dem Weg über Gruppen und/oder Rollen existieren, werden aufgelöst und direkt im Cache abgelegt. Implementierungen der Schnittstelle AccessController arbeiten mit dem vorverarbeiteten Cache-Inhalt.
Dieses Vorgehen hat Vor- und Nachteile. Es macht Rechteprüfungen effizienter, weil
die Gruppenhierarchie zum Zeitpunkt der Prüfung nicht mehr traversiert wird. Allerdings enthält der Cache weniger Informationen als das persistente Datenmodell,
dessen Mächtigkeit daher nicht vollständig ausgenutzt werden kann. Außerdem werden Änderungen an den Benutzer-/Berechtigungsdaten erst wirksam, nachdem der
Berechtigungs-Cache neu befüllt wurde. Bei einer Datenmenge realistischer Größe
liegt der Zeitaufwand hierfür in der Größenordnung von mehreren Minuten.
4.2. Verbesserungspotential
Die QuasarAuthorization hat ihren Ursprung im Projektgeschäft von sd&m. Auch Weiterentwicklungen wurden bisher überwiegend von Projekten veranlasst, die Lösungen
für ihre individuellen Autorisierungsanforderungen verlangten. Herausgekommen ist
eine Komponente, die (anders als ihr Name vermuten lässt) nicht der reinen QuasarLehre entspricht.
Wir nehmen an dieser Stelle den Faden aus dem Abschnitt Motivation und Ziel des
Einführungskapitels wieder auf: Die Komponente weist architektonische Schwächen
auf, sie ist unpräzise spezifiziert, und es fehlt ein klarer Bezug zu verwandten Produkten. Wo liegen Ansatzpunkte für Verbesserungen?
4.2.1. Architektur und Implementierung
Das Hello-World-Programm6 , das als Beispiel für die Initialisierung und den Betrieb
der QuasarAuthorization dient, wirkt mit seinen rund 500 Codezeilen7 eher abschreckend. Ein Grund für diesen Umfang ist, dass die Komponente durch Aufrufe im Programmtext konfiguriert wird, statt durch externe Konfigurationsdateien. Im Rahmen
der Initialisierung wird auf technischer Seite die Verbindung zur Persistenz hergestellt und der Berechtigungs-Cache erzeugt. Auf fachlicher Seite werden AccessibleObjectTypes, AccessRestrictionTypes und die zugehörigen Controller-Objekte
6
7
com.sdm.quasar.authorization.sample.AuthorizationSample (Version vom 19.05.2004)
Kommentare und Leerzeilen eingeschlossen
36
4.2. Verbesserungspotential
registriert.
Der vermeintlich simple Anstoß einer Rechteprüfung erfordert im Beispielprogramm mehrere Methodenaufrufe: Anstatt die Methode isAccessPermitted des AuthorizationManagers zu benutzen, bedient man sich hier direkt eines AccessController-Objekts, an das man über den Umweg des AccessibleObjectType gelangt.8
Doch auch der sauberere Weg über den AuthorizationManager ist aus Sicht des
Anwendungsprogrammierers komplizierter als nötig. Ideal wäre eine Prüfung, die nur
den Benutzer, die Ressource und die Operation als Argumente benötigt. Doch bei der
QuasarAuthorization ist bei jeder Rechteprüfung zusätzlich ein AccessibleObjectType anzugeben.
Gemäß dem Prinzip der Trennung von Zuständigkeiten sollte man sich bei der Aufgabenverteilung zwischen den Schnittstellen einer Komponente an den potentiellen
Aufrufern orientieren. Die Schnittstelle stellt im Idealfall dem Importeur genau die
Funktionalität zur Verfügung, die er zur Erfüllung seiner Aufgaben braucht. Bei der
Schnittstelle AuthorizationManager sind Zuständigkeiten vermengt: Sie enthält die
Methode zur Rechteprüfung, die von sehr vielen Programmierern sehr oft benutzt
wird; sie enthält aber auch Registrierungsmethoden, die nur für die Initialisierung
der Komponente gebraucht werden.
Das Datenmodell (Abbildungen 4.1 und 4.2) ermöglicht recht komplexe Beziehungsgeflechte, was unvermeidbar ist, wenn man viele verschiedene Anwendungsszenarien unterstützen will. Trotzdem bleiben unschöne Einschränkungen: Eine
Gruppe darf nicht mehreren anderen Gruppen angehören. Rollen sind nicht schachtelbar. AccessRestrictions sind zwar im Grunde ein universeller Erweiterungsmechanismus – doch man kann sie nur auf der Ebene der Berechtigungen definieren; was
sich damit z. B. nicht realisieren lässt, ist der wechselseitige Ausschluss von Rollenzuordnungen (separation of duty aus dem RBAC-Standard). Die QuasarAuthorization
verfügt auch nicht über ein Sitzungskonzept – Benutzer haben keine Möglichkeit, nur
Teilmengen ihrer Rechte zu aktivieren (Prinzip der minimalen Rechte).
Der Authentifizierungsdienst der QuasarAuthorization ist auf die Abfrage von
Login-Name und Passwort des Benutzers festgelegt (ebenso die externe Authentifizierung über UserAuthentication). Diese Entwurfsentscheidung schränkt die Anwendungsmöglichkeiten ein: Die Einbindung von biometrischen oder kryptographischen Mechanismen ist nicht ohne weiteres möglich, dasselbe gilt für Single-Sign-On.
Der anzuwendende Authentifizierungsmechanismus ist im Grunde ein Implementierungsaspekt, die Schnittstelle sollte darüber keine Annahmen machen. Hier können
wir von JAAS und seinem Authentifizierungsdienst lernen. Zur Erinnerung: JAAS ist
8
Die Dokumentation zum AuthorizationManager empfiehlt dieses Vorgehen bei hohen Performanzanforderungen.
37
4. QuasarAuthorization
von konkreten Authentifizierungsmechanismen unabhängig, weil diese in Login Modules ausgelagert sind. Die QuasarAuthorization wendet das gleiche Prinzip bereits bei
der Rechteprüfung an, indem es diese Aufgabe an den AccessController delegiert.
Das UserTicket, das einen erfolgreich authentifizierten Benutzer im System repräsentiert, taugt nur für den Einsatz innerhalb des trusted system, denn es verfügt über
keinerlei Schutz gegen Manipulation. Außerdem ist die Gültigkeitsdauer nicht beschränkt: Ist der Benutzer erst einmal angemeldet, kann er beliebig lange im System
agieren.
Bei der Vorstellung des Berechtigungs-Caches haben wir bereits die von ihm verursachten Einschränkungen erwähnt. Bezüglich des großen Rechenaufwands für Befüllung bzw. Aktualisierung des Caches sollte man überdenken, ob es dabei wirklich notwendig ist, jedesmal die Berechtigungen aller Benutzer zu berechnen. Im Allgemeinen
ist zu einem gegebenen Zeitpunkt nur eine überschaubare Teilmenge der Benutzer am
System angemeldet. Wir schlagen daher vor, die individuellen Berechtigungen eines
Benutzers erst zum Login-Zeitpunkt zu berechnen und im Cache abzulegen. Alternativ könnte man diese Berechtigungen auch direkt im UserTicket-Objekt speichern;
es wäre dann ein Zugriffsausweis (capability) im Sinne von Abschnitt 3.2.1.
4.2.2. Spezifikation
Die Semantik der Schnittstellen ist im Quelltext in Form von Javadoc-Kommentaren
beschrieben, und zwar informell in englischer Sprache. Es ist nicht möglich, nur anhand dieser Kommentare beispielsweise einen anwendungsspezifischen AccessController zu programmieren. Der Entwickler ist hier auf den vorhandenen SimpleAccessController angewiesen, den er quasi als Bauanleitung benutzt. Das ist aber
nicht Design by Contract (eher Design by Example).
Die Methode isAccessPermitted liefert nur true oder false, der Benutzer hat das
Recht zum Zugriff, oder er hat es nicht. Die Frage nach dem warum beantwortet
die Komponente nicht. Um zu erfahren, in welcher Weise Änderungen der Benutzerund Berechtigungsdaten das Ergebnis der Rechteprüfung beeinflussen, sind Kenntnisse über die Implikations- und Konfliktlösungsregeln nötig – doch diese Regeln sind
nirgendwo formal spezifiziert. Sie liegen nur als Programmcode vor, und dieser ist
auch noch auf mehrere Stellen verteilt: auf die Klasse PermissionEvaluationCache
(Berechtigungs-Cache) und auf alle Klassen, die AccessibleObjectType, AccessController und AccessRestrictionController implementieren.
38
4.3. Fazit
4.3. Fazit
Die aktuelle Version der QuasarAuthorization kam bisher in vier sd&m-Projekten zum
Einsatz.9 Dabei handelt es sich durchweg um mittlere bis große Projekte mit Aufwänden zwischen 14 und 50 Bearbeiterjahren.
Es gibt keine Aufzeichnungen darüber, wie viele Projekte den Einsatz der QuasarAuthorization zwar in Betracht gezogen haben, sich dann aber doch für eine Eigenentwicklung entschieden. Die dargelegten Fakten (und der hohe firmeninterne
Bekanntheitsgrad der Quasar-Komponenten) lassen aber vermuten, dass dieser Fall
schon mehrere Male eingetreten ist. Vor allem die Architekten und Entwickler in kleinen Projekten dürfte der hohe Konfigurationsaufwand (Controller- und Type-Objekte)
abschrecken.
Im Projektgeschäft ist reines Design by Contract anhand präziser Schnittstellenspezifikationen (noch) nicht allgemein üblich. Das Anfertigen der Spezifikation ist ein
Kostenfaktor, und bei Komponenten, die von einer statischen Menge von Entwicklern gebaut und gewartet werden, lohnt sich ein hoher Aufwand hierfür in der Tat
nicht. Für Standardkomponenten jedoch – mit ihren hohen Anforderungen bezüglich Verlässlichkeit, Wiederverwendbarkeit und Wartbarkeit – zahlt sich eine präzise
Spezifikation in jedem Fall aus.
In den folgenden Kapiteln entwerfen wir eine präzise spezifizierte Autorisierungskomponente, die einfach zu konfigurieren und zu bedienen ist, ohne dabei gegenüber
der existierenden Komponente zu viel an Funktionalität einzubüßen. Wo es sinnvoll
erscheint, heben wir bestehende Beschränkungen der Flexibilität auf (z. B. beim Authentifizierungsdienst). Wir betreiben dabei kein reengineering mit nachträglichem
Spezifizieren der QuasarAuthorization; die Ergebnisse der vorliegenden Arbeit sind
vielmehr als Studie zu verstehen, wie eine generische Autorisierungskomponente für
betriebliche Anwendungen prinzipiell aussehen kann.
9
ein Projekt für das Bayerische Geologische Landesamt und eines für den Reiseveranstalter Thomas
Cook AG; außerdem zwei Projekte, die wegen Vertraulichkeitsvereinbarungen zwischen sd&m und
den Kunden nicht näher genannt werden
39
»You believe in the Users?«
Tron (Walt Disney Pictures, 1982)
5. BasicAuthorization
Wir entwerfen unsere Autorisierungskomponente in zwei Stufen. Die erste nennen
wir BasicAuthorization. An ihr erproben wir unter anderem die Tragfähigkeit der noch
jungen Sprache QSL.
5.1. Funktionsumfang
Die BasicAuthorization bietet grundsätzlich die gleichen Dienste an wie die QuasarAuthorization, also
• Benutzeradministration,
• Administration von Zugriffsrechten,
• Authentifizierung und
• Rechteprüfung.
Die Einschränkungen liegen im Detail: Diese Komponente1 unterstützt nur positive
Rechtevergabe und kennt keine Randbedingungen. Außerdem definieren die Schnittstellen eine starre Auswertungslogik.
5.2. Datenmodell
Abbildung 5.1 illustriert das Datenmodell der BasicAuthorization. Für fast alle Entitätstypen gibt es Pendants bei der existierenden Komponente; teils verwenden wir
andere Namen: Die Gruppe nennen wir Group (statt UserGroup), die Berechtigung
Right (statt Permission), für die Ressource steht Resource (statt AccessibleObject) und für die Rolle Role (statt PermissionGroup). Der AbstractUser übernimmt
den Part des Accessor, der neue Typ AbstractRight fasst Berechtigungen und Rollen
zusammen.
Wir identifizieren alle Entitäten anhand symbolischer Namen. Hierzu definieren wir
als formale Basis den Typ AuthorizationEntity, von dem alle anderen Typen erben
1
Der Einfachheit halber schreiben wir Komponente statt Komponentenentwurf.
41
5. BasicAuthorization
«interface»
*
AbstractUser
«i nterface»
has
*
AbstractRight
*
*
contains
contai ns
*
*
«i nterface»
«i nterface»
«i nterface»
«interface»
Group
User
Right
Role
*
*
1
1
«interface»
«i nterface»
Operation
Resource
*
appl i es to
*
Abbildung 5.1.: Datenmodell der BasicAuthorization
(im Diagramm nicht dargestellt). Er definiert eine Methode namens getName, die den
Namen der Entität liefert und eine equals-Methode, die diesen Namen zum Unterscheidungskriterium macht. Für die QSL-Spezifikation der Entitätstypen verweisen
wir auf Anhang B.1.
Mehrere Beschränkungen des alten Modells hebt der Entwurf auf: Man kann jetzt
eine Hierarchie von Rollen definieren, und auch Gruppen sind beliebig schachtelbar. Möglich wird das durch Anwendung des Composite-Pattern (nach [GHJV95]) an
zwei Stellen: Jede Gruppe enthält beliebige viele AbstractUser-Objekte (das können
sowohl Benutzer als auch Gruppen sein), und jede Rolle enthält beliebig viele Exemplare des Typs AbstractRight (Berechtigungen und Rollen). Die Rechtefestlegung
geschieht auf der Ebene von AbstractUser und AbstractRight, woraus insbesondere folgt, dass Berechtigungen nicht nur als Bestandteil von Rollen, sondern auch
direkt einem AbstractUser zugeordnet werden können. Das steht zwar nicht im Einklang mit dem RBAC-Prinzip, doch die BasicAuthorization eignet sich damit auch zur
Umsetzung einfacher, nicht-rollenbasierter Berechtigungskonzepte.
5.3. Schnittstellen
Die Außensicht der BasicAuthorization besteht aus lediglich fünf Programmschnittstellen, Abbildung 5.2 partitioniert sie in die drei logischen Schnittstellen Operativer
Betrieb, Instrumentierung und Administration. Technische Aspekte wie die Datenhaltung bleiben unberücksichtigt. Bei der Aufteilung der Funktionalität auf die einzelnen
42
5.3. Schnittstellen
Instrum enti erung
ResourceDefiniti on
Operativer Betri eb
Authenti cation
Adm i ni strati on
BasicAuthorization
Authori zati onCheck
UserAdm i n
Authori zati onAdm i n
Abbildung 5.2.: Außensicht der BasicAuthorization
M yApplication
M yResourceDefinition
Operati ver Betrieb
Instrum enti erung
Administration
GUI
Adm inistration
BasicAuthorization
Abbildung 5.3.: Die BasicAuthorization in einer Beispielkomposition. Die Komponente My-
ResourceDefinition implementiert die Instrumentierungsschnittstelle und ist
Bestandteil der Anwendung (MyApplication). Für die Administration kommt
hier eine generische Benutzeroberfläche (Administration GUI) zum Einsatz.
43
5. BasicAuthorization
Schnittstellen lehnen wir uns an die QuasarAuthorization an, legen jedoch größeren
Wert auf die klare Trennung von Zuständigkeiten. Abbildung 5.3 illustriert, wie man
die BasicAuthorization mit der Anwendung verbindet.
Die folgenden Unterabschnitte enthalten Auszüge der Schnittstellenspezifikationen. Die komplette QSL-Spezifikation der Außensicht findet sich in Anhang B.2.
5.3.1. Operativer Betrieb
Die Schnittstellen für den operativen Betrieb repräsentieren die beiden Kerndienste
der Komponente: Authentifizierung und Rechteprüfung.
Die Authentication-Schnittstelle hat nur die Methode authenticate:
Quelltext 5.1: Authentication.authenticate
User authenticate ( const String username , const String password)
// a u t h e n t i c a t e s the user ' username ' by means o f ' password ' and r e t u r n s
// an a p p r o p r i a t e User−o b j e c t on s u c c e s s .
post
r e s u l t . getName ( ) . equals (username)
error a u t h e n t i c a t i o n F a i l e d
// There i s no user r e g i s t e r e d by t h i s name , or the password i s
// i n c o r r e c t .
Benutzer melden sich also wie bei der QuasarAuthorization mittels Name und Passwort am System an. Als Resultat übernimmt hier eine Referenz auf das User-Objekt
die Aufgabe des UserTicket. Das Scheitern der Authentifizierung wird durch einen
Fehler signalisiert. Diese Schnittstelle sieht keine Funktion zur Passwortänderung vor;
das fällt unter die Zuständigkeit der Administration.
Von allen Schnittstellen hat AuthorizationCheck die meisten Importeure und
wird bei weitem am häufigsten aufgerufen, weshalb eine möglichst einfache Bedienbarkeit anzustreben ist. Für den Großteil der Programmierer in einem Projekt
ist diese Schnittstelle das einzige, was sie von der Autorisierungskomponente zu sehen bekommen. AuthorizationCheck dient der Rechteprüfung, die einzige Methode heißt mayPerform (siehe Quelltext 5.2). Sie ist das Pendant zur Methode isAccessPermitted des AuthorizationManager der QuasarAuthorization. Allerdings benötigt mayPerform keinen AccessibleObjectType als Argument. Der Anwendungsprogrammierer, der die Rechteprüfung anstößt, übergibt nur das technische Objekt
des Zugriffs, die gewünschte Operation und den Benutzer; er braucht keine tiefer
gehenden Kenntnisse über das Berechtigungskonzept. Zur Auswahl des passenden
AccessibleObjectType wären solche Kenntnisse sehr wohl nötig.
Die Spezifikation von mayPerform überlässt dem Aufrufer die Entscheidung darüber, was zu tun ist, wenn das übergebene technische Objekt auf keine bekannte
44
5.3. Schnittstellen
Ressource abbildbar ist. In so einem Fall wird der Fehler unmanagedObject zurückgegeben.
Quelltext 5.2: AuthorizationCheck.mayPerform
boolean mayPerform( const Object resource ,
const Operation operation ,
const User user )
// r e t u r n s t r u e i f ' user ' i s permitted to perform ' operation ' on
// ' r e s o u r c e ' and f a l s e o t h e r w i s e .
error unmanagedObject // ' r e s o u r c e ' i s not under a c c e s s c o n t r o l .
5.3.2. Instrumentierung
Unter dem Begriff Instrumentierung verstehen wir die fachliche Konfiguration der
Komponente, also alle Maßnahmen zur Anpassung an den Anwendungskontext.
Bei der BasicAuthorization ist die gesamte Instrumentierung auf die angeforderte Schnittstelle ResourceDefinition konzentriert, ihre Implementierung liegt in der
Verantwortung der Anwendung. Die zwei wichtigsten Methoden sind getResource
und getOperations (siehe Quelltext 5.3). getResource bildet technische Objekte
auf Ressourcen ab, und getOperations legt fest, welche Operationen auf welche
Ressourcen anwendbar sind. In dieser Hinsicht ähnelt ResourceDefinition dem AccessibleObjectType der QuasarAuthorization. Doch es gibt einen wesentlichen Unterschied: Im Falle der QuasarAuthorization registriert man beliebig viele AccessibleObjectType-Objekte, und bei jeder Rechteprüfung ist eines davon auszuwählen.
Dagegen sieht ResourceDefinition genau eine Implementierung vor, die man während der Initialisierung festlegt – danach befasst sich kein Entwickler mehr damit.
Quelltext 5.3: Auszug aus ResourceDefinition
Resource getResource ( const Object object )
// maps a g e n e r a l o b j e c t to a r e s o u r c e e n t i t y . I f no mapping can be
// determined , n u l l i s returned .
// . . .
post . . .
pre
getResource ( o b j e c t ) != n u l l
List<Operation> getOperations ( Object object )
// r e t u r n s a l l a p p r o p r i a t e o p e r a t i o n s f o r ' o b j e c t ' .
post r e s u l t != n u l l
post . . .
45
5. BasicAuthorization
Die für den Entwurf gewählte Technik ist natürlich weniger flexibel, wir setzen hier
eine 1:n-Beziehung zwischen Ressourcen und technischen Objekten voraus (bei der
QuasarAuthorization ist n:m möglich). Jedoch können wir nur durch dieses Vorgehen
die Rechteprüfung durch AuthorizationCheck.mayPerform so einfach gestalten.
Wie stellt sich die Instrumentierung in der Praxis dar? Zur Veranschaulichung
entwerfen wir ein simples Szenario: Mitarbeiter der Personalabteilung (im Folgenden Personaler genannt) arbeiten mit personenbezogenen Daten der Angestellten des
Unternehmens. Mit Hilfe der Autorisierungskomponente ist ein Berechtigungskonzept zu realisieren, das die Zugriffsmöglichkeiten der Personaler auf die Daten einschränkt. Bei den Personaldaten (das sind die Ressourcen) ist nur grobkörnig zwischen normalen und leitenden Angestellten zu unterscheiden. Lediglich ein Teil der
Personaler soll Zugriff auf die Daten leitender Angestellter erhalten. Wir definieren
zwei Ressourcen namens employee und executive, die die normalen und leitenden Angestellten repräsentieren. Auf alle Personaldaten wird entweder lesend oder schreibend zugegriffen, also definieren wir für beide Ressourcen einheitlich die Operationen read und write. Quelltext 5.4 zeigt eine beispielhafte Java-Implementierung der
ResourceDefinition für diese Anwendung. Das Kriterium, nach dem sich normale
von leitenden Angestellten unterscheiden, ist ein typisches Beispiel für Anwendungswissen; hier wird anhand des Jahresgehaltes differenziert (Programmzeile 21).
5.3.3. Administration
Die Administrationsschnittstellen UserAdmin und AuthorizationAdmin enthalten
Methoden zum Anlegen, Ändern und Löschen der Entitäten. Über UserAdmin administriert man die Benutzerdaten, die Gruppenhierarchie und die Zuordnung von
Berechtigungen bzw. Rollen zu Benutzern bzw. Gruppen. Über AuthorizationAdmin
definiert man die Berechtigungen und Rollen.
Die Aufgabenverteilung zwischen UserAdmin und AuthorizationAdmin ist also mit
der Aufteilung zwischen AuthenticationAdministrationManager und AuthorizationAdministrationManager bei der QuasarAuthorization vergleichbar. Sie ist sinnvoll in der Hinsicht, dass die Dienste von UserAdmin häufiger in Anspruch genommen
werden als die von AuthorizationAdmin; bei betrieblichen Anwendungen ändert sich
auf Seiten der Benutzer und ihrer individuellen Privilegien häufiger etwas als bei den
Berechtigungs- und Rollendefinitionen, die eher statischer Natur sind. Beide Schnittstellen haben deshalb potentiell einen unterschiedlichen Nutzerkreis.
Das Interessanteste an den Administrationsschnittstellen ist die Auswertungslogik:
Sie ist hier als Bestandteil der Schnittstellensemantik spezifiziert. Die Auswertungslogik kommt zwar beim Vorgang der Rechteprüfung zur Anwendung, ihre Spezifikation
wäre aber bei der Schnittstelle AuthorizationCheck fehl am Platz; die meisten Auf-
46
5.3. Schnittstellen
Quelltext 5.4: Beispielimplementierung von ResourceDefinition (Java)
2
import java . u t i l . * ;
// . . . e v t l . w e i t e r e import−Anweisungen . . .
4
public class MyResourceDefinition implements ResourceDefinition {
public
public
public
public
6
8
static
static
static
static
final
final
final
final
Resource EMPLOYEE = new MyResource( " employee " ) ;
Resource EXECUTIVE = new MyResource( " executive " ) ;
Operation READ = new MyOperation ( " read " ) ;
Operation WRITE = new MyOperation ( " write " ) ;
10
private L i s t operations , dummyList ;
12
public MyResourceDefinition () {
operations = new A r r a y L i s t ( 2 ) ;
operations . add(READ) ;
operations . add(WRITE) ;
dummyList = new A r r a y L i s t ( 0 ) ;
}
14
16
18
private boolean i s E x e c u t i v e ( S t a f f s t a f f ) {
return s t a f f . getSalary () > 100000;
}
20
22
public Resource getResource ( Object o b j e c t ) {
i f ( o b j e c t instanceof S t a f f ) {
i f ( i s E x e c u t i v e (( S t a f f ) o b j e c t ) )
return EXECUTIVE ;
else
return EMPLOYEE;
} else
return null ;
}
24
26
28
30
32
public L i s t getOperations ( Object o b j e c t ) {
i f ( o b j e c t instanceof S t a f f ) {
return operations ;
} else
return dummyList ;
}
34
36
38
40
// . . . w e i t e r e Methoden . . .
42
}
47
5. BasicAuthorization
rufer von mayPerform wollen nur wissen, ob ein Zugriffsrecht gewährt ist, aber nicht,
warum. Vor dem Gros der Anwendungsprogrammierer verbergen wir die Details des
Berechtigungskonzepts. Der Administrator (oder der Entwickler eines Administrationswerkzeugs) ist aber auf die Kenntnis der Auswertungslogik angewiesen. UserAdmin erweitert AuthorizationCheck, damit der Administrator mayPerform zum Test
der Rechtezuordnungen verwenden kann.
Der Großteil der Auswertungslogik ist bei UserAdmin spezifiziert, und zwar in den
Invarianten aus Quelltext 5.5.
Quelltext 5.5: Auszug aus UserAdmin
invariants
ancestor in getClosure ( aUser ) <=> (
ancestor . equals ( aUser ) or
e x i s t s g in getParents ( aUser ) : ancestor in getClosure (g)
)
mayPerform( resource , operation , u) <=> (
operation in rDef . getOperations ( resource ) and
( e x i s t s aUser , aRight , r :
aUser in getClosure (u) and
aRight in getRights ( aUser ) and
aRight in admin . getClosure ( r ) and
admin . getResource ( r ) . equals (
rDef . getResource ( resource )) and
admin . getOperation ( r ) . equals ( operation )
)
)
Die erste Invariante definiert mit der Methode getClosure die Hülle von AbstractUser. Die Hülle eines Benutzers besteht aus ihm selbst und allen Gruppen, denen er
direkt oder indirekt angehört. Die Spezifikation von AuthorizationAdmin definiert
einen analogen Hüllenbegriff für AbstractRight: Die Hülle einer Berechtigung besteht aus ihr selbst und allen Rollen, denen sie direkt oder indirekt angehört.
Auf dieser Basis lässt sich die Semantik der Rechteprüfung recht knapp formulieren (siehe zweite Invariante): Benutzer u hat genau dann das Recht, die Operation
auf die Ressource anzuwenden, wenn irgendeinem aUser ∈ Hülle(u) eine passende
Berechtigung r oder ein Element aRight ∈ Hülle(r) zugeordnet ist.
Man beachte, dass diese Spezifikation die Auswertungslogik rein deklarativ beschreibt; sie gibt weder Algorithmus noch Datenstruktur vor, lässt also ausreichende
Freiheiten für eine effiziente Implementierung der Rechteprüfung.
48
»Speak friend and enter.«
The Lord of the Rings (J.R.R. Tolkien)
6. AdvancedAuthorization
Die BasicAuthorization ist einfacher zu konfigurieren und anzuwenden als die QuasarAuthorization. Ihr Einsatzfeld ist allerdings begrenzt, da die Rechtevergabe allein
auf dem Erlaubnisprinzip beruht (vgl. Abschnitt 3.2.3). Die zweite Stufe des Entwurfs
– wir nennen sie AdvancedAuthorization1 – bricht diese Beschränkung auf. Außerdem
realisiert sie ein flexibleres Authentifizierungskonzept.
6.1. Funktionsumfang
Auch diese Komponente bietet die Dienste
• Benutzeradministration,
• Administration von Zugriffsrechten und
• Rechteprüfung
an. Die Authentifizierung zählt dagegen nicht zu den Kerndiensten, sondern ist ausgelagert. Ersetzt wird sie durch einen Dienst zur
• Sitzungsverwaltung,
der Login und Logout abwickelt. Was genau beim Login geschieht (insbesondere, ob
und wie authentifiziert wird) definiert die Instrumentierung. Im Gegensatz zur QuasarAuthorization unterstützt diese Komponente die selektive Aktivierung von Rollen
– ein wichtiger Bestandteil des RBAC-Standards. Während der Sitzung eines Benutzers sind also nicht zwangsläufig alle seine Zugriffsrechte aktiv. Das ermöglicht die
Durchsetzung des Prinzips der minimalen Rechte.
Was die Autorisierung betrifft, so unterstützt die AdvancedAuthorization sowohl
positive als auch negative Rechtevergabe.
6.2. Datenmodell
Im Datenmodell (Abbildung 6.1) findet man alle Elemente des Modells der BasicAuthorization wieder. Die auffälligste Neuerung ist der Entitätstyp Assignment. Er
1
Für advanced existieren mehrere Übersetzungen, sie reichen von erweitert bis hochentwickelt.
49
6. AdvancedAuthorization
Assignment
posi ti ve: boolean
m andatory: bool ean
«interface»
*
«i nterface»
AbstractUser
*
* {ordered}
*
AbstractRight
contains
contai ns
* {ordered}
*
«i nterface»
«i nterface»
«interface»
«i nterface»
Group
User
Right
Role
*
*
1
«i nterface»
Resource
1
i m pl i es
positi ve
*
«i nterface»
*
Operation
*
i m pl i es
negative
*
i m pl i es
*
*
*
*
appl i es to
Abbildung 6.1.: Datenmodell der AdvancedAuthorization
repräsentiert die einzelnen Rechtezuordnungen. Im UML-Diagramm ist er als Assoziationsklasse dargestellt, die die Beziehung zwischen Benutzern/Gruppen und Berechtigungen/Rollen näher beschreibt. Aus Spezifikationssicht ist er (ebenso wie alle
anderen Typen) eine Schnittstelle (siehe Quelltext 6.1).
Berechtigungen und Rollen sind neutrale Zugriffsdefinitionen, erst bei der Zuordnung zu Benutzern und Gruppen werden sie zu Erlaubnissen (isPositive() ==
true) oder zu Verboten (isPositive() == false). Der Wert von isMandatory()
bestimmt, ob es sich um eine zwingend erforderliche (mandatory) Zuordnung handelt, oder ob sie während einer Sitzung inaktiv sein darf. Durch Setzen dieses Attributs kann man verhindern, dass ein Benutzer die ihn betreffenden Verbote einfach
Quelltext 6.1: Auszug aus Assignment
AbstractRight getRight ()
// r e t u r n s the a s s i g n e d r i g h t or r o l e .
...
boolean isMandatory ()
...
boolean i s P o s i t i v e ()
50
6.2. Datenmodell
abschaltet.2
Bei diesem Datenmodell bestehen gegenüber der BasicAuthorization auch Unterschiede seitens einiger Assoziationen: In der Gruppenhierarchie haben die Mitgliedschaftsbeziehungen eine definierte Reihenfolge, und zwar aus Sicht der Mitglieder.
Die Menge der Gruppen, denen ein gegebener Benutzer angehört, ist also geordnet.
Dasselbe gilt für die Beziehungen zwischen einer Untergruppe und ihren übergeordneten Gruppen. Die einem gegebenen Benutzer bzw. einer Gruppe zugeordneten
Berechtigungen und Rollen sind ebenfalls geordnet. Das Ordnen dieser Beziehungen erzeugt Prioritäten und ist eine notwendige (keine hinreichende!) Voraussetzung
dafür, dass die Rechteprüfung auch im Falle mehrdeutiger Rechtefestlegungen zu eindeutigen Ergebnissen kommt.3
Übrigens verwaltet auch die QuasarAuthorization Reihenfolgen auf den Gruppenmitgliedschaften und Rollenzuordnungen – mit dem feinen Unterschied, dass grantedund revoked-Zuordnungen dort getrennte Mengen sind (vgl. Abbildung 4.1). Eine
systemweite Einstellung legt pauschal fest, ob im Konfliktfall positive oder negative Rechte Vorzug genießen. Dagegen erlaubt die AdvancedAuthorization, die Rechte
unabhängig davon zu priorisieren, ob sie positiv oder negativ sind.
Im Datenmodell verfügt jetzt der Operation-Typ über zwei Beziehungen zu sich
selbst. implies positive verknüpft Operationen miteinander, die sich im Falle einer positiven Rechtezuordnung implizieren. Standardbeispiel: Wer schreiben darf, darf auch
lesen. Die Beziehung implies negative betrifft den Fall der negativen Rechtezuordnung.
Standardbeispiel: Wer nicht lesen darf, darf auch nicht schreiben. Die Regeln für den
positiven und negativen Fall sind nicht zwangsläufig invers. Die Ordnung auf den
Operationen ist Sache der Instrumentierung (die auch festlegt, welche Operationen
es überhaupt gibt).
Das Konzept der implizierenden Operationen realisiert auch die QuasarAuthorization; völlig neu ist dagegen das Merkmal, welches die implies-Beziehung des Typs Resource andeutet: Ressourcen können jetzt auch untereinander in Beziehung stehen.
Somit lassen sich Zugriffsrechte auf hierarchisch strukturierten Ressourcenmengen
effizient definieren. Ein anschauliches Beispiel für eine Implikationsregel auf Ressourcen haben wir bereits in Abschnitt 3.2.2 genannt:
2
Warum definieren wir Verbote nicht generell als zwingend? – Manchen Beschränkungen unterwirft
man sich freiwillig. Beispiel: Ein Benutzer verbietet sich selbst den Schreibzugriff auf die eigenen
Dateien, um sie vor versehentlichem Löschen zu schützen. Zum Ändern einer Datei deaktiviert er
vorübergehend das Verbot.
3
Warum sind die Berechtigungen innerhalb der Rollen nicht geordnet? – Die Ordnung dient der Auflösung von Konflikten. Zwischen den Berechtigungen einer Rolle sind Konflikte aber von vornherein ausgeschlossen: Jede positiv/negativ zugeordnete Rolle enthält nur positive/negative Berechtigungen und Rollen.
51
6. AdvancedAuthorization
In einem Verzeichnisbaum schließt das Zugriffsrecht auf ein Verzeichnis
entsprechende Rechte bezüglich aller enthaltenen Dateien und Unterverzeichnisse ein.
Die Autorisierungskomponente verwaltet die Beziehungen zwischen den Ressourcen
nicht selbst; bezogen auf das Beispiel weiß sie also nicht, welche Datei in welchem
Verzeichnis liegt. Sie bekommt die nötigen Informationen über die Instrumentierung.
In Abschnitt 6.3.3 untersuchen wir das genauer.
6.3. Schnittstellen
Die Außensicht der AdvancedAuthorization ist in Abbildung 6.2 illustriert und in Anhang B.3 spezifiziert. Sie enthält neben den drei logischen Schnittstellen der BasicAuthorization eine vierte: Technische Umgebung.
Instrum entierung
Authenti cati on ResourceDefi ni ti on
Pol i cy
Operati ver Betri eb
Adm i ni strati on
Adv ancedAuthorization
Sessi onM anagem ent
Authorizati onCheck
UserAdm i n
Authori zati onAdm i n
Reposi tory
Logging
T echni sche Um gebung
Abbildung 6.2.: Außensicht der AdvancedAuthorization
6.3.1. Technische Umgebung
Die angeforderte Schnittstelle Repository verbindet die Autorisierungskomponente
mit der Persistenz. Die erste Stufe des Entwurfs machte die gesamte Datenhaltung
zum Implementierungsgeheimnis – jetzt tragen wir der Tatsache Rechnung, dass man
die Komponente für den praktischen Einsatz nicht immer mitsamt Datenbanksystem
52
6.3. Schnittstellen
ausliefern kann. Repository definiert eine Reihe von get- und set-Methoden zum
Laden und Speichern der Entitäten und ihrer Beziehungen untereinander.
Mit der angeforderten Schnittstelle Logging führen wir die Protokollierung von
Login-/Logout-Vorgängen und Zugriffen ein. Beispiel: Nachdem die Rechteprüfung
ein positives Resultat geliefert hat, ruft die Komponente die Methode accessGranted
der Logging-Schnittstelle auf. Als Argumente übermittelt sie die Eckdaten des Zugriffs: Zeitpunkt, Benutzer, Ressource, Operation. Der Adapter, der Logging implementiert, schreibt dann z. B. einen neuen Eintrag in eine Log-Datei, oder er delegiert
den Aufruf an die systemweite Ereignisverwaltung – je nach vorhandener Infrastruktur. Die Protokolldaten kann man zur Beweissicherung heranziehen (Wer hat als Letzter auf diese Daten zugegriffen?) oder zur Suche nach Fehlern in den Rechtefestlegungen.
6.3.2. Operativer Betrieb
Die neue Schnittstelle SessionManagement dient der Sitzungsverwaltung, Quelltext
6.2 zeigt die drei wesentlichen Methoden.
Quelltext 6.2: Auszug aus SessionManagement
boolean isValid ( SessionTicket t i c k e t ) NRR
...
SessionTicket login () NRR
...
void logout ( const SessionTicket t i c k e t )
// i n v a l i d a t e s ' t i c k e t ' .
post not i s V a l i d ( t i c k e t )
login wird ohne Parameter aufgerufen und liefert im Erfolgsfall ein Objekt vom
Typ SessionTicket. Es repräsentiert die soeben eröffnete Sitzung und ist bei Rechteprüfungen als Argument zu übergeben. Mit dem Ticket sind Informationen über den
angemeldeten Benutzer und seine in dieser Sitzung aktiven Rechte verknüpft. Natürlich entsteht so ein Ticket nicht aus dem Nichts – was beim Login-Vorgang hinter den
Kulissen abläuft, erläutern wir im Zusammenhang mit der Instrumentierung (siehe
nächster Abschnitt).
Jedes SessionTicket ist entweder gültig oder ungültig; das ist der wesentliche
Unterschied zum UserTicket der QuasarAuthorization (das ist immer gültig). Ob ein
Ticket gültig ist, erfragt man von SessionManagement über die Methode isValid.
Welche Umstände machen ein SessionTicket ungültig? Auf jeden Fall der Aufruf
von logout (dies beendet die Sitzung), doch die Spezifikation lässt Raum für weitere
Bedingungen. Einige Beispiele:
53
6. AdvancedAuthorization
• Das Ticket hat ein Verfallsdatum. Nach Ablauf einer bestimmten Zeitspanne ist
es ungültig.
• Das Ticket ist mit einer Prüfsumme ausgestattet. Schlägt der Integritätstest fehl,
ist es ungültig.
• Ein virtueller Not-Aus-Schalter macht pauschal alle Tickets ungültig (zur Schadensbegrenzung, wenn z. B. ein Einbruch in das Unternehmensnetzwerk erkannt wurde).
Was letztendlich über die Ticket-Gültigkeit entscheidet, bleibt das Implementierungsgeheimnis von SessionManagement und SessionTicket.
Die Spezifikation der Schnittstelle AuthorizationCheck unterscheidet sich geringfügig von der alten Fassung: mayPerform ruft man jetzt mit einem SessionTicketParameter statt einem User auf, und ein ungültiges Ticket führt zu einem invalidTicket-Fehler.
6.3.3. Instrumentierung
Die AdvancedAuthorization fordert neben der ResourceDefinition zwei weitere Instrumentierungsschnittstellen an. Die folgenden Abschnitte behandeln nacheinander
die Schnittstellen Authentication, ResourceDefinition und Policy.
Ausgelagerte Authentifizierung
Wir wenden uns jetzt den Vorgängen zu, die sich beim Login-Vorgang hinter den Kulissen abspielen. Die Autorisierungskomponente delegiert die Authentifizierung des
Benutzers und das Auswählen seiner aktiven Rechte an die Schnittstelle Authentication (Quelltext 6.3). Das Sequenzdiagramm in Abbildung 6.3 zeigt das allgemeine
Login-Protokoll. Den Anstoß gibt der Aufruf der login-Methode an der Schnittstelle SessionManagement. Die Komponente fordert daraufhin mit getAuthenticatedUser das fertig authentifizierte User-Objekt von Authentication an. Erst jetzt weiß
die Komponente, welcher Benutzer sich anmeldet; sie erzeugt eine Liste mit Rechtezuordnungen dieses Benutzers und lässt eine Teilmenge davon als aktiv markieren
(getActiveRights). Damit hat die Autorisierungskomponente alle Informationen,
die sie braucht, um ein SessionTicket zu generieren.
Wir demonstrieren nun, wie man mit der AdvancedAuthorization die herkömmliche Passwort-Authentifizierung nachbildet. Dazu skizzieren wir eine kleine Erweiterungskomponente namens PasswordLogin, die gemäß Abbildung 6.4 mit der
AdvancedAuthorization verbunden wird. Die Schnittstelle BasicAuthentication
54
6.3. Schnittstellen
Quelltext 6.3: Auszug aus Authentication
boolean [] getActiveRights ( const User user ,
const List<Assignment> assignedRights )
// r e t u r n s an array o f f l a g s , one f o r each element o f ' a s s i g n e d R i g h t s ' .
// . . .
post r e s u l t . length == assignedRights . s i z e ()
post f o r a l l i : 0 <= i < r e s u l t . length :
assignedRights . get ( i ) . isMandatory () => r e s u l t [ i ] == true
User getAuthenticatedUser ()
// . . .
:Adv ancedAuthorization
«interface»
:Authentication
Initi ator
l ogi n()
getAuthenti catedUser()
getActi veRi ghts(user,assi gnedRi ghts)
sessi onT i cket
Abbildung 6.3.: Allgemeiner Ablauf eines Login-Vorgangs
«i nterface»
BasicAuthentication
authenticate(Stri ng, String) : Sessi onTi cket
«real ize»
Passw ordLogin
Authenti cati on
Adv ancedAuthorization
BasicAuthenti cation
UserAdm in
Initiator
«reali ze»
Sessi onM anagem ent
«interface»
BasicAuthenticationAdmin
setPassw ord(User, Stri ng) : void
Abbildung 6.4.: Konfiguration für klassische Passwort-Authentifizierung
55
6. AdvancedAuthorization
nimmt nach Art der Komponente BasicAuthorization die Benutzeranmeldung per Name und Passwort entgegen. PasswordLogin prüft die Anfrage und startet im Erfolgsfall eine Sitzung der AdvancedAuthorization, was die bekannten Rückfragen nach
sich zieht. Abbildung 6.5 zeigt den zugehörigen Ablauf. Mit dem Aufruf existAbstractUser (Schnittstelle UserAdmin) prüft PasswordLogin zunächst, ob der Benutzer überhaupt (noch) registriert ist. Ansonsten entspricht der Ablauf dem Schema von
Abbildung 6.3, allerdings mit der Besonderheit, dass PasswordLogin (als Exporteur
der Schnittstelle Authentication) während des Aufrufs der Autorisierungskomponente Rückrufe von ihr erhält.4
Dieses Beispiel geht davon aus, dass beim Login pauschal alle Rechtezuordnungen
des Benutzers aktiviert werden (analog zur BasicAuthorization). getActiveRights
markiert also sämtliche angebotenen Listeneinträge.
Über die Schnittstelle BasicAuthenticationAdmin kann man die Benutzerpasswörter anlegen und ändern. Die AdvancedAuthorization weiß nichts von Passwörtern, die Komponente PasswordLogin ist allein für deren Verwaltung verantwortlich.
Dazu legt sie im einfachsten Fall die Name-Passwort-Paare in einer Tabelle ab. Eine
andere Möglichkeit: PasswordLogin speichert die Passwörter in der Autorisierungskomponente – deren Schnittstelle UserAdmin bietet nämlich die Möglichkeit, beliebige Benutzerattribute als Schlüssel-Wert-Paare abzulegen.
Die Technik, Authentifizierungsvorgänge an externe Komponenten zu delegieren,
imitiert das PAM-Konzept von JAAS. Die Frage drängt sich auf, ob man Login Modules,
die für JAAS entwickelt wurden, auch für unsere Autorisierungskomponente nutzbar
machen kann. Im Prinzip spricht nichts dagegen; die einzige Schwierigkeit besteht
darin, die JAAS-Principals auf unser Benutzerschema abzubilden.
In Abschnitt 3.4.3 wiesen wir darauf hin, dass die Semantik der Principals variieren
kann, je nachdem, welches Login Module die Principal-Objekte erzeugt. Im Grunde
repräsentiert jeder Principal nur eine Teilidentität einer Person. Wenn sich z. B. Frau
Mustermann heute als mustermann und morgen als administrator an ihrem PC anmeldet, so sind das zwei verschiedene Teilidentitäten derselben Person. Auch die Benutzer, die die AdvancedAuthorization verwaltet, sind nur Teilidentitäten, weil Frau
Mustermann auch hier unter verschiedenen Namen registriert sein könnte. Ein Adapter zwischen JAAS und der Autorisierungskomponente braucht also Zugriff auf Wissen über die Benutzerorganisation beider Welten.
Das Konfigurationsschema in Abbildung 6.6 zeigt, wie man bei der AdvancedAuthorization die Authentifizierung mit JAAS-Mitteln bewerkstelligt. Der JAASAdapter
stellt die für unsere Komponente maßgeschneiderten Dienste bereit. Die Verknüpfung
4
Die Komponente PasswordLogin hat sicherzustellen, dass die Rückrufe sie in einem konsistenten
Zustand antreffen (vgl. [Sie04, Abschnitt 6.7]).
56
6.3. Schnittstellen
:Passw ordLogin
:Adv ancedAuthorization
Initi ator
authenti cate(usernam e,password)
exi stAbstractUser(user)
l ogin()
getAuthenticatedUser()
getActiveRights(user,assi gnedRi ghts)
sessionT icket
sessionT i cket
Abbildung 6.5.: Ablauf eines Login-Vorgangs mit klassischer Passwort-Authentifizierung
Java Security / JAAS
«i nterface»
LoginContext
LoginM odule
«i nterface»
Subj ect
*
1
*
*
Principal
IdentityM anagem ent
JAASAdapter
Authenticati on
M yIdentityM anagement
«real ize»
«i nterface»
Adv ancedAuthorization
IdentityM anagement
mapPri nci palsToUser(Li st) : User
Initiator
Sessi onM anagem ent
Abbildung 6.6.: Konfiguration für JAAS-basierte Authentifizierung
57
6. AdvancedAuthorization
der verschiedenen Teilidentitäten delegiert er an die Schnittstelle IdentityManagement. Deren Methode mapPrincipalsToUser bildet die Principals der JAAS-Welt
auf einen Benutzer ab, mit dem die Autorisierungskomponente arbeiten kann. Die
Implementierung (MyIdentityManagement) braucht natürlich Kenntnisse über beide
Welten, was im Diagramm die Abhängigkeitspfeile zu Principal und AdvancedAuthorization andeuten.
Die Klassen und Schnittstellen im oberen Teil des Bildes steuert die Java-Plattform
bei. Subject und LoginContext bedürfen hier noch einer Erklärung. Subject ist ein
Behälter für Principals. Dieser Behälter wird beim Login-Vorgang gefüllt. LoginContext realisiert bei JAAS die Sitzungsverwaltung mit Login und Logout. Nach dem Login stellt der LoginContext das Subject bereit, das die authentifizierten Principals
enthält. Außerdem entkoppelt der LoginContext die Anwendung vom LoginModule.
Hüllen auf Ressourcen und Operationen
Bei der BasicAuthorization führten wir den Hüllenbegriff für AbstractUser und AbstractRight ein. Bei der AdvancedAuthorization definieren wir zusätzliche Hüllen,
nämlich auf Ressourcen und auf Operationen. Dazu erweitern wir die Schnittstelle
ResourceDefinition um die in Quelltext 6.4 aufgezählten Methoden.
Zur Erinnerung: Die Hülle eines Benutzers besteht aus allen Gruppen, denen er
direkt oder indirekt als Mitglied zugeordnet ist. Die Hülle einer Ressource stellen
wir uns so ähnlich vor, aber da wir die Struktur der Ressourcenmenge nicht kennen,
brauchen wir eine andere Definition. Wir definieren die Ressourcenhülle auf eine
Weise, die die Rechteprüfung erleichtert:
Die Hülle der Ressource r besteht aus allen Ressourcen r0 , für die folgendes gilt: Jede Berechtigung, die auf r0 definiert ist, gilt auch für r.
Im Falle des Verzeichnisbaum-Beispiels besteht die Hülle einer Datei aus der Datei
selbst und allen Verzeichnissen, die auf dem Pfad von der Datei bis zum Wurzelverzeichnis liegen. Eine Berechtigung, die für das Wurzelverzeichnis definiert wurde, gilt
demnach für den ganzen Baum.
Quelltext 6.4: Auszug aus ResourceDefinition
List<Resource> getClosure ( const Resource resource )
...
List<Operation> getPermissiveClosure ( const Operation operation )
...
List<Operation> getProhibitiveClosure ( const Operation operation )
58
6.3. Schnittstellen
Die Methode getClosure liefert die Hülle der übergebenen Ressource in Form einer Liste. Die Methoden getPermissiveClosure und getProhibitiveClosure liefern die erlaubende bzw. verbietende Hülle der übergebenen Operation:
Die erlaubende (verbietende) Hülle der Operation o besteht aus allen
Operationen o0 , für die folgendes gilt: Jede Berechtigung, die o0 erlaubt
(verbietet), erlaubt (verbietet) auch o.
Nehmen wir als Beispiel noch einmal an, dass es nur die Operationen lesen und schreiben gibt, dass die Schreiberlaubnis die Leseerlaubnis einschließt, und dass das Leseverbot zum Schreibverbot führt. Die erlaubende Hülle der Operation lesen besteht
dann aus lesen und schreiben. Die verbietende Hülle von lesen besteht nur aus lesen
allein (Schreibverbot führt nicht zu Leseverbot).
Linearisierung der Rechte
Die Schnittstelle Policy definiert zwei Methoden, deren Verhalten das Ergebnis der
Rechteprüfung entscheidend beeinflusst (siehe Quelltext 6.5).
Quelltext 6.5: Auszug aus Policy
pre
uAdmin . e x i s t A b s t r a c t U s e r ( user )
List<Assignment> getLinearization ( const AbstractUser user )
...
error c o n f l i c t s W i t h P o l i c y // . . .
boolean mayPerformByDefault ()
...
Das Resultat der Methode mayPerformByDefault bestimmt, zu welchem Ergebnis
die Rechteprüfung gelangt, wenn weder ein explizit noch implizit festgelegtes Recht
auf den Zugriffswunsch anwendbar ist. Beim Erlaubnisprinzip liefert man in so einem
Fall false (was nicht erlaubt ist, ist verboten), beim Verbotsprinzip true (was nicht
verboten ist, ist erlaubt).
Die Methode getLinearization erzeugt eine geordnete Liste aller Berechtigungen
und Rollen, die dem gegebenen AbstractUser explizit und implizit zugeordnet sind.
Diese Liste (und den Vorgang ihrer Erzeugung) nennen wir Linearisierung. Ihre Reihenfolge hängt von der Strategie ab, nach der man den Beziehungsgraphen traversiert. Wir betrachten als Beispiel den Graphen in Abbildung 6.7. Die Gruppe A2 sei
mit einer Erlaubnis (+) verknüpft, die Gruppe B1 mit einem Verbot (-). Wenn man
nun, ausgehend vom Benutzer, auf dem Graphen eine Tiefensuche ausführt, werden
die Gruppen-Knoten in folgender Reihenfolge besucht:
59
6. AdvancedAuthorization
+
A2
B2
A1
B1
-
Priorität
(0 = höchste)
0 1 2 3
Gruppe
Mitglied
in
Abbildung 6.7.: Beispiel zur Linearisierung
• A1, A2, B2, B1
A2 wird vor B1 besucht, die Erlaubnis befindet sich in der Linearisierung also vor dem
Verbot. Eine Breitensuche auf demselben Graphen ergibt diese Sequenz:
• A1, B1, A2, B2
Hier kommt B1 vor A2, das Verbot steht in der Liste vor der Erlaubnis.
Die Policy-Schnittstelle definiert keine konkrete Linearisierungsstrategie, denn
das wäre gleichbedeutend mit dem Festverdrahten der Auswertungslogik. Man kann
aber beliebig viele Schnittstellen spezifizieren, die Policy erweitern. So lässt sich ein
Satz von Standardstrategien für die Linearisierung bereitstellen. Mit der Schnittstelle
PositiveOverridePolicy (Quelltext 6.6) geben wir ein Beispiel für dieses Vorgehen.
Diese Strategie ist sehr einfach: Positive Rechte haben generell Vorrang vor negativen. Die Methode getLinearization braucht dafür nur sicherzustellen, dass alle
positiven Rechtezuordnungen am Anfang der Ergebnisliste stehen – das besagt die
Nachbedingung der Methodenspezifikation. Die Invariante bestimmt, welche Elemente überhaupt in der Liste enthalten sind: Es sind alle Rechte, die zu Elementen der
Hülle des Benutzers gehören. Die inverse Strategie, bei der alle negativen Rechte Vorrang haben – lässt sich analog definieren; hier stellt man statt der positiven Rechte
die negativen an den Listenanfang.
Aus dem negativen Vorrang folgt ein sehr restriktives Autorisierungsmodell, und
der positive Vorrang erlaubt im Allgemeinen zu viel. Auf der Suche nach differenzierteren Linearisierungsstrategien machen wir einen Abstecher zu einem anderen Gebiet
der Informatik, das sich mit einer ähnlichen Fragestellung befasst.
60
6.3. Schnittstellen
Quelltext 6.6: Auszug aus PositiveOverridePolicy
basicQueries
pre
uAdmin . e x i s t A b s t r a c t U s e r ( user )
List<Assignment> getLinearization ( const AbstractUser user )
...
post f o r a l l aPos , aNeg in r e s u l t :
aPos . i s P o s i t i v e () and not aNeg . i s P o s i t i v e () =>
r e s u l t . indexOf ( aPos ) < r e s u l t . indexOf (aNeg)
...
invariants
// . . .
a in g e t L i n e a r i z a t i o n ( aUser ) <=> (
a in uAdmin . getAssignments ( aUser ) or
e x i s t s g in uAdmin . getParents ( aUser ) : a in g e t L i n e a r i z a t i o n (g)
)
Objektorientierte Programmiersprachen, die eine Klassenhierarchie mit Mehrfachvererbung unterstützen, brauchen eine Linearisierungsstrategie zur dynamischen Methodenbindung. Die Mehrfachvererbung führt dazu, dass jede Unterklasse beliebig
viele Oberklassen hat, von denen sie verschiedene Implementierungen der gleichen
Methode erben kann. Bei einer Methode, die von der Unterklasse nicht überschrieben wird, ist nicht eindeutig, welche der geerbten Implementierungen zur Laufzeit
an die Methodendeklaration gebunden wird. Die Implementierungen werden transitiv in der Klassenhierarchie vererbt, und so ergibt sich eine ähnliche Situation wie
bei der Gruppenhierarchie unserer Autorisierungskomponente: Für jede Klasse ist die
Menge der direkten und indirekten Vererbungsbeziehungen sinnvoll zu priorisieren.
Sinnvoll bedeutet hier, dass der Programmierer nicht mit unerwartetem Vererbungsverhalten überrascht werden sollte (Prinzip der geringsten Überraschung – principle
of least surprise).
Die Programmiersprache Python arbeitet mit Mehrfachvererbung. Die Linearisierungsstrategie nennt man dort Method Resolution Order (MRO). Die MRO funktioniert nach dem C3-Algorithmus.5 Dieser Algorithmus wird in [BCH+ 96] vorgestellt,
seine Anwendung in der Python-MRO ist in [Sim03] anschaulich beschrieben. Zwei
Bedingungen bilden die Voraussetzung für eine überraschungsarme Linearisierung:
• Die Beibehaltung lokaler Prioritäten (local precedence order): In der Linearisierung der Klasse c hat c selbst die höchste Priorität, und für die direkten Ober5
gilt für Python ab Version 2.3
61
6. AdvancedAuthorization
klassen von c gilt, dass sie in der Linearisierung von c in der gleichen Reihenfolge auftreten, in der sie c zugeordnet sind.
• Das Monotoniekriterium (monotonicity): Wenn in der Linearisierung von c die
Klasse c1 Vorrang vor der Klasse c2 hat, dann hat c1 auch in den Linearisierungen
aller Unterklassen von c Vorrang vor c2 .
Es gibt Klassenkonstellationen, bei denen die gleichzeitige Einhaltung beider Bedingungen nicht erfüllbar ist. Wir erläutern dies anhand Abbildung 6.7, indem wir
die local precedence order und das Monotoniekriterium auf unsere Gruppenhierarchie
übertragen. Unter diesen Umständen entspricht der dargestellte Graph einer ungültigen Konstellation. Der Grund: In der Linearisierung von A1 kommt A2 vor B2, und in
der Linearisierung von B1 kommt B2 vor A2 – das schreibt die local precedence order
vor. Die beiden Listen lassen sich aber nicht verschmelzen, ohne das Monotoniekriterium zu verletzen. Die gleichzeitige Mitgliedschaft des Benutzers in den Gruppen A1
und B1 wäre unter diesen Bedingungen nicht zulässig.
Die Spezifikation unserer Policy-Schnittstelle sieht ausdrücklich vor, dass der Aufruf der Methode getLinearization auch Scheitern kann (siehe error-Klausel). Die
Schnittstelle eignet sich also grundsätzlich für eine Implementierung nach Art des
C3-Algorithmus.
6.3.4. Administration
Bei der BasicAuthorization war fast die gesamte Auswertungslogik bei den Administrationsschnittstellen spezifiziert. Bei der AdvancedAuthorization ist zwar ein wesentlicher Teil der Logik (die Linearisierung der Rechte) über die Policy-Schnittstelle ausgelagert, jedoch ist auch hier die Schnittstelle UserAdmin der Ort, an dem die eigentliche Rechteprüfung spezifiziert wird. Quelltext 6.7 enthält jene Teile von UserAdmin,
die das Verhalten der Methode mayPerform der Schnittstelle AuthorizationCheck
definieren (UserAdmin erbt wieder von AuthorizationCheck).
Die Methoden isHeadApplicable und listGrantsAccess sind Hilfsmethoden; wir
führen sie ein, um die Spezifikation übersichtlicher zu machen.6
Das Resultat der Rechteprüfung wird wie folgt ermittelt:
• mayPerform prüft zunächst, ob die Operation überhaupt auf die Ressource anwendbar ist (siehe erste Invariante). Ist das der Fall, wird die Entscheidung an
listGrantsAccess delegiert.
6
Die Hilfsmethoden sind eigentlich abstrakt, weil sie nicht zur Implementierung vorgesehen sind –
QSL kennt aber keine abstrakten Methoden.
62
6.3. Schnittstellen
Quelltext 6.7: Auszug aus UserAdmin
basicQueries
...
boolean isHeadApplicable ( const List<Assignment> l i s t ,
const Resource resource ,
const Operation operation )
...
boolean listGrantsAccess ( const Resource resource ,
const Operation operation ,
const List<Assignment> l i s t )
// . . .
post l i s t . isEmpty () => r e s u l t == p o l i c y . mayPerformByDefault ()
post not isHeadApplicable ( l i s t , resource , operation )
=> r e s u l t == l i s t G r a n t s A c c e s s ( resource , operation ,
l i s t . s u b L i s t (1 , l i s t . s i z e ( ) ) )
post isHeadApplicable ( l i s t , resource , operation ) and
l i s t . get ( 0 ) . i s P o s i t i v e () => r e s u l t == true
post isHeadApplicable ( l i s t , resource , operation ) and
l i s t . get ( 0 ) . isNegative () => r e s u l t == f a l s e
invariants
...
mayPerform( object , op , s T i c k e t ) <=> (
op in rDef . getOperations ( o b j e c t )
and
l i s t G r a n t s A c c e s s ( rDef . getResource ( o b j e c t ) , op ,
g e t C a p a b i l i t y L i s t ( s T i c k e t ))
)
isHeadApplicable ( a L i s t , res , op) <=> (
e x i s t s r in aAdmin . getClosure ( a L i s t . get ( 0 ) . getRight ( ) ) :
aAdmin . getResource ( r ) in rDef . getClosure ( r e s )
and (
a L i s t . get ( 0 ) . i s P o s i t i v e () and
aAdmin . getOperation ( r ) in rDef . getPermissiveClosure (op)
or
a L i s t . get ( 0 ) . isNegative () and
aAdmin . getOperation ( r ) in rDef . g e t P r o h i b i t i v e C l o s u r e (op)
)
)
63
6. AdvancedAuthorization
• listGrantsAccess arbeitet auf der Linearisierung aller in der Sitzung aktiven
Rechte. Die Methode durchsucht die Linearisierungsliste von vorne nach hinten
– dieser Vorgang ist als rekursiver Aufruf mit immer kürzer werdenden Teillisten
spezifiziert. Die Rekursion bricht ab,
– wenn das Ende der Liste erreicht wird (dann enthielt sie kein anwendbares
Recht) oder
– wenn eine Rechtezuordnung gefunden wird, die auf die Ressource und die
Operation anwendbar ist.
Wenn kein anwendbares Recht gefunden wurde, entscheidet mayPerformByDefault, ob der Zugriff gewährt wird. Wenn ein anwendbares Recht gefunden
wurde, hängt die Entscheidung nur mehr davon ab, ob das Recht eine Erlaubnis
oder ein Verbot darstellt.
• isHeadApplicable (siehe zweite Invariante) stellt fest, ob das aktuelle Element
der Liste (bei rekursiver Abarbeitung ist das der Listenkopf) auf die Ressource
und die Operation anwendbar ist. Dazu betrachten wir die Hülle der Berechtigung/Rolle, die Hülle der Ressource und
– die erlaubende Hülle der Operation (falls wir ein positives Recht untersuchen) oder
– die verbietende Hülle der Operation (falls wir ein negatives Recht untersuchen).
Die Berechtigung/Rolle ist anwendbar, wenn die Schnittmenge der drei betrachteten Hüllen nicht leer ist.
Bei der Rechteprüfung durchsuchen wir also die linearisierte Liste aller aktiven
Rechte so lange, bis wir auf eine Berechtigung oder Rolle stoßen, die irgendwie auf
den Zugriffswunsch passt.
6.4. Potential und Grenzen
Alle betrachteten Komponenten – die QuasarAuthorization und die beiden Entwürfe
– realisieren eine zentralistische Rechteverwaltung. Ressourcen haben keine Eigentümer, die autonom entscheiden, wer wie auf ihre Objekte zugreifen darf. Zugriffsrechte
legt man ausschließlich über die Administrationsschnittstellen fest, und die sind für
den Gebrauch durch privilegiertes Personal bestimmt.
64
6.4. Potential und Grenzen
Trotzdem ist eine Delegation des Rechts zur Rechtevergabe nicht völlig ausgeschlossen. Als generische Autorisierungskomponente kann die AdvancedAuthorization beliebige Ressourcen verwalten – einschließlich sich selbst. Denkbar wäre eine Konfiguration mit zwei Instanzen der Autorisierungskomponente. Die erste verwaltet die
eigentlichen Ressourcen: Personaldaten, Verzeichnisbäume oder etwas in der Art. Die
zweite Instanz überwacht die Zugriffe auf die erste. Sie verwaltet die Administrationsschnittstellen bzw. deren Methoden als Ressourcen. So lässt sich eine Rechteverwaltung mit einer Hierarchie von Administratoren aufbauen (Abteilungsadministrator,
Niederlassungsadministrator etc.).
Die Unterstützung von Randbedingungen ist ein Leistungsmerkmal, das der AdvancedAuthorization im Vergleich zur QuasarAuthorization noch fehlt. Randbedingungen hätten den Entwurf in zweifacher Hinsicht komplizierter gemacht. Man hätte
eine weitere Instrumentierungsschnittstelle zur Definition der Semantik der Randbedingungen benötigt (ähnlich den AccessRestrictionTypes bei der QuasarAuthorization). Außerdem hätte die Annahme nicht mehr getragen, dass alle Berechtigungen,
die das gleiche Ressourcen-Operations-Paar betreffen, äquivalent sind (eine Annahme, die die Rechteprüfung vereinfacht). Im Übrigen lassen sich statische Randbedingungen über die Instrumentierung realisieren, indem man dasselbe technische Objekt – abhängig von der Erfüllung der Randbedingung – auf verschiedene Ressourcen
abbildet. Die Beispielimplementierung MyResourceDefinition (Quelltext 5.4) funktioniert im Grunde nach diesem Prinzip.
65
». . . what’s past is prologue . . . «
The Tempest (William Shakespeare)
7. Zusammenfassung und Ausblick
Die AdvancedAuthorization – so sie denn einmal implementiert wird – ist eine ernst
zu nehmende Alternative zur QuasarAuthorization. Sie ist einfacher zu konfigurieren
und anzuwenden, denn ihre Schnittstellen sind weniger komplex, besser spezifiziert,
und vermischte Verantwortlichkeiten wurden abgeschafft. Die größte Vereinfachung
betrifft die Rechteprüfung (mayPerform), die mit drei elementaren Parametern und
ohne zusätzliches Anwendungswissen auskommt.
Die Vorgehensweise, den Entwurf der neuen Komponente in zwei Stufen anzugehen, erwies sich als günstig. In der ersten Stufe (BasicAuthorization) konnten wir uns
auf das Wesentliche konzentrieren: klare Untergliederung der Außensicht; Entwicklung des Hüllenkonzepts als Grundlage einer elegant spezifizierbaren Rechteprüfung.
Das schuf ein solides Fundament für die zweite Stufe (AdvancedAuthorization): Neue
Schnittstellen fügten sich sinnvoll in die Außensicht ein, das Hüllenkonzept übertrugen wir von den Dimensionen Benutzer und Rechte auf die Dimensionen Ressourcen
und Operationen. Die Auswertungslogik ist teils per Spezifikation festgelegt und teils
variabel. Der variable Anteil konzentriert sich auf eine einzige Schnittstelle und betrifft die Linearisierung einer partiell geordneten Menge von Rechten. Der Authentifizierungsdienst von JAAS stand Pate bei der Konzeption einer neuen, flexibleren
Sitzungsverwaltung.
Die BasicAuthorization ist nicht nur eine Vorstufe zur AdvancedAuthorization, sie
ist als voll funktionsfähige Autorisierungskomponente angelegt. Für den Einsatz in
Projekten, die ein einfaches Autorisierungskonzept mit kleiner Ressourcenmenge und
rein additiver Rechtevergabe benötigen, ist die BasicAuthorization gegenüber der AdvancedAuthorization vorzuziehen.
Eine Autorisierungskomponente, die die parallele Vergabe positiver und negativer Rechte über eine tiefe Benutzerhierarchie hinweg ermöglicht, sollte eigentlich
über eine Diagnoseschnittstelle verfügen, die zur Analyse subtiler Konflikte in den
Rechtefestlegungen herangezogen werden kann. Wie sollte so eine Schnittstelle aussehen? Welche Informationen sind für den Administrator hilfreich? Kann man diese
Schnittstelle überhaupt generisch spezifizieren, ohne Kenntnis der konkreten Auswertungslogik (oder Linearisierungsstrategie)? – Das sind interessante Fragen, an denen
weitere Forschungsarbeiten ansetzen können.
67
A. Glossar
AbstractRight Entitätstyp, der eine Berechtigung oder eine Rolle repräsentiert
AbstractUser Entitätstyp, der einen Benutzer oder eine Gruppe repräsentiert
AccessibleObject Entitätstyp, der eine Ressource repräsentiert
Accessor Entitätstyp, der einen Benutzer oder eine Gruppe repräsentiert
AccessRestriction Entitätstyp, der eine Randbedingung einer Berechtigung repräsentiert
ACL Access Control List; Zugriffskontrollliste
ADF Access Control Decision Function; ISO-Normbegriff für die Rechteprüfung
Administration (von Zugriffsrechten) Rechtefestlegung als Teilaufgabe der Autorisie-
rung
AEF Access Control Enforcement Function; ISO-Normbegriff, bezeichnet die Durch-
setzung der Zugriffsrechte gemäß der Rechteprüfung
Angeforderte Schnittstelle Schnittstelle, die die importierende Komponente selbst
definiert (Synonyme: Stützschnittstelle, Anforderungsschnittstelle)
API Application Programming Interface
Assignment Entitätstyp, der eine Rechtezuordnung an Benutzer oder Gruppen repräsentiert
Authentifizierung Überprüfung der Identität eines Benutzers
Autorisierung Rechteverwaltung als Basis der Zugriffskontrolle; besteht aus Adminis-
tration und Rechteprüfung
Benutzer Subjekt eines Zugriffs
Berechtigung Eine Berechtigung verknüpft eine bestimmte Operation mit einer be-
stimmten Ressource. Aus der Zuordnung von Berechtigungen zu Benutzern ergeben sich die wirksamen Zugriffsrechte.
69
A. Glossar
DAC Discretionary Access Control; benutzerbestimmbare Zugriffskontrolle
Group Entitätstyp, der eine Gruppe repräsentiert
Gruppe Eine Gruppe fasst Benutzer und/oder weitere Gruppen zusammen.
GUI Graphical User Interface
Instrumentierung Maßnahmen zur fachlichen Konfiguration einer Komponente
ISO International Organization for Standardization
J2SE Java 2 Platform, Standard Edition
JAAS Java Authentication and Authorization Service
JML Java Modeling Language
JVM Java Virtual Machine
LDAP Lightweight Directory Access Protocol; Protokoll für den Zugriff auf Verzeich-
nisdienste
MAC Mandatory Access Control; systembestimmte Zugriffskontrolle
MRO Method Resolution Order; Strategie der dynamischen Methodenbindung bei
der Programmiersprache Python
NIST National Institute of Standards and Technology; Normungsbehörde in den USA
NRR non-repeatable read (Wiederholbarkeitseigenschaft von Methoden)
OCL Object Constraint Language (Bestandteil der UML)
Operation Zugriffsart (z. B. lesen, schreiben, ausführen)
Operation Entitätstyp, der eine Operation repräsentiert
Permission Entitätstyp, der eine Berechtigung repräsentiert
PermissionGroup Entitätstyp, der eine Rolle repräsentiert
QSL Quasar Specification Language; eine halbformale Sprache für die Spezifikation
von Schnittstellen
Quasar Qualitätssoftwarearchitektur
70
RBAC Role-Based Access Control; rollenbasierte Zugriffskontrolle
Rechteprüfung Abfrage festgelegter Zugriffsrechte als Teilaufgabe der Autorisierung
Resource Entitätstyp, der eine Ressource repräsentiert
Ressource Objekt eines Zugriffs
RestrictionParameter Entitätstyp, der einen Parameter einer AccessRestriction
repräsentiert
Right Entitätstyp, der eine Berechtigung repräsentiert
Role Entitätstyp, der eine Rolle repräsentiert
Rolle Eine Rolle fasst Berechtigungen und/oder weitere Rollen zusammen.
RRR restricted repeatable read (Wiederholbarkeitseigenschaft von Methoden)
SessionTicket Entitätstyp, der einen authentifizierten Benutzer bzw. dessen Sitzung
repräsentiert
Sitzung Eine Sitzung existiert vom Zeitpunkt der Anmeldung des Benutzers am Sys-
tem bis zu seiner Abmeldung. Während der Sitzung ist unter Umständen nur
eine Teilmenge der möglichen Zugriffsrechte aktiv.
SQL Structured Query Language; Abfragesprache für relationale Datenbanken
UML Unified Modeling Language
URL Uniform Resource Locator
URR unrestricted repeatable read (Wiederholbarkeitseigenschaft von Methoden)
User Entitätstyp, der einen Benutzer repräsentiert
UserGroup Entitätstyp, der eine Gruppe repräsentiert
VDM Vienna Development Method; eine formale Spezifikationsmethode
Z eine formale Spezifikationssprache
Zugriffskontrolle Maßnahmen, die sicherstellen, dass niemand unerlaubt auf Ressour-
cen zugreift.
71
A. Glossar
Resource
AbstractUser
Group
User
Entitätstypen der
Basic-/AdvancedAuthorization
Operation
AccessibleObjectType
AccessibleObject
Accessor
UserGroup
User
Entitätstypen und
Schnittstellen der
QuasarAuthorization
Berechtigung
Operation
Schutzobjekttyp
Schutzobjekt
Benutzergruppe
Benutzer
Begriffe aus der
Dokumentation der
QuasarAuthorization
Permission
Action
Permission
Principal
Principal
JAAS-Begriffe
Tabelle A.1.: Gegenüberstellung der Synonyme
Operation
Permission
Subjekt,
Benutzer
Gruppe
Right
Berechtigungsgruppe
Objekt,
Ressource
Zugriffsart,
Operation
Berechtigung
PermissionGroup
Randbedingung
Role
AccessRestriction
Randbedingungsparameter
Rolle
RestrictionParameter
72
B. QSL-Spezifikationen
Nachfolgend sind die Spezifikationen aller Entitätstypen und Schnittstellen der Komponentenentwürfe abgedruckt. Die Anordnung der Methoden innerhalb der basicQueries-, derivedQueries- und commands-Sektionen erfolgt alphabetisch nach dem
Methodennamen.
Dieser Arbeit liegt eine CD bei, die die Spezifikationsdokumente als Textdateien
enthält.
B.1. Entitätstypen der Basic-/AdvancedAuthorization
interface A u t h o r i z a t i o n E n t i t y
2
basicQueries
4
6
boolean equals ( const Object object )
post r e s u l t == ( o b j e c t i n s t a n c e o f A u t h o r i z a t i o n E n t i t y and
t h i s . getName ( ) . equalsIgnoreCase ( o b j e c t . getName ( ) ) )
8
10
S t r i n g getName()
post r e s u l t != n u l l
interface AbstractUser extends A u t h o r i z a t i o n E n t i t y
interface User extends AbstractUser
2
basicQueries
4
6
boolean equals ( const Object object )
post r e s u l t == true => o b j e c t i n s t a n c e o f User
// s t r e n g t h e n e d p o s t c o n d i t i o n
interface Group extends AbstractUser
2
basicQueries
4
6
boolean equals ( const Object object )
post r e s u l t == true => o b j e c t i n s t a n c e o f Group
// s t r e n g t h e n e d p o s t c o n d i t i o n
73
B. QSL-Spezifikationen
interface AbstractRight extends A u t h o r i z a t i o n E n t i t y
interface Right extends AbstractRight
2
basicQueries
4
boolean equals ( const Object object )
post r e s u l t == true => o b j e c t i n s t a n c e o f Right
// s t r e n g t h e n e d p o s t c o n d i t i o n
6
interface Role extends AbstractRight
2
basicQueries
4
boolean equals ( const Object object )
post r e s u l t == true => o b j e c t i n s t a n c e o f Role
// s t r e n g t h e n e d p o s t c o n d i t i o n
6
interface Resource extends A u t h o r i z a t i o n E n t i t y
2
basicQueries
4
boolean equals ( const Object object )
post r e s u l t == true => o b j e c t i n s t a n c e o f Resource
// s t r e n g t h e n e d p o s t c o n d i t i o n
6
interface Operation extends A u t h o r i z a t i o n E n t i t y
2
basicQueries
4
boolean equals ( const Object object )
post r e s u l t == true => o b j e c t i n s t a n c e o f Operation
// s t r e n g t h e n e d p o s t c o n d i t i o n
6
interface Assignment
2
uses AbstractRight
4
basicQueries
6
boolean equals ( Object object )
post r e s u l t == ( o b j e c t i n s t a n c e o f Assignment and
t h i s . getRight ( ) . equals ( o b j e c t . getRight ( ) ) and
t h i s . i s P o s i t i v e () == o b j e c t . i s P o s i t i v e () and
t h i s . isMandatory () == o b j e c t . isMandatory ()
)
8
10
12
74
B.2. Schnittstellen der BasicAuthorization
14
16
18
20
22
24
AbstractRight getRight ()
// r e t u r n s the a s s i g n e d r i g h t or r o l e .
post r e s u l t != n u l l
boolean isMandatory ()
// t r u e : The a s s i g n e d r i g h t or r o l e must always be a c t i v e in s e s s i o n s .
// f a l s e : The user may l e a v e the a s s i g n e d r i g h t or r o l e i n a c t i v e .
boolean i s P o s i t i v e ()
// t r u e : The a s s i g n e d r i g h t or r o l e a c t s p e r m i s s i v e .
// f a l s e : The a s s i g n e d r i g h t or r o l e a c t s p r o h i b i t i v e .
interface SessionTicket
2
uses User
4
basicQueries
6
8
User getUser ()
// r e t u r n s the user to whom t h i s t i c k e t be l on g s .
post r e s u l t != n u l l
B.2. Schnittstellen der BasicAuthorization
Operativer Betrieb
interface Authentication
2
uses User
4
basicQueries
6
8
10
12
User authenticate ( const String username , const String password)
// a u t h e n t i c a t e s the user ' username ' by means o f ' password ' and r e t u r n s
// an a p p r o p r i a t e User−o b j e c t on s u c c e s s .
post
r e s u l t . getName ( ) . equals (username)
error a u t h e n t i c a t i o n F a i l e d
// There i s no user r e g i s t e r e d by t h i s name , or the password i s
// i n c o r r e c t .
interface AuthorizationCheck
2
uses Operation , User
4
basicQueries
6
75
B. QSL-Spezifikationen
boolean mayPerform( const Object resource ,
const Operation operation ,
const User user )
// r e t u r n s t r u e i f ' user ' i s permitted to perform ' operation ' on
// ' r e s o u r c e ' and f a l s e o t h e r w i s e .
error unmanagedObject // ' r e s o u r c e ' i s not under a c c e s s c o n t r o l .
8
10
12
Instrumentierung
interface ResourceDefinition
2
uses Operation , Resource
4
basicQueries
6
boolean existResource ( const Resource resource )
// I s ' r e s o u r c e ' v a l i d ?
8
pre
existResource ( resource )
List<Operation> getOperations (Resource resource )
// r e t u r n s a l l a p p r o p r i a t e o p e r a t i o n s f o r ' r e s o u r c e ' .
post r e s u l t != n u l l
10
12
14
Resource getResource ( const Object object )
// maps a g e n e r a l o b j e c t to a r e s o u r c e e n t i t y . I f no mapping can be
// determined , n u l l i s returned .
// I f s e v e r a l o b j e c t s are mapped to the same r e s o u r c e , they are t r e a t e d
// s i m i l a r l y in terms o f a c c e s s c o n t r o l .
// Every r e s o u r c e has an i d e n t i f y i n g name . C l a s s names , o b j e c t IDs or
// a p p l i c a t i o n l e v e l keys such as account numbers are t y p i c a l examples
// o f r e s o u r c e names . The c h o i c e o f the name e v e n t u a l l y a f f e c t s the
// g r a n u l a r i t y o f a c c e s s c o n t r o l measures .
post r e s u l t != n u l l => existResource ( r e s u l t )
16
18
20
22
24
derivedQueries
26
pre
getResource ( o b j e c t ) != n u l l
List<Operation> getOperations ( Object object )
// r e t u r n s a l l a p p r o p r i a t e o p e r a t i o n s f o r ' o b j e c t ' .
post r e s u l t != n u l l
post r e s u l t . equals ( getOperations ( getResource ( o b j e c t ) ) )
28
30
32
Administration
interface UserAdmin extends AuthorizationCheck
2
76
B.2. Schnittstellen der BasicAuthorization
uses AbstractRight , AbstractUser , Group , User
4
6
8
10
variables AbstractUser ancestor , aUser ;
AbstractRight aRight ; Right r ;
Group g ; User u ;
Object resource ;
Operation operation ;
Authentication aut ; AuthorizationAdmin admin ;
ResourceDefinition rDef ;
12
basicQueries
14
16
18
20
22
24
26
28
30
32
34
boolean existAbstractUser ( const AbstractUser user )
// I s ' user ' a v a l i d user or group?
pre
e x i s t A b s t r a c t U s e r ( user )
List<Group> getParents ( const AbstractUser user )
// r e t u r n s a l l groups o f which ' user ' i s an immediate member .
post r e s u l t != n u l l
post f o r a l l g in r e s u l t : e x i s t A b s t r a c t U s e r (g)
pre
e x i s t A b s t r a c t U s e r ( user )
List<AbstractRight> getRights ( const AbstractUser user )
// r e tu r n a l l r i g h t s and r o l e s immediately a s s i g n e d to ' user ' .
post r e s u l t != n u l l
post f o r a l l aRight in r e s u l t : admin . e x i s t A b s t r a c t R i g h t ( aRight )
derivedQueries
pre
e x i s t A b s t r a c t U s e r ( user )
List<AbstractUser> getClosure ( const AbstractUser user )
post user in r e s u l t
// r e t u r n s the c l o s u r e o f ' user ' . ( s e e i n v a r i a n t s )
36
commands
38
40
42
44
46
48
pre
e x i s t A b s t r a c t U s e r ( user )
pre
group not in getParents ( user )
pre
user not in getClosure ( group ) // p r e v e n t c y c l e s
void addUser( const AbstractUser user , Group group)
// makes ' user ' an immediate member o f ' group ' .
post group in getParents ( user )
pre
e x i s t A b s t r a c t U s e r ( user )
void changePassword( const User user , const String password)
// a s s i g n s a new password to ' user ' .
post aut . a u th en t ic a te ( user . getName ( ) , password ) . equals ( user )
50
77
B. QSL-Spezifikationen
Group createGroup ( const String groupname)
// d e f i n e s a new group .
post
existAbstractUser ( result )
post
r e s u l t . getName ( ) . equals (groupname)
error duplicateName // group e x i s t s already
52
54
56
User createUser ( const String username , const String password)
// r e g i s t e r s a new user .
post
existAbstractUser ( result )
post
r e s u l t . getName ( ) . equals (username)
post
aut . a ut h en t icate (username , password ) . equals ( r e s u l t )
error duplicateName // user e x i s t s already
58
60
62
pre
e x i s t A b s t r a c t U s e r ( group )
void deleteGroup (Group group)
// d e l e t e s the group ( but not the u s e r s and subgroups i t c o n t a i n s ) .
post not e x i s t A b s t r a c t U s e r ( group )
64
66
68
pre
e x i s t A b s t r a c t U s e r ( user )
void deleteUser (User user )
// d e l e t e s the user from the system .
post not e x i s t A b s t r a c t U s e r ( user )
70
72
pre
admin . e x i s t A b s t r a c t R i g h t ( r i g h t )
pre
e x i s t A b s t r a c t U s e r ( user )
pre
r i g h t not in getRights ( user )
void grant ( const AbstractRight right , const AbstractUser user )
// e x p l i c i t l y g ra n ts ' r i g h t ' to ' user ' .
post r i g h t in getRights ( user )
74
76
78
80
pre
group in getParents ( user )
void removeUser( const AbstractUser user , Group group)
// removes ' user ' from ' group ' .
post group not in getParents ( user )
82
84
pre
admin . e x i s t A b s t r a c t R i g h t ( r i g h t )
pre
e x i s t A b s t r a c t U s e r ( user )
pre
r i g h t in getRights ( user )
void withdraw( const AbstractRight right , const AbstractUser user )
// r e v e r s e s the e f f e c t o f ' grant ( r i g h t , user ) ' .
post r i g h t not in getRights ( user )
86
88
90
92
invariants
94
// The c l o s u r e o f an a b s t r a c t user c o n s i s t s o f i t s e l f and a l l groups
// c o n t a i n i n g at l e a s t one element o f i t s c l o s u r e .
ancestor in getClosure ( aUser ) <=> (
ancestor . equals ( aUser ) or
96
98
78
B.2. Schnittstellen der BasicAuthorization
e x i s t s g in getParents ( aUser ) : ancestor in getClosure (g)
100
)
102
// A use r may perform an op eration on a r e s o u r c e , i f a matching r i g h t
// ( or an element o f the c l o s u r e o f a matching r i g h t ) i s a s s i g n e d to an
// element o f the user ' s c l o s u r e .
mayPerform( resource , operation , u) <=> (
operation in rDef . getOperations ( resource ) and
( e x i s t s aUser , aRight , r :
aUser in getClosure (u) and
aRight in getRights ( aUser ) and
aRight in admin . getClosure ( r ) and
admin . getResource ( r ) . equals (
rDef . getResource ( resource )) and
admin . getOperation ( r ) . equals ( operation )
)
)
104
106
108
110
112
114
116
testcases
118
120
unsuccessfulChecks
Object managed , unmanaged ;
pre rDef . getResource (unmanaged) == n u l l
pre rDef . getResource (managed) != n u l l
pre operation not in rDef . getOperations (managed)
mayPerform(unmanaged , operation , u) −> error unmanagedObject
mayPerform(managed , operation , u)
−> f a l s e
122
124
126
interface AuthorizationAdmin
2
uses AbstractRight , Role , Right
4
6
variables AbstractRight ancestor , aRight ;
Role r ;
ResourceDefinition rDef ;
8
basicQueries
10
12
14
16
boolean existAbstractRight ( const AbstractRight right )
// I s ' r i g h t ' a v a l i d r i g h t or r o l e ?
pre
existAbstractRight ( right )
Operation getOperation ( const Right right )
// r e t u r n s the o p e ra t io n belonging to ' r i g h t ' .
post r e s u l t != n u l l
18
pre
existAbstractRight ( right )
79
B. QSL-Spezifikationen
List<Role> getParents ( const AbstractRight right )
// r e t u r n s a l l r o l e s o f which ' r i g h t ' i s an immediate member .
post r e s u l t != n u l l
post f o r a l l r in r e s u l t : e x i s t A b s t r a c t R i g h t ( r )
20
22
24
pre
existAbstractRight ( right )
Resource getResource ( const Right right )
// r e t u r n s the r e s o u r c e belonging to ' r i g h t ' .
post r e s u l t != n u l l
26
28
derivedQueries
30
pre
existAbstractRight ( right )
List<AbstractRight> getClosure ( const AbstractRight right )
post r i g h t in r e s u l t
// r e t u r n s the c l o s u r e o f ' r i g h t ' . ( s e e i n v a r i a n t )
32
34
36
commands
38
pre
existAbstractRight ( right )
pre
r o l e not in getParents ( r i g h t )
pre
r i g h t not in getClosure ( r o l e ) // p r e v e n t c y c l e s
void addRight( const AbstractRight right , Role role )
// makes ' r i g h t ' an immediate member o f ' r o l e ' .
post r o l e in getParents ( r i g h t )
40
42
44
pre
rDef . existResource ( resource )
pre
operation in rDef . getOperations ( resource )
Right createRight ( const String rightname , const Resource resource ,
const Operation operation )
// d e f i n e s a new r i g h t .
post
existAbstractRight ( result )
post
r e s u l t . getName ( ) . equals ( rightname )
post
getResource ( r e s u l t ) . equals ( resource )
post
getOperation ( r e s u l t ) . equals ( operation )
error duplicateName // r i g h t e x i s t s already
46
48
50
52
54
56
Role createRole ( const String rolename)
// d e f i n e s a new r o l e .
post
existAbstractRight ( result )
post
r e s u l t . getName ( ) . equals ( rolename )
error duplicateName // r o l e e x i s t s already
58
60
62
pre
existAbstractRight ( right )
void deleteRight ( Right right )
// d e l e t e s the r i g h t .
post not e x i s t A b s t r a c t R i g h t ( r i g h t )
64
66
80
B.3. Schnittstellen der AdvancedAuthorization
68
70
pre
existAbstractRight ( role )
void deleteRole (Role role )
// d e l e t e s the r o l e ( but not the r i g h t s and s u b r o l e s i t c o n t a i n s ) .
post not e x i s t A b s t r a c t R i g h t ( r o l e )
72
74
76
78
80
82
84
pre
r o l e in getParents ( r i g h t )
void removeRight( const AbstractRight right , Role role )
// removes ' r i g h t ' from ' r o l e ' .
post r o l e not in getParents ( r i g h t )
invariants
// The c l o s u r e o f an a b s t r a c t r i g h t c o n s i s t s o f i t s e l f and a l l r o l e s
// c o n t a i n i n g at l e a s t one element o f i t s c l o s u r e .
ancestor in getClosure ( aRight ) <=> (
ancestor . equals ( aRight ) or
e x i s t s r in getParents ( aRight ) : ancestor in getClosure ( r )
)
B.3. Schnittstellen der AdvancedAuthorization
Technische Umgebung
interface Repository
2
4
uses AbstractUser , User , Group ,
AbstractRight , Right , Role ,
Assignment
6
basicQueries
8
// methods f o r the loading o f p e r s i s t e n t e n t i t i e s
10
List<Group> getAllGroups ()
12
List<Right> getAllRights ()
14
List<Role> getAllRoles ()
16
List<User> getAllUsers ()
18
List<Assignment> getAssignments ( const AbstractUser user )
20
List<AbstractRight> getMembers( const Role role )
22
List<Group> getParents ( const AbstractUser user )
81
B. QSL-Spezifikationen
24
Map getProperties ( const AbstractRight right )
26
Map getProperties ( const AbstractUser user )
28
30
commands
32
// methods f o r the s t o r i n g o f p e r s i s t e n t e n t i t i e s
34
void setAllGroups ( const List<Group> groups)
post getAllGroups ( ) . equals ( groups )
36
void setAllRights ( const List<Right> rights )
post g e t A l l R i g h t s ( ) . equals ( r i g h t s )
38
40
void setAllRoles ( const List<Role> roles )
post g e t A l l R o l e s ( ) . equals ( r o l e s )
42
void setAllUsers ( const List<User> users )
post g e t A l l U s e r s ( ) . equals ( users )
44
46
void setAssignments ( const AbstractUser user ,
const List<Assignment> assignments )
post getAssignments ( user ) . equals ( assignments )
48
50
void setMembers( const Role role , const List<AbstractRight> members)
post getMembers( r o l e ) . equals (members)
52
void setParents ( const AbstractUser user , const List<Group> parents )
post getParents ( user ) . equals ( parents )
54
56
void setProperties ( AbstractUser user , const Map properties )
post g e t P r o p e r t i e s ( user ) . equals ( p r o p e r t i e s )
58
void setProperties ( AbstractRight right , const Map properties )
post g e t P r o p e r t i e s ( r i g h t ) . equals ( p r o p e r t i e s )
60
interface Logging
2
commands
4
void accessDenied ( const Date timestamp , const SessionTicket ticket ,
const Resource resource , const Operation operation )
// l o g s an a u t h o r i z a t i o n check with a n e g a t i v e r e s u l t .
6
8
void accessGranted ( const Date timestamp , const SessionTicket ticket ,
82
B.3. Schnittstellen der AdvancedAuthorization
10
const Resource resource , const Operation operation )
// l o g s an a u t h o r i z a t i o n check with a p o s i t i v e r e s u l t .
12
14
16
18
20
void login ( const Date timestamp , const SessionTicket t i c k e t )
// l o g s the beginning o f a s e s s i o n .
void loginFailed ( const Date timestamp , const String message)
// l o g s a f a i l e d attempt to s t a r t a s e s s i o n . An a r b i t r a r y ' message ' may
// d e s c r i b e the reason f o r the f a i l u r e .
void logout ( const Date timestamp , const SessionTicket t i c k e t )
// l o g s the ending o f a s e s s i o n .
Operativer Betrieb
interface SessionManagement
2
uses SessionTicket
4
variables SessionTicket t ;
6
basicQueries
8
10
12
boolean isValid ( SessionTicket t i c k e t ) NRR
// r e t u r n s t r u e i f ' t i c k e t ' i s v a l i d or f a l s e o t h e r w i s e .
SessionTicket login () NRR
// r e t u r n s a S e s s i o n T i c k e t or n u l l i f no s e s s i o n could be e s t a b l i s h e d .
14
commands
16
18
void logout ( const SessionTicket t i c k e t )
// i n v a l i d a t e s ' t i c k e t ' .
post not i s V a l i d ( t i c k e t )
20
22
void logoutAll ( const SessionTicket t i c k e t )
// i n v a l i d a t e s a l l t i c k e t s belonging to the user o f ' t i c k e t ' .
post t . getUser ( ) . equals ( t i c k e t . getUser ( ) ) => not i s V a l i d ( t )
interface AuthorizationCheck
2
uses Operation , User
4
variables SessionManagement sm;
6
basicQueries
8
83
B. QSL-Spezifikationen
boolean mayPerform( const Object resource ,
const Operation operation ,
const SessionTicket t i c k e t )
// r e t u r n s t r u e i f the user a s s o c i a t e d with ' t i c k e t ' i s permitted to
// perform ' operation ' on ' r e s o u r c e ' and f a l s e o t h e r w i s e .
error not sm . i s V a l i d ( t i c k e t ) => i n v a l i d T i c k e t
error unmanagedObject // ' r e s o u r c e ' i s not under a c c e s s c o n t r o l .
10
12
14
Instrumentierung
interface Authentication
2
uses Assignment , User
4
variables i n t i ;
6
basicQueries
8
boolean [] getActiveRights ( const User user ,
const List<Assignment> assignedRights )
// r e t u r n s an array o f f l a g s , one f o r each element o f ' a s s i g n e d R i g h t s ' .
// For any ' r e s u l t [ i ] ' s e t to true , ' a s s i g n e d R i g h t s . g e t ( i ) ' i s supposed
// to be a c t i v e during ' user ' s next s e s s i o n .
// At l e a s t t h o s e assignments marked as mandatory have to be a c t i v e .
post r e s u l t . length == assignedRights . s i z e ()
post f o r a l l i : 0 <= i < r e s u l t . length :
assignedRights . get ( i ) . isMandatory () => r e s u l t [ i ] == true
10
12
14
16
18
User getAuthenticatedUser ()
// r e t u r n s an a u t h e n t i c a t e d user or n u l l i f no user could be
// a u t h e n t i c a t e d .
20
interface ResourceDefinition
2
uses Operation , Resource
4
basicQueries
6
boolean existResource ( const Resource resource )
// I s ' r e s o u r c e ' v a l i d ?
8
pre
existResource ( resource )
List<Resource> getClosure ( const Resource resource )
post resource in r e s u l t
// r e t u r n s the c l o s u r e o f ' r e s o u r c e ' .
// The r e s u l t c o n s i s t s o f a l l r e s o u r c e s whose a c c e s s r i g h t s hold f o r
// ' r e s o u r c e ' . I f a user i s ( not ) permitted to perform a c e r t a i n
10
12
14
84
B.3. Schnittstellen der AdvancedAuthorization
16
18
20
22
24
26
//
//
//
//
//
//
//
o p er a ti o n on an element o f the c l o s u r e , the user i s ( not ) permitted
to perform t h i s o p e ra t io n on ' r e s o u r c e ' as w e l l .
The c l o s u r e i s ordered . In c a s e o f a c o n f l i c t between p o s i t i v e and
n e g a t i v e r i g h t assignments within the c l o s u r e , the foremost r e s o u r c e
in the l i s t t a k e s p r e c e d e n c e .
Usually , i f the r e s o u r c e s o f a system are h i e r a r c h i c a l l y organized as
a t r e e , the c l o s u r e r e p r e s e n t s a path within t h i s t r e e .
pre
existResource ( resource )
List<Operation> getOperations ( const Resource resource )
// r e t u r n s a l l a p p r o p r i a t e o p e r a t i o n s f o r ' r e s o u r c e ' .
post r e s u l t != n u l l
28
30
32
34
36
38
40
List<Operation> getPermissiveClosure ( const Operation operation )
// r e t u r n s a l l o p e r a t i o n s t hat are e q u i v a l e n t to ' operation ' as f a r as
// p o s i t i v e a c c e s s r i g h t s are concerned .
// I f a user i s permitted to perform an operation contained in the
// c l o s u r e , the user i s permitted to perform ' operation ' as w e l l .
post operation in r e s u l t
List<Operation> getProhibitiveClosure ( const Operation operation )
// r e t u r n s a l l o p e r a t i o n s t hat are e q u i v a l e n t to ' operation ' as f a r as
// n e g a t i v e a c c e s s r i g h t s are concerned .
// I f a user i s not permitted to perform an operation contained in the
// c l o s u r e , the user i s not permitted to perform ' operation ' as w e l l .
post operation in r e s u l t
42
44
46
48
50
52
54
56
58
60
62
Resource getResource ( const Object object )
// maps a g e n e r a l o b j e c t to a r e s o u r c e e n t i t y . I f no mapping can be
// determined , n u l l i s returned .
// I f s e v e r a l o b j e c t s are mapped to the same r e s o u r c e , they are t r e a t e d
// s i m i l a r l y in terms o f a c c e s s c o n t r o l .
// Every r e s o u r c e has an i d e n t i f y i n g name . C l a s s names , o b j e c t IDs or
// a p p l i c a t i o n l e v e l keys such as account numbers are t y p i c a l examples
// o f r e s o u r c e names . The c h o i c e o f the name e v e n t u a l l y a f f e c t s the
// g r a n u l a r i t y o f a c c e s s c o n t r o l measures .
post r e s u l t != n u l l => existResource ( r e s u l t )
derivedQueries
pre
getResource ( o b j e c t ) != n u l l
List<Resource> getClosure ( const Object object )
// r e t u r n s the r e s o u r c e c l o s u r e o f ' o b j e c t ' .
// ( s e e ' g e t C l o s u r e ( Resource ) ' )
post r e s u l t . equals ( getClosure ( getResource ( o b j e c t ) ) )
pre
getResource ( o b j e c t ) != n u l l
List<Operation> getOperations ( Object object )
85
B. QSL-Spezifikationen
// r e t u r n s a l l a p p r o p r i a t e o p e r a t i o n s f o r ' o b j e c t ' .
post r e s u l t . equals ( getOperations ( getResource ( o b j e c t ) ) )
64
interface P o l i c y
2
uses AbstractUser , Assignment
4
variables UserAdmin uAdmin ;
6
basicQueries
8
pre
uAdmin . e x i s t A b s t r a c t U s e r ( user )
List<Assignment> getLinearization ( const AbstractUser user )
// r e t u r n s the l i n e a r i z a t i o n ( t o t a l o r d e r i n g ) o f a l l a s s i g n e d r i g h t s o f
// ' user ' , taking i n t o account d i r e c t and i n d i r e c t a s s o c i a t i o n s .
// The l i s t i s ordered with descending p r i o r i t y .
// S u b i n t e r f a c e s may s p e c i f y the l i n e a r i z a t i o n r u l e s .
post
r e s u l t != n u l l
error c o n f l i c t s W i t h P o l i c y // ' user ' s a s s i g n e d r i g h t s are not
// c o n s i s t e n t in terms o f the p o l i c y .
10
12
14
16
18
boolean mayPerformByDefault ()
// t r u e : A c c e s s i s granted u n l e s s a n e g a t i v e r i g h t i s a s s i g n e d .
// f a l s e : A c c e s s i s denied u n l e s s a p o s i t i v e r i g h t i s a s s i g n e d .
20
interface P o s i t i v e O v e r r i d e P o l i c y extends P o l i c y
2
uses AbstractUser , Assignment
4
6
variables AbstractUser aUser ; Assignment a , aPos , aNeg ;
Group g ; UserAdmin uAdmin ;
8
basicQueries
pre
uAdmin . e x i s t A b s t r a c t U s e r ( user )
List<Assignment> getLinearization ( const AbstractUser user )
// r e t u r n s the l i n e a r i z a t i o n ( t o t a l o r d e r i n g ) o f a l l a s s i g n e d r i g h t s o f
// ' user ' , a s s u r i n g that a l l p o s i t i v e assignments p r e c e d e a l l n e g a t i v e
// assignments .
post r e s u l t != n u l l
post f o r a l l aPos , aNeg in r e s u l t :
aPos . i s P o s i t i v e () and not aNeg . i s P o s i t i v e () =>
r e s u l t . indexOf ( aPos ) < r e s u l t . indexOf (aNeg)
10
12
14
16
18
boolean mayPerformByDefault ()
// A c c e s s i s denied u n l e s s a p o s i t i v e r i g h t i s a s s i g n e d .
post r e s u l t == f a l s e
20
22
86
B.3. Schnittstellen der AdvancedAuthorization
24
26
28
30
32
invariants
// D e f i n e the c o n t e n t s o f the l i n e a r i z a t i o n l i s t : I t i s the union o f the
// d i r e c t l y a s s i g n e d r i g h t s and o f a l l l i s t s belonging to elements o f
// the c l o s u r e o f the user /group ( i t s d i r e c t and i n d i r e c t parents ) .
a in g e t L i n e a r i z a t i o n ( aUser ) <=> (
a in uAdmin . getAssignments ( aUser ) or
e x i s t s g in uAdmin . getParents ( aUser ) : a in g e t L i n e a r i z a t i o n (g)
)
Administration
interface UserAdmin extends AuthorizationCheck
2
4
6
8
10
12
14
16
uses AbstractRight , AbstractUser , Assignment , Group , User ,
Resource , Operation , SessionTicket
variables AbstractUser ancestor , aUser ;
Assignment a ;
Right r ;
Group g ;
Object o b j e c t ;
Operation op ;
Resource r e s ;
AuthorizationAdmin aAdmin ;
Policy policy ;
ResourceDefinition rDef ;
SessionTicket s T i c k e t ;
L i s t<Assignment> a L i s t ;
18
basicQueries
20
22
24
boolean existAbstractUser ( const AbstractUser user )
// I s ' user ' a v a l i d user or group?
List<Assignment> getAssignments ( const AbstractUser user )
// r e t u r n s a l l immediate r i g h t assignments o f ' user ' .
26
28
30
32
34
List<Assignment> getCapabilityList ( const SessionTicket t i c k e t )
// r e t u r n s ( in l i n e a r i z e d form ) a l l r i g h t assignments that are a c t i v e
// in the s e s s i o n r e p r e s e n t e d by ' t i c k e t ' .
post r e s u l t != n u l l
pre
e x i s t A b s t r a c t U s e r ( user )
List<Group> getParents ( const AbstractUser user )
// r e t u r n s a l l groups o f which ' user ' i s an immediate member .
post r e s u l t != n u l l
87
B. QSL-Spezifikationen
36
post
38
pre e x i s t A b s t r a c t U s e r ( user )
Map getProperties ( const AbstractUser user )
// r e t u r n s the p r o p e r t i e s a s s o c i a t e d with ' user ' or n u l l i f
// no p r o p e r t i e s .
40
f o r a l l g in r e s u l t : e x i s t A b s t r a c t U s e r (g)
' user ' has
42
pre not l i s t . isEmpty ()
pre aAdmin . e x i s t A b s t r a c t R i g h t ( l i s t . get ( 0 ) . getRight ( ) )
pre rDef . existResource ( resource )
pre operation in rDef . getOperations ( resource )
boolean isHeadApplicable ( const List<Assignment> l i s t ,
const Resource resource ,
const Operation operation )
// h e l p e r method f o r s p e c i f y i n g ' l i s t G r a n t s A c c e s s ' ; r e t u r n s t r u e i f the
// head ( f i r s t element ) o f ' l i s t ' concerns ' r e s o u r c e ' and ' operation '
// ( or elements o f t h e i r c l o s u r e s ) and f a l s e o t h e r w i s e .
44
46
48
50
52
pre
rDef . existResource ( resource )
pre
operation in rDef . getOperations ( resource )
boolean listGrantsAccess ( const Resource resource ,
const Operation operation ,
const List<Assignment> l i s t )
// h e l p e r method f o r s p e c i f y i n g ' mayPerform ' ( s e e i n v a r i a n t s ) ;
// ' l i s t ' i s searched u n t i l an a p p l i c a b l e element i s found . I f none i s
// found , the d e f a u l t d e c i s i o n i s returned .
post l i s t . isEmpty () => r e s u l t == p o l i c y . mayPerformByDefault ()
post not isHeadApplicable ( l i s t , resource , operation )
=> r e s u l t == l i s t G r a n t s A c c e s s ( resource , operation ,
l i s t . s u b L i s t (1 , l i s t . s i z e ( ) ) )
post isHeadApplicable ( l i s t , resource , operation ) and
l i s t . get ( 0 ) . i s P o s i t i v e () => r e s u l t == true
post isHeadApplicable ( l i s t , resource , operation ) and
l i s t . get ( 0 ) . isNegative () => r e s u l t == f a l s e
54
56
58
60
62
64
66
68
70
derivedQueries
72
pre
e x i s t A b s t r a c t U s e r ( user )
List<AbstractUser> getClosure ( const AbstractUser user )
post user in r e s u l t
// r e t u r n s the c l o s u r e o f ' user ' . ( s e e i n v a r i a n t s )
74
76
commands
78
pre
pre
pre
pre
80
82
88
e x i s t A b s t r a c t U s e r ( user )
group not in getParents ( user )
user not in getClosure ( group ) // p r e v e n t c y c l e s
0 <= index <= getParents ( user ) . s i z e ()
B.3. Schnittstellen der AdvancedAuthorization
84
86
88
90
void addUser( const AbstractUser user , Group group , i n t index )
// makes ' user ' an immediate member o f ' group ' . ' group ' i s i n s e r t e d in
// the l i s t o f ' user ' s pa r e nts at p o s i t i o n ' index ' , p r e s e r v i n g the
// order o f e x i s t i n g elements .
post
getParents ( user ) . get ( index ) . equals ( group )
post
getParents ( user ) . s i z e () == 1 + ' getParents ( user ) . s i z e ()
error c o n f l i c t s W i t h P o l i c y // The a d d i t i o n o f ' user ' to ' group ' does
// not comply with the a u t h o r i z a t i o n p o l i c y .
92
94
96
98
100
102
104
106
108
110
pre
pre
pre
e x i s t A b s t r a c t U s e r ( user )
aAdmin . e x i s t A b s t r a c t R i g h t ( r i g h t )
not e x i s t s a : a in getAssignments ( user ) and
a . getRight ( ) . equals ( r i g h t )
pre
0 <= index <= getAssignments ( user ) . s i z e ()
Assignment assignRight ( const AbstractUser user ,
const AbstractRight right ,
boolean positive , boolean mandatory , i n t index )
// a s s i g n s ' r i g h t ' to ' user ' e i t h e r as a p o s i t i v e or a n e g a t i v e r i g h t
// and d e f i n e s , i f t h i s assignment i s mandatory in e v e r y s e s s i o n that
// ' user ' i n i t i a t e s . The r e s u l t i s i n s e r t e d in the l i s t o f ' user ' s
// assignments , p r e s e r v i n g the order o f e x i s t i n g elements .
post
r e s u l t . getRight ( ) . equals ( r i g h t )
post
r e s u l t . i s P o s i t i v e == p o s i t i v e
post
r e s u l t . isMandatory == mandatory
post
r e s u l t . equals ( getAssignments ( user ) . get ( index ))
post
getAssignments ( user ) . s i z e () == 1 + ' getAssignments ( user ) . s i z e ()
error c o n f l i c t s W i t h P o l i c y // This r i g h t assignment does not comply
// with the a u t h o r i z a t i o n p o l i c y .
112
114
116
Group createGroup ( const String groupname)
// d e f i n e s a new group .
post
existAbstractUser ( result )
post
r e s u l t . getName ( ) . equals (groupname)
error duplicateName // group e x i s t s already
118
120
122
User createUser ( const String username)
// r e g i s t e r s a new user .
post
existAbstractUser ( result )
post
r e s u l t . getName ( ) . equals (username)
error duplicateName // user e x i s t s already
124
126
128
130
pre
e x i s t A b s t r a c t U s e r ( group )
void deleteGroup (Group group)
// d e l e t e s the group ( but not the u s e r s and subgroups i t c o n t a i n s ) .
post not e x i s t A b s t r a c t U s e r ( group )
pre
e x i s t A b s t r a c t U s e r ( user )
void deleteUser (User user )
89
B. QSL-Spezifikationen
// d e l e t e s the user from the system .
post not e x i s t A b s t r a c t U s e r ( user )
132
134
void removeAssignment( const AbstractUser user , i n t index )
// removes the element at p o s i t i o n ' index ' from the l i s t o f ' user ' s
// assignments .
post ' getAssignments ( user ) . get ( index ) not in getAssignments ( user )
post getAssignments ( user ) . s i z e () == ' getAssignments ( user ) . s i z e () − 1
136
138
140
pre
group in getParents ( user )
pre
0 <= index < getParents ( user ) . s i z e ()
void removeUser( const AbstractUser user , Group group)
// removes ' user ' from ' group ' .
post group not in getParents ( user )
post getParents ( user ) . s i z e () == ' getParents ( user ) . s i z e () − 1
142
144
146
pre
e x i s t A b s t r a c t U s e r ( user )
void setProperties ( AbstractUser user , const Map properties )
// a s s o c i a t e s some a r b i t r a r y p r o p e r t i e s with ' user ' .
post g e t P r o p e r t i e s ( user ) . equals ( p r o p e r t i e s )
148
150
152
invariants
154
// The c l o s u r e o f an a b s t r a c t user c o n s i s t s o f i t s e l f and a l l groups
// c o n t a i n i n g at l e a s t one element o f i t s c l o s u r e .
ancestor in getClosure ( aUser ) <=> (
ancestor . equals ( aUser ) or
e x i s t s g in getParents ( aUser ) : ancestor in getClosure (g)
)
156
158
160
// A user ' s e f f e c t i v e r i g h t s depend on her ( l i n e a r i z e d ) c a p a b i l i t y l i s t .
mayPerform( object , op , s T i c k e t ) <=> (
op in rDef . getOperations ( o b j e c t )
and
l i s t G r a n t s A c c e s s ( rDef . getResource ( o b j e c t ) , op ,
g e t C a p a b i l i t y L i s t ( s T i c k e t ))
)
162
164
166
168
// The f i r s t element o f an assignment l i s t i s a p p l i c a b l e on a given
// r e s o u r c e and operation , i f t h e r e e x i s t s an i n t e r s e c t i o n between
// the c l o s u r e o f the a s s i g n e d r i g h t / r o l e and the c l o s u r e s o f the
// r e s o u r c e and o p e ration .
isHeadApplicable ( a L i s t , res , op) <=> (
e x i s t s r in aAdmin . getClosure ( a L i s t . get ( 0 ) . getRight ( ) ) :
aAdmin . getResource ( r ) in rDef . getClosure ( r e s )
and (
a L i s t . get ( 0 ) . i s P o s i t i v e () and
aAdmin . getOperation ( r ) in rDef . getPermissiveClosure (op)
170
172
174
176
178
90
B.3. Schnittstellen der AdvancedAuthorization
or
a L i s t . get ( 0 ) . isNegative () and
aAdmin . getOperation ( r ) in rDef . g e t P r o h i b i t i v e C l o s u r e (op)
180
182
)
184
)
186
testcases
188
190
unsuccessfulChecks
Object managed , unmanaged ;
Operation rightOp , wrongOp ;
SessionManagement sm;
192
194
196
198
200
pre rDef . getResource (unmanaged) == n u l l
pre rDef . getResource (managed) != n u l l
pre rightOp in rDef . getOperations (managed)
pre wrongOp not in rDef . getOperations (managed)
pre sm . i s V a l i d ( s T i c k e t )
mayPerform(unmanaged , rightOp , s T i c k e t ) −> error unmanagedObject
mayPerform(managed , wrongOp , s T i c k e t )
−> f a l s e
sm . logout ( s T i c k e t )
mayPerform(managed , rightOp , s T i c k e t )
−> error i n v a l i d T i c k e t
interface AuthorizationAdmin
2
uses AbstractRight , Role , Right
4
6
variables AbstractRight aRight , descendant , member;
ResourceDefinition rDef ;
8
basicQueries
10
boolean existAbstractRight ( const AbstractRight right )
// I s ' r i g h t ' a v a l i d r i g h t or r o l e ?
12
14
16
pre
existAbstractRight ( role )
List<AbstractRight> getMembers( const Role role )
// r e t u r n s a l l immediate members ( r i g h t s and s u b r o l e s ) o f ' r o l e ' .
post r e s u l t != n u l l
post f o r a l l aRight in r e s u l t : e x i s t A b s t r a c t R i g h t ( aRight )
18
20
22
24
pre
existAbstractRight ( right )
Operation getOperation ( const Right right )
// r e t u r n s the o p e ra t io n belonging to ' r i g h t ' .
post r e s u l t != n u l l
pre e x i s t A b s t r a c t R i g h t ( r i g h t )
Map getProperties ( const AbstractRight right )
91
B. QSL-Spezifikationen
// r e t u r n s the p r o p e r t i e s a s s o c i a t e d with ' r i g h t ' or n u l l i f
// no p r o p e r t i e s .
26
' r i g h t ' has
28
pre e x i s t A b s t r a c t R i g h t ( r i g h t )
Resource getResource ( const Right right )
// r e t u r n s the r e s o u r c e belonging to ' r i g h t ' .
post r e s u l t != n u l l
30
32
derivedQueries
34
pre
existAbstractRight ( right )
List<AbstractRight> getClosure ( const AbstractRight right )
post r i g h t in r e s u l t
// r e t u r n s the c l o s u r e o f ' r i g h t ' . ( s e e i n v a r i a n t )
36
38
40
commands
42
pre
existAbstractRight ( right )
pre
r i g h t not in getMembers( r o l e )
pre
r o l e not in getClosure ( r i g h t ) // p r e v e n t c y c l e s
void addRight( const AbstractRight right , Role role )
// makes ' r i g h t ' an immediate member o f ' r o l e ' .
post r i g h t in getMembers( r o l e )
44
46
48
pre
rDef . existResource ( resource )
pre
operation in rDef . getOperations ( resource )
Right createRight ( const String rightname , const Resource resource ,
const Operation operation )
// d e f i n e s a new r i g h t .
post
existAbstractRight ( result )
post
r e s u l t . getName ( ) . equals ( rightname )
post
getResource ( r e s u l t ) . equals ( resource )
post
getOperation ( r e s u l t ) . equals ( operation )
error duplicateName // r i g h t e x i s t s already
50
52
54
56
58
60
Role createRole ( const String rolename)
// d e f i n e s a new r o l e .
post
existAbstractRight ( result )
post
r e s u l t . getName ( ) . equals ( rolename )
error duplicateName // r o l e e x i s t s already
62
64
66
pre
existAbstractRight ( right )
void deleteRight ( Right right )
// d e l e t e s the r i g h t .
post not e x i s t A b s t r a c t R i g h t ( r i g h t )
68
70
pre
existAbstractRight ( role )
void deleteRole (Role role )
72
92
B.3. Schnittstellen der AdvancedAuthorization
74
// d e l e t e s the r o l e ( but not the r i g h t s and s u b r o l e s i t c o n t a i n s ) .
post not e x i s t A b s t r a c t R i g h t ( r o l e )
76
78
80
82
84
pre
r i g h t in getMembers( r o l e )
void removeRight( const AbstractRight right , Role role )
// removes ' r i g h t ' from ' r o l e ' .
post r i g h t not in getMembers( r o l e )
pre
existAbstractRight ( right )
void setProperties ( AbstractRight right , const Map properties )
// a s s o c i a t e s some a r b i t r a r y p r o p e r t i e s with ' r i g h t ' .
post g e t P r o p e r t i e s ( r i g h t ) . equals ( p r o p e r t i e s )
86
invariants
88
90
92
94
// The c l o s u r e o f an a b s t r a c t r i g h t c o n s i s t s o f i t s e l f and − i f i t ' s a
// r o l e − o f a l l elements o f the c l o s u r e s o f i t s members .
descendant in getClosure ( aRight ) <=> (
descendant . equals ( aRight ) or
e x i s t s member in getMembers( aRight ) :
descendant in getClosure (member)
)
93
Literaturverzeichnis
[And01]
A NDERSON, Ross J.: Security Engineering : A Guide to Building Dependable
Distributed Systems. New York : Wiley, 2001. – ISBN 0–471–38922–6
[BCH+ 96] B ARRETT, Kim ; C ASSELS, Bob ; H AAHR, Paul ; M OON, David A. ;
P LAYFORD, Keith ; W ITHINGTON, P. T.: A Monotonic Superclass Linearization for Dylan. In: Proceedings of the 11th ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications, ACM Press, 1996. – URL http://www.webcom.com/haahr/dylan/
linearization-oopsla96.html. – ISBN 0–89791–788–X, S. 69–82
[BM93]
B ERTINO, Elisa ; M ARTINO, Lorenzo: Object-Oriented Database Systems :
Concepts and Architectures. Wokingham : Addison-Wesley, 1993. – ISBN
0–201–62439–7
[Dah04]
D AHM, Peter: Quasar Authorization : Anforderungen. Januar 2004. –
sd&m AG (unveröffentlicht)
[Die03]
D IERSTEIN, Rüdiger: Grundlagen der IT-Sicherheit. Vorlesungsunterlagen,
Technische Universität München, Fakultät für Informatik. WS 2002/03.
– URL http://wwwbayer.in.tum.de/lehre/WS2002/ITS-dierstein/
[DMT04]
D ENERT, Ernst ; M ATTHES, Florian ; TAUBNER, Dirk. Betriebliche Informationssysteme und ihre Rolle im Unternehmen. Vorlesungsunterlagen,
Technische Universität München, Fakultät für Informatik. WS 2003/04
[Dre02]
D REHER, Yvonne: Analyse und Entwurf von Berechtigungskomponenten für
betriebliche Informationssysteme, Fachhochschule Konstanz, Diplomarbeit,
2002
[Eck03]
E CKERT, Claudia: IT-Sicherheit : Konzepte – Verfahren – Protokolle. 2.,
überarb. und erw. Aufl. München : Oldenbourg, 2003. – ISBN 3–486–
27205–5
95
Literaturverzeichnis
[FFS87]
F EIGE, Uriel ; F IAT, Amos ; S HAMIR, Adi: Zero Knowledge Proofs of Identity. In: Proceedings of the nineteenth annual ACM conference on Theory of
computing, ACM Press, 1987. – ISBN 0–89791–221–7, S. 210–217
[FS87]
F IAT, Amos ; S HAMIR, Adi: How to Prove Yourself : Practical Solutions to
Identification and Signature Problems. In: Advances in Cryptology – CRYPTO ’86 (Proceedings), Lecture Notes in Computer Science Bd. 263. Berlin :
Springer, 1987. – ISSN 0302–9743, S. 186–194
[FSG+ 01] F ERRAIOLO, David F. ; S ANDHU, Ravi ; G AVRILA, Serban ; KUHN, D. R. ;
C HANDRAMOULI, Ramaswamy: Proposed NIST Standard for Role-Based
Access Control. In: ACM Transactions on Information and System Security
4 (2001), Nr. 3, S. 224–274. – ISSN 1094–9224
[FSW81]
F ERNANDEZ, Eduardo B. ; S UMMERS, Rita C. ; W OOD, Christopher: Database Security and Integrity. Reading, MA : Addison-Wesley, 1981. – ISBN
0–201–14467–0
[GHJV95] G AMMA, Erich ; H ELM, Richard ; J OHNSON, Ralph ; V LISSIDES, John: Design Patterns : Elements of Reusable Object-Oriented Software. Reading, MA
: Addison-Wesley, 1995. – ISBN 0–201–63361–2
[ISO]
NORM ISO/IEC 10181-3:1996. Information technology – Open Systems
Interconnection – Security frameworks for open systems : Access control framework
[JAAa]
JAAS Dokumentation (Sun). – URL http://java.sun.com/products/
jaas/reference/
[JAAb]
JAAS Downloads (Sun). – URL http://java.sun.com/products/jaas/
index-10.html
[JH03a]
J EROMIN, Holger ; H AFT, Martin: Design Rationale : Quasar AuthorizationManager. November 2003. – Version 5.0 – sd&m AG (unveröffentlicht)
[JH03b]
J EROMIN, Holger ; H AFT, Martin: Nutzungskonzept : Quasar Authorization-Manager. November 2003. – Version 4.0 – sd&m AG (unveröffentlicht)
[JML]
The Java Modeling Language (JML). – URL http://www.jmlspecs.org/
[JSS97]
JAJODIA, Sushil ; S AMARATI, Pierangela ; S UBRAHMANIAN, V. S.: A Logical
Language for Expressing Authorizations. In: Proceedings of the 1997 IEEE
Symposium on Security and Privacy, IEEE Computer Society, 1997, S. 31–
42
96
Literaturverzeichnis
[Ker]
Frequently Asked Questions about Kerberos. – URL http://www.cmf.nrl.
navy.mil/CCS/people/kenh/kerberos-faq.html
[Lam71]
L AMPSON, Butler W.: Protection. In: Proceedings of the fifth Princeton
Symposium on Information Sciences and Systems, Princeton University,
1971, S. 437–443
[Lib]
Liberty Alliance Project. – URL http://www.projectliberty.org/
[Mar03]
M AREK, Detlef: Sprachbasierte Konstruktion sicherer Systeme, Technische
Universität München, Diss., 2003
[Mat04]
M ATTHES, Florian. Software Engineering betrieblicher Anwendungen. Vorlesungsunterlagen, Technische Universität München, Fakultät für Informatik. WS 2003/04
[Mey97]
M EYER, Bertrand: Object-Oriented Software Construction. 2nd edition.
Upper Saddle River, NJ : Prentice Hall, 1997. – ISBN 0–13–629155–4
[MM02]
M ITCHELL, Richard ; M C K IM, Jim: Design by Contract, by Example. Indianapolis, IN : Addison-Wesley, 2002. – ISBN 0–201–63460–0
[MSP]
Microsoft Passport. – URL http://www.microsoft.com/net/services/
passport/
[Oak01]
O AKS, Scott: Java Security. 2nd edition. Sebastopol, CA : O’Reilly, 2001.
– ISBN 0–596–00157–6
[OQ]
OpenQuasar. – URL http://www.openquasar.de/
[PAM95]
Open Software Foundation: RFC 86.0 : Unified Login with Pluggable Authentication Modules (PAM). 1995. – URL http://www.opengroup.org/
tech/rfc/mirror-rfc/rfc86.0.txt
[Par72]
PARNAS, David L.: On the criteria To Be Used in Decomposing Systems
into Modules. In: Communications of the ACM 15 (1972), Nr. 12, S.
1053–1058. – ISSN 0001–0782
[PCND04] PARK, Joon S. ; C OSTELLO, Keith P. ; N EVEN, Teresa M. ; D IOSOMITO,
Josh A.: A Composite RBAC Approach for Large, Complex Organizations. In: Proceedings of the ninth ACM symposium on Access control models
and technologies, ACM Press, 2004. – ISBN 1–58113–872–5, S. 163–172
97
Literaturverzeichnis
[RBKW91] R ABITTI, Fausto ; B ERTINO, Elisa ; K IM, Won ; W OELK, Darrell: A Model of
Authorization for Next-Generation Database Systems. In: ACM Transactions on Database Systems 16 (1991), Nr. 1, S. 88–131. – ISSN 0362–5915
[SD92]
S HEN, HongHai ; D EWAN, Prasun: Access Control for Collaborative Environments. In: Proceedings of the 1992 ACM Conference on ComputerSupported Cooperative Work, ACM Press, 1992. – ISBN 0–89791–542–9,
S. 51–58
[SGM02]
S ZYPERSKI, Clemens ; G RUNTZ, Dominik ; M URER, Stephan: Component
Software : Beyond Object-Oriented Programming. 2nd edition. London :
Addison-Wesley, 2002. – ISBN 0–201–74572–0
[Sie02]
S IEDERSLEBEN, Johannes (Hrsg.): Softwaretechnik : Praxiswissen für
Software-Ingenieure. 2., überarb. und aktualisierte Aufl. München : Hanser, 2002. – ISBN 3–446–21843–2
[Sie04]
S IEDERSLEBEN, Johannes: Moderne Software-Architektur : Umsichtig planen, robust bauen mit Quasar. Heidelberg : dpunkt, 2004. – ISBN 3–
89864–292–5
[Sik97]
S IKKEL, Klaas: A Group-based Authorization Model for ComputerSupported Cooperative Work / GMD. Sankt Augustin, März 1997. –
Arbeitspapier der GMD 1055. URL http://wwwhome.cs.utwente.nl/
~sikkel/papers/ps/arbeitspapier1055.ps.gz
[Sim03]
S IMIONATO, Michele: The Python 2.3 Method Resolution Order. 2003.
– URL http://www.python.org/2.3/mro.html(Aktualisierungsdatum:
17.11.2003)
[SST97]
S AAKE, Gunter ; S CHMITT, Ingo ; T ÜRKER, Can: Objektdatenbanken : Konzepte, Sprachen, Architekturen. Bonn : International Thomson Publishing,
1997. – ISBN 3–8266–0258–7
[Swo02]
S WOBODA, Joachim. Cryptography and System Security / Kryptologie. Vorlesungsunterlagen, Technische Universität München, Fakultät für Elektrotechnik und Informationstechnik. SS 2002
[VDM]
Information on VDM. – URL http://www.csr.ncl.ac.uk/vdm/
[Z]
The Z notation. – URL http://www.zuser.org/z/
98
Index
’x (QSL), 14
<=> (QSL), 14
=> (QSL), 14
AbstractUser, 41, 42, 48, 58, 59, 69,
72
Abfrage, 9
AbstractRight, 41, 42, 48, 58, 69
Access Control Decision Function, siehe
ADF
Access Control Enforcement Function,
siehe AEF
Access Control List, siehe ACL
AccessibleObject, 32, 41, 69, 72
Accessor, 30, 41, 69, 72
AccessRestriction, 32, 37, 69, 71,
72
ACL, 17, 18, 20, 69
Adapter, 32
ADF, 22–24, 26, 29, 69
Administration, 18, 21, 23, 27, 29, 41–
44, 46, 49, 62, 64, 65, 69, 76,
87
AdvancedAuthorization, 3, 19, 49–52,
54, 56, 58, 62, 65, 67, 72, 73,
81
AEF, 22–24, 26, 69
and (QSL), 13
Anforderungsschnittstelle, siehe
Schnittstelle, angeforderte
API, 26, 69
Assignment, 49, 50, 69
Außensicht, 2, 8
Ausnahme, 9, 12
Authentifizierung, 3, 15, 16, 22, 23,
27–29, 33, 35, 37–39, 41, 44,
49, 54–57, 67, 69
Autorisierung, 3, 15, 16, 19, 20, 22,
23, 27, 29, 32, 36, 49, 69, 71
-skomponente, 1–3, 7, 20, 23, 29,
32, 35, 39, 41, 44, 46, 52, 54,
56, 58, 61, 65, 67
BasicAuthorization, 3, 41–45, 49, 51,
52, 56, 58, 62, 67, 75
basicQueries (QSL), 12, 73
Bell-LaPadula-Modell, 20
Benutzer, 7, 15, 16, 18, 20, 27–30, 32,
34–38, 41, 42, 44, 46, 48–51,
53, 54, 56, 58–60, 62, 67, 69–
72
Benutzerschnittstelle, 7
Berechtigung, 21, 27, 29, 30, 32, 35–
38, 41, 42, 46, 48, 50, 51, 58,
59, 64, 65, 69–72
Berechtigungs-Cache, 35, 36, 38
Biometrie, 16
Blutgruppe, siehe Softwarekategorie
99
Index
C3-Algorithmus, 61
Capability, 17, 38
Challenge-Response-Verfahren, 16
commands (QSL), 12, 73
Composite-Pattern, 42
const (QSL), 13
DAC, 20, 70
derivedQueries (QSL), 12, 73
Design by Contract, 1, 2, 8, 38, 39
digitale Signatur, 26
Discretionary Access Control, siehe
DAC
JAAS, 2, 3, 15, 25, 27, 37, 56–58, 67,
70, 72
Java Authentication and Authorization
Service, siehe JAAS
Java Virtual Machine, siehe JVM
Javadoc, 10
JML, 10, 70
JVM, 25, 70
Fehler, 9, 12
forall (QSL), 13
Funktionssicherheit, 1, 2
Kerberos, 16
Kommando, 9
Komponente, 1–3, 5–8, 29, 30, 32–34,
36, 37, 39, 41, 43–45, 49, 53,
54, 56, 64, 67, 69, 70
Autorisierungs-, 1–3, 7, 20, 23, 29,
32, 35, 39, 41, 44, 46, 52, 54,
56, 58, 61, 65, 67
einfache, 6
Sub-, 7
zusammengesetzte, 6
Komposition, 5, 6, 8
Konfiguration, 8, 27, 45, 55, 57, 70
Konstanz, 9
Group, 41, 70, 72
Gruppe, 18, 28–30, 35–37, 41, 42, 46,
48, 50, 51, 58, 59, 61, 62, 69–
72
Lampson-Matrix, siehe Zugriffsmatrix
Liberty Alliance, 16
Linearisierung, 59–62, 64, 67
Login Module, 27, 28, 38, 56
Importeur, 8, 32, 37, 44
in (QSL), 13
Informationssicherheit, 1, 2, 15
Instrumentierung, 42, 43, 45, 53, 54,
65, 70, 76, 84
interface (QSL), 12
Invariante, 9, 10, 12, 13, 48
invariants (QSL), 13
IT-Sicherheit, 1
MAC, 20, 70
Mandatory Access Control, siehe MAC
maybenull (QSL), 12, 13
Microsoft Passport, 16
MRO, 61, 70
Eiffel, 10
Erlaubnisprinzip, 19
error (QSL), 12, 14, 62
exists (QSL), 13
Exporteur, 8, 9, 32
extends (QSL), 12
J2SE, 25, 70
100
Nachbedingung, 8–10, 12, 13
NIST, 21, 70
not (QSL), 13
NRR, 10, 70
NRR (QSL), 12
Index
OCL, 10, 70
Operation, 29, 30, 32–34, 37, 44–46,
48, 51, 53, 58, 59, 62, 64, 65,
67, 69, 70, 72
Operation, 32, 51, 70, 72
or (QSL), 13
PAM, 27, 56
Permission, 30, 32, 41, 70, 72
PermissionGroup, 30, 41, 70, 72
Pluggable Authentication Modules, siehe PAM
post (QSL), 12–14
pre (QSL), 12, 13
Principal, 27, 28, 56, 72
Programmschnittstelle, 7
Python, 61, 70
QSL, 11–14, 41, 42, 44, 62, 70, 73
Qualitätssoftwarearchitektur, siehe
Quasar
Quasar, 3, 5–7, 9, 32, 36, 39, 70
Quasar Specification Language, siehe
QSL
QuasarAuthorization, 1–3, 5, 7, 19,
29–39, 41, 44–46, 49, 51, 53,
64, 65, 67, 72
RBAC, 20–22, 37, 42, 49, 71
Rechteprüfung, 23, 24, 29, 32–34, 36–
38, 41, 44–46, 48, 49, 51, 53,
58, 59, 62, 64, 65, 67, 69, 71
Resource, 41, 51, 71, 72
Ressource, 29, 30, 32, 33, 37, 41, 45,
46, 48, 51–53, 58, 59, 62, 64,
65, 67, 69, 71, 72
RestrictionParameter, 32, 71, 72
result (QSL), 14
Right, 41, 71, 72
Role, 41, 71, 72
Role-Based Access Control, siehe RBAC
Rolle, 21, 29, 30, 35–37, 41, 42, 46,
48, 50, 51, 59, 64, 69–72
RRR, 10, 12, 71
Safety, 1
Sandbox, 25, 26
Schnittstelle, 2, 3, 5–13, 23, 30–39, 41,
42, 44, 46, 52–54, 56, 58–60,
62, 67, 69, 70, 72, 73, 75, 81
angeforderte, 32, 34, 35, 45, 52,
53, 69
Benutzer-, 7
Programm-, 7
Standard-, 7
Security, 1
Security Manager, 25, 26, 28
Session, siehe Sitzung
SessionTicket, 53, 54, 71
Single-Sign-On, 16, 37
Sitzung, 21, 22, 49, 53, 58, 67, 71
Softwarekategorie, 6, 7
Spezifikation, 2, 3, 5, 7–13, 38, 39, 42,
44, 48, 50, 54, 62, 67, 70, 73
Stützschnittstelle, siehe
Schnittstelle, angeforderte
Standardschnittstelle, 7
states (QSL), 12
testcases (QSL), 13
Testfall, 9, 12–14
UML, 10, 30, 34, 50, 70, 71
URR, 9, 71
URR (QSL), 12
User, 30, 34, 35, 44, 54, 71, 72
UserGroup, 30, 34, 35, 41, 71, 72
uses (QSL), 12
variables (QSL), 12
101
Index
VDM, 10, 71
Verbotsprinzip, 19
Vorbedingung, 8–10, 12, 13
Wiederholbarkeit, 9, 12
Z, 71
Zugriffs
-ausweis, 17, 38
-kontrolle, 1, 3, 15, 16, 20, 22, 69–
71
-kontrollliste, 17
-matrix, 17
Zustandsmodell, 9
102