Autenticazione Mutual Transport Layer Security (mTLS) dall’AEM
Scopri come effettuare chiamate HTTPS da AEM alle API web che richiedono l’autenticazione Mutual Transport Layer Security (mTLS).
L'autenticazione mTLS o TLS bidirezionale migliora la sicurezza del protocollo TLS richiedendo l'autenticazione reciproca di client e server. Questa autenticazione viene eseguita utilizzando certificati digitali. Viene comunemente utilizzato in scenari in cui la sicurezza e la verifica dell’identità sono fondamentali.
Per impostazione predefinita, quando si tenta di stabilire una connessione HTTPS a un’API web che richiede l’autenticazione mTLS, la connessione non riesce e viene visualizzato il messaggio di errore:
javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_required
Questo problema si verifica quando il client non presenta un certificato per l’autenticazione.
Scopri come chiamare correttamente le API che richiedono l’autenticazione mTLS utilizzando Apache HttpClient e AEM KeyStore e TrustStore.
HttpClient e caricamento del materiale KeyStore dell’AEM
Ad alto livello, per richiamare un’API protetta da mTLS dall’AEM sono necessari i seguenti passaggi.
Generazione di certificati AEM
Richiedi il certificato AEM collaborando con il team di sicurezza della tua organizzazione. Il team di sicurezza fornisce o richiede i dettagli relativi al certificato come chiave, richiesta di firma del certificato (CSR, Certificate Signing Request) e utilizzando CSR il certificato viene rilasciato.
A scopo dimostrativo, genera i dettagli relativi al certificato come chiave, richiesta di firma del certificato (CSR, Certificate Signing Request). Nell’esempio seguente, per rilasciare il certificato viene utilizzata una CA autofirmata.
-
Innanzitutto, genera il certificato dell’Autorità di certificazione (CA) interna.
code language-shell # Create an internal Certification Authority (CA) certificate openssl req -new -x509 -days 9999 -keyout internal-ca-key.pem -out internal-ca-cert.pem
-
Genera il certificato AEM.
code language-shell # Generate Key openssl genrsa -out client-key.pem # Generate CSR openssl req -new -key client-key.pem -out client-csr.pem # Generate certificate and sign with internal Certification Authority (CA) openssl x509 -req -days 9999 -in client-csr.pem -CA internal-ca-cert.pem -CAkey internal-ca-key.pem -CAcreateserial -out client-cert.pem # Verify certificate openssl verify -CAfile internal-ca-cert.pem client-cert.pem
-
Converti la chiave privata dell'AEM in formato DER, l'AEM KeyStore richiede la chiave privata in formato DER.
code language-shell openssl pkcs8 -topk8 -inform PEM -outform DER -in client-key.pem -out client-key.der -nocrypt
Scambio di certificati
Se per il certificato AEM utilizzi una CA autofirmata, come indicato sopra, invia il certificato o il certificato dell’Autorità di certificazione (CA) interna al provider API.
Inoltre, se il provider API utilizza un certificato CA autofirmato, riceverà il certificato o il certificato dell'Autorità di certificazione (CA) interna dal provider API.
Importazione certificati
Per importare il certificato AEM, effettua le seguenti operazioni:
-
Accedi a Autore AEM come amministratore.
-
Passa a Autore AEM > Strumenti > Sicurezza > Utenti > Crea o seleziona un utente esistente.
A scopo dimostrativo, viene creato un nuovo utente denominato
mtl-demo-user
. -
Per aprire Proprietà utente, fare clic sul nome utente.
-
Fare clic sulla scheda Registro chiavi e quindi sul pulsante Crea archivio chiavi. Quindi nella finestra di dialogo Imposta password di accesso al registro chiavi, imposta una password per il registro chiavi di questo utente e fai clic su Salva.
-
Nella nuova schermata, nella sezione ADD PRIVATE KEY FROM DER FILE (AGGIUNGI CHIAVE PRIVATA DA FILE DER), effettua le seguenti operazioni:
-
Immetti alias
-
Importa la chiave privata AEM in formato DER, generata in precedenza.
-
Importa i file della catena di certificati generati in precedenza.
-
Fai clic su Invia
-
-
Verifica che il certificato sia stato importato correttamente.
Se il provider API utilizza un certificato CA autofirmato, importa il certificato ricevuto nel TrustStore dell'AEM. Segui i passaggi descritti in qui.
Allo stesso modo, se l’AEM utilizza un certificato CA autofirmato, richiedi al provider API di importarlo.
Codice di chiamata API mTLS prototipo utilizzando HttpClient
Aggiorna il codice Java™ come segue. Per utilizzare l'annotazione @Reference
per ottenere il servizio KeyStoreService
dell'AEM, il codice chiamante deve essere un componente/servizio OSGi o un modello Sling (in cui è utilizzato @OsgiService
).
...
// Get AEM's KeyStoreService reference
@Reference
private com.adobe.granite.keystore.KeyStoreService keyStoreService;
...
// Get AEM KeyStore using KeyStoreService
KeyStore aemKeyStore = getAEMKeyStore(keyStoreService, resourceResolver);
if (aemKeyStore != null) {
// Create SSL Context
SSLContextBuilder sslbuilder = new SSLContextBuilder();
// Load AEM KeyStore material into above SSL Context with keystore password
// Ideally password should be encrypted and stored in OSGi config
sslbuilder.loadKeyMaterial(aemKeyStore, "admin".toCharArray());
// If API provider cert is self-signed, load AEM TrustStore material into above SSL Context
// Get AEM TrustStore
KeyStore aemTrustStore = getAEMTrustStore(keyStoreService, resourceResolver);
sslbuilder.loadTrustMaterial(aemTrustStore, null);
// Create SSL Connection Socket using above SSL Context
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslbuilder.build(), NoopHostnameVerifier.INSTANCE);
// Create HttpClientBuilder
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
httpClientBuilder.setSSLSocketFactory(sslsf);
// Create HttpClient
CloseableHttpClient httpClient = httpClientBuilder.build();
// Invoke API
closeableHttpResponse = httpClient.execute(new HttpGet(MTLS_API_ENDPOINT));
// Code that reads response code and body from the 'closeableHttpResponse' object
...
}
/**
* Returns the AEM KeyStore of a user. In this example we are using the
* 'mtl-demo-user' user.
*
* @param keyStoreService
* @param resourceResolver
* @return AEM KeyStore
*/
private KeyStore getAEMKeyStore(KeyStoreService keyStoreService, ResourceResolver resourceResolver) {
// get AEM KeyStore of 'mtl-demo-user' user, you can create a user or use an existing one.
// Then create keystore and upload key, certificate files.
KeyStore aemKeyStore = keyStoreService.getKeyStore(resourceResolver, "mtl-demo-user");
return aemKeyStore;
}
/**
*
* Returns the global AEM TrustStore
*
* @param keyStoreService OOTB OSGi service that makes AEM based KeyStore
* operations easy.
* @param resourceResolver
* @return
*/
private KeyStore getAEMTrustStore(KeyStoreService keyStoreService, ResourceResolver resourceResolver) {
// get AEM TrustStore from the KeyStoreService and ResourceResolver
KeyStore aemTrustStore = keyStoreService.getTrustStore(resourceResolver);
return aemTrustStore;
}
...
- Inserisci il servizio OSGi
com.adobe.granite.keystore.KeyStoreService
OOTB nel componente OSGi. - Ottenere il registro chiavi AEM dell'utente utilizzando
KeyStoreService
eResourceResolver
. Questa operazione viene eseguita dal metodogetAEMKeyStore(...)
. - Se il provider API utilizza un certificato CA autofirmato, ottenere il TrustStore AEM globale, il metodo
getAEMTrustStore(...)
esegue questa operazione. - Creare un oggetto di
SSLContextBuilder
. Vedere Java™ Dettagli API. - Caricare il registro chiavi AEM dell'utente in
SSLContextBuilder
utilizzando il metodoloadKeyMaterial(final KeyStore keystore,final char[] keyPassword)
. - La password del keystore è la password impostata durante la creazione del keystore. Deve essere memorizzata nella configurazione OSGi. Vedere Valori di configurazione segreti.
Evita le modifiche al keystore JVM
Un approccio convenzionale per richiamare in modo efficace le API mTLS con certificati privati comporta la modifica del keystore JVM. Ciò si ottiene importando i certificati privati mediante il comando Java™ keytool.
Tuttavia, questo metodo non è allineato con le best practice di sicurezza e l'AEM offre un'opzione superiore tramite l'utilizzo di KeyStores specifici dell'utente e Global TrustStore e KeyStoreService.
Pacchetto soluzione
Il progetto Node.js di esempio demo nel video può essere scaricato da qui.
Il codice del servlet AEM è disponibile nel ramo tutorial/web-api-invocation
del progetto WKND Sites, vedi.