Nuovo Fuss Launcher

I lavori all’interno del progetto Fuss proseguono spediti, come ogni anno. Quest’anno, un po’ per scommessa, un po’ per risolvere alcune problematiche degli utenti, un po’ per raccogliere una vecchia proposta di Enrico, abbiamo creato un nuovo applicativo.

La proposta era semplice: sfrutture le potenzialità di apt-xapian-index per accedere all’indice delle applicazioni sul sistema operativo (e, perché, anche quelle non installate) per facilitare la ricerca delle stesse da parte degli utenti, per poi ovviamente avviarle.

Quindi, il solito launcher? Non proprio. Uno dei problemi principali che spesso incontriamo all’interno di Fuss (ma anche all’interno di progetti di migrazione a software libero) è quello che forniamo troppo software. Troppo software perché possiamo liberamente fornirlo, e spesso i nostri utenti scoprono che possono fare più cose con il loro computer che in precedenza. Questo è senza dubbio un vantaggio. Dove sta il problema?

  1. Imparare i nomi degli applicativi rispetto a cosa questi fanno
  2. Ricordare i nomi imparati al punto 1
  3. Ricordarsi come si scrivono
  4. Ricordarsi dove tipicamente si trovano nel menu

L’idea dunque è quella di fornire l’accesso al software disponibile (installato e installabile) attraverso una interfaccia di ricerca, basandosi su di un indice (di sistema) che contiene descrizioni (in varie lingue), tags e quanto altro. Per riuscire a trovare l’applicazione che serve non partendo necessariamente dal suo nome (facile ricordarsi “kdissert” per le mappe mentali, vero?) ma attraverso parole chiave basate sulla descrizione del software.

Altro problema: ci troviamo spesso con tante applicazioni che si occupano della stessa cosa, in modo più o meno elegante, migliore etc. Il problema talvolta diventa quindi: “Ok, ho questo file, con cosa lo posso aprire?”. Sicuramente la logica consolida del “Apri con..” disponibile in molti file manager funziona, ma volendo accentrare l’avvio delle applicazioni in un unico punto, abbiamo fornito all’applicativo anche la possibilità di mostrare, cercando nell’indice, le applicazio in grado di gestire particolari file. Quindi dal mio file manager, trascino il file che voglio aprire sul launcher e questo mi mostra le applicazioni che lo possono aprire. “Droppo” (come si traduce in italiano?) il file sull’applicazione con l’icona più bella e questa verrà avviata, aprendo il file selezionato. Funziona anche con più file!

E le mie applicazioni preferite? Il metodo e’ semplice: non cercando niente di particolare, vengono mostrate le applicazioni più utilizzata, ordinate secondo il loro utilizzo. Quindi i preferiti vengono creati automaticamente, senza sforzo da parte dell’utente. D’altra parte, se avvio 100 volte al giorno il solitario, di sicuro è il mio preferito.

Maggiori informazioni su questo software si trovano nella home page del progetto, ancora in costruzione. E si, sicuramente la user interface ha ancora bisogno di tanto amore.

DURC

DURC – s.m. [dúrc]

Pratica burocratica barbarica, praticata in paesi in cui l’informatizzazione è un concetto oscuro, per cui un ente pubblico richiede ad ente privato la certificazione della regolarità contributiva, emessa, in cartaceo via posta ordinaria, sempre dall’ente pubblico ma sbagliata[1]. Una volta ricevuto per posta ordinaria in cartaceo il pubblico deve verificarne la validità interrogando il pubblico emittente, in forma cartacea e via posta ordinaria. Dalla richiesta del privato alla ricezione del documento, passa un mese e mezzo. All’arrivo, il documento ha validità di un mese. La verifica di validità, come procedure, impiega circa un mese.

In sostanza, il privato deve pagare e perdere tempo per dare al pubblico una informazione che è già di sua pertinenza e che potrebbe reperire ad un costo vicino allo zero.

[1] E non si parla di errorini eh.. roba del tipo che dichiara che applichi un contratto nazionale di un tipo, quando in realtà stai usando tutt’altro…

Il bello è che nel mezzo di sono le Poste Italiane™ !

XML, XML-RPC e Python nel 2009

Durante la fase di qualificazione di un progetto software che stiamo portando avanti da quasi 3 anni, è stato riscontrato un bug che mi ha fatto perdere più di una giornata per trovarne la soluzione. Il tempo perso non è dovuto tanto alla complessità del problema (la soluzione, ovviamente, era più che banale), ma piuttosto al fatto che, inconsciamente, non accettavo il fatto che quello potesse essere il problema.

Il software è un sistema di gestione centralizzato di un parco macchina. Tramite un demone implementato su Twisted, fornisce un servizio per l’accesso alla configurazione e uno per il controllo verso le macchine. Quest’ultimo è basato su una interfaccia piuttosto semplice in XML-RPC. Le macchine controllate accedono ai dati e riportano i risultati.

Una delle funzionalità implementate riguarda la possibilità di eseguire campagne di esecuzione di script (di qualunque natura, purchè la macchina abbia gia’ a disposizione l’interprete con cui viene scritto). Le macchine ricevono lo script, lo eseguono, restituiscono indietro alcuni dati, tra cui l’exit code e l’output (stdout + stderr in formato annotated).

Sembra facile, no?

La codifica utilizzata è sempre e ovunque UTF-8, per cui l’output dello script viene (anzi, veniva) dichiarato nel payload XML-RPC come un semplice <string>. Tanto, UTF-8, qualunque cosa va bene, no?

I primi test vanno a buon fine. Poi il problema: alcuni script fanno sollevare una eccezione di “malformed token” da parte del servizio che riceve i dati. Possibile?

Server e client implementati in python. Il client utilizza xmlrpc, che si trova nella libreria standard.

Ora, possibile che nel 2009 , utilizzando un linguaggio ad alto livello, utilizzando un modulo della libreria standard, debba essere io a preoccuparmi che i caratteri che non possono stare in XML vengano codificati correttamente, come, ad esempio, i caratteri ASCII da 0 a 31? Perchè alcuni di questi vengono codificati automagicamente ( come ‘&’, o ‘<’), mentre altri no? Ma poi neanche tutti gli ASCII da 0 a 31, anche tra questi, alcuni sono gestiti dalla libreria, come il 9, il 10 e il 13…

Soluzione al problema: il dato passato non deve essere str ma xmlrpclib.Binary. Che si preoccupa di codifica/decofidica in base64 del payload. Semplice e veloce. Ma perchè ci devo pensare io? :)

LDAP e la disperazione

Ho maturato, grazie anche ai commenti di Enrico, lo stato dell’arte rispetto a LDAP su sistemi liberi.

Problema: in azienda abbiamo svariati repository SVN/GIT con rispettivi project tracker, per i singoli progetti (interni, dei clienti, di spippolamento generico, etc). Come gestire nel modo più comodo autenticazione e autorizzazione ai rispettivi progetti da parte di utenti di varia provenienza (utenti interni, clienti, collaborati,etc) ?

Per “modo più comodo” si intende:

  • Evitare la duplicazione delle informazioni di autenticazione
  • Gestire gli accessi ai singoli progetti
  • Delegare la gestione degli accessi ai singoli progetti
  • Permettere agli utenti di gestire i propri account, inclusa la partecipazione ai singoli progetti

Trac può funzionare tranquillamente con autenticazione HTTP, SVN/GIT pure.. perfetto, mi dico, usiamo i vari moduli di autenticazione forniti da Apache, web server che attualmente fa da frontend.

I dati? Beh, la risposta viene spontanea: LDAP!

LDAP, LDAP.. si, ma veramente è la soluzione?

Esistono moduli Apache per autenticare utenti e gruppi su LDAP, quindi una soluzione possibile è:

  1. OU separate per le varie tipologie di utenti (interni, collaboratori, clienti)
  2. OU per i “progetti”, contenente oggetti di tipo gruppo
  3. Utenti associati a questi gruppi
  4. Scope di ricerca utenti sub a partire dalla root

In lingua Apache, la cosa si traduce in qualcosa del tipo:

<Location /progetto-x>
                AuthName "Tracker Progetto X"
                AuthType Basic
                AuthBasicProvider ldap
                AuthLDAPURL ldap://127.0.0.1/dc=myroot,dc=com
                AuthLDAPGroupAttributeIsDN off
                AuthLDAPGroupAttribute memberUid
                require ldap-group cn=progetto-x,ou=Projects,dc=myroot,dc=com
</Location>

(omessi i dettagli su trac e la configurazione base di authz-ldap)

In questo modo, l’autenticazione utente permette di cercare nelle varie OU dove questi si trovano, es. ou=collaborati,dc=myroot,dc=com, e i gruppi invece nella OU dei progetti.

Dal punto di vista della gestione, quando viene creato un pogetto, si crea il gruppo, si inseriscono gli utenti nel gruppo (crearli prima, se necessario), creare trac e svn (anche tramite hook, ma questa é un’altra storia).

Fino a qui, la cosa funziona.

Dove sono i problemi?

  1. Se il server LDAP principale non e’ esposto sulla rete, o si trova su una macchina diversa, dalla quale riceviamo una replica in sola lettura, non abbiamo un modo facile e comodo (anche dal punto di vista di una UI) per permettere gli utenti di gestire i propri account. Possiamo cambiare la password, ma gestire l’appartenenza ad un progetto? Lasciare la scrittura sul gruppo tramite una ACL significa che gli utenti possono aggiungere anche altri al gruppo.
  2. Delegare la gestione del gruppo a qualcuno, significa, se si utilizza l’implementazione LDAP server slapd, di creare una o piu’ acl per ogni gruppo. Se l’albero e’ replicato da un server centrale, auguri…

Se avete altri punti a sfavore, commentate, che li aggiungo…

Soluzioni?

Ho pensato un pò a possibili soluzioni a questo problema. Esiste un modo per cui:

  1. Ho un database di autenticazione verso il quale posso autenticare tramite un web server e
  2. Gli utenti possono gestire i propri dati (password, autenticazione, etc) e
  3. Posso delegare la gestione di uno o più gruppi/progetti a una o più persone e
  4. Avere possibilità di stabilire criteri di accesso ai progetti per ogni singolo progetto?

Una soluzione possibile è implementare un applicativo web o simili per la gestione dei dati su database e le operazioni di cui sopra, e utilizzando gli appositi moduli di autenticazione, configurare opportunamente il web server.

Ma esiste qualcosa che possa evitare questo sforzo, visto che c’è anche altro da fare?

Una soluzione che ho individuato, e realizzato con pochissimo sforzo, e che, apparentemente risolve gran parte di questi problemi, è utilizzare Mailman.

Se riesco ad autenticare HTTP contro il database di iscrizioni di una specifica lista Mailman, ottengo:

  1. Delega di gestione: mailman permette di associare ad una lista uno o più amministratori, che possono aggiungere(iscrivere)/togliere(deiscrivere) utenti, e stabilire anche i criteri di accesso (conferma, conferma e autorizzazione, etc)
  2. Gli utenti possono gestirsi in proprio i dati personali: cambio password, appartenenza o meno ad un progetto, tutto autonomamente
  3. Ho già una lista con tutti i partecipanti al progetto dove inviare ticket e commits :)
  4. Da quando mailman ha l’opzione “cambia la password e mettila uguale a tutte le liste a cui sono iscritto” risolve anche il problema di avere N password, una per progetto.
  5. Avere come username l’indirizzo email dell’utente è comodo per Trac, soprattutto quando si aprono ticket: abbiamo l’indirizzo del mittente a cui inviare notifiche sui ticket che sono stati aperti

Se vedete altri vantaggi, fatemi sapere, che aggiorno…

Come si realizza?

Tramite mod_python è possibile scrivere un handler per gestire, in Apache, il processo di autenticazione. Un semplice script Python che riceve utente e password e restituisce lo stato di autenticazione (OK o HTTP_UNAUTHORIZED). Visto che Mailman è pure scritto in Python, la cosa diventa semplice.

Risultato in Apache:

<Location /progetto-x>
                AuthName "Tracker Progetto X"
                AuthType Basic
                PythonPath "sys.path+['/path/a/script/di/auth/']"
                PythonAuthenHandler mailmanauth
                PythonOption MailmanList lista-progetto-x
                AuthUserFile /dev/null
                AuthBasicAuthoritative Off
                require valid-user
</Location>

Voilà. Gli iscritto alla mailing list lista-progetto-x possono accedere. Da ripetere per ogni progetto e repository di progetto SVN.

Troppo faticoso? Usare mod_macro può aiutare:

<Macro MailmanProject $name $list>
        <Location /svn/$name>
                AuthName "SVN for project $name"
                AuthType Basic
                PythonPath "sys.path+['/path/to/script/']"
                PythonAuthenHandler mailmanauth
                PythonOption MailmanList $list
                AuthUserFile /dev/null
                AuthBasicAuthoritative Off
                require valid-user
        </Location>
        <Location /$name>
                AuthName "Tracker for project $name"
                AuthType Basic
                PythonPath "sys.path+['/path/to/script/']"
                PythonAuthenHandler mailmanauth
                PythonOption MailmanList $list
                AuthUserFile /dev/null
                AuthBasicAuthoritative Off
                require valid-user
        </Location>
</Macro>

E per ogni progetto:

Use MailmanProject progetto-x lista-progetto-x

nel VirtualHost relativo.

Se poi aggiungere un bell’hook alla creazione della lista, per creare repository svn, environment per trac, il gioco è fatto:

# newlist progetto-y

e poi, è tutto in mano al gestore della mailing list.

Altre soluzioni sono benvenute :)

Goodbye stranger..

E via così

Niente doccia, un bacio, e via in macchina. Poi vediamo…