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
    
TIP
I certificati CA autofirmati vengono utilizzati solo a scopo di sviluppo. Per la produzione, utilizza un’autorità di certificazione (CA) attendibile per rilasciare il certificato.

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:

  1. Accedi a Autore AEM come amministratore.

  2. Passa a Autore AEM > Strumenti > Sicurezza > Utenti > Crea o seleziona un utente esistente.

    Crea o seleziona un utente esistente

    A scopo dimostrativo, viene creato un nuovo utente denominato mtl-demo-user.

  3. Per aprire Proprietà utente, fare clic sul nome utente.

  4. 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.

    Crea registro chiavi

  5. Nella nuova schermata, nella sezione ADD PRIVATE KEY FROM DER FILE (AGGIUNGI CHIAVE PRIVATA DA FILE DER), effettua le seguenti operazioni:

    1. Immetti alias

    2. Importa la chiave privata AEM in formato DER, generata in precedenza.

    3. Importa i file della catena di certificati generati in precedenza.

    4. Fai clic su Invia

      Importa chiave privata AEM

  6. Verifica che il certificato sia stato importato correttamente.

    Chiave privata AEM e certificato importati

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 e ResourceResolver. Questa operazione viene eseguita dal metodo getAEMKeyStore(...).
  • 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 metodo loadKeyMaterial(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.

recommendation-more-help
c92bdb17-1e49-4e76-bcdd-89e4f85f45e6