Liferay 7.2: Esempio di Two-Way SSL/TLS Mutual Authentication Client
Tags: blog, liferay, security, ssl
Published: 2020-09-10 21:20:00

---
title: Liferay 7.2: Esempio di Two-Way SSL/TLS Mutual Authentication Client
published: true
date: 2020-02-25 00:00:16 UTC
tags: Blog,Liferay,Security,SSL
canonical_url: https://www.dontesta.it/2020/02/25/liferay-7-2-esempio-di-two-way-ssl-tls-mutual-authentication-client/
---

Quanti di voi hanno dovuto affrontare i problemi legati alla realizzazione di un client **HTTPS** verso un servizio in **Mutua Autenticazione**? E quanti di voi in un contesto Liferay? Posso immaginare che il numero sia alto, per non contare le notti passate a fare debugging.

In questo articolo vorrei indicarvi tutti gli step necessari per portare a casa il risultato senza alcuna fatica e notti insonne. Lo scenario presentato è calato su [Liferay](https://www.liferay.com), ricordo però che i concetti espressi sono di carattere generale.

La versione Liferay di riferimento per questo articolo è la [7.2.1 GA2 in formato Bundle Tomcat](https://sourceforge.net/projects/lportal/files/Liferay%20Portal/7.2.1%20GA2/liferay-ce-portal-tomcat-7.2.1-ga2-20191111141448326.tar.gz/download). Affinché possiate seguire per intero gli step mostrati nel corso dell’articolo, è necessario che sulla vostra macchina sia installato Docker (versione 17.x, 18.x o 19.x).

Nel video [Liferay 7.2 – Gogo Shell Command for the Two-Way SSL/TLS Mutual Authentication](https://www.youtube.com/watch?v=Etc2_Dm0M98) mostro come eseguire l’esempio del progetto GitHub [gogo-shell-tls-mutual-sample](https://github.com/amusarra/gogo-shell-tls-mutual-sample) in semplici passaggi usando Docker e Docker Compose.

<iframe width="560" height="315" src="https://www.youtube.com/embed/Etc2_Dm0M98" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="allowfullscreen"></iframe>

## 1. Two-Way SSL/TLS Mutual Authentication

La mutua autenticazione basata sul protocollo [**SSL/TLS**](https://it.wikipedia.org/wiki/Transport_Layer_Security) (_Secure Sockets Layer_ e il successore _Transport Layer Security_)  si riferisce a due parti che si autenticano reciprocamente attraverso la verifica del certificato digitale fornito in modo che entrambe i partecipanti siano sicuri dell’identità altrui.

Il processo di autenticazione e creazione di un canale crittografato utilizzando il meccanismo di autenticazione reciproca (o mutua autenticazione o Two-Way SSL/TLS Mutual Authentication) basata su certificati prevede i passaggi seguenti:

1. Un client richiede l’accesso a una risorsa protetta;
2. Il server presenta il suo certificato al client;
3. Il client verifica il certificato del server;
4. Se ha successo, il client invia il suo certificato al server;
5. Il server verifica le credenziali del cliente;
6. In caso di esito positivo, il server concede l’accesso alla risorsa protetta richiesta dal client.

In Figura 1 è mostrato quello che accade durante il processo di autenticazione reciproca (o mutua autenticazione).

[![Figura 1 - Cosa succede durante il processo di autenticazione reciproca (immagine da https://docs.oracle.com)](https://github.com/amusarra/docker-apache-ssl-tls-mutual-authentication/raw/master/images/security-sslBMAWithCertificates.gif "Figura 1 - Cosa succede durante il processo di autenticazione reciproca (immagine da https://docs.oracle.com)")](https://github.com/amusarra/docker-apache-ssl-tls-mutual-authentication/raw/master/images/security-sslBMAWithCertificates.gif)

Figura 1 – Cosa succede durante il processo di autenticazione reciproca (immagine da https://docs.oracle.com)

Nel caso in cui vogliate approfondire l’argomento su questo meccanismo di autenticazione, posso consigliare la lettura dell’articolo [An Introduction to Mutual SSL Authentication](https://www.codeproject.com/Articles/326574/An-Introduction-to-Mutual-SSL-Authentication) pubblicato su CodeProject da [Elvin Cheng](https://twitter.com/elvinzheng).

 

## 2. Presentazione dello scenario e obiettivo

Supponiamo che dal nostro portale Liferay abbiamo la necessità di accedere ad uno o più servizi esposti in HTTPS e protetti da una **Two-Way SSL/TLS Mutual Authentication**. In questo tipo di scenario (mostrato in figura 2) come possiamo implementare il client per accedere al servizio? Quali sono inoltre i prerequisiti?

 

[![Scenario HTTPS Two-Way Mutual Authentication Client](https://www.dontesta.it/wp-content/uploads/2020/02/Liferay_HTTPS_Two-Way_Mutual_Authentication_Client_Architecure_1-1024x384.png "Figura 2. Scenario HTTPS Two-Way Mutual Authentication Client")](https://www.dontesta.it/wp-content/uploads/2020/02/Liferay_HTTPS_Two-Way_Mutual_Authentication_Client_Architecure_1.png)

Figura 2. Scenario HTTPS Two-Way Mutual Authentication Client

 

Liferay facilità di gran lunga il lavoro d’implementazione del client HTTPS, in virtù del fatto che la piattaforma mette a disposizione la classe [HttpUtil](https://github.com/liferay/liferay-portal/blob/7.2.1-ga2/portal-impl/src/META-INF/util-spring.xml#L360) (esistente dalle versioni 6.x di Liferay) che si sposa in pieno con le nostre necessità e che implementa l’interfaccia [**com.liferay.portal.kernel.util.Http**](https://docs.liferay.com/ce/portal/7.2-latest/javadocs/portal-kernel/com/liferay/portal/kernel/util/Http.html).

Affinché sia possibile accedere al servizio è indispensabile soddisfare una serie di prerequisiti e applicare un set di configurazioni al portale. A seguire il dettaglio dei prerequisiti e configurazioni.

1. Devono essere aperti i flussi tra il portale Liferay e il servizio HTTPS a cui dobbiamo accedere. Può sembrare ovvio ma preferisco ricordarlo;
2. Dobbiamo avere il _certificato digitale_ solitamente rilasciato dal proprietario del servizio o dalla [**PKI**](https://en.wikipedia.org/wiki/Public_key_infrastructure) di competenza. Senza di esso non sarà possibile accedere al servizio. Il formato del certificato può essere solitamente scelto tra: [**JKS**](https://en.wikipedia.org/wiki/Java_KeyStore) o [**PKCS#12**](https://en.wikipedia.org/wiki/PKCS_12);
3. Dobbiamo eventualmente ottenere il bundle della [_Certificate Chains_](https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_7.1.0/com.ibm.mq.doc/sy10600_.htm) qualora sia necessario e inserirlo nel [_trustStore_](https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#Stores) utilizzato dal nostro portale Liferay. Per impostazione predefinita, il trustStore letto è quello della JVM con cui il portale è eseguito (location per macOS: /Library/Java/JavaVirtualMachines/jdk1.8.0\_181.jdk/Contents/Home/jre/lib/security/cacerts);
4. Dobbiamo configurare l’application server (Tomcat, WildFly, JBOSS EAP, etc.) affinché sia impostato il [_keyStore_](https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#Stores) ed eventualmente anche il [_trustStore_](https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#Stores).

Prima di passare all’implementazione del client HTTPS, occorrerà quindi soddisfare i punti indicati in precedenza. Nel prossimo paragrafo affronteremo la configurazione del portale Liferay.

 

## 3. Dettagli sul servizio HTTPS

L’ambientazione descritta nel capitolo **2. Presentazione dello scenario e obiettivo** e mostrata in figura 2, menziona l’accesso ai servizi HTTPS protetti da una Two-Way SSL/TLS Mutual Authentication. Dato l’aspetto pratico di questo articolo, mi son preoccupato di mettere a vostra disposizione un’ambiente per eseguire il test dell’implementazione del client SSL/TLS in Mutua Autenticazione.

Più di un anno fa ho realizzato il progetto [Apache HTTP 2.4: How to Build a Docker Image for SSL/TLS Mutual Authentication](https://dzone.com/articles/apache-http-24-how-to-build-a-docker-image-for-ssl) il cui codice sorgente è disponibile sul repository GitHub [docker-apache-ssl-tls-mutual-authentication](https://github.com/amusarra/docker-apache-ssl-tls-mutual-authentication) e l’immagine Docker su Docker Hub [amusarra/apache-ssl-tls-mutual-authentication](https://hub.docker.com/r/amusarra/apache-ssl-tls-mutual-authentication).

L’idea è quella di sfruttare quest’immagine Docker per avere a disposizione dei servizi HTTPS protetti dal meccanismo di Mutua Autenticazione. Dalla versione 1.2.0 di questo progetto è stato introdotto [httpbin](https://github.com/postmanlabs/httpbin.git), quest’ultimo realizzato da [Kenneth Reitz](http://kennethreitz.org/bitcoin).

A seguire i dettagli del servizio Apache SSL/TLS Mutual Authentication:

- **Base URL HTTPS Services** : https://tls-auth.dontesta.it/secure/api
- **Server Certificate** :
  - **CN** : tls-auth.dontesta.it
  - **Issuer** : Let’s Encrypt Authority X3
- **Client Certificate** :
  - **Subject** : EMAILADDRESS=antonio.musarra@gmail.com, CN=antonio.musarra@gmail.com, OU=IT Labs, O=Antonio Musarra Digital Personal Certificate, ST=Italy, L=Bronte, C=IT
  - **Issuer** : EMAILADDRESS=soc@dontesta.it, CN=Antonio Musarra’s Blog Certification Authority, OU=IT Security Department, O=Antonio Musarra’s Blog, ST=Italy, L=Rome, C=IT

La figura a seguire mostra alcuni dettagli del _Server Certificate_ rilasciato da Let’s Encrypt Authority X3 ed esposto dal servizio HTTPS che risponde all’FQDN tls-auth.dontesta.it.

 

[![Dettaglio Certificato Server per tls-auth.dontesta.it](https://www.dontesta.it/wp-content/uploads/2020/02/DetailServerCertificate_tls-auth_dontesta_it-1024x986.png "Figura 3. Dettaglio Certificato Server per tls-auth.dontesta.it")](https://www.dontesta.it/wp-content/uploads/2020/02/DetailServerCertificate_tls-auth_dontesta_it.png)

Figura 3. Dettaglio Certificato Server per tls-auth.dontesta.it

Il certificato client ci permetterà di accedere ai servizi HTTPS protetti. Questo certificato (per ovvie ragioni di test) è pubblicamente disponibile e in formato JKS e PKCS#12. Teniamo da parte il certificato in formato JKS che utilizzeremo successivamente nella configurazione del portale Liferay.

- [tls-client.dontesta.it.jks](https://github.com/amusarra/docker-apache-ssl-tls-mutual-authentication/blob/master/configs/certs/tls-client.dontesta.it.jks "tls-client.dontesta.it.jks")
- [tls-client.dontesta.it.p12](https://github.com/amusarra/docker-apache-ssl-tls-mutual-authentication/blob/master/configs/certs/tls-client.dontesta.it.p12 "tls-client.dontesta.it.p12")

La figura a seguire mostra alcuni dettagli del _Client Certificate_ rilasciato dalla CA (di pura invenzione) Antonio Musarra’s Blog Certification Authority.

[![Dettaglio Certificato Client da utilizzare per accedere ai servizi HTTPS](https://www.dontesta.it/wp-content/uploads/2020/02/DetailClientCertificate_tls-auth_dontesta_it-1024x816.png "Figura 4. Dettaglio Certificato Client da utilizzare per accedere ai servizi HTTPS")](https://www.dontesta.it/wp-content/uploads/2020/02/DetailClientCertificate_tls-auth_dontesta_it.png)

Figura 4. Dettaglio Certificato Client da utilizzare per accedere ai servizi HTTPS

Dopo questa breve introduzione sul servizio HTTPS che utilizzeremo come test per il nostro client in esecuzione su Liferay, non dobbiamo fare altro che lanciare il container Docker [docker-apache-ssl-tls-mutual-authentication](https://github.com/amusarra/docker-apache-ssl-tls-mutual-authentication) utilizzando il comando a seguire.

Il servizio sarà disponibile sulla porta (standard SSL/TLS) 443, che deve essere libera, in caso contrario potreste utilizzare un numero di porta libero (esempio: 9443, 8443, etc.).

```
docker run -i -t -d -p 443:10443 --name=tls-auth amusarra/apache-ssl-tls-mutual-authentication
```

Se non ci sono stati errori di esecuzione del comando docker, da questo momento sarà possibile raggiungere il servizio di mutua autenticazione SSL/TLS utilizzando il browser. Per evitare il comune errore **SSL\_ERROR\_BAD\_CERT\_DOMAIN** da parte del browser accedendo al servizio tramite la URL https://127.0.0.1, bisogna aggiungere al proprio file di hosts la riga a seguire.

```
### Servizio di mutua autenticazione via Apache 2.4 HTTP##127.0.0.1 tls-auth.dontesta.it
```

Adesso che il servizio HTTPS è attivo possiamo procedere con il successivo step di configurazione del portale Liferay.

 

## 4. Configurazione del portale Liferay

Le specifiche [**Java Secure Socket Extension (JSSE)**](https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html) prevedono la personalizzazione di diversi aspetti attraverso l’impostazione di specifiche _system properties _e _security properties_. La sezione [Customizing JSSE](https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#InstallationAndCustomization) riassume quali di questi aspetti possono essere personalizzati, quali sono le impostazioni predefinite e quali meccanismi sono utilizzati per fornire la personalizzazione.

Nel nostro caso le system properties che dobbiamo impostare sono le seguenti:

- **javax.net.ssl.keyStore** : Indicare il path assoluto del keyStore (esempio: /home/amusarra/client-keystore.jks);
- **javax.net.ssl.keyStorePassword** : Indicare la password di accesso al keyStore;
- **javax.net.ssl.trustStore** : Indicare il path assoluto del trustStore (esempio: /home/amusarra/client-truststore.jks);
- **javax.net.ssl.keyStorePassword** : Indicare la password del trustStore.

In ambienti di produzione è vivamente sconsigliato specificare in chiaro le password del keyStore e trustStore ma utilizzare un meccanismo che metta al sicuro le password.

Ogni application server, OOTB (out-of-the-box) offre il proprio meccanismo di sicurezza. Prendiamo il caso di **Red Hat JBoss Enterprise Application Platform** che prevede il [_Credential Store_](https://access.redhat.com/documentation/en-us/red_hat_jboss_enterprise_application_platform/7.2/html/how_to_configure_server_security/securely_storing_credentials) e [_Password Vault_](https://access.redhat.com/documentation/en-us/red_hat_jboss_enterprise_application_platform/7.2/html/how_to_configure_server_security/securely_storing_credentials). Fate riferimento alla documentazione ufficiale del vostro application server utilizzato su cui è installato il portale Liferay.

Esistono altre due proprietà che in alcuni casi possono essere utilizzate per impostare il tipo di keyStore. Il tipo di keyStore di default è JKS, potrebbero presentarsi dei casi per cui sia necessario impostare un tipo di keyStore diverso. La sezione [Additional Keystore Formats (PKCS12)](https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#KeystoreFormats) del documento JSSE tratta nel dettaglio questo argomento. Le due system properties per specificare il tipo di store sono:

- **javax.net.ssl.keyStoreType**
- **javax.net.ssl.trustStoreType**

Nel nostro caso utilizzeremo il tipo di store di default JKS. Il documento (in realtà l’eBook) [Liferay SSL/TLS Security. Come configurare il bundle Liferay per abilitare il protocollo SSL/TLS](http://bit.ly/2ZI0rSN) mostra un esempio di creazione ed utilizzo di keyStore in formato **PKCS#12**.

Una volta ottenuti keyStore e trustStore potremmo posizionarli all’interno della directory _$LIFERAY\_HOME/security/keystore_ (vedi figura 5). In alcuni casi potremmo fare anche a meno del trustStore, per esempio quando i servizi a cui vogliamo accedere presentano un certificato e una Certificate Chains trusted.

 

[![Posizione di KeyStore e TrustStore in $LIFERAY_HOME](https://www.dontesta.it/wp-content/uploads/2020/02/Liferay_KeyStrore_TrustStore-1024x265.png "Figura 5. Posizione di KeyStore e TrustStore in $LIFERAY\_HOME")](https://www.dontesta.it/wp-content/uploads/2020/02/Liferay_KeyStrore_TrustStore.png)

Figura 5. Posizione di KeyStore e TrustStore in $LIFERAY\_HOME

A seguire un esempio d’impostazione delle _system properties_ per il mio ambiente Liferay 7.2 GA2. In questo caso eviteremo d’inserire la system properties che riguarda il trustStore perchè il servizio HTTPS che andremo ad utilizzare ha un certificato rilasciato da una [**CA**](https://en.wikipedia.org/wiki/Certificate_authority) (Certificate Authority) trusted ([Let’s Encrypt Authority X3](https://letsencrypt.org/certificates/)).

 

```
-Djavax.net.ssl.keyStore=/Users/antoniomusarra/dev/liferay/liferay-ce-portal-7.2.1-ga2/security/keystore/tls-client.dontesta.it.jks-Djavax.net.ssl.keyStorePassword=secret-Djavax.net.debug=ssl
```

Fate attenzione alla system properties _javax.net.debug=ssl_, questa potrebbe essere utile in caso di troubleshooting ma in ogni caso può aiutare i neofiti a capire meglio le fasi del processo di _handshake_.

Quello a seguire è il contenuto integrale del file _$LIFERAY\_HOME/tomcat-9.0.17/bin/setenv.sh _(per ambienti Unix/Linux/macOS) che imposta le system properties JSSE all’avvio del portale Liferay.

```
SSL\_OPTS="$SSL\_OPTS -Djavax.net.ssl.keyStore=/Users/antoniomusarra/dev/liferay/liferay-ce-portal-7.2.1-ga2/security/keystore/tls-client.dontesta.it.jks"SSL\_OPTS="$SSL\_OPTS -Djavax.net.ssl.keyStorePassword=secret"SSL\_OPTS="$SSL\_OPTS -Djavax.net.debug=ssl"CATALINA\_OPTS="$SSL\_OPTS $CATALINA\_OPTS -Dfile.encoding=UTF-8 -Djava.locale.providers=JRE,COMPAT,CLDR -Djava.net.preferIPv4Stack=true -Duser.timezone=GMT -Xms2560m -Xmx2560m -XX:MaxNewSize=1536m -XX:MaxMetaspaceSize=768m -XX:MetaspaceSize=768m -XX:NewSize=1536m -XX:SurvivorRatio=7"
```

All’avvio del portale, grazie al fatto di aver impostato la system properties _javax.net.debug=ssl_, dovreste vedere in console (standard output) parecchie informazioni che riguardano il caricamento dei certificati contenuti all’interno del trustStore e keyStore. In questo caso il trustStore è quello della JVM. Per maggiori dettagli puoi consultare il file [Liferay 7.2 GA2 SSL/TLS StartUp Log File](https://www.dontesta.it/wp-content/uploads/2020/02/Liferay72_GA2_SSL_TLS_StartUp_LOG.txt).

Dopo aver configurato il portale Liferay e accertato il corretto funzionamento, il passo successivo riguarda il come implementare in modo semplice il client HTTPS con pochissime righe di codice.

 

## 5. Implementazione del Client HTTPS

Per dare subito evidenza della semplicità, potremmo realizzare un comando Gogo Shell che prenda in input l’end point del servizio e restituisca in output la risposta. Il codice a seguire mostra il comando **getProtectedResource(URI)**. Le righe evidenziate sono le uniche fondamentali per il corretto funzionamento del client.

Il codice delle righe 41-42 inietta sul componente _HTTPSProtectedResourcesCommand_ l’implementazione dell’interfaccia Http. Il codice della riga 17 effettua invece la chiamata verso il servizio HTTPS specificato tramite il parametro _uri_ e accedendo in Mutua Autenticazione restituisce la risposta direttamente in console (e in formato JSON).

```
/\*\* \* @author Antonio Musarra \*/@Component(property = {"osgi.command.function=getProtectedResource","osgi.command.scope=security"},service = Object.class)public class HTTPSProtectedResourcesCommand {public void getProtectedResource(String uri) throws Exception {String response = null;try {response = \_httpClient.URLtoString(uri);if (\_log.isInfoEnabled()) {\_log.info("Response: " + response);}System.out.println(response);}catch (IOException ioe) {if (\_log.isErrorEnabled()) {\_log.error(ioe.getMessage(), ioe);}throw new Exception(String.format("They occurred in the service call. {EndPoint: %s} - {Error Message: %s}",uri, ioe.getMessage()),ioe);}}private static final Log \_log = LogFactoryUtil.getLog(HTTPSProtectedResourcesCommand.class);@Referenceprivate Http \_httpClient;}
```

La figura 6 mostra l’output del comando `g! security:getProtectedResource https://tls-auth.dontesta.it/secure/api/headers` eseguito tramite la Gogo Shell.

Sempre da figura 6, la sezione in giallo evidenzia parte del processo di _handshake_ tra client e server. Guardando [l’output completo del comando Gogo Shell security:getProtectedResource](https://www.dontesta.it/wp-content/uploads/2020/02/RunGogoShellCommand_SecurityGetProtectedResource_output.txt), dovreste essere in grado di identificare ogni fase del processo di handshake, così come indicato nel diagramma di figura 1.

Sempre da figura 6, la sezione in rosso evidenzia invece la risposta del servizio https://tls-auth.dontesta.it/secure/api/headers.

[![Esempio di output del comando Gogo Shell getProtectedResource](https://www.dontesta.it/wp-content/uploads/2020/02/OutputComandoGogoShell_getProtectedResource_1-1024x471.png "Figura 6. Esempio di output del comando Gogo Shell security:getProtectedResource")](https://www.dontesta.it/wp-content/uploads/2020/02/OutputComandoGogoShell_getProtectedResource_1.png)

Figura 6. Esempio di output del comando Gogo Shell security:getProtectedResource

Sul repository GitHub [amusarra/gogo-shell-tls-mutual-sample](https://github.com/amusarra/gogo-shell-tls-mutual-sample) è disponibile tutto il codice sorgente del comando Gogo Shell **security:getProtectedResource**.

 

## 6. A quali problemi potremmo andare incontro

In questo tipo di scenario i problemi più “fastidiosi” che solitamente potremmo incontrare riguardano nella maggior parte dei casi l’errata configurazione dell’ambiente di runtime. Riporto i casi più comuni.

1. Errore di accesso ai certificati (sia nel keyStore sia nel trustStore). In genere questo avviene per l’errata configurazione delle _system properties_; path del keyStore o trustStore errati, oppure password errata;
2. Errore durante il processo di _handshake_. Potrebbe accadere a causa del fatto che il certificato client non venga trovato sul keyStore;
3. Certificate Chains non soddisfatta.

Quelle a seguire sono le possibili eccezioni che potremmo ottenere e descritte poco prima.

```
java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)java.io.IOException: java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)at com.liferay.portal.util.HttpImpl.URLtoInputStream(HttpImpl.java:1985)at com.liferay.portal.util.HttpImpl.URLtoByteArray(HttpImpl.java:1669)at com.liferay.portal.util.HttpImpl.URLtoByteArray(HttpImpl.java:1190)at com.liferay.portal.util.HttpImpl.URLtoByteArray(HttpImpl.java:1203)at com.liferay.portal.util.HttpImpl.URLtoString(HttpImpl.java:1263)at it.dontesta.labs.liferay.security.tls.auth.gogoshell.HTTPSProtectedResourcesCommand.getProtectedResource(HTTPSProtectedResourcesCommand.java:54)...Caused by: java.security.PrivilegedActionException: java.io.FileNotFoundException: /Users/antoniomusarra/dev/liferay/liferay-ce-portal-7.2.1-ga2/security/keystore/tls-client.dontesta.it (No such file or directory)at java.security.AccessController.doPrivileged(Native Method)at sun.security.ssl.SSLContextImpl$DefaultManagersHolder.getKeyManagers(SSLContextImpl.java:829)at sun.security.ssl.SSLContextImpl$DefaultManagersHolder.<clinit>(SSLContextImpl.java:765)at sun.security.ssl.SSLContextImpl$DefaultSSLContext.<init>(SSLContextImpl.java:920)at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)at java.lang.reflect.Constructor.newInstance(Constructor.java:423)at java.security.Provider$Service.newInstance(Provider.java:1595)... 40 more

Caused by: java.io.IOException: Keystore was tampered with, or password was incorrectat sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:780)at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:56)at sun.security.provider.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:224)at sun.security.provider.JavaKeyStore$DualFormatJKS.engineLoad(JavaKeyStore.java:70)at java.security.KeyStore.load(KeyStore.java:1445)at sun.security.ssl.SSLContextImpl$DefaultManagersHolder.getKeyManagers(SSLContextImpl.java:858)at sun.security.ssl.SSLContextImpl$DefaultManagersHolder.<clinit>(SSLContextImpl.java:765)at sun.security.ssl.SSLContextImpl$DefaultSSLContext.<init>(SSLContextImpl.java:920)at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)at java.lang.reflect.Constructor.newInstance(Constructor.java:423)at java.security.Provider$Service.newInstance(Provider.java:1595)... 40 moreCaused by: java.security.UnrecoverableKeyException: Password verification failedat sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:778)... 52 more

2020-02-21 20:54:21.991 ERROR [pipe-security:getProtectedResource https://tls-auth.dontesta.it/secure/api/headers][HTTPSProtectedResourcesCommand:64] javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake\_failurejava.io.IOException: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake\_failure at com.liferay.portal.util.HttpImpl.URLtoInputStream(HttpImpl.java:1985) at com.liferay.portal.util.HttpImpl.URLtoByteArray(HttpImpl.java:1669) at com.liferay.portal.util.HttpImpl.URLtoByteArray(HttpImpl.java:1190) at com.liferay.portal.util.HttpImpl.URLtoByteArray(HttpImpl.java:1203) at com.liferay.portal.util.HttpImpl.URLtoString(HttpImpl.java:1263) at it.dontesta.labs.liferay.security.tls.auth.gogoshell.HTTPSProtectedResourcesCommand.getProtectedResource(HTTPSProtectedResourcesCommand.java:54) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.felix.gogo.runtime.Reflective.invoke(Reflective.java:139) at org.apache.felix.gogo.runtime.CommandProxy.execute(CommandProxy.java:91) at org.apache.felix.gogo.runtime.Closure.executeCmd(Closure.java:599) at org.apache.felix.gogo.runtime.Closure.executeStatement(Closure.java:526) at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:415) at org.apache.felix.gogo.runtime.Pipe.doCall(Pipe.java:416) at org.apache.felix.gogo.runtime.Pipe.call(Pipe.java:229) at org.apache.felix.gogo.runtime.Pipe.call(Pipe.java:59) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake\_failure at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.Alerts.getSSLException(Alerts.java:154) at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2038) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1135) at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:940) at sun.security.ssl.AppInputStream.read(AppInputStream.java:105) at

...Thread-139, READ: TLSv1.2 Handshake, length = 28\*\*\* ServerHelloDoneWarning: no suitable certificate found - continuing without client authentication\*\*\* Certificate chain<Empty>Thread-139, READ: TLSv1.2 Alert, length = 26Thread-139, RECV TLSv1.2 ALERT: fatal, handshake\_failure%% Invalidated: [Session-3, TLS\_ECDHE\_RSA\_WITH\_AES\_256\_GCM\_SHA384]%% Invalidated: [Session-4, TLS\_ECDHE\_RSA\_WITH\_AES\_256\_GCM\_SHA384]Thread-139, called closeSocket()Thread-139, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake\_failureThread-139, called close()Thread-139, called closeInternal(true)java.io.IOException: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake\_failure...

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
```

 

## 7. Qual è stata la tua esperienza?

In questo articolo ho voluto presentare una soluzione semplice per implementare una connessione verso servizi HTTPS protetti da una meccanismo di autenticazione di tipo Two-Way SSL/TLS Mutual Authentication in un contesto Liferay.

Che tipo di esperienza hai avuto? Sei riuscito a trovare in questo articolo le informazioni necessarie per affrontare e risolvere il tuo problema?

In uno dei prossimi articoli vedremo degli scenari diversi, uno dei quali potrebbe essere la necessità di scegliere quale certificato client utilizzare per accedere ad uno specifico servizio HTTPS.

 

## 8. Risorse

Vi lascio alcune risorse che potrebbero essere utili come compendio.

1. [Importazione Certificati SSL sul Java Keystore (JKS)](http://bit.ly/2to0ed9)
2. [Liferay SSL/TLS Security. Come configurare il bundle Liferay per abilitare il protocollo SSL/TLS](http://bit.ly/2Xan9q9)
3. [Docker Image Apache SSL/TLS Mutual Authentication on Azure Cloud](http://bit.ly/2Sm5dU7)
4. [GitHub – amusarra/docker-apache-ssl-tls-mutual-authentication](http://bit.ly/2VjbJ1x)
5. [Apache HTTP 2.4 – Docker image for SSL/TLS Mutual Authentication](https://www.youtube.com/watch?v=VIRWJjqb0y0)

 

<iframe width="560" height="315" src="https://www.youtube.com/embed/VIRWJjqb0y0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="allowfullscreen"></iframe>

L'articolo [Liferay 7.2: Esempio di Two-Way SSL/TLS Mutual Authentication Client](https://www.dontesta.it/2020/02/25/liferay-7-2-esempio-di-two-way-ssl-tls-mutual-authentication-client/) sembra essere il primo su [Antonio Musarra's Blog](https://www.dontesta.it).

[![](http://feeds.feedburner.com/~ff/dontesta/blog?d=yIl2AUoC8zA)](http://feeds.feedburner.com/~ff/dontesta/blog?a=U2tRXUa1FT0:Z0aOtlW6LaA:yIl2AUoC8zA) [![](http://feeds.feedburner.com/~ff/dontesta/blog?d=dnMXMwOfBR0)](http://feeds.feedburner.com/~ff/dontesta/blog?a=U2tRXUa1FT0:Z0aOtlW6LaA:dnMXMwOfBR0) [![](http://feeds.feedburner.com/~ff/dontesta/blog?i=U2tRXUa1FT0:Z0aOtlW6LaA:D7DqB2pKExk)](http://feeds.feedburner.com/~ff/dontesta/blog?a=U2tRXUa1FT0:Z0aOtlW6LaA:D7DqB2pKExk) [![](http://feeds.feedburner.com/~ff/dontesta/blog?d=YwkR-u9nhCs)](http://feeds.feedburner.com/~ff/dontesta/blog?a=U2tRXUa1FT0:Z0aOtlW6LaA:YwkR-u9nhCs) [![](http://feeds.feedburner.com/~ff/dontesta/blog?i=U2tRXUa1FT0:Z0aOtlW6LaA:F7zBnMyn0Lo)](http://feeds.feedburner.com/~ff/dontesta/blog?a=U2tRXUa1FT0:Z0aOtlW6LaA:F7zBnMyn0Lo) [![](http://feeds.feedburner.com/~ff/dontesta/blog?i=U2tRXUa1FT0:Z0aOtlW6LaA:V_sGLiPBpWU)](http://feeds.feedburner.com/~ff/dontesta/blog?a=U2tRXUa1FT0:Z0aOtlW6LaA:V_sGLiPBpWU) [![](http://feeds.feedburner.com/~ff/dontesta/blog?d=qj6IDK7rITs)](http://feeds.feedburner.com/~ff/dontesta/blog?a=U2tRXUa1FT0:Z0aOtlW6LaA:qj6IDK7rITs) [![](http://feeds.feedburner.com/~ff/dontesta/blog?i=U2tRXUa1FT0:Z0aOtlW6LaA:KwTdNBX3Jqk)](http://feeds.feedburner.com/~ff/dontesta/blog?a=U2tRXUa1FT0:Z0aOtlW6LaA:KwTdNBX3Jqk) [![](http://feeds.feedburner.com/~ff/dontesta/blog?i=U2tRXUa1FT0:Z0aOtlW6LaA:gIN9vFwOqvQ)](http://feeds.feedburner.com/~ff/dontesta/blog?a=U2tRXUa1FT0:Z0aOtlW6LaA:gIN9vFwOqvQ)
 ![](http://feeds.feedburner.com/~r/dontesta/blog/~4/U2tRXUa1FT0)