mTLS-autentisering (Mutual Transport Layer Security) från AEM
Lär dig hur du gör HTTPS-anrop från AEM till webb-API:er som kräver mTLS-autentisering.
mTLS- eller tvåvägs TLS-autentisering förbättrar TLS-protokollets säkerhet genom att kräva att både klienten och servern autentiserar varandra. Autentiseringen görs med digitala certifikat. Det används ofta i scenarier där stark säkerhet och identitetsverifiering är avgörande.
Som standard misslyckas anslutningen när du försöker göra en HTTPS-anslutning till ett webb-API som kräver mTLS-autentisering. Följande fel uppstår:
javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_required
Det här problemet inträffar när klienten inte har något certifikat som kan autentiseras.
Låt oss lära oss hur du kan anropa API:er som kräver mTLS-autentisering med Apache HttpClient och AEM KeyStore och TrustStore.
HttpClient och läsa in AEM KeyStore-material
På en hög nivå krävs följande steg för att anropa ett mTLS-skyddat API från AEM.
Generering av AEM
Begär AEM certifikat genom att samarbeta med din organisations säkerhetsteam. Säkerhetsteamet tillhandahåller eller frågar om certifikatrelaterade detaljer som nyckel, CSR (Certificate Signing Request) och använder CSR för att utfärda certifikatet.
Generera certifikatrelaterade detaljer som nyckel, CSR (Certificate Signing Request) för demonstrationssyften. I exemplet nedan används en självsignerad certifikatutfärdare för att utfärda certifikatet.
-
Generera först det interna certifikatutfärdarcertifikatet (CA).
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
-
Generera 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
-
Konvertera den AEM privata nyckeln till DER-format, AEM KeyStore kräver den privata nyckeln i DER-format.
code language-shell openssl pkcs8 -topk8 -inform PEM -outform DER -in client-key.pem -out client-key.der -nocrypt
Certifikatutbyte
Om du använder en självsignerad certifikatutfärdare för AEM, som ovan, skickar du certifikatet eller det interna certifikatutfärdarcertifikatet till API-providern.
Om API-providern använder ett självsignerat certifikatutfärdarcertifikat tar du dessutom emot certifikatet eller det interna certifikatutfärdarcertifikatet från API-providern.
Certifikatimport
Så här importerar du AEM certifikat:
-
Logga in på AEM författare som administratör.
-
Navigera till AEM Författare > Verktyg > Dokumentskydd > Användare > Skapa eller välj en befintlig användare.
För demoändamål skapas en ny användare med namnet
mtl-demo-user
. -
Klicka på användarnamnet för att öppna användaregenskaperna.
-
Klicka på fliken Nyckelbehållare och sedan på knappen Skapa nyckelbehållare . Ange sedan ett lösenord för användarens nyckelbehållare i dialogrutan Ange lösenord för KeyStore-åtkomst och klicka på Spara.
-
Följ stegen nedan på den nya skärmen under avsnittet LÄGG TILL PRIVAT KEY FRÅN DER FILE:
-
Ange alias
-
Importera den AEM privata nyckeln i DER-format som genereras ovan.
-
Importera filerna för certifikatkedjan som genererats ovan.
-
Klicka på Skicka
-
-
Kontrollera att certifikatet har importerats.
Om API-providern använder ett självsignerat CA-certifikat importerar du det mottagna certifikatet till AEM TrustStore, följer du stegen från här.
Om AEM använder ett självsignerat CA-certifikat ber du API-providern att importera det.
Prototypisk mTLS API-anropskod med HttpClient
Uppdatera Java™-kod enligt nedan. Om du vill använda @Reference
-anteckningen för att hämta AEM KeyStoreService
-tjänsten måste den anropande koden vara en OSGi-komponent eller en Sling-modell (och @OsgiService
används där).
...
// 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;
}
...
- Mata in OTB
com.adobe.granite.keystore.KeyStoreService
OSGi-tjänsten i OSGi-komponenten. - Hämta användarens AEM KeyStore med
KeyStoreService
ochResourceResolver
, det gör metodengetAEMKeyStore(...)
. - Om API-providern använder ett självsignerat CA-certifikat hämtar du det globala AEM TrustStore, gör metoden
getAEMTrustStore(...)
det. - Skapa ett objekt av
SSLContextBuilder
, se Java™ API-information. - Läs in användarens AEM KeyStore till
SSLContextBuilder
med metodenloadKeyMaterial(final KeyStore keystore,final char[] keyPassword)
. - Nyckellösenordet är det lösenord som angavs när nyckelbehållaren skapades. Det bör lagras i OSGi-konfigurationen, se Hemliga konfigurationsvärden.
Undvik JVM-nyckelbehållarändringar
Ett vanligt tillvägagångssätt för att effektivt anropa mTLS API:er med privata certifikat är att ändra JVM Keystore. Detta uppnås genom att importera privata certifikat med kommandot Java™ keytool .
Den här metoden är dock inte anpassad efter bästa säkerhetspraxis och AEM erbjuder ett överlägset alternativ genom att använda användarspecifika KeyStores och Global TrustStore och KeyStoreService.
Lösningspaket
Exempelprojektet Node.js som har nedgraderats i videon kan hämtas från här.
Den AEM serletkoden är tillgänglig i WKND Sites Projects tutorial/web-api-invocation
-gren, se.