JBoss AS 7 e datasource: come criptare la password del database

Nelle architetture applicative a 3 livelli, e quindi quelle web solitamente, l’account dell’utente che vi accede non è mai quello del database, come invece avviene comunemente in quelle a due livelli. Questo significa che in realtà l’account che ha accesso ai dati è impersonale (e fin qui…), non deve essere quello di amministrazione – leggi root in MySQL per esempio (già qualcuno potrebbe sentirsi in colpa…) e soprattutto non deve avere la password in chiaro scritta in qualche file di configurazione (dai su non ti vergognare, succede… 😉 )!

In questo e in altri due post vedremo come non lasciare più in giro la password del database in chiaro senza troppi sforzi, ma sfruttando i meccanismi che JBoss (affrontato in questo post), Tomcat o Spring (che vedremo prossimamente) ci mettono a disposizione per risolvere questa necessità comune.

Account applicativi

Gli applicativi web di solito lavorano con pool di connessioni al database sempre aperte e sempre pronte, per evitare l’handshake di connessione. Questo è un motivo in più per creare un account sul db dedicato esclusivamente all’uso di un certo applicativo, che aiuta al monitoraggio, e soprattutto che abbia le sole grant necessarie all’applicativo stesso, ne più, ne meno, per ovvii motivi di sicurezza.

Ma tutta questa sicurezza va a farsi benedire se metto nella configurazione del mio application server la password del database in chiaro!! Fortunatamente con JBoss 7 questa operazione è estremamente semplice!

Caccia alla password

Apriamo quindi il file di configurazione principale di JBoss, ovvero lo standalone.xml e cerchiamo la sezione dedicata al datasource. Lo stesso discorso vale anche se si usano le altre varianti dello standalone-*.xml o del domain.xml.

Troveremo qualcosa del tipo (che è il database di default):

<subsystem xmlns="urn:jboss:domain:datasources:1.0">
	<datasources>
	    <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
	        <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</connection-url>
	        <driver>h2</driver>
	        <security>
	            <user-name>sa</user-name>
	            <password>sa</password>
	        </security>
	    </datasource>
	</datasources>
</subsystem>

La parte che ci interessa è la sezione security che così in chiaro non va bene per un ambiente di produzione. Come fare allora?

Nascondiamo la password

Per prima cosa dobbiamo criptare la password. JBoss 7 di default usa PicketBox come framework per la gestione della sicurezza. Chiediamo quindi a lui come criptarla! Visto che è un operazione una tantum, non ci sconvolge farla da riga di comando 🙂 . La classe SecureIdentityLoginModule di PicketBox dispone di un metodo statico main che come unico argomento prende in ingresso la password da criptare (sa in questo esempio). Per farla funzionare c’è bisogno di impostare qualche jar nel classpath, come per esempio in linux (per Windows è quasi identica) :

java -cp $JBOSS_HOME/modules/org/picketbox/main/picketbox-4.0.7.Final.jar:$JBOSS_HOME/modules/org/jboss/logging/main/jboss-logging-3.1.0.GA.jar org.picketbox.datasource.security.SecureIdentityLoginModule sa

Come risultato otteniamo la nostra password criptata:
Encoded password: 9fdd42c2a7390d3

Che algoritmo usa? Blowfish con parole chiave “jaas is the way”.

Dove metto la password cifrata?

A questo punto il gioco è quasi fatto: sostituiamo la sezione security evidenziata in precedenza facendo riferimento ad un nuovo security domain:

<security>
   <security-domain>EncryptedPassword</security-domain>
</security>

i security domains sono definiti nel subsystem security dello standalone.xml:

<subsystem xmlns="urn:jboss:domain:security:1.1">
   <security-domains>
  ...
      <security-domain name="EncryptedPassword" cache-type="default">
         <authentication>
            <login-module code="org.picketbox.datasource.security.SecureIdentityLoginModule" flag="required">
               <module-option name="username" value="sa"/>
               <module-option name="password" value="9fdd42c2a7390d3"/>
            </login-module>
         </authentication>
      </security-domain>
  ...
   </security-domains>
</subsystem>

Conclusioni

A questo punto il cerchio è chiuso! Riavviate JBoss e viaggiate sicuri! O almeno un po’ più sicuri… infatti con questo tipo di soluzione abbiamo spostato il problema: la password non è più in chiaro, ma una volta noto l’algoritmo usato per la cifratura e la sua passphrase, deducibile dal sorgente della classe SecureIdentityLoginModule, non è difficile recuperare la password del database, solo che richiede più tempo ;). Una alternativa potrebbe essere estendere la classe SecureIdentityLoginModule e personalizzare la passphrase: questo richiederebbe una decompilazione della classe stessa per risalire ai dati necessari alla decifratura rendendola più difficile ad un utente mal intenzionato.

Andrea Como

Sono un software engineer focalizzato nella progettazione e sviluppo di applicazioni web in Java. Presso OmniaGroup ricopro il ruolo di Tech Leader sulle tecnologie legate alla piattaforma Java EE 5 (come WebSphere 7.0, EJB3, JPA 1 (EclipseLink), JSF 1.2 (Mojarra) e RichFaces 3) e Java EE 6 con JBoss AS 7, in particolare di CDI, JAX-RS, nonché di EJB 3.1, JPA2, JSF2 e RichFaces 4. Al momento mi occupo di ECM, in particolar modo sulla customizzazione di Alfresco 4 e sulla sua installazione con tecnologie da devops come Vagrant e Chef. In passato ho lavorato con la piattaforma alternativa alla enterprise per lo sviluppo web: Java SE 6, Tomcat 6, Hibernate 3 e Spring 2.5. Nei ritagli di tempo sviluppo siti web in PHP e ASP. Per maggiori informazioni consulta il mio curriculum pubblico. Follow me on Twitter - LinkedIn profile - Google+