Eclipse Summit Europe 08 - Aspect Weaving for OSGi
Eclipse Magazin 12 - Security does matter
1. Praxis
AJEER
AJEER: Eclipse und Security Aspekt-orientiert
Security Does Matter
Quellcode
auf CD
>> peter friese, martin lippert und heiko seeberger
sinnvoll, wenn die Funktionalität der
Mehr und mehr Anwendungen werden auf Basis von Eclipse RCP entwi- Anwendung so gekapselt wird, dass
sie schön auf einzelne Plug-ins verteilt
ckelt. Der Anteil der Anwendungen, die im Unternehmensumfeld einge- ist und der Anwender durch das Ab-
setzt werden und im Bereich Security besondere Anforderungen stellen, schalten der Funktionen nicht zu sehr
eingeschränkt wird. Das Abschalten des
nimmt ebenfalls zu. Bisher bietet Eclipse jedoch keine native Unterstüt-
Wertpapierverwaltungs-Plug-ins wäre
zung für dieses wichtige Thema. Dieser Artikel stellt einen Ansatz vor, z.B. für einen Bankangestellten, der an
der Kasse arbeitet, noch sinnvoll. Kon-
der Aspekt-orientierte Techniken nutzt, um eine Funktions-orientierte
traproduktiv wäre jedoch das Abschal-
Autorisierung in einem RCP Frontend zu ermöglichen. ten des Personalverwaltungs-Plug-ins
für einen Mitarbeiter in der Rentenab-
teilung. D.h., dass es nicht ausreicht,
S ecurity hat viele Facetten: Unter diesen Backend verwendet wird. Das Token lässt die Plug-ins entlang der fachlichen En-
Begriff fallen Themen wie Authentifi- idealerweise keinen Rückschluss auf das titäten zu schneiden. Man muss noch
zierung („Ist der Anwender tatsächlich die Passwort des Benutzers zu, um ein Ha- feingranularer schneiden und sowohl
Person, für die er sich ausgibt?“), Autori- cken der Verbindung zu erschweren. die Entitäten als auch das, was man da-
sierung („Welche Funktionen darf der An- Nachdem also die Identität des Be- mit machen will, beachten. Ergo: Dieser
wender ausführen, und welche Daten darf nutzers festgestellt worden ist, sollen Ansatz ist mit viel Nachdenken bzw.
er sehen?“) und Sicherheit des Programm- einerseits die Daten eingeschränkt wer- aufwendigem Refactoring verbunden
codes (insbes. Schutz vor Manipulation den, die er sehen darf, und andererseits und führt zu einer schwer wartbaren
des Codes). Für all diese Themen gibt es die Funktionen, die er ausführen darf. Zersplitterung der Anwendung.
im Java-Universum diverse Frameworks, Wir wollen uns hier nicht mit dem Filtern • Capabilities: Kim Horne hat dazu auf
deren Einsatzmöglichkeit teilweise jedoch der sichtbaren Daten beschäftigen (diese der EclipseCon 2005 im Rahmen ih-
von der eingesetzten Basistechnologie ab- Aufgabe fällt eher in den Bereich des Ba- rer Session „Addressing UI Scalability
hängt. So ist das Thema Authentifizierung ckends), sondern mit der Frage, wie man Issues in Eclipse“ [2] einen Vorschlag
und Autorisierung im Web-Umfeld bereits die vom Benutzer ausführbaren Funkti- gemacht. Prinzipiell ist das keine
so gut abgedeckt, dass es eigentlich kein onen effektiv einschränken kann. schlechte Idee, allerdings kann der An-
Problem darstellt, eine Webapplikation Die vom Benutzer ausführbaren wender ja problemlos eine deaktivierte
auf geeignete Weise und mit vertretbarem Funktionen werden in Eclipse durch Ac- Capability wieder anschalten.
Aufwand abzusichern. Für Rich Clients tions ausgelöst. Actions implementieren • Die Einführung einer eigenen Ober-
sieht das ein wenig anders aus. Insbeson- entweder das Interface IAction oder das klasse für alle Actions, die autorisiert
dere für Eclipse-RCP-Applikationen exis- Interface IActionDelegate. Das Interface werden müssen: An sich ein vernünf-
tiert bislang keine Lösung, die out-of-the- IAction definiert die Methoden run() tiger Ansatz, allerdings bekommt man
box verwendbar ist. und runWithEvent(Event event), in de- die Default Actions der Eclipse-Platt-
Bevor wir einen Überblick über die nen die Funktion dann ausgeführt wird. form nicht zu fassen.
derzeit diskutierten Möglichkeiten geben, Außerdem können Actions aktiv oder • Der hier vorgestellte Weg nutzt Aspekt-
ist eine kurze Aufstellung der typischen inaktiv sein – dies wird über die Proper- orientierte Programmierung (AOP),
Anforderungen angebracht: Zunächst ist ty enabled gesteuert. Sowohl die run()-/ um die Berechtigung des Benutzers auf
es unerlässlich, dass der Anwender sich runWithEvent()-Methoden als auch die dem Client durchzusetzen. Es werden
an der Applikation anmeldet – üblicher- enabled Property stellen gute Kandidaten ausschließlich Aktionen, für die der Be-
weise mit einem Passwort-Dialog. Die er- für die Berechtigungssteuerung dar. nutzer die erforderliche Berechtigung
fragten Anmeldeinformationen werden besitzt, angezeigt bzw. ausgeführt.
Diskussion der möglichen Ansätze
dann an ein Backend-System übergeben,
AOP in OSGi-Anwendungen
das die Gültigkeit dieser Informationen • Die Deaktivierung ganzer Plug-ins (z.B.
überprüft und im Erfolgsfall ein Session mit Eclipse JAAS; André Oosthuizen Naheliegenderweise verwenden wir als
Token ausgibt, das im weiteren Verlauf hat dazu zahlreiche Beiträge in seinem Aspekt-orientiertes Hilfsmittel AspectJ
der Kommunikation zwischen Client und Blog veröffentlicht [1]): Sie ist nur dann [3], weil AspectJ der De-facto-Standard
87
www.eclipse-magazin.de eclipse magazin Vol. 12
2. Praxis AJEER
gigkeiten zu dem eingewobenen Aspekt
in den Bytecode der Klasse eingefügt. In
einer gängigen Java-Anwendung ist dies
kein Problem, weil der Aspekt und die ver-
wobene Klasse im gleichen Classpath lie-
gen und die zusätzlichen Abhängigkeiten
damit keine Probleme verursachen. In
der OSGi-Welt entstehen aber Abhän-
gigkeiten, die im OSGi-Manifest nicht
berücksichtigt sind. Können sie ja auch
nicht, denn wir wollen mit unserem As-
pekt ja auch solche Plug-ins beeinflussen,
die wir NICHT implementiert haben.
Load-Time Weaving für OSGi
Glücklicherweise ermöglicht die Eclipse-
OSGi-Implementierung (Equinox-) An-
passungen am Classloading-Standard-
verhalten. Seit Eclipse 3.2 gibt es dafür den
Hookable Adaptor [6]. Über so genannte
Abb. 1: AJEER Launcher
Framework Extension Fragments, d.h.
für AOP mit Java und ebenfalls ein Eclip- net). Bundles definieren im so genannten Fragment Bundles für das System Bundle,
se-Projekt ist, sodass mit AJDT [4] eine Bundle-Manifest (META-INF/MANI- können ClassLoadingHooks beigesteu-
schöne Integration in die Entwicklungs- FEST.MF), welche Packages zum exter- ert werden. Dieser Mechanismus kann
umgebung genutzt werden kann. Aller- nen API gehören und somit für andere beispielsweise ausgenutzt werden, um
dings ist das Aspect Weaving von AspectJ Bundles sichtbar sind. Weiterhin wird der OSGi Runtime selbst das Load-Time
zunächst einmal mit Blick auf „norma- festgelegt, welche Packages importiert Weaving beizubringen.
le“ Java-Anwendungen implementiert werden bzw. zu welchen anderen Bundles Eine entsprechende Erweiterung
und harmoniert nicht ohne Weiteres mit Abhängigkeiten bestehen. Diese Infor- für die Equinox-OSGi-Implementie-
dem Plug-in-Konzept von Eclipse. Rufen mationen werden von der OSGi Runtime rung existiert bereits, sogar in zwei un-
wir uns daher ins Gedächtnis zurück, wie zur Laufzeit ausgewertet und beim Class- terschiedlichen Facetten: Zum einen
RCP-Anwendungen aufgebaut sind: loading berücksichtigt. Letztendlich gibt es das Equinox-Incubator-Projekt
Applikationen auf Basis von Eclip- besitzt jedes Bundle einen eigenen Class- „Aspects“, welches eine entsprechende
se bzw. OSGi [5] bestehen aus Plug-ins Loader, der nur die eigenen Klassen und OSGi-Extension für AspectJ bereitstellt.
genannten Modulen (in der OSGi-Welt die importierten Klassen sieht. Dadurch Zum anderen existiert ein Sourceforge-
werden die Module als Bundles bezeich- wird für jedes Bundle ein eigener, abge- Open-Source-Projekt namens AJEER [7],
schotteter Classpath definiert. welches ebenfalls eine solche Erweiterung
Soll AspectJ innerhalb eines Bund- implementiert. Beide Projekte setzen auf
Listing 1
les eingesetzt werden, kann direkt das der Original-AspectJ-Weaving-Imple-
<extension point=”org.eclipse.ajeer.
AspectJ Tooling und das Compile-Time mentierung auf und binden dieses Wea-
weavingruntime.aspects”>
Weaving genutzt werden. Das Bundle ving geeignet in die OSGi Runtime ein.
<aspect class=”org.eclipse.ajeer.examples.hello.
wird vom AspectJ Compiler kompiliert, Das Prinzip bei beiden Projekten ist
aspects.HelloAspect”/>
und die Aspekte werden in den Code des sehr ähnlich: Bundles können Aspekte
</extension>
Bundles eingewoben. Soweit alles kein enthalten und deklarieren, dass diese
Problem. Was passiert aber, wenn ein As- Aspekte mit anderen Bundles verwoben
pekt in einem Bundle implementiert wer- werden sollen. Im Falle von AJEER wird
Listing 2
den soll, der andere bereits existierende dies über den Extension-Point-Mecha-
osgi.framework.extensions=org.eclipse.ajeer.
Bundles beeinflusst? Genau das wollen nismus realisiert. Mit einer passenden
bytecodetransformer
wir ja schließlich in unserem Security- Extension kann also ein Plug-in einen
osgi.bundles=...,org.eclipse.ajeer.
Anwendungsfall nutzen. Aspekt der Runtime „bekanntmachen“.
weavingruntime@:start,
Die Antwort heißt natürlich zunächst Dieser Aspekt wird grundsätzlich in alle
org.eclipse.ajeer.bytecodetransformer
Load-Time Weaving. Leider lässt sich anderen Bundles des Systems eingewo-
...
durch den sehr speziellen Classloading- ben, wenn Klassen geladen werden. Ein-
Mechanismus von OSGi das Standard zig die Definition des Aspekts selbst (ge-
Listing 3 Load-Time Weaving von AspectJ nicht nauer gesagt, die enthaltenen Pointcuts)
ohne Weiteres nutzen. Das Hauptprob- entscheidet, ob der Aspekt die gerade zu
pointcut enablement(IAction action):
lem besteht darin, dass durch das Aspect ladende Klasse beeinflusst oder nicht.
target(action) && execution(public boolean
Weaving der Code der verwobenen Klas- Im Equinox-Incubator-Projekt kann
IAction.isEnabled());
se verändert wird. Dabei werden Abhän- sehr viel genauer gesteuert werden, wie
88 eclipse magazin Vol. 12 www.eclipse-magazin.de
3. Praxis
AJEER
der Aspekt verwoben werden soll. Dazu fe des Eclipse PDE Template RCP appli- Wenn alles richtig läuft, lässt sich
können die von AspectJ bereits bekannten cation with a view erzeugte Miniappli- die Anwendung starten, und die Be-
aop.xml-Dateien verwenden werden. Es kation, die um ein ActionSet inklusive rechtigung lässt sich für die Actions
ist aber auch möglich, eine wie bei AJEER Beispiel Action sowie eine View Action über die Properties-Datei steuern. Das
sehr globale Regel einzustellen. erweitert wurde. Diese Applikation soll Format für die Berechtigungen lautet
Die OSGi Runtime Extension sorgt nun um die notwendigen Sicherheitsfea- action.[Benutzername.]Klassenname
nun in beiden Projekten dafür, dass die so tures erweitert werden. derAction=enabled,also z.B.action.Peter.
bekannt gemachten Aspekte beim Class- Den Zugriff auf eine Benutzerdaten- org.eclipse.ui.internal.QuitAction=true
loading mit den entsprechenden Klassen bank inklusive Berechtigungsschema oder action.de. eclipsemagazin.aspects.
verwoben werden und dadurch entste- wird mithilfe der Klassen Authorizer demo.SampleAction=false.
hende Abhängigkeiten zwischen den und AuthorizationDAO sowie einer Ein kurzer Test offenbart, dass die
Bundles korrekt behandelt werden. Damit Properties-Datei (authorizations.txt) Actions zwar aktiviert bzw. deaktiviert
ist man in der Lage,Aspekte innerhalb von simuliert, welche die Berechtigungen werden, allerdings ist es nicht möglich,
Bundles modular zur Verfügung zu stellen enthält. im laufenden Betrieb die Autorisierung
und zur Laufzeit in das System weben zu Wie bereits beschrieben, sollen Ac- für eine Action zu ändern. Dies liegt
lassen. Für das Beispiel verwenden wir der tions möglichst nur dann als aktiviert daran, dass Eclipse den enablement
Einfachheit halber die AJEER-Variante. dargestellt werden, wenn der Benutzer State einer Action im Normalfall nur
berechtigt ist, sie auszuführen. Ziel ist es einmal prüft. Eine Ausnahme bilden
AJEER verwenden also, den enablement State aller Actions die View Actions: Ihr enablement State
Die Installation von AJEER erfolgt am zu steuern. Ein Blick in das API offenba- wird überprüft, sofern die Auswahl im
besten über die AJEER Update Site [8], rt folgende Signatur für IActions: public zugehörigen View geändert wurde. Al-
wobei unbedingt darauf zu achten ist, boolean isEnabled(). Um alle Aufrufe lerdings wird diese Prüfung nicht direkt
dass das AJEER Feature, welches das dieser Methode abfangen und entspre- im Anschluss an den Selektionswechsel
Framework Extension Fragment enthält, chend der Benutzerberechtigung reagie- ausgeführt, sondern erst direkt bevor
in das Installationsverzeichnis des Eclip- ren zu können, wird ein AspectJ Pointcut die Action aufgerufen wird – und da-
se SDK installiert wird und nicht in eine benötigt, der alle Aufrufe einer Methode zwischen können Minuten liegen!
separate Extension Location. Nur wenn isEnabled mit einem Boole’schen Pa-
die Framework Extension im selben rameter auf Subklassen des Interface
Listing 4
Verzeichnis wie das System Bundle (org. IAction markiert (Listing 3). Die Über-
eclipse.osgi) liegt, kann sie gefunden und prüfung der Benutzerberechtigung wird boolean around(IAction action):
zum Framework hinzugefügt werden. dann mit einem recht einfachen Advice enablement(action) {
Das Plug-in org.eclipse.ajeer.wea- (Listing 4) durchgeführt. String function = action.getClass().getName();
vingruntime definiert den Extension Sowohl der Aspekt als auch die
Point aspects, der dazu verwendet wird, Hilfsklassen Authorizer und Autho- System.out.println(“Getting enablement state for [“
Aspekte zu registrieren, die beim Load- rizationDAO werden in einem sepa- + function + “]”);
Time Weaving berücksichtigt werden raten Plug-in-Projekt mit dem Namen boolean enabled = isAuthorized(function);
sollen (Listing 1). de.eclipsemagazin.aspects.demo.secu- if (enabled) {
Um der Eclipse Runtime die Verwen- rity abgelegt. Mittels des Menüeintrags System.out.println(“The user is authorized to
dung von Framework Extensions be- AspectJ Tools | Convert to AspectJ execute [“ + function +
kannt zu machen, muss die System Pro- Project wird das Projekt in ein AspectJ- “], but maybe the action is diabled nevertheless?”);
perty osgi.framework.extensions gesetzt Projekt umgewandelt. Im Plug-in-Ma- enabled = proceed(action);
}
und mit dem Bundle-SymbolicName des nifest müssen die Plug-ins org.eclipse.
System.out.println(“Enablement state: [“ + enabled
Framework Extension Bundle versehen ajeer.weavingruntime und org.aspectj.
+ “].”);
werden. Weiterhin ist es nötig, das Plug- runtime als Dependencies hinzugefügt
return enabled;
in org.eclipse.ajeer.weavingruntime zu werden.
}
starten. Beides wird in der Datei config. Zum Starten der Beispielapplika-
ini vorgenommen, die für jede Eclipse- tion mit aktivierter Sicherheit muss
Applikation existiert (Listing 2). im Launch-Dialog eine neue AspectJ
Listing 5
Zur Vereinfachung der Verwendung Launch-Konfiguration angelegt wer-
innerhalb des Eclipse SDK liefert das den. Die auszuführenden Plug-ins sind pointcut actionDelegateInvocation(IActionDelegate
AJEER Tools Fragment einen AJEER de.eclipsemagazin.aspects.demo3 und delegate, IAction action):
Launcher, der auch diese Einstellungen de.eclipsemagazin.aspects.demo3.secu- target(delegate) && args(action) &&
in die automatisch generierte config.ini rity, die erforderlichen Abhängigkeiten execution(void IActionDelegate.run(IAction));
einträgt. können durch Klicken auf Add re-
quired Plug-ins hinzugefügt werden.
Design und Implementierung einer Listing 6
Auf der Seite Main muss als zu startende
konkreten Lösung für unser Problem Applikation de.eclipsemagazin.aspects. pointcut actionInvocation(IAction action):
Nun zurück zum eigentlichen Problem. demo3.aosapplication ausgewählt wer- target(action) && execution(void IAction.run());
Als Beispielapplikation dient eine mithil- den.
89
www.eclipse-magazin.de eclipse magazin Vol. 12
4. Praxis AJEER
Da diese erste Herangehensweise Aufgabe ist und der Bytecode der gela- ting Concerns auch in einer OSGi-Welt
(Actions aktivieren/deaktivieren je nach denen Klassen geparst und weiterge- zu modularisieren.
Berechtigung) nicht wie gewünscht hend analysiert werden muss. Die Lö-
funktioniert, hat die Stunde für den al- sung für diese Probleme liegt in einem Peter Friese ist Senior-Software-
ternativen Lösungsansatz (Ausführung geschickten Caching der bereits gewo- Architekt bei Gentleware. Er ist
der Actions abfangen) geschlagen: Wie benen Klassen für den nächsten Start spezialisiert auf Modell-getriebene
bereits angemerkt, müssen dazu sowohl des Systems. Das Equinox-Incubator- Softwareentwicklung, Spring sowie
Eclipse-Technologien. Peter ist Com-
alle Aufrufe der Methode public void Projekt hat dafür bereits eine Caching-
mitter für FindBugs und openArchitectureWare.
IAction.run() als auch der Methode pu- Implementierung, die sich spezielle Ei-
Kontakt: peter.friese@gentleware.com
genschaften der IBM Java VM zu Nutze
blic void IActionDelegate.run(Action
Martin Lippert ist Senior-IT-Berater
action) abgefangen werden. Die dazu macht und sehr effizient ist. Die Per- bei it-agile. Er arbeitet dort als
benötigten Pointcuts finden sich in Lis- formance und der Speicherverbrauch Coach und Berater für agile Soft-
ting 5 bzw. 6. einer bereits gecachten Anwendung las- wareentwicklung, Refactoring und
Die Überprüfung der Benutzerbe- sen sich praktisch nicht mehr von einer Eclipse-Technologie und ist Commit-
rechtigung wird in den zugehörigen Ad- Anwendung ohne Load-Time Weaving ter im Eclipse Equinox Incubator-Projekt. Kontakt:
martin.lippert@it-agile.de
vices durchgeführt (Listing 7 und 8). unterscheiden. Eine Implementierung
Heiko Seeberger leitet die Market
Ein nochmaliges Ausführen der Ap- für VMs, die nicht von IBM stammen,
Unit Enterprise Architecture der me-
plikation zeigt, dass die Actions nun steht noch aus, sollte aber in Zukunft
tafinanz GmbH. Er erstellt seit etwa
nicht mehr disabled werden. Verfügt verfügbar sein. AJEER implementiert zehn Jahren Enterprise Applications
der aktuelle Benutzer allerdings über die einen nicht so effizienten Cache, kann mit Java, wobei sein aktueller Fokus
notwendigen Rechte, so wird eine Warn- dafür aber auch auf diesen VMs einge- auf Eclipse und AspectJ liegt. Heiko ist Committer
meldung ausgegeben. setzt werden. von AJEER und ContractJ. Kontakt: heiko.seeberger
@metafinanz.de
Diese Lösung ist noch nicht perfekt,
Fazit
zeigt aber gut, wie sich mit Aspekt-ori-
entierter Programmierung und Load- Die Ausführungen und Beispiele in
>>Links & Literatur
Time Weaving für OSGi pragmatische diesem Artikel zeigen, dass durch Fra-
[1] www.ji.co.za/unplugged
und elegante Lösungen implementieren mework-Erweiterungen AspectJ Load-
[2] www.eclipsecon.org/2005/presentations/
lassen. Time Weaving auch für Eclipse-RCP-
EclipseCon2005_7.1Scalability.pdf
Applikationen möglich ist und dass
Auswirkungen [3] www.eclipse.org/aspectj
dieser Ansatz hervorragend geeignet ist,
[4] www.eclipse.org/ajdt
Das Load-Time Weaving von Aspekten um das Thema Security zu adressieren.
[ 5] www.osgi.org
benötigt in nicht unerheblichem Um- Die vorgestellte Lösung wird derzeit in
fang Speicher- und Prozessorressour- einem kommerziellen Projekt produktiv [6] wiki.eclipse.org/index.php/Adaptor_Hooks
cen. Dies resultiert daraus, dass das As- eingesetzt und erlaubt es auf eine ele- [7] ajeer.sourceforge.net
pect Weaving selbst eine nicht-triviale gante Art und Weise, echte Cross Cut- [8] ajeer.sourceforge.net/updatesite
Listing 7
void around(IActionDelegate delegate, IAction action): System.out.println(“The user is authorized to execute [“ +
actionDelegateInvocation(delegate, action) { function + “], but maybe the action is diabled nevertheless?”);
proceed(delegate, action);
String function = delegate.getClass().getName(); }
System.out.println(“Action [“ + function + “] invoked on delegate [“ else {
+ delegate.getClass().getName() + “]”); MessageDialog.openInformation(null, “Authorization failed“,
“You are not authorized to invoke this function.“);
System.out.println(“Getting enablement state for [“ + function + “]”); }
boolean enabled = isAuthorized(function); }
if (enabled) {
Listing 8
void around(IAction action): actionInvocation(action) { proceed(action);
String function = action.getClass().getName(); }
System.out.println(“Action [“ + function + “] invoked.”); else {
System.out.println(“Getting enablement state for [“ + function + “]”); MessageDialog.openInformation(null, “Authorization failed”,
boolean enabled = isAuthorized(function); “You are not authorized to invoke this function.”);
if (enabled) { }
System.out.println(“The user is authorized to execute [“ + }
function + “], but maybe the action is diabled nevertheless?”);
90 eclipse magazin Vol. 12 www.eclipse-magazin.de