CERCA SITEMAP FEED RSS 1280
Ultimo aggiornamento: 30 Agosto 2009

Secure Sockets Layer (SSL) in JBoss AS 5

Secure Sockets Layer (SSL) è un protocollo basato su certificato che abilita la cifratura e l’autenticazione della sorgente.
JBoss Web Server ha un supporto interno per SSL attraverso il suo connettore http pertanto è possibile configurare SSL per le web application in maniera semplice.
Quando l’autenticazione riguarda esclusivamente il server allora si parla di server authentication, in questo schema quando il client prova ad accedere al server ne verifica il certificato fornito durante l’handshaking.
Se l’autenticazione riguarda anche il client si parla invece di mutua autenticazione.
E’ possibile infine autenticare il client a livello applicazione in base alle informazioni contenute nel certificato (client-certificate authentication): per fare ciò occorre definire un security domain che faccia uso di SSL.

Abilitare HTTPS

Per gestire le richieste HTTPS, occorre:
  • creare o ottenere un certificato per il server
  • inserire il certificato nel keystore del server
  • definire un connettore HTTPS
  • collegare il connettore al keystore
Per abilitare HTTPS in JBoss Web Server occorre ottenere o creare un certificato per il server e inserirlo nel keystore.
E’ possibile creare un certificato self-signed oppure ottenerne uno da un’authority di certificato (CA).
Se usiamo keytool allora il comando da utilizzare per ottenere un certificato è:
keytool -genkey -alias mioserver -keyalg RSA -validity 1500 -keystore server.keystore
Tale comando crea una coppia di chiavi (publica e privata) usando l’algoritmo RSA e le inserisce nel keystore server.keystore utilizzando l’alias mioserver.
Una volta eseguito verranno richieste diverse informazioni costitutive del certificato X.509 (nome del proprietario, località, password della chiave, password del keystore…)
Quando si crea un keystore da usare con JBoss Web Server occorre fare in modo che la password del keystore e la password della key corrispondano, altrimenti si ottiene un’eccezione del tipo java.io.IOException: Cannot recover key.
Se si vuole esportare la Certificate Signing Request (CSR) per il certificato self-signed che si è creato si può usare il comando
keytool -certreq -alias mioserver -keystore server.keystore -file richiesta.csr
Quando si esegue questo comando viene richiesta la password del keystore e il keytool crea una CSR che può essere inviata ad una CA per la firma.
Dopo aver ricevuto una risposta dalla CA si può importare il certificato nel keystore usando il comando
keytool -import -alias mioserver -keystore server.keystore -file certificatofirmato.cer
E’ possibile anche esportare il certificato dal keystore se si vuole distribuirlo usando il comando:
keytool -export -alias mioserver -keystore server.keystore -file miocertificato.cer
Dopo la creazione del keystore con un certificato al suo interno occorre mettere in piedi il connettore in JBoss Web Server per ascoltare il traffico SSL.

La configurazione del file server.xml dovrebbe essere del tipo:
<Connector port="8443"
  ...
  scheme="https"
  secure="true"
  clientAuth="false"
  keystoreFile="${jboss.server.home.dir}/conf/server.keystore"
  keystorePass="serverpass"
  sslProtocol = "TLS" />
L’attributo scheme definisce lo schema del protocollo che si sta usando, se non specificato il valore di default è http, settando l’attributo secure a true si comunica a JBoss Web Server di utilizzare un connettore sicuro.
Impostando l’attributo clientAuth a false comunichiamo al server l’intenzione di non voler effettuare la mutua autenticazione ma solo l’autenticazione del server.
Gli attributi keystoreFile e keystorePass definiscono la locazione del file keystore contenente il certificato del server e la password per il file keystore.
L’attributo sslProtocol specifica la versione del protocollo SSL da usare (TLS di default).
L’attributo keystorePass dovrebbe contenere la password che è stata usata nella creazione della coppia chiave/keystore (che come detto, devono essere uguali).
Fatto ciò il client può accedere al server usando il suo browser su una connessione sicura https sulla porta 8443.

Confidenzialità e integrità

Se si vuole ottenere l’accesso all’applicazione solo attraverso un connettore HTTPS anche se è stato definito un connettore HTTP, è possibile usare un meccanismo detto “transport guarantee” messo a disposizione dalle specifiche Java EE.
Il transport guarantee è definito all’interno dell’elemento security-constriant del file WEB-INF/web.xml: se viene abilitato e l’utente prova ad accedere all’applicazione mediante un connettore non sicuro, il connettore invia la richiesta alla porta specificata dall’attributo redirectPort dove è in ascolto il connettore sicuro configurato.
<Connector protocol="HTTP/1.1" port="8080"  address="${jboss.bind.address}"
  connectionTimeout="20000"
  redirectPort="8443" />
<security-constraint>
  ...
  <user-data-constraint>
    <transport-guarantee>
      CONFIDENTIAL
    </transport-guarantee>
  </user-data-constraint>
</security-constraint>
Il valore assunto dall’elemento transport-guarantee può essere CONFIDENTIAL, INTEGRAL e NONE:
  • CONFIDENTIAL significa i dati trasmessi dall’applicazione non devono poter essere letti da terze parti e quindi vanno cifrati.
  • INTEGRAL significa che i dati inviati tra client e server non devono poter essere modificati da terze parti durante il transito.
  • NONE è equivalente a non settare alcuna “transport guarantee”.

Abilitare la mutua autenticazione

Alcune applicazioni richiedono uno schema di mutua autenticazione (tipicamente applicazioni in intranet o comunque limitate ad un certo numero di utenti).
La mutua autenticazione rihiede che il client fornisca un certificato e che il server abbia un certificato e un truststore con i certificati dei client al suo interno.
Per implementare la mutua autenticazione occorre:
  • creare un certificato per il server e inserirlo nel keystore del server
    keytool -genkey -alias serverCertificate -keyalg RSA -validity 1500 -keystore server.keystore
    
  • creare un certificato per il client che verrà automaticamente piazzato nel keystore lato client
    keytool -genkey -alias clientCertificate -keyalg RSA -validity 1500 -keystore client.keystore
    
  • esportare il certificato del client dal suo keystore e inserirlo nel truststore del server
    keytool -export -alias clientCertificate -keystore client.keystore -file client.cer
    
    keytool -import -alias clientCertificate -keystore server.truststore -file client.cer
    
  • importare il certificato del client nel browser,convertendolo prima in una formato compatibile.
  • configurare il connettore https settando a true l’attributo clientAuth
    <Connector protocol="HTTP/1.1" SSLEnabled="true" port="8443"
      address="${jboss.bind.address}" scheme="https" secure="true"
      clientAuth="true"
      keystoreFile="${jboss.server.home.dir}/conf/server.keystore"
      keystorePass="server-keystore-pass"
      truststoreFile="${jboss.server.home.dir}/conf/server.truststore"
      truststorePass="server-truststore-pass"
      sslProtocol="TLS" />
    
La maggior parte dei browser supportano il formato di certificato PKCS12 pertanto occorre convertire il certificato X.509 creato con il keytool in tale formato (esistono diversi tool che consentono di convertire il certificato nel formato PKCS12, openssl è uno dei più popolari).

Client-certificate authentication

Per abilitare un security domain SSL occorre definire un’istanza dell’MBean JaasSecurityDomain che punta a un trustore contenente i certificati dei client.
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=MioSecurityDomain">
    <constructor>
      <arg type="java.lang.String" value="miosecuritydomain" />
    </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 al JNDI context the java:/jaas/my-security-domain.
KeyStoreURL e KeyStorePass definiscono la locazione e la password del truststore.
L’argomento constructor dell’elemento security domain dell’MBean e l’attributo name dell’application-policy nel file login-config.xml devono coincidere:
<application-policy name="miosecuritydomain">
  <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/miosecuritydomain</module-option>
    </login-module>
    <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required">
      <module-option name="password-stacking">useFirstPass</module-option>
      <module-option name="usersProperties">myusers.properties</module-option>
      <module-option name="rolesProperties">myroles.properties</module-option>
    </login-module>
  </authentication>
</application-policy>
Come vediamo vengono definiti due login-module dei quali uno è di tipo BaseCertLoginModule, si occupa dell’autenticazione e punta al security domain (nome JNDI completo) definito dall’Mbean JaasSecurityDomain, l’altro invece si occupa dell’autorizzazione.
A questo punto occorre modificare il file WEB-INF/web.xml utilizzando la modalità di autenticazione CLIENT-CERT
<login-config>
  <auth-method>CLIENT-CERT</auth-method>
</login-config>
e il file WEB-INF/jboss-web.xml che definisce il security domain dell’applicazione:
<jboss-web>
  <security-domain>java:/jaas/miosecuritydomain</security-domain>
</jboss-web>
Quando si usa l’autenticazione password-based, l’utente inserisce un username come principal è una password come credenziale.
Nel caso di un’autenticazione basata su certificato occorre definire una strategia che consenta di formare il principal sulla base del contenuto del certificato stesso.
Per fare ciò si utilizza l’attributo certificatePrincipal dell’elemento Realm nel file server.xml
<Realm className="org.jboss.web.tomcat.security.JBossWebRealm"  
  certificatePrincipal="org.jboss.security.auth.certs.SubjectCNMapping"
  allRolesMode="authOnly" />
I valori disponibili sono:
  • org.jboss.security.auth.certs.SerialNumberIssuerDNMapping
  • org.jboss.security.auth.certs.SubjectCNMapping
  • org.jboss.security.auth.certs.SubjectDNMapping
  • org.jboss.security.auth.certs.SubjectX500Principal
e fanno riferimento alle parti del certificato corrispondenti.
L’opzione definita determina quale parte del certificato viene passata come principal ai login module che autenticano e autorizzano l’utente.
Naturalmente la parte scelta deve essere memorizzata come principal nel datastore relativo alle autorizzazioni (insieme al corrispondente ruolo).

Nel nostro esempio nel file delle proprietà sarà presente:
CN = ruolo1, ruolo2 ...
dove CN è il valore del campo DN del certificato del client.
I certificati dei client che vengono importati nel trstustore del server devono avere un alias corrispondente alla parte di certificato usata come principal.

Nel nostro caso
keytool -import -alias DN -keystore server.truststore –file client.cer