martedì, settembre 16, 2008

J2EE SecurityService: potente ma...

...decisamente "entropico"!

Niente da dire su JAAS lato autenticazione, realizzato un po' sul modello di PAM (con cui tra l'altro può interagire), JAAS è decisamente costruito bene dal punto di vista dell'autenticazione.. per J2SE.. in J2EE le cose non vanno altrettanto bene dato che:
  1. ci si può autenticare in Ackerman(N,N) modi con N>3... il che tradotto da "modoDiDire" a "italiano standard" significa "troppi";
  2. l'autenticazione avvenuta in ognuno di questi modi porta a risultati diversi.. se almeno uno potesse scegliere una delle modalità di autenticazione qualunque (la più standard, la più comoda, ...) ottenendo lo stesso risultato... invece ci si può autenticare:
    • lato web-tier, utilizzando uno dei metodi vari (BASE,FORM,DIGEST,CUSTOM ecc) con identità salvata lato web-tier e propagata lato EJB;
    • direttamente tramite API dell'AS (come "com.sun.appserv.security.ProgrammaticLogin" in glassfish) saltando tutti i meccanismi di autenticazione standard.. e anche questo lato web e lato business con enormi differenze sul risultato;
    • utilizzando librerie che interagiscano con JAAS e con il SO, ad esempio per effettuare il login usando l'identità locale dell'utente (ad esempio un client di una applicazione EE potrebbe usare le credenziali di Windows o di PAM in Linux, Unix, MacOSX, "/.*[xX]/");
    • creando un proprio LoginModule e Realm (tanto per aggiungere entropia.. finiremo per confonderci con il "rumore di fondo"!!!)...
    • ...mi fermo ma potrei proseguire, sicuramente uno standard (anche de-facto) farebbe piacere.
  3. autenticazione=??? Ok, abbiamo controllato tutti i LoginModule di questa terra, username+password, impronte digitali, scansione retinica, statistiche di digitazione, impronta vocale, eco nel padiglione auricolare destro, ecc ecc... e mò? Salvataggio di Subject, Principal, Credentials... Tutto qui? E poi? Perché devo scrivere nel subject che sono "Gabriele Lombardi", creare un principal con dentro scritto "Gabirele Lombardi" e magari salvare le credenziali "Gabriele Lombardi"+"PasswdFuffa"???
Ma mica abbiamo finito.. eh no! Diamo un occhio lato autorizzazioni, da questo lato l'architettura è stra-fine: gestione di risorse, gestione di policy sulle risorse, di regole nelle policy, di permissions sulle risorse, di...
...insomma un casino!

Allora, dico io, va bene che bisogna poter fare mille cose.. che la sicurazza è una cosa, che bisogna essere generali e che usare i DesignPatterns aiuta a sviluppare software riutilizzabile e corretto... però a tutto c'é un limite! OPPURE...
Bene.. cari Sunnisti, esiste un simpatico BANALE pattern GOF di nome "Facade", lo usate sempre... ci sono package che fanno anche il caffé e nelle API pubbliche se ne vedono 4 classi/interfacce/annotazioni in croce! (Vedasi javax.persistence... fa l'impossibile.. ma "di nascosto")... usarlo anche per il SecurityService no eh? Magari usarlo UNA SOLA VOLTA ma bene.. creando un solo standard di accesso al servizio... non 27 modi diversi, non standard, vendor-dependent... e in generale diversi o peggio... quasi uguali ma con sfumature "cangianti"!!!

DETTO QUESTO...

Butto li una domanda-esempio: se volessi gestire dinamicamente utenti (e gruppi di utenti/gruppi organizzati in un DAG) nonché risorse (organizzate ad albero o DAG anche loro)... e poi volessi creare dei permessi che associno risorse e utilizzatori (utenti o gruppi) in maniera da poter risolvere i permessi sfruttando ereditarietà sia sulle risorse che sugli utenti/gruppi... come potrei fare? Ovviamente il tutto lo voglio fare dinamicamente.. non voglio uno staticissimo policy-file!

ESEMPIO:

RISORSE:
  • PhotoGallery
    • Gallery1
    • Gallery2
con permessi ordinati "edit">"comment"> "browse" (cioè che si implicano l'un l'altro).

UTENTI:
  • Users
    • Admin
    • Owner
    • KnownUser
PERMESSI:

  • Admin->Risorse: "*"
  • Owner->PhotoGallery: "*" (o "edit" dato che implica le altre)
  • KnownUser->Gallery1: "comment"
  • User->PhotoGallery: "browse"
Al che "Ciccio", associato al gruppo KnownUser, può vedere tutte le gallerie, ma può commentare solo Gallery1 e non può editare. "MasterOfPuppets" associato al gruppo Admin può fare tutto, mentre "QuiQuoQua", owner della galleria, può fare tutto.. ma solo sulla (sua) galleria.

Soluzione? Ovviamente costruibile a run-time.. cioè creando la struttura di risorse e utilizzatori a run-time aggiungendo tuple in una o più tabelle, creando le tuple di utenti e gruppi e creando le tuple per i permessi.

Vi prego... FLAMMATEMI questo post, così magari ci capisco un po' di più!!! ;)

2 commenti:

Gabriele Lombardi ha detto...

Mi rispondo da solo... non è stato banale trovare un buon articolo/esempio, però questo risponde (in parte) alle mie domande:

http://www.tedneward.com/files/Papers/JavaPolicy/index.html

Fermo resta che spostandosi in ambiente J2EE il tutto si incasina ancora di più.. e fermo resta che un'implementazione di default del Policy provider configurabile e basato su DataSource invece che su File, sarebbe molto gradito.

Ok, mi sono flammato da solo (un pochino).. adesso aspetto voi... DAI.. SU.. CAZZIATEMI! Ho solo e sempre da imparare! ;)

Gabriele Lombardi ha detto...

Ok, non mi risponde nessuno, mi rispondo da solo, sono un pochino picio! Alcune delle cose che ho detto sono vere, le modalità per effettuare il login sono molte e daglie ffetti diversi, l'autenticazione è sicuramente un punto devole dello standard EJB3.0.. perché è vendor-dependent. Ci sono metodi standard di autenticazione, lato web.. ma non lato EJB. L'utilizzo dei reami risolve comunque.

Per quanto riguarda la gestione dei permessi esiste JACC apposta: pensavo fosse fatto per lavorare solo con policy-files.. ma può essere anche utilizzato dinamicamente. Esempio:

[code]
import javax.security.jacc.*;
...
PolicyConfiguration pc = PolicyConfigurationFactory.getPolicyConfigurationFactory().getPolicyConfiguration();
pc.addToRole("roleName",new WebResourcePermission("/pageUrl",new String[]{"GET","POST"}));
[/code]

ecc ecc ecc... diciamo che sicuramente è un inizio per gestire dinamicamente i permessi.. certo sarebbe meglio poterseli gestire persistentemente, in pratica se si vuole realizzare un sistema che faccia serio e pesante utilizzo di permessi (standard e custom) si deve reimplementare java.security.Policy o utilizzare una sua sottoclasse già implementata da qualcun'altro (ad esempio messa a disposizione dell'AS).