Dokumentation Diplomarbeit Philipp Gantert ([email protected]) Version 1.0 Grenchen, 8. Mai 2007 Zusammenfassung Der Name des Frameworks Heracles stammt aus der griechischen Mythologie. Heracles war der Sohn des Zeus und der Alkmene. Eine seiner Taten war es Kerberos, den dreiköpfigen Höllenhund, zu bezwingen und zu fesseln. Genau diese Aufgabe erledigt dieses Framework. Es bezwingt und zähmt den Kerberos Netzwerkdienst. Heracles kann in eine bestehende Applikation oder Web-Applikation eingebunden werden und realisiert auf eine einfache, übersichtliche Art und Weise, eine Authentifizierung über Kerberos. Heracles ist nicht umsonst ein Halbgott, das Framework besitzt auch die Macht Benutzerinformationen aus dem LDAP-Netzwerkdienst abzufragen und an andere Java Applikationen weiter zu leiten. Inhaltsverzeichnis 1 Einleitung 1.1 Ausgangslage . . . . 1.2 Aufgabenstellung . . 1.3 Aufbau und Ziele des 1.4 Zeitplan . . . . . . . 1.5 Zielerreichung . . . . 1.6 Personen . . . . . . . 1.7 Journal . . . . . . . . . . . . . . . . . . . . . . . Dokumentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Analyse 2.1 Exkurs . . . . . . . . . . . 2.1.1 LDAP . . . . . . . 2.1.2 Kerberos . . . . . . 2.1.3 Zusammenfassung 2.2 IST-Zustand . . . . . . . . 2.3 Bestimmung der Attribute 2.4 Problematiken . . . . . . . 2.5 UseCases . . . . . . . . . 2.5.1 Auhtentifizierung . 2.5.2 LDAP abfragen . . 2.5.3 ACEGI Provider . . . . . . . . . . . . 3 Architektur 3.1 Werkzeuge . . . . . . . . . . 3.2 Klassendiagramm . . . . . . 3.3 API . . . . . . . . . . . . . 3.4 Konfiguration von Heracles 3.4.1 Das Objektmodell . 3.4.2 Die XML Datei . . . 3.5 ACEGI . . . . . . . . . . . 3.6 Test . . . . . . . . . . . . . 3.7 Lösung der Probleme . . . . 3.7.1 Mehrere Domänen . 3.7.2 LDAP Attribute . . 3.8 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 6 6 6 7 7 7 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 9 10 12 13 14 15 17 17 17 20 23 . . . . . . . . . . . . 25 25 26 27 28 29 30 31 32 32 32 33 34 . . . . . . . . . . . . . . . . . . . . . . . . 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dokumentation, Heracles Inhaltsverzeichnis 4 Design, Implementation und Tests 4.1 Einleitung . . . . . . . . . . . . . 4.2 UC1: Authentifizierung . . . . . . 4.2.1 Validierung . . . . . . . . 4.2.2 Einsatz von JAAS . . . . 4.2.3 Exception Handling . . . 4.2.4 JUNIT Tests . . . . . . . 4.3 UC2: Ldap abfragen . . . . . . . 4.3.1 Validierung . . . . . . . . 4.3.2 Einsatz von JNDI . . . . 4.3.3 LdapUser und LdapGroup 4.3.4 Exception Handling . . . 4.3.5 JUNIT Test . . . . . . . . 4.4 UC3: Acegi Provider . . . . . . . 4.4.1 Funktionsweise . . . . . . 4.4.2 ACEGI Konfiguration . . 4.4.3 Exception Handling . . . 4.4.4 JUNIT Test . . . . . . . . 4.5 Heracles Konfiguration . . . . . . 4.6 Zusammenfassung . . . . . . . . 5 Tests 5.1 Voraussetzung . . . . . . . . . . 5.2 Die Klasse CreateTestData.java 5.2.1 Klassendiagramm . . . . 5.2.2 Verwendung . . . . . . . 5.2.3 Funktionsweise . . . . . 5.3 Testdaten . . . . . . . . . . . . 5.4 Latenzzeit Berechnung . . . . . 5.4.1 Test Programme . . . . 5.4.2 Messwerte . . . . . . . . 5.5 UseCase Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Objekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 36 37 39 39 41 41 42 43 44 46 50 50 51 51 53 53 54 55 57 . . . . . . . . . . 58 58 59 60 61 61 62 64 65 65 65 6 Benutzerhandbuch 6.1 Installation . . . . . . . . . . . . . . 6.2 XML Konfiguration . . . . . . . . . . 6.3 Beispiel: einfache Authentifizierung . 6.4 Beispiel: erweiterte Authentifizierung 6.5 Beispiel: LDAP abfragen . . . . . . . 6.6 Troubleshooting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 67 68 69 69 70 71 7 Prototyp 7.1 Übersicht . . . 7.2 Architektur . . 7.3 Funktionsweise 7.4 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 72 75 76 77 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Dokumentation, Heracles 7.5 Inhaltsverzeichnis Prototyp in der HFT-SO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 8 Schlusswort 80 9 Fazit 81 Glossar 82 A Anforderungszuordnung A.1 Pflichtenheft . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.2 Offene Punkte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 86 86 B Anhang Probleme B.1 Gelöste Probleme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.2 Offene Probleme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 88 89 C Anhang Zukunft 90 D Anhang heracles-config.dtd 91 E Anhang KerberosQueryImpl.java 92 F Anhang Beilagen F.1 Ausdruck . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . F.2 Elektronisch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 93 93 5 1 Einleitung In der Einleitung wird die Ausgangslage, die zu diesem Projekt führte erläutert, der Aufbau des Dokumentes beschrieben und organisatorische Informationen festgehalten. 1.1 Ausgangslage Die Höhere Fachschule für Technik des Kantons Solothurn entwickelt unterschiedliche Java Applikationen, auch solche die produktiv eingesetzt werden. Die Informatik-Klasse TIN05 aus dem Jahre 2006 entwickelte die Applikation Erfolgskontrolle (EFK). Diese Applikation macht es möglich ISO Umfragen zu erstellen und auszuwerten. Für weitere Applikationen gibt es noch Pläne wie eine Softwareverwaltung, eine Softwareinstallationsverwaltung oder eine Authentifizierungsapplikation für VPN1 . All diese Applikationen haben eines gemeinsam: Sie benötigen eine Möglichkeit um Benutzer über ADS zu authentifizieren. 1.2 Aufgabenstellung Die Aufgabenstellung zur Diplomarbeit sowie das darin referenzierte Pflichtenheft befinden sich im Anhang F. 1.3 Aufbau und Ziele des Dokumentes In der Analyse wird die Funktionalität des künftigen Systems wie auch seine Schnittstellen aus der Sicht des Anwenders definiert. Demzufolge wird das “Was” (was das System leisten soll) und nicht das “Wie” (technische Realisierung) definiert. Die technischen Details der Schnittstellen und die Werkzeuge zur Realisierung des Projektes werden in der Architektur beschrieben. Wie die einzelnen UseCases aufgebaut und realisiert sind, wird im Kapitel “Design, Implementation und Test” eingegangen. Knacknüsse der Implementation und die dazugehörigen Testresultate sind festgehalten. 1 Virtual Private Network; http://de.wikipedia.org/wiki/Virtual_Private_Network 6 Dokumentation, Heracles Kapitel 1. Einleitung Das Kapitel “Tests” erläutert die nötige Testumgebung und die Testdaten. Den performance Tests ist ein Unterkapitel gewidmet und die Messresultate sind dort festgehalten. Wie am Ende der Benutzer Heracles einsetzen und nutzen kann, wird in einem Benutzerhandbuch beschrieben. Ein kleines Kapitel erläutert, wie gewisse Fehler beim Einsatz von Heracles behoben werden können. 1.4 Zeitplan Der Zeitplan befindet sich im Anhang F. 1.5 Zielerreichung Wie und ob die Ziele erreicht wurden wird im Anhang A verraten. 1.6 Personen Kunde: Höhere Fachschule für Technik des Kantons Solothurn Sportstrasse 2 2540 Grenchen Diplomand: Philipp Gantert Speiserstrasse 36 4600 Olten Tel: 032 654 28 60 Mail: [email protected] Betreuer: Ruedi Baumann Sportstrasse 2 2540 Grenchen Tel: 032 654 28 88 Mail: [email protected] Expert: Rolf Gisin Mobil: 079 439 84 65 Mail: [email protected] Tabelle 1.1: Personen 7 Dokumentation, Heracles Kapitel 1. Einleitung 1.7 Journal Das Tagesjournal befindet sich im Anhang F. 8 2 Analyse Die Analyse ist in mehrere Teile unterteilt. Als Erstes wird ein kurzer Exkurs in das Themengebiet von Lightweight Directory Access Protocol (LDAP) und von Kerberos dem Authentifizierungsdienst gegeben. Dieser Exkurs vermittelt für diese Arbeit die nötigen Kenntnisse. Der nächste Teil befasst sich mit einem Ausschnitt der IT-Infrastruktur der HFT-SO. Diese Aufnahme des IST-Zustandes wird benötigt um die Dimension des zu entwickelnde Framework bestimmen zu können. Dabei spielt der Aufbau des Active Directory (wird im Folgenden nur noch als ADS bezeichnet) eine zentrale Rolle. Wichtig sind Informationen über die Anzahl Domänen, die Angaben deren Domänencontroller1 und die Attribute der Benutzerobjekte. Bereits bei der Analyse sind einige Problemstellungen oder eventuelle Schwierigkeiten aufgetaucht. Diesen ist ein weiterer Teil der Analyse gewidmet. Am Ende der Analyse werden die einzelnen ausgearbeiteten UseCases aus dem Pflichtenheft beschrieben. 2.1 Exkurs Dieses Kapitel kann von den Lesern, welche sich bereits mit dieser Materie auseinandergesetzt haben, ausgelassen werden. LDAP und Kerberos sind heutzutage nicht mehr aus den grossen Netzwerken wegzudenken. Diese beiden Dienste sind standardisiert und werden von unterschiedlichen Firmen auf ihre Weise eingesetzt. Beispielsweise gibt es einen Kerberosdienst von MIT2 , Heimdal3 oder Microsoft4 . Bei LDAP ist das nicht anders. Dort stehen OpenLdap5 , Novell eDirectory6 oder Microsoft LDAP7 zur Verfügung. In den folgenden Kapiteln wollen wir nicht auf einen spezifischen Hersteller Rücksicht nehmen, sondern die Technologie an und für sich erläutern. 1 Ein Domänencontroller verwaltet die Domäne und besitzt die dazugehörige Datenbank. Auf diesen Computer können neue LDAP Objekte erstellt, gelöscht oder abgefragt werden. 2 Massachusetts Institute of Technology; http://web.mit.edu/Kerberos/dist/index.html 3 http://www.pdc.kth.se/heimdal/ http://www.microsoft.com/windowsserver2003/technologies/security/kerberos/default.mspx 5 http://www.openldap.org/ 6 http://www.novell.de/prodinfos/edirectory.html 7 http://www.microsoft.com/windowsserver2003/techinfo/overview/ldapcomp.mspx 4 9 Dokumentation, Heracles Kapitel 2. Analyse 2.1.1 LDAP Wer sich in der objektorientierten Programmierung zuhause fühlt, hat sich schnell in LDAP eingearbeitet. Ein LDAP Verzeichnis besteht aus einem Schema, welches mit Weiteren ergänzt werden kann. In einem Schema befindet sich eine Anzahl von Objektklassen. Jede Objektklasse besitzt unterschiedliche Eigenschaften. Das hört sich doch wirklich sehr vertraut an. Machen wir ein Beispiel und erstellen ein Benutzerobjekt. Es gibt eine Standard-Objektklasse Person. Diese Klasse definiert, dass ein solches Objekt einen Nachnamen (eng. Surname, abk. sn) und einen Spitznamen (eng. Commonname, abk. cn) besitzen muss. Optional darf ein solches Objekt ein Passwort haben. Jedoch benötigt eine Person noch weitere Eigenschaften, wie einen Titel oder eine Adresse. Somit definieren wir, dass unser Objekt nicht nur aus der Objektklasse Person stammt, sondern auch von der Objektklasse organizationalPerson abgeleitet wird. Um jedoch dem Benutzerobjekt ein Foto oder eine Faxnummer mitzugeben, muss das Objekt um die Objektklasse inetOrgPerson erweitert werden. Ein LDAP Verzeichnis kann mehrere tausend oder gar hunderttausend Objekte beinhalten. Von einem Benutzerobjekt, über ein Computerobjekt, zu einem Freigabeobjekt. Dies hat zur Folge, dass das Verzeichnis strukturell organisiert werden muss. Dazu stehen zwei Möglichkeiten zur Verfügung. LDAP arbeitet sehr nahe mit DNS8 zusammen, dies hat den Vorteil, dass ein LDAP Verzeichnis mit Hilfe von DNS Domänen unterteilt werden kann. Abbildung 2.1 zeigt eine Domäne und zwei Subdomänen. Jede dieser Domänen kann unterschiedlich viele Objekte verwalten, wobei jede einen eigenen Namensraum für diese Objekte bildet. Abbildung 2.1: DNS Domänen Eine einzelne Domäne kann weiter unterteilt werden mit der Hilfe von Container. Diese Container werden in LDAP als Organisationseinheiten beschrieben und werden als Ordner dargestellt. Aus Gründen der Performance sollte jedoch eine zu tiefe Hierarchie vermieden werden. Es empfiehlt sich eher eine breite Struktur zu haben. 8 Domain Name System http://de.wikipedia.org/wiki/Domain-Name-System 10 Dokumentation, Heracles Kapitel 2. Analyse Um nun die Möglichkeit zu haben ein Objekt direkt anzusprechen bedarf es einem eindeutigen Namen. Dieser wird fachsprachlich als Distinguished Name (wird im Folgenden nur noch als DN bezeichnet) betitelt. Die Abbildung 2.2 macht dazu ein Beispiel. Abbildung 2.2: Distinguished Name Die Abbildung 2.2 zeigt zwei Benutzerobjekte mit ihren DN. Der DN wird über den Pfad zum Objekt zusammengesetzt. Die Domäne hat als DN dc=test,dc=lan. Innerhalb der Domäne ist eine Organisationseinheit “Benutzer” und diese enthält die beiden Benutzerobjekte cn=hans muster, ou=benutzer, dc=test, dc=lan und cn=susi muster, ou=benutzer, dc=test, dc=lan. Aus den einzelnen Attributen, welche die Objekte über die Zuordnung zu den Objektklassen erhalten, wird der Name zusammengesetzt. Es können alle Attribute für die Zusammenstellung zum DN genommen werden, jedoch ist es nur sinnvoll solche einzusetzen, welche mit grösster Wahrscheinlichkeit einzigartig im ganzen LDAP Verzeichnis sind. Wir erinnern uns, dass der DN eindeutig auf ein Objekt im ganzen Verzeichnis zeigt. Dieser Exkurs ist sehr konzentriert und kompakt. Für weitere Informationen über LDAP sind einige Internetseiten zu empfehlen. • http://www.mitlinx.de/ldap/index.html?http://www.mitlinx.de/ldap/ldap_schema.htm • http://www.microsoft.com/germany/technet/itsolutions/network/grundlagen/tec_comp_2_2_1. mspx • http://www.microsoft.com/germany/technet/itsolutions/network/grundlagen/tec_comp_2_2_2. mspx • http://www.microsoft.com/germany/technet/itsolutions/network/grundlagen/tec_comp_2_2_3. mspx 11 Dokumentation, Heracles Kapitel 2. Analyse • http://www.amazon.de/verstehen-einsetzen-Grundlagen-Praxiseinsatz-Single-sign/dp/3898642178 2.1.2 Kerberos Die Entwickler von Kerberos gingen vom Grundsatz aus, dass jede Netzwerkverbindung unsicher ist. Aus diesem Grund entwickelten sie Kerberos für den Austausch von Passwörtern. In der Sprache von Kerberos gibt es keine Benutzernamen sondern Principals und die Passwörter werden Credential genannt. Auch das Wort Domäne ist nicht bekannt, unter Kerberos nennt sich das REALM. Der Key Distribution Center (im weiteren Verlauf KDC) kennt alle Principals und verwaltet diese. In der Welt von Kerberos besitzen alle Benutzer und Computer ein Principal. Warum dies so ist, soll die Abbildung 2.3 zeigen. Abbildung 2.3: Kerberos 1. Der Benutzer Hans Muster besitzt einen Principal und sein Credential. Der Benutzer macht an den KDC nun eine Anfrage für die Authentifizierung und übermittelt seinen Principal. 12 Dokumentation, Heracles Kapitel 2. Analyse 2. Der KDC erstellt einen Session Key9 und dieser wird in ein TGT10 eingepackt. Das ganze verschlüsselt der KDC mit dem Credential (geheim) des Principals. 3. Der Benutzer versucht mit seinem Credential den TGT zu dechiffriert. Was nur mit dem richtigen Passwort funktionieren kann. 4. Besitzt der Benutzer ein TGT kann er mit seiner Hilfe den KDC anfragen für ein TGS11 , um auf andere Netzwerkdienste zu zugreifen. 5. Der KDC sendet dem Benutzer, bei einem gültigen TGT, das TGS. Dieses TGS beinhaltet wieder einen eigenen Session Key. 6. Bei Anfragen des Benutzers an den entsprechenden Dienst, sendet dieser diese Anfrage mit dem erhaltenen TGS. 7. Der Server erkennt ein gültiges TGS und einen gültigen Session Key und somit wird die Kommunikation aufgebaut. Der Grund warum alle Benutzer und Computer einen Principal benötigen ist für die Erstellung und den Austausch von Tickets. Das wichtigste aus der Abbildung 2.3 ist, dass das Credential nur ein einziges Mal ausgetauscht wird. Für weitere Informationen sind die folgenden Internetseiten empfehlenswert. • http://www.microsoft.com/windowsserver2003/technologies/security/kerberos/default.mspx • http://www.zeroshell.net/eng/kerberos/ • http://hell.org.ua/Docs/oreilly/tcpip2/fire/ch21_05.htm • http://www.esolpartners.com/prd/security_authAgent_kerberos.html • http://de.wikipedia.org/wiki/Kerberos_(Informatik) 2.1.3 Zusammenfassung LDAP ist eine Informationsquelle für andere Dienste des Netzwerkes. Es speichert von unterschiedlichen Objekten die Informationen. Dieser Verzeichnisdienst wird mit Domänen und Organisationseinheiten strukturiert. Über einen eindeutigen Namen, den DN, kann jedes Objekt darin 9 Diese enthält die Zeit, Datum, Gültigkeit, Principal. Ticket Grantering Ticket, kann als Master Ticket angeschaut werden. 11 Service Ticket von Servern und deren Diensten. 10 13 Dokumentation, Heracles Kapitel 2. Analyse gefunden werden. Es existiert eine Vielzahl von Objektklassen, welche Objekte beschreiben und diese Klassen sind in einem Schema festgehalten. Ein Principal ist nichts anderes als ein Benutzername. Ein Credential ist das Passwort eines Benutzers und der REALM beschreibt die Domäne. Diese Ausdrücke werden in Kerberos gebraucht. Die Aufgabe von Kerberos ist es, Passwörter von Benutzern zu verwalten. Kerberos gilt zurzeit als sehr sicher, da das Passwort nur einmal übertragen wird und innert einer gewissen Zeit geknackt werden muss. 2.2 IST-Zustand Die HFT-SO nutzt den LDAP- und Kerberosdienst von Microsoft. Ab hier wird sich dieses Dokumenten nur noch auf diesen Hersteller und dessen spezifischen Änderungen konzentrieren. Das Active Directory der HFT-SO umfasst drei Domänen. Die Domäne BBZ-SG.LAN ist die sogenannte Stammdomäne und verleiht dem ganzen Baum den Namensraum. ZZ.BBZ-SG.LAN ist die Domäne des Zeitzentrums Grenchen. Die Domäne HFT-SO.BBZ-SG.LAN beinhaltet alle Ressourcen12 der HFT-SO. Die Abbildung 2.4 zeigt eine Übersicht der Domänen und deren Domänencontroller. Diese Domänencontroller haben alle ein Windows 2003 SP1 Englisch installiert. In der letzten Spalte sind die Netzwerkports der einzelnen Dienste ersichtlich. Die Protokolle ldap und ldaps werden für die Abfragen von LDAP benötigt und die beiden Anderen für Kerberos. Abbildung 2.4: Active Directory IST-Zustand Die HFT-SO hat in der Dokumentation des ADS festgehalten, welche Informationen für welche Benutzer gespeichert werden (siehe Tabelle 2.1). Die HFT-SO unterscheidet für sich zwischen Mitarbeiter, Lehrbeauftragten und Studierende. Je nach Person werden mehr oder weniger LDAP Attribute festgehalten. 12 Unter Ressourcen versteht man im ADS Computer, Server, Drucker, Benutzer, Gruppen, Freigaben, etc... 14 Dokumentation, Heracles Name Vorname Anzeige Name Büro Telefonnummer Mail Webseite Strasse Stadt Kanton PLZ Land Accountname Fax Titel Abteilung Firma Mail Alias Mitarbeiter x x x x x x x x x x x x x x x x x x Kapitel 2. Analyse Lehrbeauftragter x x x x x x x x x x x x x x x x x x Student x x x x x x x x x x Beispiel Muster Hans Muster Hans 217 +41 32 654 28 28 [email protected] www.hft-so.ch Sportstrasse 2 Grenchen Solothurn 2540 Schweiz hans.muster +41 32 654 28 28 Lehrbeauftragter Lehrbeauftragte HFT-SO hans.muster Tabelle 2.1: Festgelegte Attribute der HFT-SO 2.3 Bestimmung der Attribute Wie im Pflichtenheft festgelegt müssen die Attribute, welche Heracles aus dem LDAP holen soll, definiert werden. Welche LDAP Attribute für die HFT-SO wichtig sind, ist im oberen Kapitel beschrieben. Diese werden zusätzlich um vier weitere Attribute erweitert. Sie werden einerseits für ACEGI13 benötig und andererseits können sie auch für die HFT-SO interessant sein, wenn diese später irgendwelche Statistiken erstellen möchte. • Die Information ob ein Account aktiviert oder deaktiviert ist. • Ob das Passwort des Benutzers abgelaufen ist. • Wie oft ein Benutzer sich am Netzwerk bereits angemeldet hat. • Wann er sich das letzte Mal erfolgreich angemeldet hat. Die Tabelle 2.2 enthält die Attributnamen von LDAP, welche alle diese Informationen beinhalten. Diese Attribute muss Heracles abfragen und den externen Applikationen übergeben. 13 Im Pflichtenheft wurde festgelegt, dass dieses Java Framework eingesetzt werden soll http://en.wikipedia. org/wiki/Acegi_security_framework_(Java) 15 Dokumentation, Heracles Attributname givenName sn displayName company department title cn streetAddress postalCode l st c description telephoneNumber mailAddress mailNickname wWWHomePage dn userPrincipalName lastLogon logonCount userAccountControl memberOf Kapitel 2. Analyse Beschreibung Vorname Nachname Im LDAP kann das Benutzerobjekt unter einem anderen Namen angezeigt werden Firmennamen Abteilungsnamen Titel Der Commonname ist der Name, unter welchem das Objekt angesprochen wird Strasse und Nummer PLZ Stadt Kanton Land Die Beschreibung kann genutzt werden um weitere Informationen zu hinterlassen Telefonnummer E-Mail Adresse des Objektes Dieser Name ist wichtig für IMAP oder POP Authentifizierungen Homepage Dieses Attribut beinhaltet den ganzen Pfad im LDAP zu diesem Benutzerobjekt Kerberos Loginname Die letzte erfolgreiche Anmeldung Anzahl aller erfolgreichen Anmeldungen am Netzwerk Spezifisches Microsoft Attribut, enthält verschiedene Informationen Gruppenangehörigkeit, in welchen Gruppen der Benutzer Mitglied ist Tabelle 2.2: Attribute 16 Dokumentation, Heracles Kapitel 2. Analyse In der Tabelle 2.2 wird das userAccountControl Attribut erwähnt. Microsoft speichert in diesem Integer14 Attribut gleichzeitig mehrere verschiedene Informationen. Wie zum Beispiel ob der Benutzeraccount deaktiviert ist oder ob das Passwort des Benutzeraccountes nicht mehr gültig ist. Es gibt einen ganzen Microsoft Artikel [Mic06] zu diesem Attribut. 2.4 Problematiken Aus der bisherigen Analyse sind zwei Problematiken hervorgegangen. Mehrere Domänen Aus dem Kapitel 2.2 ist ersichtlich, dass die HFT-SO mehrere LDAP Server und mehrere Kerberos Server besitzt. Die zwei Domänencontroller der gleichen Domäne besitzen dieselben Informationen. Das heisst, dass Heracles mehrere Domänen unterstützen muss. LDAP Attribute Nicht alle Benutzerobjekte haben die gleichen LDAP Attribute ausgefüllt. Die Einen haben mehr, die Anderen weniger. Auch dies stellt eine Problematik dar, welche dieses Framework lösen muss. 2.5 UseCases Da im Pflichtenheft bereits einige Technologien angesprochen wurden, wird die Analyse der UseCase nicht immer neutral oder unabhängig davon sein. Abbildung 2.5 zeigt das UseCase Diagramm, welches bereits im Pflichtenheft beschrieben wurde. Mit den Aktoren JAAS und LDAP Server welche das Heracles Framework nutzt und den Aktoren ACEGI und externe Applikation welche Heracles nutzen. Im Folgenden werden die UseCases detaillierter beschrieben. 2.5.1 Auhtentifizierung UseCase Id: UseCase Name: UseCase Autor: Version: Priorität: Aufwand: UC1 Authentifizierung Gantert Philipp 1.0 hoch hoch Tabelle 2.3: UseCase UC1 14 Ein Zahlenwert wird in vielen Programmiersprachen als Integer bezeichnet. 17 Dokumentation, Heracles Kapitel 2. Analyse Abbildung 2.5: UseCase Diagramm Annahmen • Die notwendigen Konfigurationsangaben für Heracles wurden gemacht. Vorbedingungen • Benutzernamen mit Angabe der Domäne und ein Passwort wurde Heracles übergeben. Auslöser/Trigger • Die externe Applikation übergibt Heracles, über das API, einen Benutzernamen und ein Passwort. Szenarios Das Aktivitätsdiagramm 2.6 zeigt den Ablauf des UseCases UC1. Der UseCase erhält einen Benutzernamen und ein Passwort, die erst geprüft werden. Im Benutzernamen muss die Angabe zur Domäne gemacht werden, das Passwort darf nicht null sein. Diese Angaben werden bei einer erfolgreichen Validierung an Kerberos übergeben, der die Au- 18 Dokumentation, Heracles Kapitel 2. Analyse Abbildung 2.6: UC1 Authentifizierung thentifizierung durchführt. Es gibt nun vier mögliche Gründe, warum eine Exception15 geworfen werden könnte. 1. Der Kerberos Server wurde nicht gefunden. 2. Der Benutzername stimmt mit dem Passwort nicht überein. 3. Der Account ist deaktiviert. 4. Das Passwort ist nicht mehr gültig. Der erste Punkt kann aus unterschiedlichen Gründen eintreten und ist ein globales Problem16 . Das kann an einer falschen Konfiguration von Heracles liegen oder schlimmer an einem Netzwerkproblem. Die anderen Gründe für eine Exception sind auf der Ebene eines einzelnen Accounts zu suchen. Wird keine Exception geworfen, dann ist die Authentifizierung erfolgreich gewesen. Nun muss entschieden werden ob es sich um eine einfache oder erweiterte Authentifizierung handelt. Bei einer einfachen Authentifizierung wird der UseCase beendet, bei einer erweiterten Authentifizierung wird der UseCase UC2 aufgerufen. 15 16 deutsch Ausnahme http://de.wikipedia.org/wiki/Ausnahmebehandlung Das bedeutet, dass Heracles generell keine erfolgreichen Anmeldungen machen kann. 19 Dokumentation, Heracles Kapitel 2. Analyse Dialog Dieser UseCase besitzt weder einen grafischen noch einen consolenbasierenden Dialog. Die Angaben für den UseCase werden über einen Methodenaufruf gemacht. Ausstieg/Beendigung • Wird kein Kerberos Server gefunden, dann wird eine Exception geworfen. • Es wird ein Server gefunden, aber Login schlägt fehl, dann wird eine Exception geworfen. • Ein Server wurde gefunden und Authentifizierung ist erfolgreich, dann wird keine Exception geworfen. Nachbedingungen • Bei einer erweiterten Authentifizierung wird UC2 aufgerufen. • Bei einer einfachen Authentifizierung erhält die externe Applikation nichts und somit war die Authentifizierung erfolgreich. • Bei einem Fehler wird die Exception der externen Applikation übergeben. 2.5.2 LDAP abfragen UseCase Id: UseCase Name: UseCase Autor: Version: Priorität: Aufwand: UC2 Ldap abfragen Gantert Philipp 1.0 hoch mittel Tabelle 2.4: UseCase UC2 Annahmen • Die notwendigen Konfigurationsangaben für Heracles wurden gemacht. 20 Dokumentation, Heracles Kapitel 2. Analyse Vorbedingungen • Das Suchkriterium, das Suchelement und die Angabe der Domäne dürfen nicht null sein. Auslöser/Trigger • Die externe Applikation gibt Heracles den Auftrag, dass etwas im LDAP gesucht werden soll. • Der UC1 ruft UC2 auf, da es sich um eine erweiterte Authentifizierung handelt. Szenarios Abbildung 2.7: UC2 Ldap abfragen Die Abbildung 2.7 zeigt, dass der UseCase gestartet wird, indem man ihm das Suchkriterium, ein Suchelement und die Angabe der Domäne übergibt. Als Beispiel wäre ein Suchkriterium “mailAddresse” und das Suchelement “gan”. Somit werden alle Benutzerobjekte, welche eine Mail Adresse besitzen und in der eine Kombination “gan” vorkommt, herausgeholt. 21 Dokumentation, Heracles Kapitel 2. Analyse Als Erstes werden die Angaben geprüft, dass sie nicht null sind. Falls dies jedoch zutrifft, wird eine Exception geworfen. Nach einer erfolgreichen Validierung wird das LDAP Verzeichnis der angegebenen Domäne durchsucht. Wird kein LDAP Server gefunden - bei einer falschen Heracles Konfiguration oder bei Netzwerkproblemen - wird eine Exception geworfen. Besitzt die Suche keine Suchresultate wird ebenfalls die Suche als fehlgeschlagen definiert und wirft somit auch eine Exception. Hat UC1 den UC2 gestartet, dann wird LDAP durchsucht und das Resultat besteht immer nur aus einem einzigen Benutzerobjekt. Dem Objekt, zu welchem der Benutzername und das Passwort passen. Wurde jedoch die Anfrage von dem Aktor externe Applikation gemacht, kann es sein, dass mehrere Benutzerobjekte gefunden werden. Deshalb werden die Resultate einer solchen Anfrage in eine Liste gepackt und dem Aktor zurückgegeben. Dialog Dieser UseCase besitzt weder einen grafischen noch einen consolenbasierenden Dialog. Die Angaben für den UseCase werden über einen Methodenaufruf gemacht. Ausstieg/Beendigung • Wird kein LDAP Server gefunden, wird eine Exception geworfen. • Die Suche enthält keine Suchresultate, so wird eine Exception geworfen. • Bei einer erfolgreichen Suche werden die Resultate dem Auslöser übergeben. Nachbedingungen • Bei einer erweiterten Authentifizierung werden die festgehaltenen Informationen dem UC1 übergeben. • Bei einer Anfrage einer externen Applikation werden die Informationen an diese übergeben. • Bei einem Fehler wird die Exception der externen Applikation oder dem UC1 übergeben. 22 Dokumentation, Heracles Kapitel 2. Analyse 2.5.3 ACEGI Provider UseCase Id: UseCase Name: UseCase Autor: Version: Priorität: Aufwand: UC3 ACEGI Provider Gantert Philipp 1.0 hoch mittel Tabelle 2.5: UseCase UC3 Annahmen • Die notwendigen Konfigurationsangaben für Heracles wurden gemacht. Vorbedingungen • Keine. Auslöser/Trigger • Das ACEGI Framework möchte über den Provider eine Authentifizierung machen. Szenarios Das ACEGI Framework bietet eine Schnittstelle für weitere Provider an. Der UC3 ist nur eine eigenständige Implementierung dieser Schnittstelle. ACEGI übergibt ihr die von ACEGI festgelegten Angaben. Die Implementierung ruft dann den UC1 auf für eine erweiterte Authentifizierung. Für den UC1 sieht es aus, als würde eine externe Applikation den UseCase starten und deshalb verhält sich der UC1 wie beschrieben. Wirft der UC1 eine Exception, dann erhält die Implementierung diese und kann diese an ACEGI weitergeben. Ist jedoch die Anmeldung erfolgreich, dann erhält die Implementierung die Informationen des Benutzers die sie, wie es die Schnittstelle von ACEGI definiert, an ACEGI übergeben. Dialog Dieser UseCase besitzt weder einen grafischen noch einen consolenbasierenden Dialog. Die Angaben für den UseCase werden über einen Methodenaufruf gemacht. 23 Dokumentation, Heracles Kapitel 2. Analyse Abbildung 2.8: UC3 ACEGI Provider Ausstieg/Beendigung • Der UC1 wirft eine Exception die dem ACEGI Framework weitergegeben wird. • Bei Erfolg werden die nötigen Informationen an ACEGI übergeben. Nachbedingungen • ACEGI besitzt die nötigen Informationen für eine erfolgreiche Authentifizierung. • ACEGI erhält eine Exception. 24 3 Architektur Dieses Kapitel beschreibt den Aufbau von Heracles. Von den eingesetzten Werkzeugen, über das Klassendiagramm der Modell-Klassen, zu den angepassten Schnittstellen von Heracles und bis zu den externen Applikationen. Ein weiteres wichtiges Thema der Architektur ist, wie Heracles seine Konfigurationsinformationen einliest. Im letzten Teil wird beschrieben wie die Problematiken aus der Analyse (siehe Kapitel 2.4) gelöst werden. 3.1 Werkzeuge Heracles baut auf der Java Version 1.51 auf. Java 1.5 enthält JNDI2 für eine LDAP Anbindung und JAAS3 für eine Authentifizierung gegenüber Kerberos. Für den Aufbau und den Betrieb von Heracles werden weitere Helfer eingesetzt. Im Folgenden werden ihre spezifischen Informationen und Einstellungen für Heracles erläutert. Heracles Paketstruktur Durch Maven 4 2.0 wird die Paketstruktur vorgegeben. Über das Plugin5 “site” wird die Projekthompage6 realisiert. Die Konfigurationsdatei pom.xml für Maven liegt direkt unter dem Projektverzeichnis. Das Projekt besitzt zwei Unterordner src und target. Im Verzeichnis src liegt der Quelltext des Programmes und der Projekthomepage. Der Quelltext der produktiven Applikation wird von dem Quelltext der Tests getrennt. Das Verzeichnis target enthält die kompilierten Java Klassen und das von Maven erstellte JAR-Archive7 von Heracles (siehe Abbildung 3.1). 1 2 Diese Version wird auch als Java 5.0 betitelt. Java Naming and Directory Interface; http://en.wikipedia.org/wiki/Java_Naming_and_Directory_ 3 Java Authentication and Authorization Service; http://en.wikipedia.org/wiki/Java_Authentication_ Interface and_Authorization_Service http://maven.apache.org/ 5 http://de.wikipedia.org/wiki/Plugin 6 Ist unter http://heracles.sourceforge.net erreichbar. 7 Java Archiv; http://de.wikipedia.org/wiki/Java_Archive 4 25 Dokumentation, Heracles Kapitel 3. Architektur Abbildung 3.1: Maven 2.0 Paketstruktur Objekterzeugung Für die Erzeugung der Objekte wird Spring8 in der Version 2.0 eingesetzt. Die Konfigurationsdatei heisst applicationContext.xml und liegt im Projektverzeichnis resources. Debugging Für das Debugging wird Log4j9 von Apache integriert. Die Konfiguration liegt unter resources und heisst log4j.xml. Testing Die Tests werden mit JUnit10 und mit den JUnit-Addons11 realisiert. Alle Testklassen liegen im Projektverzeichnis test. Für die Leistungs-Tests und den damit verbundenen Messungen wird JUnitPerf12 eingesetzt. 3.2 Klassendiagramm Abbildung 3.2 zeigt das Klassendiagramm der Modell-Klassen von Heracles. Dieses Klassendiagramm gehört in das Handbuch des Heracles Benutzers und der Inhalt in dessen Kopf. 8 http://de.wikipedia.org/wiki/Spring_(Framework) http://de.wikipedia.org/wiki/Log4j 10 http://de.wikipedia.org/wiki/JUnit 11 http://sourceforge.net/projects/junit-addons 12 http://clarkware.com/software/JUnitPerf.html 9 26 Dokumentation, Heracles Kapitel 3. Architektur Abbildung 3.2: Klassendiagramm Die Klasse LdapUser besitzt für sämtliche LDAP Attribute, die in der Analysephase im Kapitel 2.3 definiert sind, lokale Attribute. Jedes dieser Attribute besitzt eine Getter- und SetterMethode. Aus Gründen der Übersicht wurde darauf verzichtet, alle Attribute aus dem Kapitel 2.3 noch einmal aufzulisten. Die lokalen Attribute werden nicht abgekürzt, sondern ausgeschrieben. Zum Beispiel: Anstelle des LDAP Attributes “l” heisst das Java Attribut “location”. Dies soll zur Benutzerfreundlichkeit beitragen. Ein LdapUser kann mehrere Objekte von LdapGroup enthalten. Ein LdapGroup Objekt stellt eine Gruppe aus dem LDAP dar. Als einziges Attribut besitzt diese Klasse den Namen der LDAP Gruppe. Somit ist es möglich, über einen LDAP Benutzer herauszufinden, in welchen LDAP Gruppen er Mitglied ist. Durch die festgelegte Navigierbarkeit von LdapUser zu LdapGroup ist es möglich, über den Benutzer auf die Gruppe zu schliessen. Über eine Gruppe kann jedoch nicht herausgefunden werden, welche Mitglieder sie enthält. Diese Abfragemöglichkeit ist für Heracles nicht wichtig und nicht gefordert. 3.3 API Gegenüber dem Pflichtenheft hat sich die API ein wenig geändert. Die Methode getHeracles ist dazu gekommen. Die Parameter der Methode searchInLdap mussten geändert werden. Eine wichtige Rolle spielte dabei auch die Problematik, dass Heracles mehrere Domänen unterstützen muss. Das API ist keine Schnittstelle sondern eine abstrakte Klasse. Der Grund dafür ist die Methode getHeracles (siehe Abbildung 3.3). getHeracles Über diese Methode erhält eine externe Applikation eine Instanz des Frameworks. Sie ermöglicht, dass die externe Applikation den Hintergrund - die Implementation der 27 Dokumentation, Heracles Kapitel 3. Architektur Abbildung 3.3: Heracles API API - nicht kennen muss. Das Ganze ist als Singleton13 realisiert und somit erhalten die externen Applikationen immer das gleich Objekt bei mehreren Anfragen. authSimple Besitzt die externe Applikation eine Heracles-Instanz, so kann sie den Benutzernamen und das Passwort an diese Methode übergeben und es wird eine einfache Authentifizierung gemacht. authAdvanced Um die LDAP Informationen eines Benutzer zu erhalten, kann diese Methode genutzt werden. Die Übergabeparameter sind die Gleichen wie bei simpleAuth. searchInLdap Diese Methode kann in einer bestimmten Domäne das LDAP Verzeichnis durchsuchen. Dabei muss angegeben werden, in welchem LDAP Attribut was gesucht werden soll. Sie durchsucht alle Benutzerobjekte. Als Resultat werden alle Objekte, die im angegebenen Attribut die gesuchte Zeichenkette enthalten, zurückgegeben. Die Rückgabe erfolgt als Liste mit LdapUser Objekten. 3.4 Konfiguration von Heracles Dem Heracles Framework muss beim Einsatz mitgeteilt werden, wo sich die Dienste im Netzwerk befinden und mit welchen Berechtigungen darauf zugegriffen werden kann. Die Konfiguration wird in einer externen XML14 Datei gespeichert. Diese Konfigurationsdatei wird in ein Java Objektmodell umgesetzt, damit innerhalb von Heracles objektorientiert auf die entsprechenden Informationen zugegriffen werden kann. “Commons-Digester ” von Apache realisiert ein XMLJavaObjekt Mapping. Dieses Werkzeug vervollständigt die Werkzeugkiste für Heracles. 13 Ein Singleton kann mit der Hilfe des Singleton-Patterns der Gang of Four umgesetzt werden http://en. 14 Extensible Markup Language, http://de.wikipedia.org/wiki/Extensible_Markup_Language wikipedia.org/wiki/Singleton_pattern 28 Dokumentation, Heracles Kapitel 3. Architektur 3.4.1 Das Objektmodell Die Abbildung 3.4 zeigt das Objektmodell. Abbildung 3.4: Heracles Konfigurations Modell Über die Klasse HeraclesConfig sind unterschiedliche Domänenkonfigurationen und Realmkonfigurationen15 zugänglich. Die Klasse Domain repräsentiert eine reale LDAP Domäne und besitzt die wichtigsten Angaben für Heracles. name Dieses Attribut enthält den Namen der Domäne. Sie wird später wichtig, damit Heracles mehrere Domänen unterstützen kann (siehe Kapitel 3.7). principal Um ein LDAP Verzeichnis durchsuchen zu können, muss ein Account16 angegeben werden, welcher die entsprechenden Rechte im Verzeichnis besitzt. credential Das zum Principal zugehörige Passwort. provider Der Name “Provider” stammt von JNDI und referenziert die LDAP Server. 15 Aus dem Kapitel 2.1.2 wissen wir, das ein REALM nichts anderes als eine Domäne ist, einfach in der Sprache von Kerberos. 16 Zu einem Account gehört ein Benutzername und ein Passwort. 29 Dokumentation, Heracles Kapitel 3. Architektur searchBase Mit der Hilfe der SearchBase können Suchvorgänge eingeschränkt werden. Die SearchBase muss jedoch im DN-Format angegeben werden17 . emptyValues In der Analyse wurde erwähnt, dass die HFT-SO den Studierenden nicht die gleichen LDAP Attribute ausfüllt wie den Mitarbeitern. Der Wert dieses Attributes wird überall dort eingesetzt, wo ein LDAP Attribut keinen Wert hat. Die Klasse Realm, welche alle nötigen Angaben für Kerberos umfasst, ist wesentlich einfacher. Diese Klasse besitzt lediglich zwei Attribute. namen Dieses Attribut besitzt den Realmnamen von Kerberos und des zu authentifizierenden Benutzers. kdc Die Namen oder die IP-Adressen18 der Kerberos Server werden in diesem Attribut festgehalten. 3.4.2 Die XML Datei Im Anhang D ist die DTD19 Datei, welche den Aufbau der XML Datei für Heracles definiert und beschreibt. Listing 3.1 zeigt wie eine mögliche Konfigurationsdatei für Heracles aussieht. Auf der Zeile 5 von Linsting 3.1 ist das Wurzelelement. Dieses kann genau ein ldap-config und ein kerberos-config Element besitzen. Wie die Namen es schon verraten, werden in einem Element alle LDAP Angaben festgelegt und im Anderen alle Angaben für Kerberos. Ein ldap-config Element kann mehrere domain Elemente haben. Wobei jedes domain Element alle Informationen über eine LDAP Domäne enthält. Hier im Listing wird an einem Beispiel gezeigt, wie mehrere Domänencontroller einer Domäne angegeben werden können(siehe Zeile 10). Das Element kerberos-config ist ähnlich aufgebaut. Dieses kann mehrere realm Elemente beinhalten. Dabei wird der Name des Realms als Elementattribut angegeben und der KDC20 Server im Elementrumpf. Auch hier wurden mehrere KDC Server definiert. Listing 3.1: Heracles XML Konfigurationsdatei 1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <!DOCTYPE heracles PUBLIC "//UNKNOWN/" "heracles-config.dtd"> 4 5 6 7 <heracles> <ldap-config> <domain name="DOMAINNAME"> 17 Als Beispiel: dc=MYDOMAIN, dc=LOCAL. 18 http://de.wikipedia.org/wiki/IP-Adresse 19 Dokumenttyp-Definition; http://de.wikipedia.org/wiki/Dokumenttypdefinition 20 siehe Kapitel 2.1.2. 30 Dokumentation, Heracles 8 9 10 11 12 13 14 Kapitel 3. Architektur <principal>administrator@REALMNAME</principal> <credential>GEHEIM</credential> <provider>ldap://DC1:389/ ldap://DC2:389/</provider> <searchBase>DOMAIN DN</searchBase> <emtpyValues>no information</emtpyValues> </domain> </ldap-config> 15 16 17 18 19 <kerberos-config> <realm name="REALMNAME">KDC1 KDC2</realm> </kerberos-config> </heracles> 3.5 ACEGI Wir müssen zwei Klassen erstellen. Die Erste ist von der abstrakten Klasse AbstractUserDetailsAuthenticationProvider abgeleitet, während die Andere die SchnittstelleUserDetails implementiert (siehe Abbildung 3.5). Abbildung 3.5: ACEGI Heracles-Klassen 31 Dokumentation, Heracles Kapitel 3. Architektur Die abstrakte Klasse AbstractUserDetailsAuthenticationProvider ist abgeleitet von der Schnittstelle AuthenticationProvider. Ein Authentication Provider ist verantwortlich für die Authentifizierung der Benutzer. Es gibt eine Vielzahl von unterschiedlichen Providern. Einige davon übernehmen die Authentifizierung selber, zum Beispiel für eine Authentifizierung über eine Datenbank oder über ein XML Dokument. Wir wollen die Authentifizierung über Heracles machen und müssen somit einen eigenen Authentication Provider schreiben. In der Analyse wurde erläutert, wie LDAP die Dinge bezeichnet und Kerberos für die Selbigen andere Namen besitzt. Auch ACEGI bringt neue Namen für die gleichen Sachen. So zum Beispiel wird ein Benutzerobjekt zu einem UserDetails Objekt und die Gruppen werden als “Granted Authorities” bezeichnet. Die Methode additionalAuthenticationChecks müssen wir implementieren jedoch nicht ausprogrammieren, da die Checks von Heracles (resp. von Kerberos) gemacht werden. Die Klasse HeraclesUserDetails besitzt einen Konstruktor, welcher für alle Attribute, ausser für accountNonExpierd 21 , ein Parameter definiert hat. 3.6 Test Der Testarchitektur, den Testdaten und den Testprogramme ist ein eigenes Hauptkapitel gewidmet (siehe Kapitel 5). 3.7 Lösung der Probleme In der Analyse im Kapitel 2.4 wurden zwei festgestellte Probleme beschrieben. Durch die Architektur wurden beide Probleme gelöst. In diesem Kapitel wollen wir darauf näher eingehen. 3.7.1 Mehrere Domänen Diese Problematik wird mit zwei Punkten entschärft. Die Konfiguration von Heracles verlangt den Namen der LDAP-Domäne und der des Realms. Somit kann Heracles die Konfigurationen der unterschiedlichen ADS Domänen unterscheiden. Damit Heracles jedoch weiss welche dieser Konfigurationen er benötigt, muss die externe Applikation beim Aufruf der Methoden authSimple oder authAdvanced im Parameter username den Namen der Domäne mitgeben. 21 Diese Frage lässt sich über LDAP nicht beantworten, deshalb besitzt dieses Attribut immer den Wert true. 32 Dokumentation, Heracles Kapitel 3. Architektur In der Welt von Windows ist dies ein alt bewährtes Mittel. An der HFT-SO treffen wir bei der Anmeldung an Microsoft Outlook WebAccess22 oder bei Moodle23 diese Lösung an. Da der Parameter username ein einziger String ist, müssen wir Trennzeichen festlegen damit Heracles zwischen Benutzernamen und Domänennamen unterscheiden kann. Wir bleiben beim Konzept von Microsoft und nehmen als Trennzeichen \ und @. Heracles macht keinen Unterschied zwischen der Gross- und Kleinschreibung. Folgende zwei Beispiele sollen dies verdeutlichen. • hans.muster@NAME • NAME\hans.muster Dies hat zur Folge, dass die LDAP Domäne und der Realm von Kerberos immer den gleichen Namen in der Konfiguration erhalten. Ob diese Namen auch in der realen Welt existieren, spielt keine Rolle. 3.7.2 LDAP Attribute Heracles bietet die Möglichkeit an, dass der Benutzer bei der Konfiguration einen emptyValues Parameter definieren kann. Der Wert dieses Parameters setzt Heracles bei allen String LDAPAttributen ein, welche keinen Wert besitzen. Bei den Integer Attributen setzt Heracles den Wert auf 0. Tabelle 3.1 zeigt hier ein Beispiel wie die Ausgabe eines Mitarbeiters aussehen würde und die eines Studenten, wenn der Parameter emptyValues den Wert no info hätte. Mitarbeiter HFT-SO Mitarbeiter Hans Muster Sportstrasse 2 2540 Grenchen Studierende HFT-SO Studierende Susi Muster no info no info no info Tabelle 3.1: Beispiel: emptyValues Mithilfe dieses einheitlichen Strings kann die externe Applikation filtern und entsprechend reagieren. 22 Abkürzung OWA. Zugriff auf E-Mails der HFT-SO für Studierende, Dozierende und Mitarbeiter; https:// 23 Moodle ist eine OpenSource E-Learning Plattform, die die HFT-SO einsetzt; https://moodle.hft-so.ch webmail.hft-so.ch 33 Dokumentation, Heracles Kapitel 3. Architektur 3.8 Zusammenfassung Die Architektur von Heracles kann als Schichtenmodell zusammengefasst werden (siehe Abbildung 3.6). Heracles wird in die drei Architekturschichten Präsentations-24 , Service-25 und Datenzugriffsschicht26 unterteilt. Jede dieser Schichten stellt der nächst Höheren eine Schnittstelle zur Verfügung, über welche sie kommunizieren. In der Präsentationsschicht von Heracles befindet sich anstelle der Benutzeroberfläche die API27 . Auf der rechten Seite der Abbildung 3.6 sind die Modell-Klassen von Heracles dargestellt. Es ist schön zu sehen, dass diese Klassen in allen Schichten von Heracles genutzt werden, aber auch in den externen Applikationen. Die grün markierten Elemente realisieren die Datenzugriffsschicht (DAO ist die Abkürzung von Data Access Object). Hier wird auf die Konfigurationsdatei zugegriffen und da findet auch die Kommunikation zu den SUN APIs JNDI und JAAS statt. Die wichtigsten Werkzeuge die im Kapitel 3.1 beschrieben wurden, sind orange in der Abbildung festgehalten. Spring und Log4J werden in allen Schichten eingesetzt. Commons-Digester, für das Mapping XML-JavaObjekt, wird in der Datenzugriffsschicht genutzt. 24 Beinhaltet die Benutzeroberfläche einer Applikation. Sie besitzt die Logik, das Wissen einer Applikation. 26 Verantwortlich für die Verwaltung der Nutzdaten einer Applikation. 27 Die API kann aus der Sicht einer externen Applikation auch als Benutzeroberfläche angesehen werden. 25 34 Dokumentation, Heracles Kapitel 3. Architektur Abbildung 3.6: Schichtenmodell 35 4 Design, Implementation und Tests Dieses Kapitel beschreibt die Realisierung der einzelnen UseCase aus Kapitel 2.5. Ein Sequenzdiagramm wird das Design des einzelnen UseCases vermitteln und der Leser erhält eine Orientierung mit der er sich in Heracles zu recht finden wird. Anschliessend zum Diagramm wird der Leser auf die wichtigsten Punkte des UseCases aufmerksam gemacht. Somit erhält er die Kenntnisse der Eigenheiten von Heracles. Jeder UseCase wird nach der Implementierung auch gleich mithilfe von JUNIT getestet. Am Ende des Kapitels gehen wir auf die Umsetzung der Konfigurationsmöglichkeit von Heracles ein. 4.1 Einleitung Bevor mit der konkreten Implementierung der UseCases begonnen werden kann wird das Gerüst für Heracles erstellt. Dieses Gerüst umfasst alles aus der Architektur. • Erstellen des Projektes mittels Maven. • Anlegen der Paketstruktur und das Realisieren der Klassendiagramme. • Die zusätzlichen Frameworks in Maven konfigurieren. • Für die einzelnen Schichten leere Schnittstellen eröffnen. Im Kapitel 3.3 ist bereits erwähnt, dass die API von Heracles eine abstrakte Klasse ist und dass das Singleton Pattern eingesetzt wird. Das Listing 4.1 zeigt den dazugehörigen CodeAusschnitt. Listing 4.1: Heracles als Singleton 1 2 3 4 5 6 7 8 9 private static Heracles heracles; .. . public static Heracles getHeracles() if (heracles == null) { heracles=new HeraclesImpl(); } return heracles; } { 36 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests Die Methode aus Listing 4.1 erzeugt ein neues HeraclesImpl Objekt. Im Konstruktor dieser Klasse wird der Spring Container initialisiert1 . Das Listing 4.2 zeigt wie ein Spring Container in einer “nicht Web-Applikation” initialisiert werden kann. Listing 4.2: Spring Container initialisieren 1 2 3 4 5 6 public HeraclesImpl(){ String path=this.getClass().getResource("/applicationContext.xml").toString(); ApplicationContext ctx = new FileSystemXmlApplicationContext(path); auth = (Authentication) ctx.getBean("auth"); search = (Search) ctx.getBean("search"); } Die Zeile 3 erzeugt ein ApplicationContext Objekt, dabei wird der Pfad zur Spring XML Konfigurationsdatei übergeben. Die Zeile 4 erzeugt ein im XML definiertes Objekt mit dem Namen “auth”, die Zeile 5 ein Objekt “search”. Spring erstellt daraufhin automatisch die zusätzlichen Objekte von dem die Objekte “auth” und “search” abhängig sind. Nun steht das Gerüst und wir können mit dem UseCase UC1 beginnen. 4.2 UC1: Authentifizierung Der UC1 besitzt in der API (siehe Kapitel 3.3) zwei Methoden. Das Sequenzdiagramm 4.1 zeigt, dass der Aktor externe Applikation erst eine Instanz von Heracles benötigt und anschliessend kann er eine einfache Authentifizierung durchführen. Hinter der API2 wird die Anfrage an die Serviceschicht und an die Datenzugriffsschicht weitergereicht. Die Datenzugriffsschicht nutzt den Aktor JAAS. Wir gehen später näher darauf ein. Der Aktor liefert der Datenzugriffsschicht ein Objekt und dieses wird an die Serviceschicht übergeben. Hier endet die einfache Authentifizierung. Das Sequenzdiagramm 4.2 stellt die erweiterte Authentifizierung dar. Auf den ersten Blick ähnelt dieses Diagramm dem Diagramm der einfachen Authentifizierung. Jedoch ruft der Aktor externe Applikation eine andere Methode der API auf. Diese ruft ebenfalls eine Andere in der Serviceschicht auf. Die Serviceschicht nutzt für die Authentifizierung die gleichen Objekte und Methoden wie eine einfache Authentifizierung. Jedoch dort wo die einfache Authentifizierung endet ruft die erweiterte Authentifizierung den UseCase UC2 auf, indem die Methode searchInLdap der Schnittstelle Search aufgerufen wird. Ist die Arbeit des UseCase UC2 erledigt erhält die Serviceschicht des UC1 eine Antwort, die sie über das API dem Aktor externe Applikation übergeben kann. 1 Der Spring Container kann nicht direkt in einer abstrakten Klasse geladen werden. Mehr Informationen sind im Anhang B.1 2 Die Objekte im Sequenzidagramm sind so beschriftet, dass erst der Paketname (z.B. Service) und danach der Name der Schnittstelle (z.B. Authentication) folgt. Auf die Parameter der Methoden wurde aus Gründen der Übersicht verzichtet. 37 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests Abbildung 4.1: UC1 Sequenzdiagramm authSimple Abbildung 4.2: UC1 Sequenzdiagramm authAdvanced 38 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests 4.2.1 Validierung In der UseCase Beschreibung aus Kapitel 2.5 steht, dass der UC1 eine Validierung macht. Diese prüft zwei Dinge: • Ist einerseits das Format des Benutzernames korrekt und • ist dass Passwort nicht null. Diese findet in der Implementation der Service Schnittstelle statt. Beide Methoden authSimple und authAdvanced der Serviceschicht rufen eine private Methode validating auf. Diese prüft erst ob der String username ein gültiges Format besitzt. Schlägt die Validierung fehl, so wird eine HeraclesException mit einer entsprechenden Fehlermeldung geworfen. Listing 4.3 zeigt den Methodenrumpf. Interessant ist die Zeile 1. Der “\” ist unter Java ein Sonderzeichen. Bei der Arbeit mit Regular Expressions muss, wenn mit einem Backslash gearbeitet wird, vier Backslashe verwendet werden3 . Listing 4.3: UC1 Validator 1 2 3 4 5 6 7 8 9 10 String[] parts = username.split("\\\\"); String[] parts2 = username.split("@"); if (parts.length != 2) { if (parts2.length != 2) { throw new HeraclesException("The username contains no domain info. (DOMAIN\\ username or username@DOMAIN)"); } } if (password == null) { throw new HeraclesException("The password could not be NULL"); } 4.2.2 Einsatz von JAAS Listing 4.4: UC1 JAAS 1 2 Subject kerberosSubject = null; Realm realm=heraclesConfig.getRealm(domainname); 3 4 5 6 System.setProperty("java.security.auth.login.config", this.getClass().getResource("/ heracles.conf").toString()); System.setProperty("java.security.krb5.realm", realm.getName()); System.setProperty("java.security.krb5.kdc", realm.getKdc()); 7 8 9 10 loginContext = new LoginContext("kerberos", new Krb5CallbackHandler(username, password)); loginContext.login(); kerberosSubject = loginContext.getSubject(); 3 Mehr Informationen zu Regular Expressions und “\” hier; http://www.regular-expressions.info/java.html 39 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests In beiden Sequenzdiagrammen 4.1 und 4.2 nutzt die Datenzugriffsschicht den Aktor JAAS. JAAS verfügt über eine Konfigurationsdatei. Diese muss vor dem ersten Gebrauch von JAAS angegeben werden. Dies wird auf der Zeile 4 des Listings 4.4 gemacht, indem eine (von JAAS definierte) Umgebungsvariable gesetzt wird. Über zwei weitere Umgebungsvariablen wird dem JAAS Framework mitgeteilt, welcher Realm und welchen KDC uns interessiert. Im Listing 4.4 ist das auf den Zeilen 5 und 6 ersichtlich. bei hier auf das Klassenmodell aus dem Kapitel 3.4.1 zugegriffen wird. Nach den Umgebungsvariablen ist es möglich ein LoginContext Objekt zu erzeugen. Als Parameter wird einerseits der Name des Konfigurationabschnittes aus der Konfigurationsdatei und andererseits ein Objekt, welches von der Schnittstelle CallbackHandler abgeleitet ist, übergeben. Die Aufgabe des CallbackHandlers ist es, die erforderlichen Login-Informationen des Benutzers innerhalb von JAAS zu verarbeiten. Im Anhang E ist der Handler für Kerberos. Über den Aufruf der Methode login() wird die Authentifizierung gemacht (Zeile 9 des Listings 4.4). Schlägt die Authentifizierung fehl, wirft JAAS eine LoginException. Bei einer erfolgreichen Anmeldung kann mittels der Methode getSubject() das Subject ermittelt werden, welches die ermittelten Benutzerinformationen aus Kerberos enthält (Zeile 10). Listing 4.5 offenbart den Inhalt einer möglichen JAAS Konfigurationsdatei. Der Ausdruck vor der geschweiften Klammer ist der Name des Abschnittes, welcher dem Konstruktor der Klasse LoginContext als Parameter mitgegeben werden muss. Listing 4.5: UC1 JAAS 1 2 3 4 5 kerberos { com.sun.security.auth.module.Krb5LoginModule required debug=false useTicketCache=false }; Die drei Konfigurationsparameter aus dem Listing 4.5 haben folgende Aussagen. JAAS muss das LoginModul von Kerberos nutzen. Der Debug-Modus für die Fehlerbehebung soll ausgeschaltet und der Ticket Cache nicht genutzt werden. Hat der Computer, auf welchem Heracles läuft, bereits eine Kerberos Anmeldung erfolgreich gemacht4 , wird das Kerberos Ticket in einen speziellen Bereich im RAM abgelegt. JAAS kann auf diesen Bereich zugreifen und würde jenes Ticket nutzen und keine Kerberos Authentifizierung mehr versuchen. Für Heracles muss dieses Single Sign-On5 Verfahren ausgeschaltet werden. 4 Dies kann der Fall sein, wenn beispielsweise der Computer sich an der ADS Domäne bereits angemeldet wurde. 5 http://de.wikipedia.org/wiki/Single_Sign-On 40 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests 4.2.3 Exception Handling Heracles verarbeitet keine Exceptions. Alle Exceptions werden der externen Applikation übergeben. Diese ist selber verantwortlich für deren Verarbeitung. Aus diesem Grund ist es wichtig zu verstehen, welche Exceptions der UC1 wirft und was diese bedeuten. Stimmen die Login-Informationen (Benutzername und Passwort) nicht überein, so wirft der UC1 die folgende Exception: javax.security.auth.login.LoginException: Pre-authentication information was invalid (24) Kann das JAAS den oder die KDCs nicht ermitteln, wird das an einer fehlerhaften Heracles Konfiguration oder an einem Netzwerkproblem liegen. Dann wird folgende Exception ausgegeben: javax.security.auth.login.LoginException: SERVERNAME: SERVERNAME Wenn das Format des Benutzernamens mit der Angabe der Domäne nicht korrekt ist, wird folgende Exception geworfen: net.sourceforge.heracles.utilities.HeraclesException: The username contains no domain info. (DOMAIN\username or username@DOMAIN) Ist das Format korrekt, aber der Name der Domäne falsch geschrieben, dann wird diese Exception geworfen: net.sourceforge.heracles.utilities.HeraclesException: No realm would be found in the XML File with the name: XXXX Hat der Benutzer als Passwort null übergeben wird diese Exception geworfen: net.sourceforge.heracles.utilities.HeraclesException: The password could not be NULL Es besteht auch die Möglichkeit, dass eine NamingException geworfen wird. Dabei handelt es sich jedoch um ein LDAP Problem des UseCases UC2. Diese Exceptions werden im Abschnitt des UC2 erläutert. 4.2.4 JUNIT Tests Der UseCase UC1 besitzt drei 3 JUnit Methoden für die funktionellen Tests und 2 Methoden für die performance Tests. Die Methoden testAuthSimple() und testAuthAdvanced() testen über die Heracles API die einfache und erweiterte Authentifizierung. Die Methode testValidatiung() prüft den Validator. Abbildung 4.3 deutet auf erfolgreiche Tests hin. 41 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests Abbildung 4.3: UC1 funkionelle JUnit Tests Die beiden performance Tests testen die Latenzzeiten6 des UseCases. Die Ausgangswerte für die Latenzzeit-Berechnung kennen wir (siehe Kapitel 5.4.2). JUnitPerf ermöglicht uns die maximal Zeit eines Vorgangs zu definieren. Bei einer Überschreitung wirft das Framework eine Exception. JAAS benötigt durchschnittlich 820ms für eine Authentifizierung. Bei einer einfachen Authentifizierung reicht Heracles die Anfrage durch zwei Schichten hindurch und validiert dabei die Methoden Parameter. Wir legen fest, dass dieser Vorgang maximal 300ms länger dauern darf. Wir fügen 200ms dazu für die Faktoren JUnit und JUnitPerf. Schlussendlich darf eine einfache Authentifizierung maximal 1250ms benötigen. Die erweiterte Authentifizierung benötigt mindestens die Zeit 1250ms. Hinzu kommt der UseCase UC2 mit der LDAP Abfrage. Aus der Tabelle 5.3 ist ersichtlich, dass JNDI mindestens 490ms benötigt. Diese Zeit addieren wir zur Zeit der einfachen Authentifizierung und erhalten eine maximale Zeit von 1750ms. Die Abbildung 4.4 zeigt die Resultate der performance Tests. Abbildung 4.4: UC1 performance JUnit Tests Im Kapitel 5.5 wird darauf hingewiesen, dass die gemessenen Zeiten von Maven nicht stimmen. Dies hat gravierende Auswirkungen bei den performance Tests mit JUnitPerf. Unter Eclipse sind die Test erfolgreich, doch beim Kompilieren des Maven Projektes schlägt meistens der Erste performance Test fehl. 4.3 UC2: Ldap abfragen Wie beim UC1 benötigt der Aktor externe Applikation eine Heracles-Instanz. Das Sequenzdiagramm 4.5 betont, dass die Suchanfrage der externen Applikation bis in die Datenzugriffsschicht zum Objekt LdapQuery durchgereicht wird. Mit der Hilfe von JNDI greift die Datenzugriffsschicht auf den LDAP Server zu und dieser liefert die Suchresultate. Die gleiche Schicht verar6 Diese sind im Kapitel 5.4 näher beschrieben. 42 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests beitet die Resultate und erstellt die nötigen LdapUser und LdapGroup Objekte7 . Diese Objekte werden am Ende durch alle Schichten durchgereicht bis zur externen Applikation. In der Beschreibung des Sequenzdiagrammes 4.2 steht, dass über die Schnittstelle Search der Serviceschicht auf den UseCase UC2 zugegriffen wird. Der UC1 startet nicht, wie eine externe Applikation, den UC2 über die API. Im Sequenzdiagrammes 4.5 wird auf den UC1 verzichtet. Abbildung 4.5: UC2 Sequenzdiagramm 4.3.1 Validierung Synonym zum UseCase UC1 befindet sich der Validator in der Serviceschicht mit dem gleichen Methodennamen validating. Die Aufgabe des Validators des UC2 ist es, die Parameter der Me7 Dies ist im Diagramm sehr vereinfacht dargestellt. 43 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests thode searchInLdap() auf den Wert null zu prüfen. Das Listing 4.6 zeigt den dazugehörigen Code. Listing 4.6: UC2 Validator 1 2 3 4 5 6 7 8 9 if(domainName==null){ throw new HeraclesException("The domainName value NULL is not valid"); } if (where==null) { throw new HeraclesException("The where value NULL is not valid"); } if (like==null) { throw new HeraclesException("The like value NULL is not valid"); } 4.3.2 Einsatz von JNDI Für ein einfaches Verständnis können wir die einzelnen Schritte von JNDI in drei Teile aufteilen. Wir gehen Schrittweise vor und definieren als Erstes das Was, zweitens das Wo und zu letzt das Weshalb. Die Suche Das Was beantwortet was wir machen wollen: “Wir wollen etwas suchen”. Somit müssen wir die Suche konfigurieren. Das Listing 4.7 zeigt wie so etwas aussehen könnte. Listing 4.7: UC2 Die Suche 1 SearchControls search = new SearchControls(); 2 3 4 5 6 7 8 9 String returnedAtts[] = { "sn", "givenName", "cn", "displayName", "distinguishedName", "userPrincipalName", "description", "mail", "mailNickname", "telephoneNumber", "lastLogon", "logonCount", "memberOf", "userAccountControl", "company","department","title","streetAddress","postalCode","l", "st","c","wWWHomePage" }; 10 11 search.setReturningAttributes(returnedAtts); 12 13 String searchBase = "HFT-SO.BBZ-SG.LAN"; 14 15 search.setSearchScope(SearchControls.SUBTREE_SCOPE); 16 17 String searchFilter = "(&(objectClass=user)("userPrincipalName"="[email protected] -SG.LAN"))"; Erst wird ein SearchControls Objekt instanziert. Der Klassenname des Objektes deutet darauf hin, dass dieses Objekt die Suche steuern/beeinflussen kann. 44 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests Die Zeilen 3-9 definieren die Namen der Attribute welche abgefragt und als Resultat erwartet werden. Hier sind alle Attribute festgehalten welche in der Analyse im Kapitel 2.3 definiert wurden. Die Reihenfolge spielt bei der Auflistung keine Rolle. Die Namen der Attribute werden in einem String-Array festgehalten und dieses wird auf der Zeile 11 dem SearchControls Objekt übergeben. Das searchBase Objekt auf Zeile 13 legt fest, dass die Suche vom angegebenen LDAP Container aus startet. Auf der Zeile 15 definieren wir, dass wir unterhalb des Ausgangspunkt den ganzen LDAP Baum durchsuchen möchten und nicht nur die Ebene des Ausgangspunktes. Über einen Filter können wir schliesslich einschränken was wir im LDAP suchen. Der Filter auf der Zeile 17 bedeutet, dass wir nach einem Benutzerobjekt suchen (objectClass=user). Dieses Objekt muss im LDAP Attribut userPrincipalName den Wert [email protected] besitzen. In Heracles heissen diese beiden Angaben like und where. Die Umgebung Ist die Suche festgelegt, so müssen wir das Wo dieser Suche festlegen. In unserem Fall ist dies das LDAP Verzeichnis auf einem oder mehreren LDAP Servern. Listing 4.8: UC2 Die Umgebung 1 Hashtable<String, String> envoierment = new Hashtable<String, String>(11); 2 3 4 5 6 envoierment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory") ; envoierment.put(Context.PROVIDER_URL, "hftso1.hft-so.bbz-sg.lan"); envoierment.put(Context.SECURITY_PRINCIPAL, "administrator"); envoierment.put(Context.SECURITY_CREDENTIALS, "secret"); 7 8 9 DirContext ctx = new InitialDirContext(envoierment); ctx.search(searchBase, searchFilter, search); Erstellen wir erst einmal eine Hashtable. Diese füllen wir mit allen nötigen Informationen, die die Umgebung für unseren Suchvorgang beschreiben (siehe Listing 4.8). Auf den Zeilen 3-6 werden die Informationen in die Hashtable gelegt. Erst die Information, dass wir eine LDAP Umgebung haben und anschliessend die Informationen zum Server8 . Sind alle diese Angaben in der Hashtable abgelegt, kann diese als Parameter des Konstruktors für ein neues InitialDirContext 9 mitgegeben werden. Das erzeugte InitialDirContext Objekt ist in der Lage auf den Verzeichnisdienst zu zugreifen. Auf der letzten Zeile des Listing 4.8 durchsuchen wir unsere LDAP Umgebung mit den zuvor beschriebenen Suchangaben. 8 9 Wie die Adresse und dem Account mit der Berechtigung das LDAP Verzeichnis zu durchsuchen. Das “Dir” im Namen weist darauf hin, dass es sich um ein Directory (deutsch Verzeichnis) Dienst handelt und nicht um einen Namensdienst. 45 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests Die Suchresultate Bis jetzt haben wir eine Suchabfrage definiert, die Umgebung der Suche festgelegt und die Suche gestartet. Was noch fehlt ist die Verarbeitung der Suchresultate. Wenn wir die Suche starten (wie oben beschrieben) liefert sie uns ein NamingEnumeration Objekt. Diese Enumeration enthält alle, also auch mehrere Suchresultate. Über eine While-Schleife können wir jedes einzelne Resultat heraus holen und verarbeiten. Listing 4.9 zeigt den Java-Code. Listing 4.9: UC2 Die Suchresultate 1 NamingEnumeration resultSet = ctx.search(searchBase, searchFilter, search); 2 3 4 5 6 7 8 9 10 while (resultSet.hasMoreElements()) { try { SearchResult searchResult = (SearchResult) resultSet.next(); System.out.println("Results are: " + searchResult.getAttributes()); } catch (NamingException ex) { ex.printStackTrace(); } } 4.3.3 LdapUser und LdapGroup Objekte Die Funktionsweise von JNDI haben wir im Kapitel 4.3.2 gesehen. Die Suchresultate müssen wir nun aus einem SearchResult Objekt überführen in unser Klassenmodell aus Kapitel 3.2. Für diesen Zweck besitzt die Klasse LdapQuery eine Methode createLdapUser. Jedes einzelne SearchResult Objekt wird zu einem LdapUser Objekt. Ein SearchResult Objekt besitzt nur wenige Methoden um die Aufgabe zu erfüllen. Wir benötigen ein neues Objekt der Schnittstelle javax.naming.directory.Attributes. Diese Schnittstelle ist vom Typ “Collection” die wie ein Container zu hand haben ist. Über diesen Container können wir auf die einzelnen LDAP Attribute zugreifen. Listing 4.10 holt den Container aus dem Suchresultat. Listing 4.10: UC2 LDAP Attribut 1 Attributes userAttributes = searchResult.getAttributes(); Listing 4.11 zeigt wie einzelne Attribute aus dem Container herausgeholt und auf der Console ausgegeben werden. Die Ausgabe ist im Listing enthalten. Listing 4.11: UC2 LDAP Attribut Ausgabe 1 2 3 4 5 System.out.println(userAttributes.get("cn").toString()); .. .. // Ausgabe cn: Muster Hans 46 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests Auf der Console wird der Wert des LDAP-Attributes nicht alleine dargestellt. Wir müssen die Ausgabe noch ein wenig ändern, damit nur noch der Wert ausgegeben wird. Diesen können wir dann einem LdapUser Objekt übergeben. Listing 4.12 macht dazu ein Beispiel. Listing 4.12: UC2 LDAP Attribut für LdapUser Objekt 1 LdapUser ldapUser = new LdapUser(); 2 3 4 5 6 7 try { ldapUser.setCommonname(userAttributes.get("cn").toString().replaceFirst("cn: ", "")); } catch (NullPointerException ex) { ldapUser.setCommonname(emptyValues); } Das Ganze machen wir mit jedem einzelnen LDAP Attribut des Containers und übergeben sie dem LdapUser Objekt. Nun leider ist es doch nicht ganz so einfach. Denn wir haben drei LDAP Attribute, die wir nicht ohne weiteres auf diese einfache Art übergeben können. lastLogon Das LDAP Attribute lastLogon speichert die Information, wann sich ein LDAP Benutzerobjekt das letzte Mal angemeldet hat. Leider ist diese Information nicht als Datumswert festgehalten sondern als Zahlenwert. Die Klasse LdapQuery konvertiert diesen Zahlenwert zu einem Datumswert und übergibt dies dem LdapUser Objekt. Für diese Konvertierung müssen wir wissen, wie dieser Zahlenwert berechnet wird. Microsoft hat für seine Berechnung ein Ausgangsdatum gewählt, den 01.01.160110 . Vom Ausgangsdatum aus werden nun die Anzahl 100-Nanosekunden bis zum gewünschten Datum berechnet. Diese Anzahl ergibt den Zahlenwert. Über dieses Thema und über die Konvertierung selbst wurde ein Forumsbeitrag11 bei SUN gefunden. Das Listing 4.13 erläutert wie wir von der Anzahl 100-Nanosekunden zu einem Datumswert kommen. Auf der ersten Zeile ist zusehen, dass wir ein neues Date Objekt erzeugen mit der Information, dass das Ausgangsdatum der 01.01.1601 sein soll. Wir ermitteln davon die Anzahl Millisekunden. Wichtig: Java liefert einen negativen Wert, da das Ausgangsdatum in der Vergangenheit liegt. Bei der Rechnung auf Zeile 3 wandeln wir den Zahlenwert von Microsoft in Anzahl Millisekunden12 um und subtrahieren13 die Anzahl Millisekunden des Java Objektes. 10 Java geht auf dieselbe Art mit Datumswerten um. Einziger unterschied ist, dass bei Java das Ausgangsdatum der 01.01.1970 ist. 11 http://forum.java.sun.com/thread.jspa?threadID=716240&messageID=4267441 12 Deshalb dividieren wir durch 10’000. Da der Zahlenwert negativ ist, müssen wir diesen Addieren. 13 47 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests Das Resultat ist die Differenz und diese können wir dem Konstruktor für ein neues Date Objekt übergeben. Dieses geben wir dem LdapUser Objekt. Listing 4.13: UC2 Konvertieren von Integer zu Date 1 2 3 4 GregorianCalendar win32Epoch = new GregorianCalendar(1601, Calendar.JANUARY, 1); Long lWin32Epoch = win32Epoch.getTimeInMillis(); long ldate = (((lastLogon / 10000) + lWin32Epoch)); Date date = new Date(ldate); memberOf Das Listing 4.11 hat aufgezeigt, wie auf einzelne Attribute eines Suchresultates zugegriffen werden kann. Die Problematik des LDAP Attributes memberOf ist, dass dieses Attribut eine Liste mit mehreren Information enthält und nicht wie alle anderen einfach nur einen Wert. Aus diesem Grund müssen wir alle Elemente einzeln aus der Liste holen und einzeln verarbeiten. Listing 4.14 zeigt den Code. Listing 4.14: UC2 Gruppenzugehörigkeit 1 NamingEnumeration roles = userAttributes.get("memberOf").getAll() 2 3 List<LdapGroup> groups = new ArrayList<LdapGroup>(); 4 5 6 7 8 9 10 11 12 13 while (roles.hasMoreElements()) { String fullRoleName = roles.nextElement().toString(); if (fullRoleName.indexOf("CN") != -1) { String roleName = fullRoleName.substring(fullRoleName.indexOf("CN") + 3, fullRoleName.indexOf(",")); groups.add(new LdapGroup(roleName)); } else { logger.info("user has no roles"); } } Wir holen aus dem userAttributes Objekt den Container und über eine While-Schleife greifen wir auf die einzelnen Werte zu. Ein Wert speichert den DN der LDAP Gruppe, von welcher der LDAP Benutzer ein Mitglied ist. Wir modifizieren den DN auf der Zeile 8, damit wir den kurzen CN der Gruppe erhalten. Diesen Namen können wir dann schlussendlich als Parameter für den Konstruktor eines neuen LdapGroup Objektes übergeben. Die Liste mit allen neuen LdapGroup Objekten können wir dem LdapUser Objekt übergeben14 . 14 ldapUser.setLdapGroups(groups) 48 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests userAccountControl Bereits im Kapitel 2.3 wurde darauf hingewiesen, dass das LDAP Attribut userAccountControl mehrere Informationen speichert. Bestimmte Zahlenwerte des Attributes haben eine feste Bedeutung. Diese sind bei Microsoft15 tabellarisch festgehalten. Für uns sind drei Informationen interessant. Account deaktiviert Wurde das Benutzeraccount deaktiviert? Zahlenwert=2 Account gesperrt Ist das Benutzeraccount gesperrt? Zahlenwert=16 Passwort abgelaufen Ist das Passwort des Benutzers abgelaufen? Zahlenwert=8388608 Machen wir ein Beispiel. Nehmen wir an, das LDAP Attribut hat den Wert 530. Dies würde bedeuten, dass es sich um ein “Normales Account” handelt (512), dass dieses Account aber gesperrt ist (16) und dass der Account auch deaktiviert sein muss (2). Zählt man die Werte zusammen (512+16+2) so erhalten wir 530. Das Listing 4.15 zeigt den Code wie die Informationen aus dem LDAP Attribut herausgeholt werden können. Als Ausgangsvariable wurde der höchste Zahlenwert aus der Microsoft Tabelle genommen. Listing 4.15: UC2 UserAccountControl Attribut 1 int userAccountControl=XXXX 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 int ausgang = 16777216; int resultat; while (userAccountControl != 0) { resultat = userAccountControl - ausgang; if (resultat >= 0) { if (ausgang == 8388608) { // Passwort ist abgelaufen } if (ausgang == 16) { // Account ist gesperrt } if (ausgang == 2) { // Account ist deaktiviert } ausgang = ausgang / 2; userAccountControl = resultat; } else { ausgang = ausgang / 2; } 15 http://support.microsoft.com/kb/305144/de 49 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests 4.3.4 Exception Handling Wie in UC1 gibt es auch im UC2 viele verschiedene Gründe für Exceptions, welche an die externen Applikationen übergeben werden. Der Validator schlägt fehl falls ein Methoden Parameter null ist, so können folgende drei Exceptions geworfen werden. net.sourceforge.heracles.utilities.HeraclesException: The domainName value NULL is not valid net.sourceforge.heracles.utilities.HeraclesException: The where value NULL is not valid net.sourceforge.heracles.utilities.HeraclesException: The like value NULL is not valid Besitzt die Suche keine Resultate, wird auch eine Exceptions geworfen. Kein Suchresultat kann mehrere Gründe haben. Es gibt wirklich kein Resultat oder die Suche ist falsch definiert. net.sourceforge.heracles.utilities.HeraclesException: There are no results for this search Wird ein Domänenname als Parameter übergeben den es in der Konfigurationdatei nicht gibt, wird folgende Meldung ausgegeben. net.sourceforge.heracles.utilities.HeraclesException: No domain would be found in the XML File with the name: XXXX Sind die Anmeldeinformationen falsch wird eine AuthenticationException geworfen. Bei einem falschen Passwort heisst die Exception ...data 525..., bei einem unbekannten Benutzernamen ...data 52e.... javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 525, vece javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 52e, vece Wird der oder die Server nicht gefunden, falsche Adresse oder falscher Port, werden folgende Exceptions geworfen. javax.naming.CommunicationException: SERVER:389 [Root exception is java.net.UnknownHostException: SERVER] javax.naming.CommunicationException: SERVER:388 [Root exception is java.net.ConnectException: Connection refused: connect] 4.3.5 JUNIT Test Dieser UseCase besitzt vier funktionelle Tests und einen performance Test. 50 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests Ein funktioneller Test prüft den ganzen UC2 aus der Sicht einer externen Applikation. Einer prüft den Validator und die beiden Anderen prüfen die Methoden zur Verarbeitung der LDAP Attribute lastLogon und userAccountControl. Die Abbildung 4.6 zeigt die erfolgreichen Tests. Abbildung 4.6: UC2 funktionelle JUnit Tests JNDI benötigt für eine LDAP Abfrage 490ms (siehe Tabelle 5.3). Die Anfrage einer externen Applikation wird bis in die Datenzugriffsschicht gereicht. Nach der Suche muss aus jedem Suchresultat ein LdapUser Objekt erstellt werden. Für einen Suchvorgang mit 10 Resultaten geben wir 300ms Zeit. Dazu addieren wir, wie beim UC1, 200ms für JUnit und JUnitPerf. Abbildung 4.7 zeigt die Testresultate. Abbildung 4.7: UC2 performance JUnit Tests 4.4 UC3: Acegi Provider Das Sequenzdiagramm 4.8 zeigt, dass ACEGI eine Methode der Klasse HeraclesAuthenticationProvider aufruft. Diese Methode nutzt die erweiterte Authentifizierung von Heracles. Nach einer erfolgreichen Authentifizierung übergibt Heracles ihr ein LdapUser Objekt. Die gleiche Methode erstellt später ein HeraclesUserDetails Objekt. Am Ende übergibt sie ein Objekt des Typs UserDetails an ACEGI . 4.4.1 Funktionsweise In der Architektur im Kapitel 3.5 wurde die nötige Architektur für den UseCase UC3 beschrieben. Zusammengefasst sieht die Situation wie folgt aus. ACEGI arbeitet mit Authentication Providern, da ACEGI kein Provider für Heracles besitzt, müssen wir einen eigenen realisieren. Weiter Arbeitet ACEGI ausschliesslich mit Objekten des Typs UserDetails und GrantedAuthority. Dies hat zur Folge, dass wir aus den LdapUser Objekten und LdapGroup Objekten die uns Heracles liefert, UserDetails Objekte und GrantedAuthority Objekte machen müssen. Wenn ACEGI ein Benutzer authentifizieren möchte, so übergibt er der Methode retrieveUser des Authentication Providers den Benutzernamen und das Passwort. Das Passwort wird jedoch nicht als String übergeben, sondern als ein UsernamePasswordAuthenticationToken Objekt. Für 51 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests Abbildung 4.8: UC3 Sequenzdiagramm eine erweiterte Authentifizierung müssen wir das Passwort als String an Heracles übergeben. Das Listing 4.16 zeigt den Code. Listing 4.16: UC3 erweitere Authentifizierung 1 2 3 4 Heracles heracles = Heracles.getHeracles(); String password = null; password = (String) userNamePasswdAuthToken.getCredentials(); LdapUser ldapUser = heracles.authAdvanced(userName, password); Nach dem Listing 4.16 wurde die Authentifizierung des Benutzers bereits gemacht. Wir müssen nun nur noch das erhaltene LdapUser Objekt so verarbeiten, dass es ACEGI akzeptiert. Dazu erstellen wir aus den LdapGroup Objekten, welche im LdapUser Objekt enthalten sind GrantedAuthority Objekte (siehe Listing 4.17). Listing 4.17: UC3 GrantedAuthority Objekte 1 2 3 4 5 6 7 GrantedAuthority[] authorities = new GrantedAuthority[ldapUser.getLdapGroups().size ()]; Iterator iter = ldapUser.getLdapGroups().iterator(); int i = 0; while (iter.hasNext()) { LdapGroup ldapGroup = (LdapGroup) iter.next(); authorities[i++] = new GrantedAuthorityImpl(ldapGroup.getName()); } Haben wir die GrantedAuthority Objekte, geht es nun darum aus dem LdapUser Objekt ein UserDetails Objekt zu erzeugen. Hier kommt nun unsere Implementierung des Interfaces UserDetails ins Spiel. Die Klasse HeraclesUserDetails bietet ein Konstruktor an, welcher alle nötigen Informationen verlangt. Haben wir über diesen Konstruktor ein Objekt erzeugt, können wir dieses an ACEGI übergeben. Listing 4.18 zeigt den Konstruktor-Aufruf. Zeile 1 zeigt die Reihenfolge 52 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests der Konstruktor-Parameter. Die drei Boolean Ausdrücke müssen invertiert werden, da das UserDetails Objekt anders befragt wird, als das LdapUser Objekt (UserDetails: Ist Account nicht gesperrt? LdapUser: Ist Account gesperrt?). Dies wird leider von ACEGI so definiert. Mit dem letzten Parameter des Konstruktors wird das Objekt LdapUser übergeben. Listing 4.18: UC3 UserDetail Objekte erzeugen 1 2 //(String username, String password, boolean accountNonLocked, boolean credentialsNonExpired, boolean enabled, GrantedAuthority[] authorities, LdapUser ldapUser) userDetails = new HeraclesUserDetails(userName, password, !ldapUser.isAccountLockout (), !ldapUser.isPasswordExpired(), !ldapUser.isAccountDisable(), authorities, ldapUser); 4.4.2 ACEGI Konfiguration ACEGI wird in diversen Applikationen eingesetzt. Möchte nun eine Applikation Heracles nutzen, ist es nötig die Konfiguration von ACEGI zu ändern und natürlich Heracles als eine neue Library einzubinden. ACEGI muss wissen, welchen Authentication Provider es nutzen soll. Listing 4.19 zeigt die Zeilen, welche geändert werden müssen. Listing 4.19: UC3 ACEGI Konfiguration 1 2 3 4 5 6 7 8 9 <!-- = = = = = = = = AUTHENTICATION = = = = = = = --> <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager"> <property name="providers"> <list> <ref bean="heraclesAuthenticationProvider"/> </list> </property> </bean> 10 11 12 13 <bean id="heraclesAuthenticationProvider" class="net.sourceforge.heracles.acegi.HeraclesAuthenticationProvider"> </bean> 4.4.3 Exception Handling Innerhalb der Methode retrieveUser der Klasse HeraclesAuthenticationProvider können die bereits beschriebenen Exceptions in den Kapiteln 4.2.3 und 4.3.4 anfallen. Die abstrakte Klasse von welcher wir ableiten, leitet jedoch nur AuthenticationException an ACEGI weiter. Damit der ACEGI Benutzer die Exceptions von Heracles erhält, müssen wir diese abfangen und als neue Exceptions von Typ AuthenticationException werfen. Diese Exceptionklasse besitzt einige Subklassen, welche genutzt werden können. 53 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests • AccountExpiredException, AuthenticationCredentialsNotFoundException, AuthenticationServiceException, BadCredentialsException, ConcurrentLoginException, CredentialsExpiredException, DisabledException, InsufficientAuthenticationException, LockedException, NonceExpiredException, ProviderNotFoundException, ProxyUntrustedException, SessionAlreadyUsedException Listing 4.20 zeigt ein mögliches Beispiel. Listing 4.20: UC3 Exception Handling 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 try{ ... .. } catch (LoginException ex) { if (ex.getMessage().contains("(24)")) { throw new BadCredentialsException("Bad Credentials Presented", ex); } else { throw new ProviderNotFoundException("Provider not found", ex); } } catch (HeraclesException ex) { throw new AuthenticationServiceException("Something not good", ex); } catch (CommunicationException ex) { throw new ProviderNotFoundException("Provider not found", ex); }catch (NamingException ex) { throw new ProviderNotFoundException("Provider not found", ex); } 4.4.4 JUNIT Test Der UC3 besitzt keine performance Tests. Abbildung 4.9 zeigt die drei funktionellen Tests. Der eine Test prüft den Konstruktor der Klasse HeraclesUserDetails. Die beiden Anderen prüfen die Methode retrieveUser der Klasse HeraclesAuthenticationProvider. Eine prüft auf die volle Funktionalität und die andere auf das werfen von Exceptions. Abbildung 4.9: UC3 funktionelle JUnit Tests 54 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests 4.5 Heracles Konfiguration Heracles wird über eine XML Datei konfiguriert. Die Architektur16 der Datei wurde bereits erläutert. Somit konzentrieren wir uns auf das Einlesen der Datei in Java anhand eines kleinen Beispiels. Nehmen wir an, wir führen eine Liste mit allen Dingen die wir noch zu erledigen haben. Diese Liste haben wir in Form einer XML Datei angelegt (siehe Listing 4.21). Eine solche Liste kann mehrere Aufträge enthalten. Listing 4.21: XML Beispiel 1 2 3 4 5 6 7 8 9 10 <todo> <auftrag nummer="1"> <name>Lesen</name> <beschreibung>Kapitel 1</zeit> </auftrag> <auftrag nummer="2"> <name>Schreiben</name> <beschreibung>Aufsatz "Was wir wollen"</zeit> </auftrag> </todo> Wir entscheiden uns, dass wir diese Liste in eine Java Applikation einlesen möchten und über einen grafischen Dialog ausgeben wollen. Dazu benötigt es Hilfswerkzeuge, die uns beim Einlesen von XML Dateien helfen. Wir haben uns für commons-digester entschieden von Apache. Listing 4.22 zeigt wie die obere XML Datei eingelesen wird, ein Auftrag Objekt erstellt wird und wie dieses in eine ArrayListe hinzugefügt werden kann. Listing 4.22: Digester Beispiel 1 2 Digester digester = new Digester(); digester.setValidating(false); 3 4 5 6 7 8 9 digester.addObjectCreate("todo/", ArrayList.class); digester.addObjectCreate("todo/auftrag", Auftrag.class); digester.addSetProperties("todo/auftrag", "nummer", "nummer"); digester.addBeanPropertySetter("todo/auftrag/name/", "name"); digester.addBeanPropertySetter("todo/auftrag/beschreibung/", "beschreibung"); digester.addSetNext("todo/", "add"); 10 11 List liste = (ArrayList) digester.parse("todo.xml"); Was benötigen wir? Bei der Arbeit mit Digester wird vorausgesetzt, dass wir für die XML Elemente Java Objekte und Java Attribute bereitstellen. Deshalb müssen wir erst einmal eine Java Klasse Auftrag programmieren. Diese Klasse besitzt drei Attribute nummer, name und beschreibung. Für jedes Attribut erstellen wir eine Getter- und eine Setter-Methode. Für das XML Element “list” nutzen wir die Klasse ArrayList von Java. 16 Kapitel 3.4.2 55 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests Sind wir soweit, dann können wir mit Digester beginnen. Als Erstes holen wir uns eine Instanz des Frameworks und definieren, dass die XML Datei nicht gegen eine DTD validiert werden soll (siehe Listing 4.22 Zeile 1 und 2). Das Digester Objekt bietet uns viele verschiedene Methoden an, doch für unsere XML Datei interessieren uns nur fünf. addObjectCreate Diese Methode mappt ein bestimmtes XML Element zu einem Java Objekt. Die Methode verlangt zwei Parameter, den XPath17 des XML Elementes und die Angabe der Java Klasse des zu mappenden Objektes. addSetProperties Wenn XML Elemente über Attribute verfügen, so ist es möglich über diese Methode darauf zu zugreifen. Es werden drei Parameter benötigt. Den XPath des XML Elementes, den Namen des XML Attributes und der Name des Java Attributes. Nun stellt sich die Frage; welches Java Attribut? Wir sehen im Listing 4.22 auf den Zeilen 5 und 6, dass der XPath auf dasselbe XML Element zeigt. Die Zeile 5 definiert, dass das XML Element zu einem Auftrag Objekt gemappt wird. So ist das gesuchte Attribut ein Attribut der Klasse Auftrag. addBeanPropertySetter Diese Methode mappt ein XML Element nicht zu einem Objekt, sondern zu einem Java Attribut. Auch hier zeigt der XPath auf das Auftrag Objekt, so muss dieses Objekt ein Attribut besitzen für das XML Element. addSetNext Haben wir das Mapping eines XML Elementes zu einem Objekt abgeschlossen, so legen wir dieses Objekt in eine Liste. Diese Methode wünscht zwei Parameter. Der Erste ist der XPath des XML Elementes, welches wir zu einer Liste gemappt haben und der zweite Parameter legt den Namen der Methode fest, welcher für das Hinzufügen aufgerufen werden muss. parse Diese Methode startet den Parser-Vorgang. Das heisst, das XML Dokument wird eingelesen und so verarbeitet, wie wir es mit den obigen Methoden definiert haben. Am Ende des Vorgangs wird ein Objekt erwartet welches zuvor entsprechend gemappt wurde (siehe Listing 4.22 Zeilen 3 und 11). Die Reihenfolge wann ein XML Element eingelesen wird ist unwichtig. Sobald ein Element auf einen definierten XPath passt, wird das entsprechende Mapping durchgeführt. So wird für jedes Auftragselement ein Auftrags Objekt erstellt und in die ArrayListe gefüllt. Auf diese Art liest Heracles die XML Datei ein und erstellt davon die Objekte Domain und Realm aus dem Kapitel 3.4.1. Innerhalb von Heracles kann über Getter-Methoden auf die Informationen zugegriffen werden. 17 http://de.wikipedia.org/wiki/XPath 56 Dokumentation, Heracles Kapitel 4. Design, Implementation und Tests 4.6 Zusammenfassung Wir haben die wichtigsten Informationen über die drei UseCases von Heracles kennengelernt. Die Sequenzdiagramme erläuterten das Design, aber auch die Kommunikationswege von Heracles. Die Erläuterung zu den APIs (JAAS, JNDI) und zu den Frameworks (ACEGI, Commons-Digester) sind sehr konzentriert. Deshalb müssen die Grundverständnisse der einzelnen Elemente bekannt sein und in anderen Literaturen gesucht werden. 57 5 Tests Dieses Kapitel befasst sich mit den Testdaten und den zu berechnenden Latenzzeiten. Die Testdaten können über die Klasse CreateTestData.java automatisiert erstellt und gelöscht werden. Als Erstes werden kurz die nötigen Voraussetzungen für die erfolgreiche Nutzung dieser Hilfsklasse aufgezeigt. Anschliessend wird erklärt wie diese Klasse gebraucht werden kann und wie sie funktioniert. Gegen Ende des Kapitels beschäftigen wir uns mit den Latenzzeiten. 5.1 Voraussetzung Microsoft bietet eine netzwerkfähige Schnittstelle an, die es ermöglicht entfernt (engl. remote) neue LDAP Objekte zu erstellen, zu rapportieren oder zu löschen. Alle diese Aktionen können ohne weiteres durchgeführt werden. Einzig das Setzen des Passwortes eines Objektes, setzt eine verschlüsselte Verbindung zwischen dem Client und dem LDAP Server voraus. Eine Verschlüsselung der Kommunikation kann mithilfe von SSL1 realisiert werden. Dazu benötigt der LDAP Server ein SSL Zertifikat. Wenn in der bestehenden IT-Infrastruktur nicht bereits eine Zertifizierungsstelle2 installiert ist, kann der Zertifikatsdienst von Microsoft installiert werden. Empfohlene Lektüren über das Thema Microsoft Zertifiaktsdienst. • Grundsätzliche Informationen über LDAP und SSL http://support.microsoft.com/kb/273753/ de • Microsoft LDAP und SSL Zertifikate von Fremdanbietern http://support.microsoft.com/kb/ 321051/de Besitzt der LDAP Server ein Zertifikat so ist LDAP über das Port 636 (Standard Port für das Protokoll ldaps) erreichbar und dies ist das Zeichen, dass der Server richtig konfiguriert ist. Normalerweise arbeitet LDAP nur auf dem Port 389 (Standard Port für das Protokoll ldap). Aus dem IST-Zustand (siehe Kapitel 2.2) wissen wir, dass der LDAP Dienst der HFT-SO über das 1 2 Secure Socket Layer; http://de.wikipedia.org/wiki/Transport_Layer_Security eng. Certificate Authority, Abkürzung CA; http://de.wikipedia.org/wiki/Zertifizierungsstelle 58 Dokumentation, Heracles Kapitel 5. Tests Protokoll ldaps erreichbar ist. Die HFT-SO hat bereits für andere Zwecke den LDAP Servern ein Zertifikat gegeben. Wer schon einmal mit Zertifikaten gearbeitet hat weiss, dass wir noch nicht fertig sind. Auf dem Client, von welchem man eine SSL Verbindung zum LDAP Server aufbauen möchte, muss das öffentliche Zertifikat der Zertifizierungsstelle als vertrauenswürdig konfiguriert werden. In unserem Fall ist die Java Klasse, resp. JNDI der Client. Wir müssen JNDI mitteilen, dass dieses Zertifikat vertrauenswürdig ist und dazu bietet SUN das Tool keytool 3 an. Dieses Programm wird mit der Java Runtime mitgeliefert. Ein Handbuch für keytool ist bei SUN4 zu finden. Über den Befehl5 aus Listing 5.1 wird eine .keystore Datei erstellt und diese kann später bei der Konfiguration von JNDI angegeben werden. Die Datei c:\ca.cer enthält das öffentliche Zertifikat der Zertifizierungsstelle. Das HFT-SO Zertifikat kann über die Webseite6 der HFT-SO herunter geladen werden. Listing 5.1: Keytool für keystore-Datei 1 keytool -import -alias CA -file c:\ca.cer --keystore c:\.keystore Die neu erstellte Datei .keystore wird in der folgenden Java Klasse angegeben, siehe dazu Kapitel 5.2.3. 5.2 Die Klasse CreateTestData.java Die Aufgabe dieser Klasse ist es, auf Wunsch des Benutzers mehr oder weniger Testdaten in einem Active Directory zu erstellen und später zu löschen. Diese Klasse verhindert, dass manuell Testdaten erstellt werden müssen. Alle Testdaten, die von dieser Klasse verwaltet werden, sind in einer fest definierten Organisationseinheit HeraclesOU abgelegt. Im Folgenden wird erläutert, wie diese Klasse eingesetzt wird und anschliessend wie sie aufgebaut ist. 3 Hier ein Beispiel aus dem Internet: http://www.talkingtree.com/blog/index.cfm?mode=entry\&entry= 4 25AA75A4-45A6-2844-7CA3EECD842DB576 http://java.sun.com/j2se/1.5.0/docs/tooldocs/solaris/keytool.html 5 Dieser kann in einem DOS-Prompt ausgeführt werden. 6 http://www.hft-so.ch/hft-so/pdf/HFT-SO-CA.crt 59 Dokumentation, Heracles Kapitel 5. Tests 5.2.1 Klassendiagramm Die Abbildung 5.1 zeigt das Klassendiagramm dieser Test Klasse. Diverse Konstanten enthalten die Werte der Testdaten und können vom Benutzer abgefragt werden. Die Klasse bietet vier Methoden an. Abbildung 5.1: Klassendiagramm CreateTestData CreateTestData Der Konstruktor der Klasse benötigt vier Integer als Parameter. Diese Zahlenwerte definieren wieviele LDAP Benutzer erstellt werden, wieviele eine Telefonnummer oder eine E-Mail Adresse haben und wieviele deaktiviert sind. Die Klasse erstellt somit Testdaten mit unterschiedlichen Eigenschaften, die bei den Tests für das Durchsuchen des LDAPs interessant sein werden. createGroup Der String Parameter definiert den Namen der zu erstellenden LDAP Gruppe. Der Integer Parameter definiert, wieviele Objekte, die über den Konstruktor erstellt wurden, ein Mitglied dieser Gruppe sind. getTestData Diese Methode liefert eine Liste aller erstellten Testdaten. 60 Dokumentation, Heracles Kapitel 5. Tests deleteTestData Über diese Methode werden die Testdaten im LDAP gelöscht. Als Parameter kann die Liste von getTestData übergeben werden. 5.2.2 Verwendung Das Listing 5.2 zeigt einen möglichen Gebrauch dieser Hilfsklasse. Wird der Konstruktor der Klasse CreateTestData.java aufgerufen, werden auf dem LDAP Server die Testdaten eröffnet. Listing 5.2: Arbeiten mit CreateTestData.java 1 CreateTestData testData = new CreateTestData(10,5,2,1); 2 3 4 5 testData.createGroups("Heracles_Group1",3); testData.createGroups("Heracles_Group2",1); testData.createGroups("Heracles_Group3",2); 6 7 testData.deleteTestData(testData.getTestData()); Auf der Zeile 1 wird ein Objekt der Hilfsklasse erstellt. Der erste Parameter des Konstruktors bedeutet, dass zehn Benutzerobjekte im LDAP eröffnet werden. Der Zweite sagt aus, dass die ersten fünf Objekte, von diesen zehn, eine Mail-Adresse haben. Die ersten zwei Benutzer haben eine Telefonnummer und der erste Benutzer ist deaktiviert. Zusammengefasst bedeutet dies, dass der erste Benutzer eine Mail-Adresse und eine Telefonnummer hat, aber der Account deaktiviert ist. Der dritte Benutzer besitzt eine Mail-Adresse, aber keine Telefonnummer und ist nicht deaktiviert. Mit dieser Klasse ist es möglich beliebig viele Benutzerobjekte, mit mehr oder weniger Attributen, zu erstellen. Die Zeilen 3-5 zeigen wie Gruppenobjekte im LDAP erstellt werden können. Der erste Parameter definiert den Namen der Gruppe und der Zweite definiert die Anzahl Benutzerobjekte, die Mitglied dieser Gruppe sind. Als Erklärung: Das Benutzerobjekt, welches deaktiviert ist, ist in allen drei Gruppen Mitglied. Das zweite Benutzerobjekt, der zehn erstellten, ist in zwei Gruppen Mitglied. Wenn die Testdaten nicht mehr benötigt werden, können diese über eine Methode gelöscht werden. 5.2.3 Funktionsweise Die dem Konstruktor übergebenen Parameter werden als Klassen Attribute gespeichert. Weiter wird im Konstruktor JNDI konfiguriert. 61 Dokumentation, Heracles Kapitel 5. Tests Listing 5.3: JNDI und SSL 1 2 Hashtable<String, String> env = new Hashtable<String, String>(11); DirContext ctx = null; 3 4 5 6 7 env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldaps://hftso1.hft-so.bbz-sg.lan:636/DC=HFT-SO,DC=BBZ -SG,DC=LAN"); env.put(Context.SECURITY_PRINCIPAL, "[email protected]"); env.put(Context.SECURITY_CREDENTIALS, "XXXXXXXXXXX"); 8 9 10 11 //System.setProperty("javax.net.debug", "all"); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PROTOCOL, "ssl"); 12 13 14 15 16 /*THE LOCATION OF THE CACERTS MUST BE SPECIFIED*/ java.security.Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); System.setProperty("javax.net.ssl.keyStore", "c://.keystore"); System.setProperty("javax.net.ssl.trustStore","c://.keystore"); 17 18 19 /*Connection to the ads*/ ctx = new InitialDirContext(env); Das Listing 5.3 zeigt wie eine SSL-Verbindung mit einem Domänencontroller des ADS aufgebaut werden kann. Die Zeilen 4-7 sind die üblichen Angaben wie Provider7 , Domänennamen, Benutzeraccount und Passwort. Die Zeile 9 zeigt eine auskommentierte Debug-Möglichkeit, diese sollte bei Problemen einkommentiert werden. Die Zeilen 10-11 sagen dem JNDI, dass eine SSL Verbindung gewünscht ist. Zeile 14 definiert einen SSL Provider und die Zeilen 15-16 geben die .keystore Datei an, die im Kapitel 5.1 erstellt wurde. 5.3 Testdaten Durch diese flexible Art der Erstellung der Testdaten, kann nun nicht einfach eine Liste zur Beschreibung der Testdaten angegeben werden. Deshalb werden in diesem Kapitel die Werte der Konstanten der Testklasse festgehalten (siehe Tabelle 5.1). Der Buchstabe “X” steht stellvertretend für eine Zahl. Denn die Werte werden durchnummeriert damit jedes Objekt andere Werte erhält. Nicht alle Eigenschaften eines Benutzers sind als Konstanten definiert. Einige werden aus diesen Konstanten zusammengestellt. Tabelle 5.2 listet die Namen der LDAP Attribute auf und die Zusammenstellung mithilfe der Konstanten. 7 Der Provider wird als URL angegeben. Dabei geht das Protokoll voran ldaps://. Anschliessend folgt der Servername, der Port des Dienstes und die Angabe der Domäne. 62 Dokumentation, Heracles Kapitel 5. Tests Konstante OUNAME PASSWORD SURNAME GIVENNAME DESCRIPTION TELEPHONE COMPANY DEPARTMENT TITLE STREETADDRESS POSTALCODE LOCATION STATE COUNTRY HOMEPAGE MAIL Wert HeraclesOU heracles HeraclesX UserX Test User of Heracles Project +41 32 666 44 9X Company Development Master Sportstrasse 2 2540 Grenchen Solothurn CH Homepage @heracles.sourceforge.net Tabelle 5.1: Konstanten der Klasse CreateTestData.java Name E-Mail displayName name sAMAccountName userPrincipalName Zusammenstellung GIVENNAMEX.SURNAMEX@MAIL SURNAMEX GIVENNAMEX SURNAMEX GIVENNAMEX GIVENNAMEX.SURNAMEX [email protected] Tabelle 5.2: Zusammengestellte Eigenscahften 63 Dokumentation, Heracles Kapitel 5. Tests 5.4 Latenzzeit Berechnung Wie im Pflichtenheft verlangt müssen Tests geschrieben werden, welche für die LatenzzeitBerechnung der Applikation benötigt werden. Wir müssen als Erstes gute Messwerte festlegen. Abbildung 5.2: Latenzzeit Berechnung Die Latenzzeit wird wie folgt berechnet(siehe Abbildung 5.2). t1 ist die Zeit welche die Frameworks JAAS oder JNDI benötigen. Diese wird mit einer rudimentären Applikation gemessen, damit wir möglichst genau an die effektiven Zeiten herankommen. Diese Zeiten können von uns nicht beeinflusst werden. Die Zeiten werden schwanken, da das Gemessene über das Netzwerk eine Verbindung zu einem Dienst aufbauen muss. t2 wird bei Fertigstellung des Heracles Frameworks gemessen. Haben wir beide Messwerte, so kann folgende Rechnung gemacht werden: t1 + t2 = δt δt ist unsere Latenzzeit. Es ist im Ermessen des Testers zu befinden, ob die Latenzzeit für die einzelnen Vorgänge akzeptabel sind oder nicht, da es kein Patentrezept gibt. Im Anhang F werden die beiden rudimentären Testprogramme für t1 mitgegeben. 64 Dokumentation, Heracles Kapitel 5. Tests 5.4.1 Test Programme Es wurde bereits erwähnt, dass für die Messung von t1 einfache und rudimentäre Programme entwickelt werden. Dabei handelt es sich um zwei Klassen die die Logik enthalten und vier Klassen, die diese mit JUNIT und JUNITPERF testen. Die einen Test Klassen prüfen die Funktionalität und die Anderen das zeitliche Verhalten der Abarbeitung. Diese vier Test Klassen können im Eclipse ausgeführt werden oder mithilfe der ausführbaren Datei Heracles-TestApps.bat, welche sich im Projektverzeichnis befindet. Wird diese gestartet, werden die geschriebenen Tests nacheinander ausgeführt. Der grafische Swing-Dialog von JUNIT wird gestartet und zeigt, ob die Tests erfolgreich waren und die Information über deren Laufzeiten. Die Tests zur Zeitmessung werden absichtlich fehlschlagen, damit wir die Zeit von JUnitPerf ablesen können. 5.4.2 Messwerte Dieses Kapitel hält die Messwerte von JAAS und JNDI fest (siehe Tabelle 5.3). Es werden 10 Messungen gemacht und davon der Durchschnitt berechnet. Somit sollte der Faktor “Netzwerk” berücksichtigt sein. Messung 1 2 3 4 5 6 7 8 9 10 Durchschnitt JAAS 780ms 796ms 796ms 796ms 796ms 889ms 811ms 812ms 811ms 921ms 820ms JNDI 546ms 421ms 437ms 390ms 608ms 531ms 374ms 500ms 608ms 484ms 490ms Tabelle 5.3: Messwerte JNDI und JAAS 5.5 UseCase Tests Heracles ist keine eigenständige, lauffähige Java Applikation, sondern nur eine Bibliothek. Diese besitzt keine Konfigurationsdatei welche die wichtigen Informationen für Heracles enthält8 . Dass 8 Die Konfigurationsdatei liegt in der externen Applikation. 65 Dokumentation, Heracles Kapitel 5. Tests trotzdem die einzelnen UseCases erfolgreich getestet werden können, wird eine XML Datei im Eclipse Pojekt abgelegt. Für die Zeitmessung wird mit dem Framework JUnitPerf gearbeitet, das bei einer Zeitüberschreitung eine Exception wirft. Bei den Tests der UseCases wird mit Abbildungen gearbeitet. Diese werden von Maven über das Plugin “site” generiert. Auf diesen Bildern sind Laufzeiten zusehen, die nicht stimmen. Die gemessenen Zeiten werden durch das Laden und Entladen von Maven Informationen in den Arbeitsspeicher beeinflusst. Deshalb dauert der erste Durchgeführte Test länger als die Folgenden. Dies Führt auch zu Problemen wenn mit JUnitPerf gearbeitet wird, denn meistens schlägt der erste Test beim Kompilieren fehl. 66 6 Benutzerhandbuch Dieses Kapitel beschreibt einige Beispiele wie mit Heracles gearbeitet werden kann. Zuvor muss Heracles aber erst installiert werden. Bei den Beispielen beginnen wir mit einer gültigen Konfigurationsdatei für Heracles. Dem Leser wird vermittelt wie er die beiden Authentifizierungsarten einsetzen kann und wie das LDAP Verzeichnis durchsucht wird. Am Ende des Kapitels wird erklärt wie bei einem Fehlerfall vorgegangen werden kann. 6.1 Installation Heracles wird nicht im eigentlichen Sinne installiert. Der Benutzer benötigt einzig das JAR Archiv und muss dieses als Library in seine Java Applikation einbinden. Das JAR Archiv ist im Anhang F oder auf der Webseite1 von Heracles zugänglich. Abbildung 6.1: Heracles Abhängigkeiten 1 http://heracles.sourceforge.net 67 Dokumentation, Heracles Kapitel 6. Benutzerhandbuch Auf der Projekthomepage sind weitere Hilfreiche Informationen zum Projekt. Wie zum Beispiel die Abhängigkeiten des Heracles Frameworks zu anderen Frameworks (siehe Abbildung 6.1). Diese Abhängigkeiten müssen von der externen Applikation aufgelöst werden. Auch die nötige Konfigurationsdatei muss die externe Applikation enthalten. Sie muss direkt unter dem Classpath mit dem Namen heracles-config.xml abgelegt sein. 6.2 XML Konfiguration Wie eine Konfigurationsdatei heracles-config.xml von Heracles aussehen kann zeigt Listing 6.1. Das XML beschreibt zwei LDAP Domänen und zwei Kerberos Realms. Auf den Zeilen 10, 17, 24, 25 ist zusehen, dass mehrere LDAP Server und mehrere KDC Server angegeben sind. Zur Trennung der Server genügt ein Leerschlag. JNDI benötigt nicht nur die Adresse des Servers, sondern die vollständige URL2 des LDAP Verzeichnisses. Die DTD Definition auf Zeile 3 muss gemacht werden. Bei fehlender Definition oder bei fehlgeschlagener Validierung wird eine SAXException geworfen. Die den Einsatz von Heracles nicht stören wird, aber in der Logdatei3 angezeigt wird. Listing 6.1: Heracles XML Konfigurationsbeispiel 1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <!DOCTYPE heracles PUBLIC "http://heracles.sourceforge.net/NS/DTD/" "heracles-config .dtd"> 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <heracles> <ldap-config> <domain name="bbz-sg.lan"> <principal>[email protected]</principal> <credential>---heracles---!</credential> <provider>ldap://bbzsg1.bbz-sg.lan:389/ ldap://bbzsg2.bbz-sg.lan:389/</ provider> <searchBase>DC=BBZ-SG,DC=LAN</searchBase> <emptyValues>no information</emptyValues> </domain> <domain name="hft-so.bbz-sg.lan"> <principal>[email protected]</principal> <credential>---heracles---!</credential> <provider>ldap://hftso1.hft-so.bbz-sg.lan:389/ ldap://hftso2.hft-so.bbz-sg. lan:389/</provider> <searchBase>DC=HFT-SO,DC=BBZ-SG,DC=LAN</searchBase> <emptyValues>no information</emptyValues> </domain> </ldap-config> 22 <kerberos-config> 23 2 3 Uniform Resource Locator; http://de.wikipedia.org/wiki/Uniform_Resource_Locator Nur wenn das Logging in einer Applikation aktiviert ist. Siehe Kapitel B.2. 68 Dokumentation, Heracles 24 25 26 27 Kapitel 6. Benutzerhandbuch <realm name="BBZ-SG.LAN">bbzsg1.bbz-sg.lan bbzsg2.bbz-sg.lan</realm> <realm name="HFT-SO.BBZ-SG.LAN">hftso1.hft-so.bbz-sg.lan hftso2.hft-so.bbz-sg. lan</realm> </kerberos-config> </heracles> 6.3 Beispiel: einfache Authentifizierung Listing 6.2: Einfache Authentifizierung 1 Heracles heracles = Heracles.getHeracles(); 2 3 4 5 6 7 8 9 10 try{ heracles.authSimple(username, password); System.out.println("login success"); }catch(LoginException ex){ System.out.println("login failed"); }catch(HeraclesException ex){ System.out.println("login failed"); } Listing 6.2 zeigt, wie die einfache Authentifizierung realisiert wird. Als Erstes muss eine Instanz von Heracles geholt werden. Anschliessend kann über diese Instanz die Methode authSimpl aufgerufen werden. Wird aus irgendeinem Grund eine LoginException oder HeraclesException geschmissen, ging die Authentifzierung schief. 6.4 Beispiel: erweiterte Authentifizierung Eine erweiterte Authentifizierung besitzt wesentlich mehr Möglichkeiten als eine Einfache. Der Benutzer kann beispielsweise innerhalb seiner eigenen Java Applikation, das Berechtigungskonzept aus dem ADS nutzen. Der Benutzer erhält vom ADS Administrator die Information über die LDAP Gruppen und deren Mitglieder. Anschliessend setzt er sein Berechtigungskonzept mittels diesen Gruppen um und nutzt die erweiterte Authentifizierung von Heracles. Über sie findet er heraus, welche LDAP Benutzer in welchen LDAP Gruppen Mitglieder sind. Über eine Selektion kann die Applikation prüfen ob ein Benutzer berechtig ist eine Aktion auszuführen. Listing 6.3: Erweiterte Authentifizierung 1 2 Heracles heracles = Heracles.getHeracles(); LdapUser ldapUser = heracles.authAdvanced(name, passwd); 3 4 String gruppe = ""; 69 Dokumentation, Heracles Kapitel 6. Benutzerhandbuch 5 6 7 8 9 10 11 12 13 14 15 Iterator iter = ldapUser.getLdapGroups().iterator(); while (iter.hasNext()) { LdapGroup ldapGroup = (LdapGroup) iter.next(); if(ldapGroup.getName().equals("gg_admin")){ gruppe=ldapGroup.getName(); } if(ldapGroup.getName().equals("gg_mitarbeiter")){ gruppe=ldapGroup.getName(); } } 16 17 18 // Prüfung der Berechtigung 19 20 21 22 23 if(gruppe.equals("gg_admin")){ .. .. } 6.5 Beispiel: LDAP abfragen Heracles besitzt die Fähigkeit ein LDAP Verzeichnis abzufragen und die Resultate einer externen Applikation zu übergeben. Das Listing 6.4 zeigt einige Abfragen, die dem Benutzer ein Anwendungsgefühl vermitteln sollen. Der Stern als Suchstring hat die übliche Bedeutung, eine beliebige Folge von beliebig vielen Zeichen. Listing 6.4: Ldap abfragen 1 2 3 4 /** Instance von Heracles holen * */ Heracles heracles = Heracles.getHeracles(); 5 6 7 8 9 10 try{ /** Hole alle Benutzer mit einer Telefonnummer * */ List result = heracles.searchInLdap("hft-so.bbz-sg.lan","telephonNumber","*"); 11 12 13 14 15 /** Hole alle Benutzer mit einer E-Mail Adresse * */ List result = heracles.searchInLdap("hft-so.bbz-sg.lan","mailAddress","*"); 16 17 18 19 20 /** Suche alle Benutzer, bei denen die Beschreibung mit abc anfängt * und irgendwie aufhört. * */ 70 Dokumentation, Heracles Kapitel 6. Benutzerhandbuch List result = heracles.searchInLdap("hft-so.bbz-sg.lan","description","abc*"); 21 22 23 24 25 26 27 /** Suche alle Benutzer, bei denen die Beschreibung mit dem Wort abc anfängt * und mit irgendwelchen Wörtern aufhört . * */ List result = heracles.searchInLdap("hft-so.bbz-sg.lan","description","abc *"); 28 29 30 31 32 33 34 35 36 /** Suche alle Benutzer, bei denen die Beschreibung mit irgendetwas anfängt * und irgendwie aufhört, jedoch muss mindestens einmal abc vorkommen. * */ List result = heracles.searchInLdap("hft-so.bbz-sg.lan","description","*abc*"); }catch(NamingException ex){ System.out.println("Ldap error"); } 6.6 Troubleshooting Beim Einsatz von Heracles können unterschiedlich Exceptions geschmissen werden. Diese sind in den Kapiteln 4.2.3, 4.3.4 und 4.4.3 beschrieben. Über die Projekthomepage erhält der Benutzer die Möglichkeit sich an der Mailing Liste von Heracles anzumelden oder er kann sich dem “Issue Tracking” System4 zu wenden. 4 Über ein solches System haben Endkunden und Entwickler die Möglichkeit Fehler zu dokumentieren und Lösungsvorschläge zu machen. 71 7 Prototyp Heracles besitzt keinen grafischen oder consolenbasierenden Dialog. Um denn noch die Funktionalität von Heracles zu präsentieren wird ein Prototyp entwickelt. Da dieser nur zur Präsentation der eigentlichen Diplomarbeit benötigt wird, informiert dieses Kapitel konzentriert über die Funktionsweise, die Architektur und den Gebrauch. Beim Prototyp handelt es sich um eine Web-Applikation. Mit ihr kann der Authentication Provider für ACEGI aus dem UseCase UC3 präsentiert werden. Der wird die erweiterte Authentifizierung des UC1 aufrufen. Eine Suchfunktion in der Applikation kann den UseCase UC2 vorstellen. Wie Heracles besitzt auch der Prototyp eine Projekthomepage1 mit diversen Informationen zur Web-Applikation. 7.1 Übersicht Abbildung 7.1: Das Ablaufdiagramm Das Ablaufdiagramm 7.1 zeigt den Funktionsumfang des Prototypes. Der Benutzer gelangt beim Aufruf der Webseite direkt auf die Anmeldeseite. Dort besitzt er die Möglichkeit den Namen 1 http://heracles.sourceforge.net/heracles-http-client 72 Dokumentation, Heracles Kapitel 7. Prototyp und das Passwort einzugeben. Über eine DropDown Liste kann er seine Domäne auswählen (Abbildung 7.2). Die Anmeldung sendet die Informationen an Heracles für eine erweiterte Authentifizierung. Wirft Heracles eine Exception, erhält der Benutzer eine Fehlermeldung und wird aufgefordert sich erneut anzumelden. Übergibt Heracles dem Prototypen ein LdapUser Objekt, hat die Anmeldung funktioniert. Abbildung 7.2: Die Anmeldung Hat Heracles die Authentifizierung erfolgreich durchgeführt, prüft die Web-Applikation selbst ob der Benutzer in einer gültigen ADS Gruppe Mitglied ist. Als gültig betrachtet der Prototyp die Gruppen heracles_admin oder heracles_mitarbeiter. Falls dies nicht der Fall ist erscheint die Fehlermeldung aus Abbildung 7.3. Abbildung 7.3: Die Fehlermeldung War auch die Prüfung der Web-Applikation erfolgreich, erhält der Benutzer einige Informationen über seine Person. Die Applikation besitzt diese Informationen dank dem LdapUser Objekt von Heracles. Die Abbildung 7.4 verrät uns, dass sich gerade der Benutzer admin.muster angemeldet hat. Dieser ist in beiden Gruppen Mitglied. Wäre er nicht in der Gruppe heracles_admin Mitglied, so würde auf der linken Seite der Menüpunkt “Suchen” nicht erscheinen. Wählt er diesen 73 Dokumentation, Heracles Kapitel 7. Prototyp Abbildung 7.4: Hauptseite Menüpunkt aus, so besitzt er die Möglichkeit etwas zu suchen. Eine weitere DropDown Liste hilft dem Benutzer zu definieren, wo2 er suchen möchte. Die Abbildung 7.5 verdeutlicht dies. Abbildung 7.5: Die Suche Enthält die Suche keine Resultate, wird dem Benutzer das gleiche Fenster angezeigt, ansonsten erhält er eine tabellarische Übersicht über alle gefundenen Benutzerobjekte (siehe Abbildung 7.6). Diese Tabelle besitzt unterhalb ein kleines Navigationsmenü um durch die Resultate zublättern. 2 Das Wo definiert in welchem LDAP Attribut. 74 Dokumentation, Heracles Kapitel 7. Prototyp Abbildung 7.6: Die Resultate 7.2 Architektur Der Prototyp besteht aus einer Präsentationsschicht und einer Serviceschicht. Die Serviceschicht stellt die Schnittstelle zu Heracles dar. Sie besitzt für die Präsentationsschicht eine einzige Methode searchInLdap(). Diese Methode startet den UseCase UC2 von Heracles und leitet am Ende die Suchresultate weiter. Für die Entwicklung der Web-Oberfläche sind weitere Werkzeuge hinzu gekommen, diese wollen wir kurz vorstellen Java 1.5 ist die Grundlage des Prototypes. Wie bei Heracles wird seine Paketstruktur von Maven vorgegeben. Abbildung 7.7 offenbart, dass der Java Quelltext von den Webseiten getrennt ist. Der Ordner web enthält die Java Klassen für die Logik der Benutzeroberfläche. Der Ordner webapp enthält die Webseiten und XML Dateien der Oberfläche. Benutzeroberfläche JSF3 wird für den strukturierten Aufbau der Benutzeroberfläche eingesetzt. Es abstrahiert HTTP4 mittels verschiedenen Java Komponenten. Die Konfigurationsdatei liegt unter webapp\WEB-INF und heisst faces-config.xml. 3 4 Java Server Faces; http://de.wikipedia.org/wiki/JavaServer_Faces Hypertext Transfer Protocol; http://de.wikipedia.org/wiki/HTTP 75 Dokumentation, Heracles Kapitel 7. Prototyp Abbildung 7.7: Maven Paketstruktur Modularisierung Für die Modularisierung der Benutzeroberfläche wird Facletes5 eingesetzt. Dies hat den Vorteil dass beispielsweise die Navigation einmalig erstellt und auf anderen Seiten wieder gebraucht werden kann. Funktions-Bibliothek Die zusätzliche Funktions-Bibliothek JSTL6 von SUN unterstützt den dynamischen Aufbau von Webseiten. Sicherheit Für die Authentifizierung und Autorisierung setzen wir ACEGI ein. Die Konfiguration ist unter dem Namen applic-security.xml im Verzeichnis webap\WEB-INF abgelegt. 7.3 Funktionsweise Dieses Kapitel beschreibt lediglich, wie über den Heracles ACEGI Authentication Provider das LdapUser Objekt herausgeholt werden kann. Damit die Web-Applikation im Besitzt der ADS Informationen über den authentifizierten Benutzer ist. Listing 7.1: ACEGI Prototyp Konfiguration 1 2 String userName = "administrator"; String password = "geheim"; 5 https://facelets.dev.java.net/ 6 JavaServer Pages Standard Tag Library; http://de.wikipedia.org/wiki/JSTL 76 Dokumentation, Heracles Kapitel 7. Prototyp 3 4 5 6 7 8 UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(userName,password); authReq.setDetails(new WebAuthenticationDetails(request)); Authentication auth = getAuthenticationManager().authenticate(authReq); HeraclesUserDetails userDetails= (HeraclesUserDetails)auth.getPrincipal(); LdapUser ldapUser=userDetails.getLdapUser(); Auf Zeile 4 des Listings 7.1 wird erst einmal ein UsernamePasswordAuthenticationToken Objekt erzeugt, indem der Benutzername und das eingegebene Passwort übergeben wird. Anschliessend wird dem Objekt ein WebAuthenticationDetails Objekt übergeben. Dieses Objekt enthält die Informationen über den Client, wie beispielsweise Browser, Client Betriebssystem oder IP-Adresse des Clients. Auf der Zeile 6 wird ein Authentication Objekt erzeugt. ACEGI muss wie im Kapitel 4.4.2 beschrieben, konfiguriert sein. Nämlich dann wird mit getAuthenticationManager() der Heracles Authentication Provider geladen. Mittels authenticate() wird die Authentifizierung durchgeführt und die Methode retrieveUser() der Klasse HeraclesAuthenticationProvider aufgerufen. War die Authentifizierung erfolgreich und das Authentication Objekt erzeugt, kann über dies das HeraclesUserDetails Objekt geholt werden und dieses besitzt das LdapUser Objekt. 7.4 Installation Damit der Prototyp überhaupt auf einem Computer ausgeführt werden kann, benötigt es einen Java Web-Container wie Tomcat7 oder Jetty8 . Getestet wurde der Prototyp mit Tomcat 5.5.12. Im Anhang F oder auf der Projekthompage ist ein WAR9 Archiv zugänglich. Dieses muss in das webapps Verzeichnis von Tomcat gelegt werden und der Tomcat Server packt automatisch das Archiv aus und die Anmeldeseite des Prototypes sollte zur Verfügung stehen. Auf dem Testsystem ist Tomcat so konfiguriert, dass der Webserver über die Adresse http://localhost:8080/ erreichbar ist. Um auf die Applikation zugreifen zu können, würde der Aufruf im Browser http://localhost:8080/heracles-http-client heissen. Taucht die Anmeldeseite auf, so ist die erste Hürde überwunden. Jedoch muss Heracles für die ADS Infrastruktur noch konfiguriert werden. Im WAR Archiv ist eine Konfiguration mitgeliefert10 . Diese ist jedoch nur in der IT-Infrastruktur der HFT-SO lauffähig. Wie Heracles für eine andere Umgebung konfiguriert werden muss, ist im Kapitel 6 beschrieben. 7 http://tomcat.apache.org/ http://www.mortbay.org/ 9 Web Archiv; http://de.wikipedia.org/wiki/Web_Archive 8 10 Die heracles-config.xml Datei liegt unter WEB-INF\classes 77 Dokumentation, Heracles Kapitel 7. Prototyp Mit der Konfiguration von Heracles ist die Installation abgeschlossen. Abbildung 7.8 zeigt die im WAR-Archiv enthaltenen, abhängigen Frameworks des Prototypen. Abbildung 7.8: Abhängigkeiten des Prototypes In Abbildung 7.8 ist das Heracles Framework zu sehen. 7.5 Prototyp in der HFT-SO In der HFT-SO ist alles Aufgebaut um einen installierten Prototypen zu benutzen. Im ADS wurden vier Benutzer und die Gruppen heracles_admin und heracles_mitarbeiter erstellt. Tabelle 7.1 zeigt eine Übersicht. Mit dem Benutzer “Student” kann eine Fehlermeldung provoziert werden. 78 Dokumentation, Heracles Name Muster Muster Muster Student Vorname Admin Peter Susi Kapitel 7. Prototyp Benutzername admin.muster peter.muster susi.muster student Passwort heracles heracles heracles 12341234 Gruppe heracles_admin, heracles_mitarbeiter heracles_mitarbeiter heracles_mitarbeiter - Tabelle 7.1: Prototyp Benutzer 79 8 Schlusswort Heracles ermöglicht eine einfache, schnelle Realisierung einer Authentifizierung gegen Kerberos. Dabei wird der Programmieraufwand in den einzelnen Applikationen minimiert und reduziert somit auch die Komplexität. Das Framework ist nicht nur in einfachen Consolenapplikationen oder in RichClient Appliaktionen einsetzbar. Sondern auch in grösseren webbasierenden Applikationen mit ACEGI Framework. Wie ein Façade Pattern versteckt das Heracles API den Programmieraufwand und verhindert, dass Änderungen in Heracles Einfluss auf die externen Applikationen haben könnten. Durch einfache und aussagekräftige Namen von Attributen und von Konfigurationselementen ist das Handling von Heracles einfach und für jeden Entwickler und Systemadministrator verständlich. Heracles unterstütz ein Multidomänenmodell und kann somit interessant für grössere Unternehmen werden. Auch die Begrenzung auf reine ADS Umgebungen ist nicht fest. Firmen mit anderen LDAP und Kerberos Produkten können Heracles gleich wohl einsetzen. Durch eine sauber und durchdachte Planung besitzt Heracles die Möglichkeit sich weiter zu entwickeln und auszubauen. Bereits deutsche Java-Entwickler haben über die Projekthomepage Interesse an Heracles gezeigt. Die Zukunft von Heracles steht nicht in den Sternen sondern bereits auf der TODO-Liste des Entwicklers. 80 9 Fazit Da ich bei der HFT-SO seit acht Jahren arbeite, habe ich schon einige Diplomarbeiten gesehen, welche zwar einen guten Anfang einer Idee präsentierten, jedoch meist nie produktiv eingesetzt werden konnten. Mit Heracles glaube ich, dass das nicht der Fall ist. Dieses Framework ist von AY abgeschlossen und dokumentiert. Das Z, welches noch fehlt, umfasst zwei bis drei Kleinigkeiten. Die jedoch den produktiven Einsatz von Heracles nicht verhindern können. Die Schwierigkeiten in dieser Arbeit lagen hauptsächlich in der Einarbeitung von JNDI, JAAS, ACEGI und der Entwicklung des Prototypen. Durch eine saubere Analyse stiess ich früh genug auf die Problematik, dass Heracles mehrere Domänen unterstützen muss und dass JNDI und JAAS keine Lösungen lieferten. Eine grosse Hilfe waren die Dokumente der Firma “Orientation in Objects” über ACEGI[Sot06] und JAAS[Lüt02]. Für JNDI gab es sehr viele Informationen in den einzelnen Sun-Foren. Nach jeder Projektarbeit hatte ich das Gefühl, dass meine Arbeiten immer besser werden. Deshalb bin ich glücklich, dass ich auch dieses Mal ein solches Gefühl habe. Jedoch musste ich einmal mehr feststellen, dass ich unter Zeitdruck Mühe habe mich in der Dokumentation korrekt und sauber auszudrücken. Ich glaube, mit dieser Arbeit haben Sie den Beweis vor sich liegen, dass ich das Gelernte auch einsetzen kann. Mit diesen paar Worten (und natürlich einer noch kommenden Präsentation) schliesse ich hoffentlich mein Studium an der HFT-SO mit Erfolg ab. 81 Glossar ADS (Active Directory) Dieses Produkt von Microsoft bringt die eigenständigen Netzwerkdienste LDAP und Kerberos unter einen Hut. Dies ist nur möglich, da Microsoft neue, eigene Dienste in das Gesamtpaket integrierte. Seit Windows 2000 ist dieser Dienst in Microsoft Umgebungen für Benutzerauthentifizierungen unumgänglich. Authentifizierungsdienst Verantwortlicher Dienst zur Prüfung von Erkennungsinformationen und eindeutiger Identifizierung von Objekten. Commons-Digester Framework von Apache. Realisiert ein Mapping zwischen XML Elementen und Java Objekten. Credential Unter Kerberos werden so die Passwörter genannt. Jeder Credential gehört zu einem Principal. Distinguished Name (DN) Referenziert eindeutig ein Objekt in einem LDAP Verzeichnis. DNS (Domain Name System) Dieser Netzwerkdienst verknüpft Computernamen mit IP-Adressen. Somit haben die Benutzer von Computer die Möglichkeit, Computer über ihre Namen anzusprechen und nicht nur über ihre Adresse. Einen Namen kann man sich einfacher merken als ein Adresse mit 32Bits. Dieses Mapping wird in einer DNS Datenbank gemacht, die mehrere tausend Einträge besitzen kann. DNS besitzt auch die Möglichkeit Adressen in die Namen umzuwandeln. Domänen Eine Domäne kann als eine Art Gruppe betrachtet werden. Alle Objekte in einer Domäne haben Gemeinsamkeiten und deshalb werden sie zusammengefasst. Es gibt unterschiedliche Domänen. Von Microsoft Domänen, über DNS Domänen bis zu LDAP Domänen. Domänencontroller Das Wort Domänencontroller wird nur in Microsoft Umgebungen gebraucht. Ein solcher Server ist im Besitzt einer Datenbank über alle Informationen einer Domäne. Über diesen Server können Änderungen an einer Domäne vorgenommen werden. DTD (Dokumenttyp-Definition) Der Inhalt einer DTD Datei definiert, wie ein XML Dokument aufgebaut werden muss. 82 Dokumentation, Heracles Glossar Exception Unterbruch des normalen Ablaufes oder Prozesses eines Programms. Oftmals im Fehlerfall wird eine Exception geworfen, die das Programm zwingt etwas anderes auszuführen. Kann in der Hardware als Interrupt verstanden werden. Wie bei den Interrupts gibt es unterschiedliche Arten und jede einzelne Art kann individuell abgefangen werden. Facletes Setzt verschiedene Module einer Webseite zusammen und ermöglicht dadurch, dass der gleiche Code mehrfach an verschiedenen Stellen genutzt werden kann. Framework Dieser Begriff wird in der objektorientierten Softwareentwicklung gebraucht. Ein Framework enthält einen Rahmen oder ein Gerüst für die Lösung von Problemen. Diese Lösungen können in den eigenen Programmen wiederverwendet werden und vermindern somit den Programmieraufwand. Bekannte und viel verwendete Frameworks können als Standardisierung in der Softwareentwicklung angesehen werden. HTML (Hypertext Markup Language) Oft auch kurz als Hypertext bezeichnet, ist eine textbasierte Auszeichnungssprache zur Darstellung von Inhalten wie Texten, Bildern und Hyperlinks in Dokumenten. HTTP (Hypertext Transfer Protocol) Ist ein Übertragungsprotokoll für Dateien. Wird hauptsächlich für den Datentransfer im Internet gebraucht. Beispielsweise das Übertragen von Webseiten. IP-Adresse Jedes Gerät das an das Internet angeschlossen wird benötigt eine eigene Adresse unter der es erreichbar ist. Da das im Internet verwendetet Protokoll “Internet Protokoll” (IP) heisst, wird diese Adresse IP-Adresse genannt. Eine solche Adresse kann z.B. 16.124.123.32 sein. JAAS (Java Authentication and Authorization Service) Ist seit der Version 1.4 von Java ein fester Bestandteil. JAAS ist eine standardisierte Schnittstelle für Benutzerauthentifizierungen und -autorisierungen. Über externe Module ist es möglich JAAS an unterschiedliche Authentifizierungsquellen anzuhängen (Kerberos, LDAP, Windows NT 4.0, usw. . . ). JAR (Java Archiv) Enthält und komprimiert den Inhalt einer ganzen Java Applikation. JNDI (Java Naming and Directory Interface) Standardisierte Schnittstelle für den Zugriff auf Namens- und Verzeichnisdiensten von Java Applikationen aus. DNS ist ein Beispiel für einen Namensdienst, LDAP für ein Verzeichnisdienst. JSF (Java Server Faces) Mit JSF lassen sich Bedienoberflächen für Web-Anwendungen aus vorgefertigten Komponenten zusammenbauen. Das Framework generiert selbstständig HTMLCode für den Browser. 83 Dokumentation, Heracles Glossar JSTL Standardisierte Funktions-Bibliothek für den Aufbau von dynamischen Webseiten. Wird hauptsächlich beim Einsatz von Java Server Pages eingesetzt. JUnit Der Test-Code kann mittels JUnit von Programm-Code getrennt werden. Diese Funktion wird als Unit-Tests bezeichnet. Kerberos Verwaltung von Passwörter bestimmter Objekte. Als Objekte werden Personen, Server oder einzelne Netzwerkdienste angesehen. Dieser Dienst baut auf dem Sicherheitskonzept von Tickets auf. Nach einer erfolgreichen Anmeldung werden Objekte anhand ihrer Tickets identifiziert. LDAP (Lightweight Directory Access Protocol) Ein Container um Informationen über Objekte zu verwalten. Objekte können Personen, Computer, Freigaben, Drucker, etc. . . sein. Je nach Objekttyp gibt es unterschiedliche Eigenschaften, Attribute. Dieser Netzwerkdienst dient als Datenquelle für andere Dienste und wird oft als Telefonbuch oder Nachschlagewerk verglichen. Log4J Realisiert das Sammeln von Informations-Meldungen für Entwickler an einer zentralen Stelle. Wird für die Suche nach Fehlern benötigt. Maven Ein Werkzeug für die Verwaltung von Java Projekten. In einem XML Dokument sind alle Einstellungen eines Projektes festgehalten. Es beginnt mit dem Namen und der Version des Projektes, über die Auflösung von Abhängigkeiten zu anderen Java Frameworks, bis hin zur Definition der Projektmitglieder und Foren des Projektes. Alle diese Informationen werden beim Kompilieren der Applikation genutz und bei der Erstellung einer Projekthomepage. Plugin Ein zusätzliches Softwaremodul das die Funktionalität einer Basis Software erweitert. Realm Ein Kerberosserver kann mehrere Namensräume verwalten. Ein Namensraum gruppiert mehrere Principals und wird als Realm bezeichnet. Single Sign-On Über eine zentrale Authentifizierung erhält der Benutzer auf möglichst viele Dienste Zugriff, ohne sich ein weiteres Mal anzumelden. Spring In einer XML Datei werden Objekte und Objektabhängigkeiten definiert. Beim Start der Applikation erstellt Spring alle definierten Objekte mit ihren Abhängigkeiten. Der daraus gewonnene Vorteil ist, dass bei einer Änderung die Applikation nicht mehr neu kompiliert werden muss. SSL (Secure Socket Layer) Realisiert eine mit Zertifikaten verschlüsselte Kommunikation. Diese Zertifikate müssen von einer Zertifizierungsstelle erstellt und unterschrieben worden sein. 84 Dokumentation, Heracles Glossar URL (Uniform Resource Locator) Referenziert eindeutig auf Ressourcen mit der Angabe des Netzwerkprotokolles. Beispielsweise http://www.hft-so.ch UseCase Ein UseCase beschreibt einen Anwendungsfall in einem Programm. Dieser Anwendungsfall wird benötigt, damit das Programm seine Aufgaben oder Pflichten erfüllen kann. Diese repräsentieren meist einen Geschäftsprozess und müssen deshalb sehr sorgfältig und durchstudiert geplant werden. Oftmals werden auch die zukünftigen Anwender eines Programms zur UseCase Beschreibung herbeigezogen. VPN (Virtual Private Network) Ist eine Technologie zum Verbinden von lokalen Netzen verschiedener Standorte, sowie zum Einbinden von Einzelarbeitsplätzen und mobilen Mitarbeitern zu einem ganzheitlichen Unternehmensnetzwerk. WAR (Web-Archiv) Enthält sämtliche Klassen, Konfigurationsdateien und Bibliotheken für eine lauffähige Web-Applikation. XML (Extensible Markup Language) Ist eine Auszeichnungssprache zur Darstellung hierarchisch strukturierter Daten in Form von Textdateien. XPath Mittels XPath kann ein bestimmtes Element in einem XML Dokument eindeutig adressiert werden. 85 A Anforderungszuordnung A.1 Pflichtenheft Im Pflichtenheft von Heracles sind diverse “muss” und optionale Kriterien beschrieben. Die Tabelle A.1 hält in kurzen Worten fest, ob und wie sie gelöst wurden. Alle “muss” und optionalen Kriterien des Pflichtenheftes sind analysiert, geplant, realisiert und getestet. A.2 Offene Punkte Während der Diplomarbeit sind verschiedene Punkte aufgetaucht, die Heracles noch weiter optimieren könnten. Diese Punkte sind jedoch nicht Probleme, die den produktiven Einsatz von Heracles verhindern können. Mann könnte sie umgangssprachlich als “Nice To Have” bezeichnen. Administrator Passwort Das Passwort des Administrators in der Konfigurationsdatei ist unverschlüsselt. Aus zeitlichen Gründen konnte dieser Punkt nicht realisiert werden. Die Idee wäre eine kleine, eigenständige Applikation zu entwickeln, welche dem Benutzer die Möglichkeit geben würde, irgendein Passwort einzugeben. Dieses Passwort würde dann über einen bestimmten Algorythmus verschlüsselt. Der gleiche Algorythmus müsste dann im Heracles Framework sein, welcher das Passwort wieder entschlüsselt. Vereinfachung LDAP Attribute Neue LDAP Attribute in Heracles hinzuzufügen ist aufwendig. Optimal wäre es, wenn wie bei Struts ein Bean1 in einer XML Deiten definiert werden könnte und für sämtliche Attributwerte dieses Beans automatisch Getter- und Setter-Methoden erstellt würden. Auch in der Datenzugriffsschicht müsste das neue Attribut in die Suche automatisch integriert werden. 1 Ein Bean ist ein einfaches Java Objekt. Es zeichnet sich dadurch aus, dass es für jedes lokale Attribut eine Getter- und eine Setter-Methode hat und einen parameterlosen Konstruktor besitzt. 86 Dokumentation, Heracles Anhang A. Anforderungszuordnung Kriterium Einfache Authentifizierung Beschreibung Sie ist über den UC1 realisiert worden. Der UC1 wurde als Erstes aufgebaut und implementiert. Erweiterte Authentifizierung Der Authentifizierungsteil des Kriteriums stimmt mit der einfachen Authentifizierung überein. Der zweite Teil (LDAP Informationen) wurde im UC2 realisiert. ACEGI Plugin Dieses Kriterium ist als UC3 in dieser Dokumentation festgehalten und beschrieben. Das Kriterium ist umgesetzt und getestet. Konfiguration Heracles kann über eine XML Datei konfiguriert werden. Dieses optionale Kriterium konnte wegen genügender Zeit realisiert werden. Die Architektur ist im Kapitel 3.4 und die Realisierung im Kapitel 4.5 beschrieben. LDAP Abfragen Beim Design des UC2 wurde festgestellt, dass dieses optionale Kriterium einen kleinen Mehraufwand bedeutet und wurde deshalb mit UC2 umgesetzt. Framework API Heracles besitzt eine API. Diese ist jedoch keine Schnittstelle sondern eine abstrakte Klasse. Die API ist gegenüber dem Pflichtenheft ein wenig geändert worden (siehe Kapitel3.3). Schichtenmodell In der Architektur 3 wird der Aufbau von Heracles beschrieben und im Kapitel 3.8 zusammengefasst. Auch bei der Beschreibung der UseCases mit Sequenzdiagrammen ist ersichtlich, dass Heracles in Schichten aufgeteilt ist. Java Applikation Heracles benötigt als Runtime Java 1.5. Dies wird in der Architektur beschrieben (siehe Kapitel 3.1). Werkzeuge Es sind bekannte und standardisierte Werkzeuge eingesetzt. Diese sind im Kapitel 3.1 beschrieben. Tabelle A.1: Anforderungszuordnung 87 B Anhang Probleme B.1 Gelöste Probleme Verschlüsselung Für die automatisierte Erstellung von TestDaten verlangt Microsoft eine verschlüsselte Verbindung zwischen dem Client und dem LDAP Server. Diese Verschlüsselung kann mittels SSL realisiert werden. Die HFT-SO hat die Server bereits soweit konfiguriert, aus anderen Gründen, so musste nur noch java-seitig das Problem gelöst werden. In diversen JNDI Foren wurden Beispiele für eine verschlüsselte Kommunikation gezeigt. Durch diese und dem Benutzerhandbuch des Tools keytool konnte das Problem gelöst werden. Konfiguration Im Pflichtenheft ist beschrieben, dass Heracles über “Properties” Dateien konfiguriert wird. Jedoch als optionales Kriterium wird die Möglichkeit beschrieben, dass Heracles auch über eine XML Datei konfiguriert werden könnte. Dies würde natürlich dem Ganzen einen professionelleren Touch verleihen. Ich habe mich entschieden, dass innerhalb von Heracles die Konfiguration über ein objektorientiertes Modell verfügbar sein soll (siehe Kapitel 3.4.1). Dies hat den Vorteil, wenn ich später ein Werkzeug einsetze, welches aus einer XML Datei Java Objekte erstellt, so existiert das Objektmodell bereits. Maven Tests Beim Kompilieren eines Maven Projektes werden die JUnit Test ausgeführt. Wenn ein Test fehlschlägt wird der Vorgang abgebrochen und es wird kein Archiv erstellt. Am Anfang eines Projektes kann dies sehr störend sein. Deshalb kann der Kompiliertvorgang mit einem zusätzlichen Parameter gestartet werden und die Fehler werden ignoriert. • mvn clean package -Dmaven.test.failure.ignore=true Spring Container initialisieren Grundsätzlich war die Idee den Spring Container innerhalb der abstrakten Klasse zu initialisieren. Anfänglich, als das Java Projekt nur innerhalb von Eclipse kompiliert und ausgeführt wurde, funktionierte es. Doch als das Projekt zum ersten Mal mittels Maven kompiliert wurde, wurden NullPointerExceptions geworfen. Sehr wahrscheinlich liegt das Problem beim ClassLoader. Eclipse nutzt sehr wahrscheinlich einen anderen ClassLoader als die JVM Runtime und daher kam es, dass es unter Eclipse funktioniert und unter Maven nicht. 88 Dokumentation, Heracles Anhang B. Anhang Probleme Das Problem wurde so behoben, dass die Inizialisierung nicht mehr in der abstrakten Klasse durchgeführt wird, sondern in der abgeleiteten Klasse HeraclesImpl. B.2 Offene Probleme XML Validierung Commons-Digester ist so konfiguriert, dass die heracles-config.xml Datei mithilfe der DTD validiert wird. Wenn die Validierung fehlschlägt wirft Digester eines SAXException. Diese wird jedoch nicht wie gewünscht an den Benutzer übergeben, sondern sie wird von Spring geschluckt. Die Validierung des XMLs wird bei der Initialisierung des Spring Containers gemacht. In Log4J wird die Exception angezeigt, doch Spring arbeitet einfach weiter, als wäre nichts passiert. Ich habe noch keinen Weg gefunden, wie wir diese Exception so auslösen können, dass bei einer fehlgeschlagenen Validierung die externe Applikation die Exception erhält. 89 C Anhang Zukunft Die Zukunft von Heracles ist bereits geplant. Als Erstes werden natürlich alle offenen Punkte realisiert. Dies wird in einer zwischen Version veröffentlicht. Für Heracles Version 2 wurden jedoch auch schon die ersten Pläne geschmiedet. Das Ziel der Version 2 ist es, dass Heracles als eine verteilte Applikation1 eingesetzt werden kann. Arbeitet eine Firma mit verschiedenen Applikationen, welche Heracles nutzen, so wäre es von Vorteil, wenn die Konfiguration von Heracles und Heracles selbst an einer zentralen Stelle liegen würde und die diversen Applikationen auf das gleiche Heracles Framework zugreifen könnten. Bei Änderungen an ADS oder Kerberos müsste somit die Konfiguration von Heracles nur an einer Stelle angepasst werden und nicht pro Applikation. 1 Stichwort RMI und JNDI 90 D Anhang heracles-config.dtd Listing D.1: Heracles XML Documenttyp-Definition 1 <?xml version="1.0" encoding="ISO-8859-1"?> 2 3 <!ELEMENT heracles (ldap-config , kerberos-config)> 4 5 <!ELEMENT ldap-config (domain+)> 6 7 8 9 10 <!ELEMENT domain (principal , credential , provider, searchBase, emtpyValues)> <!ATTLIST domain name CDATA #REQUIRED > 11 12 13 14 15 16 <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT principal (#PCDATA)> credential (#PCDATA)> provider (#PCDATA)> searchBase (#PCDATA)> emtpyValues (#PCDATA)> 17 18 19 20 21 22 <!ELEMENT kerberos-config (realm+)> <!ELEMENT realm (#PCDATA)> <!ATTLIST realm name CDATA #REQUIRED > 91 E Anhang KerberosQueryImpl.java Listing E.1: JAAS CallbackHandler von Heracles 1 2 3 4 5 6 7 8 9 10 11 12 13 package net.sourceforge.heracles.utilities; /** KerberosCallbackHandler.java<br> * Title: HFT-SO<br> * Copyright: Java Version: JDK 1.5<br> * * * @author Philipp Gantert * @version 1.0 */ import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; 14 15 16 17 public class KerberosCallbackHandler implements CallbackHandler { private String username; private String password; 18 public KerberosCallbackHandler(String username, String password) { this.username = username; this.password = password; } 19 20 21 22 23 public void handle(Callback[] cb) { for (int i = 0; i < cb.length; i++) { if (cb[i] instanceof NameCallback) { NameCallback nc = (NameCallback) cb[i]; nc.setName(this.username); } if (cb[i] instanceof PasswordCallback) { PasswordCallback pc = (PasswordCallback) cb[i]; pc.setPassword(this.password.toCharArray()); } } } 24 25 26 27 28 29 30 31 32 33 34 35 36 public void setUsername(String username) { this.username = username; } 37 38 39 40 public void setPassword(String password) { this.password = password; } 41 42 43 44 } 92 F Anhang Beilagen Zur Diplomarbeit werden diverse Beilagen in ausgedruckter und in elektronischer Form abgegeben. F.1 Ausdruck • Zeitplan • Tagesjounal F.2 Elektronisch • Pflichtenheft • Applikation • Dokumentation • Zeitplan • Tagesjournal • Testprogramme für Zeitmessung von JNDI und JAAS. • Prototyp 93 Abbildungsverzeichnis 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 DNS Domänen . . . . . . . . Distinguished Name . . . . . Kerberos . . . . . . . . . . . . Active Directory IST-Zustand UseCase Diagramm . . . . . . UC1 Authentifizierung . . . . UC2 Ldap abfragen . . . . . . UC3 ACEGI Provider . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 11 12 14 18 19 21 24 3.1 3.2 3.3 3.4 3.5 3.6 Maven 2.0 Paketstruktur . . . . Klassendiagramm . . . . . . . . Heracles API . . . . . . . . . . Heracles Konfigurations Modell ACEGI Heracles-Klassen . . . . Schichtenmodell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 27 28 29 31 35 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 UC1 UC1 UC1 UC1 UC2 UC2 UC2 UC3 UC3 Sequenzdiagramm authSimple . . Sequenzdiagramm authAdvanced funkionelle JUnit Tests . . . . . . performance JUnit Tests . . . . . Sequenzdiagramm . . . . . . . . . funktionelle JUnit Tests . . . . . performance JUnit Tests . . . . . Sequenzdiagramm . . . . . . . . . funktionelle JUnit Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 38 42 42 43 51 51 52 54 5.1 5.2 Klassendiagramm CreateTestData . . . . . . . . . . . . . . . . . . . . . . . . . . Latenzzeit Berechnung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 64 6.1 Heracles Abhängigkeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 7.1 7.2 7.3 7.4 7.5 7.6 7.7 Das Ablaufdiagramm Die Anmeldung . . . Die Fehlermeldung . Hauptseite . . . . . . Die Suche . . . . . . Die Resultate . . . . Maven Paketstruktur 72 73 73 74 74 75 76 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dokumentation, Heracles 7.8 Abbildungsverzeichnis Abhängigkeiten des Prototypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 78 Tabellenverzeichnis 1.1 Personen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1 2.2 2.3 2.4 2.5 Festgelegte Attribute Attribute . . . . . . UseCase UC1 . . . . UseCase UC2 . . . . UseCase UC3 . . . . . . . . . 15 16 17 20 23 3.1 Beispiel: emptyValues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 5.1 5.2 5.3 Konstanten der Klasse CreateTestData.java . . . . . . . . . . . . . . . . . . . . . Zusammengestellte Eigenscahften . . . . . . . . . . . . . . . . . . . . . . . . . . . Messwerte JNDI und JAAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 63 65 7.1 Prototyp Benutzer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 A.1 Anforderungszuordnung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 der . . . . . . . . HFT-SO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Listings 3.1 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 4.11 4.12 4.13 4.14 4.15 4.16 4.17 4.18 4.19 4.20 4.21 4.22 5.1 5.2 5.3 6.1 6.2 6.3 6.4 7.1 D.1 E.1 Heracles XML Konfigurationsdatei . . . . Heracles als Singleton . . . . . . . . . . . Spring Container initialisieren . . . . . . . UC1 Validator . . . . . . . . . . . . . . . UC1 JAAS . . . . . . . . . . . . . . . . . UC1 JAAS . . . . . . . . . . . . . . . . . UC2 Validator . . . . . . . . . . . . . . . UC2 Die Suche . . . . . . . . . . . . . . . UC2 Die Umgebung . . . . . . . . . . . . UC2 Die Suchresultate . . . . . . . . . . . UC2 LDAP Attribut . . . . . . . . . . . . UC2 LDAP Attribut Ausgabe . . . . . . . UC2 LDAP Attribut für LdapUser Objekt UC2 Konvertieren von Integer zu Date . . UC2 Gruppenzugehörigkeit . . . . . . . . UC2 UserAccountControl Attribut . . . . UC3 erweitere Authentifizierung . . . . . UC3 GrantedAuthority Objekte . . . . . . UC3 UserDetail Objekte erzeugen . . . . . UC3 ACEGI Konfiguration . . . . . . . . UC3 Exception Handling . . . . . . . . . . XML Beispiel . . . . . . . . . . . . . . . . Digester Beispiel . . . . . . . . . . . . . . Keytool für keystore-Datei . . . . . . . . . Arbeiten mit CreateTestData.java . . . . . JNDI und SSL . . . . . . . . . . . . . . . Heracles XML Konfigurationsbeispiel . . . Einfache Authentifizierung . . . . . . . . . Erweiterte Authentifizierung . . . . . . . . Ldap abfragen . . . . . . . . . . . . . . . . ACEGI Prototyp Konfiguration . . . . . . Heracles XML Documenttyp-Definition . . JAAS CallbackHandler von Heracles . . . 97 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 36 37 39 39 40 44 44 45 46 46 46 47 48 48 49 52 52 53 53 54 55 55 59 61 62 68 69 69 70 76 91 92 Literaturverzeichnis [Com06] ComputerPerformance. Research ldap properties for the user object. http://www.computerperformance.co.uk/Logon/LDAP_attributes_active_directory.htm, 2006. [ES02] JavaWorld.com Erik Swenson. Simplify xml file processing with the jakarta commons digester. http://www.javaworld.com/javaworld/jw-10-2002/jw-1025opensourceprofile.html, 10 2002. [Jas03] Garman Jason. Kerberos: The Definitive Guide. O’Reilly, 2003. 0-596-00403-6. [KD03] Laser Jochen Klünter Dieter. LDAP verstehen, OpenLDAP einsetzen. Dpunkt Verlag für digitale Tech- nologie GmbH, 2003. 3-89864-217-8. [Lüt02] Andreas Spall Dirk M. Sohn Josef Lüth. Jaas http://www.oio.de/public/java/jaas/sso-jaas-kerberos-tutorial.htm, 2002. tutorial. [Mic06] Microsoft. Verwendung der useraccountcontrol-flags zur bearbeitung von benutzerkontoeigenschaften. http://support.microsoft.com/kb/305144/de, 10, Juni 2006. [Pro] Jakarta Project. Commons-digester. http://jakarta.apache.org/commons/digester/. [Seca] ACEGI Security. Javadoc. security/apidocs/index.html. http://www.acegisecurity.org/multiproject/acegi- [Secb] Acegi Security. Reference documentation. http://www.acegisecurity.org/docbook/acegi.html. [Sec06] ACEGI Security. Frequently asked questions. http://www.acegisecurity.org/faq.html, Dezember 2006. [Sot06] Soenke Sothmann. Acegi - method based security für spring. http://www.oio.de/acegiartikel-tutorial-method-security-spring.htm, 2006. [SUNa] SUN. Jaas authentication tutorial. http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/tutorials/GeneralAcnOnly.html. 98 Dokumentation, Heracles Literaturverzeichnis [SUNb] SUN. Jaas project. http://java.sun.com/products/jaas/. [SUNc] SUN. Jndi project. http://java.sun.com/products/jndi/. 99