CERCA SITEMAP FEED RSS 1280
Ultimo aggiornamento: 30 Agosto 2009

Sicurezza in JBoss AS 5

La sicurezza costituisce uno degli aspetti più importanti delle applicazioni enterprise, i suoi tre aspetti più importanti sono l’autenticazione, l’autorizzazione e la sicurezza delle comunicazioni.
L’autenticazione è il processo mediante il quale un sistema verifica l’identità di un utente.
L’autenticazione non riguarda solo gli esseri umani ma anche programmi ed in generale Principal: con il termine Principal facciamo riferimento a umani o macchine che devono provare la loro identità ad un altro sistema attraverso una o più forme di identificazione dette credenziali (password, certificati, dati biometrici…).
L’autorizzazione è invece il processo mediante il quale si verifica se un Principal ha accesso ad una data risorsa e viene tipicamente implementata mediante l’assegnazione di uno o più ruoli al Principal e quindi definendo i ruoli che possono accedere alle risorse che si vogliono proteggere.
Quando il Principal prova ad avere accesso ad una data risorsa, il sistema controlla se il ruolo del Principal corrisponde ad almeno uno dei ruoli ai quali è concesso l’accesso e in caso positivo ne concede l’utilizzo.
Questo modo di implementare l’autorizzazione prende il nome di autorizzazione basata su ruoli.

JBoss SX

Per proteggere le risorse in esecuzione sul server, JBoss AS fa uso diJBoss SX che è costruito su Java Authentication and Authorization Service (JAAS).
Quando una daterminata risorsa (componente, web-application, EJB…) riceve una richiesta, questa viene reindirizzata verso un componente detto security domain che effettua ogni controllo di sicurezza necessario e notifica alla risorsa se l’utente può procedere o meno.
I security domain, che vengono collegati a JNDI quando il server viene avviato, sono configurati a livello server e possono essere usati da qualsiasi componente interno al server.
E’ possibile aggiungere o modificare le definizioni dei security domain all’interno del file server/xxx/conf/login-config.xml.
<application-policy name="jmx-console">
  <authentication>
    <login-module code = "org.jboss.security.auth.spi.UsersRolesLoginModule" flag = "required">
      <module-option name="usersProperties">
        props/jmx-console-users.properties
      </module-option>
      <module-option name="rolesProperties">
        props/jmx-console-roles.properties
      </module-option>
    </login-module>
  </authentication>
</application-policy>
Il blocco application-policy definisce un security domain e l’attributo name specifica il nome del security domain.
JBoss SX usa questo nome per generare il context JNDI al quale collegare il security domain: in questo caso il nome jmx-console fa si che il context associato al security domain sarà java:/jaas/jmx-console perché tutti i security domain sono collegati al namespace java:/jaas.
All’interno dell’application-policy è possibile definire uno o più login-module; nell’esempio si punta ad un login-module di tipo UsersRolesLoginModule che carica le informazioni di sicurezza da file di proprietà sul file system.
In generale però un sistema in produzione mantiene le informazioni di sicurezza in database o server LDAP.

Dynamic login configuration

JBoss SX contiene una feature chiamata dynamic login configuration che permette di definire la sicurezza negli application archive piuttosto che nel file login-config.xml.
Per abilitare questa caratteristica è necessario creare ed effettuare il deploy del corrispondente MBean per il servizio nella cartella server/xxx/deploy
<server>
  <mbean code="org.jboss.security.auth.login.DynamicLoginConfig" name="jboss:service=DynamicLoginConfig">
    <attribute name="AuthConfig">
      dynamic-login-config.xml
    </attribute>
    <depends optional-attribute-name="LoginConfigService">
      jboss.security:service=XMLLoginConfig
    </depends>
    <depends optional-attribute-name="SecurityManagerService">
      jboss.security:service=JaasSecurityManager
    </depends>
  </mbean>
</server>
E’ possibile chiamare questo file come si vuole purchè abbia il suffisso –service.xml così che JBoss possa trattarlo come un MBean di servizio.
L’attributo AuthConfig consente di specificare il nome del file che conterra le definizioni del security domain.
Il formato di questo file è esattamente lo stesso del file login-config.xml.
JBoss lo cercherà nella cartella META-INF dell’applicaione EAR: se si ha un file WAR occorre metterlo dentro un file EAR perché il classpath per il WAR non è accessibile.

Loggin della sicurezza

Di default il loggin relativo alla sicurezza è minimo; è posibile però agire sul file server/xxx/conf/jboss-log4j.xml aggiungendo le seguenti righe:
<category name="org.jboss.security">
  <priority value="TRACE" class="org.jboss.logging.XLevel"/>
</category>
<category name="org.jboss.web.tomcat.security">
  <priority value="TRACE" class="org.jboss.logging.XLevel"/>
</category>
<category name="org.apache.catalina">
  <priority value="DEBUG"/>
</category>

Comunicazione sicura

Spesso abbiamo la necessità di inviare dati attraverso la rete cercando di mantenere confidenzialità, integrità dei dati e integrità della sorgente.
La confidenzialità fa riferimento alla protezione del contenuto dei messaggi da terze parti e tipicamente viene implementata mediante tecniche di cifratura.
L’integrità dei dati fa riferimento al fatto che il contenuto di un messaggio ricevuto non deve essere manipolato da terze parti mentre viaggia attraverso la rete.
Infine l’integrità della sorgente assicura che il messaggio ricevuto sia stato inviato dal mittente indicato nel messaggio e non da qualcuno che si spaccia per esso.
L’integrità della sorgente viene assicurata mediante Certificate Authority (CA) che assegnano certificati a differenti persone e organizzazioni: se un soggetto vuole confermare la propria identità ad un altro deve ottenere un certificato e inviarlo all’altra parte la quale potrà valutarne l’autenticità.

Cifratura simmetrica e asimmetrica

Esistono due tecniche di cifratura:
  • la cifratura simmetrica o a chiave privata è quella nella quale mittente e destinatario condividono una stessa chiave segreta che viene utilizzata per le operazioni di cifratura e decifratura pertanto finchè la segretezza della chiave non viene compromessa le due parti possono comunicare in sicurezza.
    Il punto debole di questo sistema è rappresentato dalla distribuzione iniziale della chiave segreta condivisa.
  • La cifratura asimmetrica o a chiave publica invece si basa sull’utilizzo di una coppia di chiavi (una publica e una privata) ricavate matematicamente delle quali una viene usata per la cifratura e l’altra per la decifratura.
    Se un soggetto A invia la propria chiave publica ad un altro B e quest’ultimo cifra il messaggio utilizzando la chiave ricevuta da A allora soltanto A sarà in grado di decifrare il messaggio con la propria chiave privata.
    Allo stesso modo se A cifra un messaggio utilizzando la propria chiave privata, lo invia a B e B lo decifra utilizzando la chiave publica di A allora B ha la certezza che è stato A ad inviare il messaggio perchè soltanto A dispone della chiave privata.
    La cifratura a chiave publica è conveniente perché non è necessaria una distribuzione iniziale di una chiave segreta ma a differenza della cifratura simmetrica è molto più lenta.
    Per questa ragione molti protocolli di sicurezza (incluso SL) usano la chiave publica per cifrare una chiave segreta condivisa da utilizzare in ottica di una cifratura simmetrica.

Certificati

Naturalmente quando si fa uso di cifratura asimmetrica occorre essere certi che la chiave publica ricevuta per cifrare il messaggio provenga dalla persona giusta.
Per questa ragione in aggiunta alla cifratura di un messaggio il protocollo SSL supporta l’autenticazione del client e del server mediante certificati a chiave publica.
Un certificato a chiave publica è un certificato digitale che consiste di diverse informazioni sull’identità del proprietario del certificato.
Per verificare che la chiave pubblica appartiene all’utente la cui identità è contenuta nel certificato, una CA firma il certificato.
Parliamo di Server authetication quando sia il client chee il server usano SSL ma solo il server dispone di un certificato: in questo schema quando il client prova ad accedere al server il client verifica il certificato del server durante l’hand-shaking.
SSL è capace di autenticare anche un client che dispone di un proprio certificato, in questo caso di parla di mutua autenticazione.
Con la mutua autenticazione quando un client prova ad accedere al server l’handshaking forza entrambe le parti a verificare il reciproco certificato.
La mutua autenticazione è tipicamente usata nelle intranet e nelle applicazioni in cui la certezza che le richieste provengano da una sorgente sicura è un requisito indispensabile (come avviene ad esempio nelle transazioni fra banche).
Sebbene l’autenticazione potrebbe essere fatta mediante una password, i certificati danno alla banca maggiori informazioni sull’identità del client e assicurano che le informazioni siano criptate prima di essere inviate sulla rete.
Il server potrebbe usare le credenziali del client come credenziali per l’autenticazione a livello applicazione: questa è detta autenticazione client-certificate.

Configurare un security domain su SSL

JBoss Web Server ha un supporto interno per SSL attraverso il suo connettore http così che si possa configurare SSL per le web application in maniera semplice.
Se si vuole autenticare un client in base all’intormazioni del certificato allora occorre definire un security domain che faccia uso di SSL, in particolare occorre definire un’istanza dell’MBean JaasSecurityDomain che punta a un trustore.
Per definire l’MBean JaasSecurityDomain occorre creare il solito file con suffiso –service.xml e metterlo nella cartella server/xxx/deploy.
<server>
  <mbean code="org.jboss.security.plugins.JaasSecurityDomain" name="jboss.security:service=MySecurityDomain">
    <constructor>
      <arg type="java.lang.String" value="my-security-domain"/>
    </constructor>
    <attribute name="KeyStoreURL">
      ${jboss.server.home.dir}/conf/server.truststore
    </attribute>
    <attribute name="KeyStorePass">servercert</attribute>
    <depends>jboss.security:service=JaasSecurityManager</depends>
  </mbean>
</server>
L’attributo value dell’elemento constructor è il nome del security domain che si sta definendo.
Nell’esempio il security domain è collegato sono il JNDI context the java:/jaas/my-security-domain.
KeyStoreURL e KeyStorePass definiscono la locazione e la password del truststore.
Se si vuole che il security domain gestisca autenticazione e autorizzazione occorre definire il security domain nel file login-config.xml.
L’elemento constructor dell’elemento security domain dell’MBean e l’attributo name dell’application-policy nel file login-config.xml devono coincidere:
<application-policy name="my-security-domain">
  ...
</application-policy>

LoginModule

Un LoginModule è un componente che sa come accedere alle informazioni sicurezza per verificare password e ruolo del principal e determinare quindi autenticazione e autorizzazione.

Ogni security domain può avere al suo interno uno o più moduli di login:
  • BaseCertLoginModule: effettua l’autenticazione del client mediante certificato mentre l’autorizzazione viene demandata ad un altro modulo di login
  • CertRolesLoginModule: costituisce un’estenzione di BaseCertLoginModule che effettua l’autenticazione mediante certificato e l’autorizzazione mediante file di proprietà.
  • ClientLoginModule: usato da client standalone che vogliono loggarsi ad un server sicuro
  • DatabaseCertLoginModule: un’estenzione di BaseCertLoginModle che autentica il client mediante certificato ed effettua l’autorizzazione attraverso un database
  • DatabaseServerLoginModule: carica le informazioni user/role da un database
  • IdentityLoginModule: usato in fase di sviluppo fa si che tutti gli utenti si autentichino con le stesse credenziali
  • LdapExtLoginModule: carica le informazioni user/role da un server LDAP (supporta strutture di ruoli gerarchiche)
  • LdapLoginModule: carica le informazioni user/role da un server LDAP (supporta solo ruoli flat)
  • RunAsLoginModule: viene utilizzato insieme ad altri moduli per definire lo status RunAs
  • SimpleServerLoginModule: modulo di testing che consente a qualsiasi utente con password null di autenticarsi
  • SRPCacheLoginModule: usato per autenticare gli utenti con protocollo Secure Remote Password
  • SRPLoginModule: usato per autenticare client standalone con protocollo Secure Remote Password
  • UsersRolesLoginModule: carica le informazioni user/role da file di proprietà.

UsersRolesLoginModule

UserRolesLoginModule memorizza informazioni username e di ruolo in file proprietà
<application-policy name = "my-security-domain">
  <authentication>
    <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag = "required">
      <module-option name="usersProperties">
        my-users.properties
      </module-option>
      <module-option name="rolesProperties">
        my-roles.properties
      </module-option>
    </login-module>
  </authentication>
</application-policy>
usersProperties e rolesProperties puntano ai file che dovrebbero essere posti o nela cartella conf del server o nella radice dell’application archive.

Il formato dei due file è del tipo:
username1 = password1
username2 = password2

...
e
username1 = ruolo1
username2 = ruolo2

...
E’ possibile assegnare più ruoli separandoli mediante virgola.
Se si vogliono associare le definizioni di utenti e ruoli con più security domain si possono mettere utenti e ruoli comuni nei file di default condivisi dai security domain: questi file devono essere nella cartella conf e possono essere specificati mediante le opzioni defaultUsersProperties e defaultRolesProperties
  • unauthenticatedIdentity definisce l’identità (principal name) per qualsiasi client che non fornisce informazioni di autenticazione
  • ignorePasswordCase se posto a true considera la password come se fosse case insensitive
  • defaultUsersProperties specifica il file di proprietà di default per le informazioni utente condivise fra più domini
  • defaultRolesProperties specifica il file di proprietà di default per le informazioni sui ruoli utente

DatabaseServerloginModule

Una soluzione migliore anche dal punto di vista della gestione consiste nel memorizzare informazioni utente e ruolo in un database relazionale.
A tal propostito JBoss fornisce il DatabaseServerLoginModule che carica le informazioni di autorizzazione autenticazione da un database:
<application-policy name ="database-domain">
  <authentication>
    <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag = "required">
      <module-option name="dsJndiName">
        java:/OracleDS
      </module-option>
      <module-option name="principalsQuery">
        SELECT PASSWD FROM USERS WHERE USERID=?
      </module-option>
      <module-option name="rolesQuery">
        SELECT ROLEID, 'Roles' FROM ROLES WHERE USERID=?
      </module-option>
    </login-module>
  </authentication>
</application-policy>
Il valore dell’opzione dsJndiName punta al nome JNDI del data source che contiene le informazioni di sicurezza.
L’opzione principalsQuery definisce la query che il modulo di login esegue per autenticare il Principal in base alla sua password, se non viene settata viene eseguita la query di default:
select Password from Principals where PrincipalID=?
La rolesQuery invece è quella che viene eseguita quando si vuole autorizzare un Principal in base ai suoi ruoli, se non viene specificata si esegue la query di default:
select Role, RoleGroup from Roles where PrincipalID=?
Se si sovrascrivono le query di default occorre mantenere lo stesso ordine dei campi estratti dal db.
La colonna RoleGroup descrive il gruppo di ruoli al quale l’utente appartiene e deve essere settata a Roles, è possibile usare:
select Role, 'Roles' FROM Roles WHERE PrincipalID=?
unauthenticatedIdentity definisce l’identità (principal name) per qualsiasi client che non fornisce informazioni di autenticazione.

IdentityLoginModule

E’ spesso più facile sviluppare e testare applicazioni nelle quali non bisogna preoccuparsi dei vincoli di sicurezza ma disabilitare la configurazione di sicurezza non è necessariamente una buona idea.
JBoss SX fornisce un login module chiamato IdentityLoginModule che permette a chiunque di avere accesso al sistema senza fornire credenziali.
<login-module code="org.jboss.security.auth.spi.IdentityLoginModule" flag="required">
  <module-option name="principal">javid</module-option>
  <module-option name="roles">texan,newyorker</module-option>
</login-module>
L’opzione principal definisce l’username con il quale tutti gli utenti saranno autenticati (default guest).
roles invece definisce i ruoli separati da virgola.

Collegare LoginModule

I LoginModule possono essere posti uno sopra l'altro come nel seguente esempio:
<application-policy name="my-stacked-policy">
  <authentication>
    <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required">
      ...
    </login-module>
    <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required">
      ...
    </login-module>
  </authentication>
</application-policy>
Nell’esempio entrambi i moduli hanno il flag posto a required: il flag specifica quali moduli di login sono necessari o sufficienti per l’autenticazione.
  • required: significa che quel modulo di login deve produrre un successo affinchè l’autenticazione abbia successo: se un modulo required fallisce l’autenticazione fallisce.
  • requisite: richiede che il login module abbia successo e se fallisce il controllo passa all’applicazione.
  • sufficient: se ha successo il controllo passa all’applicazione altrimenti continua agli altri moduli
  • optional: non richieste che il modulo di login abbia successo.
Se si vuole effettuare l’autenticazione da un modulo solo ma collezionare le informazioni di ruolo da tutti gli altri si piò usare l’attributo password-stacking posto a useFirstPass su tutti i moduli:

BaseCertLoginModule

Se si vuole autenticare il client mediante certificati si può specificare un’application-policy che sa come leggere un keystore usando l’MBean JassSecurityDomain.

A questo scopo JBoss SX fornisce il BaseCertLoginModule:
<application-policy name="my-client-cert">
  <authentication>
    <login-module code="org.jboss.security.auth.spi.BaseCertLoginModule" flag="required">
      <module-option name="password-stacking">
        useFirstPass
      </module-option>
      <module-option name="securityDomain">
        java:/jaas/my-client-cert
      </module-option>
    </login-module>
    <login-module
      code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required">
      <module-option name="password-stacking">
        useFirstPass
      </module-option>
      ...
    </login-module>
  </authentication>
</application-policy>
L’opzione che bisogna configurare è securityDomain: l’opzione password-stacking è settata a password-stacking su entrambi i moduli.