HttpClient und Laden des AEM KeyStore-Materials
Im Großen und Ganzen sind die folgenden Schritte erforderlich, um eine mTLS-geschützte API über AEM aufzurufen.
Generierung von AEM-Zertifikaten
Fordern Sie das AEM-Zertifikat in Zusammenarbeit mit dem Sicherheits-Team Ihres Unternehmens an. Das Sicherheits-Team stellt die zertifikatbezogenen Details wie Schlüssel, Zertifikatsignaturanfragen (CSR) bereit oder fragt sie ab und verwendet CSR, um das Zertifikat auszustellen.
Generieren Sie zu Demozwecken die zertifikatbezogenen Details wie Schlüssel, Zertifikatsignaturanfragen (CSR). Im folgenden Beispiel wird eine selbstsignierte Zertifizierungsstelle verwendet, um das Zertifikat auszustellen.
-
Generieren Sie zunächst das Zertifikat der internen Zertifizierungsstelle (CA).
# Create an internal Certification Authority (CA) certificate openssl req -new -x509 -days 9999 -keyout internal-ca-key.pem -out internal-ca-cert.pem
-
Generieren Sie das AEM-Zertifikat.
# 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
-
Konvertieren Sie den privaten AEM-Schlüssel in das DER-Format. Der AEM-KeyStore benötigt den privaten Schlüssel im DER-Format.
openssl pkcs8 -topk8 -inform PEM -outform DER -in client-key.pem -out client-key.der -nocrypt
Zertifikataustausch
Wenn Sie wie oben eine selbstsignierte Zertifizierungsstelle für das AEM-Zertifikat verwenden, senden Sie das Zertifikat oder das Zertifikat der internen Zertifizierungsstelle (CA) an den API-Provider.
Wenn der API-Provider ein selbstsigniertes CA-Zertifikat verwendet, erhalten Sie das Zertifikat oder das Zertifikat der internen Zertifizierungsstelle (CA) vom API-Provider.
Zertifikatimport
Gehen Sie wie folgt vor, um AEM-Zertifikate zu importieren:
-
Melden Sie sich bei AEM Author als Admin an.
-
Navigieren Sie zu AEM Author> Tools> Sicherheit> Benutzer> Vorhandenen Benutzer erstellen oder auswählen.
Zu Demozwecken wird ein neuer Benutzer mit dem Namen
mtl-demo-user
erstellt. -
Klicken Sie auf den Benutzernamen, um die Benutzereigenschaften zu öffnen.
-
Öffnen Sie die Registerkarte Keystore und klicken Sie auf Keystore erstellen. Legen Sie im Dialogfeld KeyStore-Zugriffskennwort festlegen ein Kennwort für den Keystore dieses Benutzers fest und klicken Sie auf „Speichern“.
-
Führen Sie im neuen Bildschirm unter dem Abschnitt PRIVATEN SCHLÜSSEL AUS DER DATEI HINZUFÜGEN folgende Schritte aus:
-
Eingeben eines Alias
-
Importieren Sie den privaten AEM-Schlüssel im zuvor generierten DER-Format.
-
Importieren Sie die zuvor generierten Zertifikatkettendateien.
-
Klicken Sie auf „Senden“
-
-
Überprüfen Sie, ob das Zertifikat erfolgreich importiert wurde.
Wenn der API-Provider ein selbstsigniertes CA-Zertifikat verwendet, importieren Sie das erhaltene Zertifikat im AEM TrustStore und führen Sie die Schritte ab hier aus.
Wenn AEM ein selbstsigniertes CA-Zertifikat verwendet, fordern Sie den API-Provider ebenfalls auf, es zu importieren.
Prototypischer mTLS-API-Aufruf-Code mithilfe von HttpClient
Aktualisieren Sie den Java™-Code wie unten beschrieben. Um die @Reference
-Anmerkung zum Abrufen des AEM KeyStoreService
-Dienstes verwenden zu können, muss der Aufruf-Code eine OSGi-Komponente/Dienst oder ein Sling-Modell sein (und dort @OsgiService
verwendet werden).
...
// 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;
}
...
- Fügen Sie den vorkonfigurierten OSGi-Dienst
com.adobe.granite.keystore.KeyStoreService
in Ihre OSGi-Komponente ein. - Rufen Sie den AEM KeyStore der Benutzerin bzw. des Benutzers mit
KeyStoreService
undResourceResolver
ab. Dies erfolgt mit der MethodegetAEMKeyStore(...)
. - Wenn der API-Provider ein selbstsigniertes Zertifizierungsstellenzertifikat verwendet, rufen Sie den globalen AEM TrustStore ab. Dies erfolgt mit der Methode
getAEMTrustStore(...)
. - Erstellen Sie ein Objekt von
SSLContextBuilder
, siehe Java™ API-Details. - Laden Sie den AEM KeyStore der Benutzerin bzw. des Benutzers in
SSLContextBuilder
mit der MethodeloadKeyMaterial(final KeyStore keystore,final char[] keyPassword)
. - Das Keystore-Kennwort ist das Kennwort, das beim Erstellen des Keystores festgelegt wurde. Es sollte in der OSGi-Konfiguration gespeichert werden, siehe Geheime Konfigurationswerte.
Vermeiden von JVM-Keystore-Änderungen
Ein herkömmlicher Ansatz zum effektiven Aufrufen von mTLS-APIs mit privaten Zertifikaten beinhaltet die Änderung des JVM Keystores. Hierzu werden die privaten Zertifikate mithilfe des Java™-Befehls keytool importiert.
Da diese Methode jedoch nicht den Best Practices zur Sicherheit entspricht, bietet AEM eine bessere Option durch die Verwendung von benutzerspezifischen KeyStores und Global TrustStore und KeyStoreService.
Lösungspaket
Das im Video vorgestellte Node.js-Beispielprojekt kann von hier heruntergeladen werden.
Der AEM-Servlet-Code ist in der Verzweigung tutorial/web-api-invocation
des WKND Sites-Projekts verfügbar, siehe.