Authentification Transport Layer Security mutuelle (mTLS) à partir d’AEM

Découvrez comment effectuer des appels HTTPS à partir d’AEM vers les API web qui nécessitent une authentification Transport Layer Security mutuelle (mTLS).

L’authentification mTLS ou TLS bidirectionnelle renforce la sécurité du protocole TLS en exigeant une authentification mutuelle entre le client ou la cliente et le serveur. Cette authentification est effectuée à l’aide de certificats numériques. Elle est généralement utilisée dans les cas où une sécurité renforcée et une vérification de l’identité sont essentielles.

Par défaut, lorsque vous tentez d’établir une connexion HTTPS à une API web nécessitant une authentification mTLS, la connexion échoue avec l’erreur :

javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_required

Ce problème se produit lorsque le client ou la cliente ne présente pas de certificat pour s’authentifier.

Découvrez comment appeler avec succès des API qui nécessitent une authentification mTLS à l’aide d’Apache HttpClient et du KeyStore et TrustStore d’AEM.

HttpClient et charger le matériel KeyStore d’AEM

À un niveau élevé, les étapes suivantes sont requises pour appeler une API protégée par mTLS à partir d’AEM.

Génération de certificats AEM

Demandez le certificat AEM en vous associant à l’équipe de sécurité de votre entreprise. L’équipe de sécurité fournit ou demande les informations relatives au certificat, telles que la clé ou la demande de signature de certificat (CSR). Le certificat est émis à l’aide de la CSR.

À des fins de démonstration, générez les détails liés au certificat, tels que la clé, la demande de signature de certificat (CSR). Dans l’exemple ci-dessous, une autorité de certification auto-signée est utilisée pour émettre le certificat.

  • Tout d’abord, générez le certificat de l’autorité de certification (CA) interne.

    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
    
  • Générez le certificat 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
    
  • Convertissez la clé privée AEM au format DER. Le KeyStore d’AEM nécessite la clé privée au format DER.

    code language-shell
    openssl pkcs8 -topk8 -inform PEM -outform DER -in client-key.pem -out client-key.der -nocrypt
    
TIP
Les certificats auto-signés de l’autorité de certification sont utilisés à des fins de développement uniquement. Pour la production, utilisez une autorité de certification approuvée pour émettre le certificat.

Échange de certificats

Si vous utilisez une autorité de certification auto-signée pour le certificat AEM, comme ci-dessus, envoyez le certificat ou le certificat de l’autorité de certification interne au fournisseur d’API.

En outre, si le fournisseur d’API utilise un certificat d’autorité de certification auto-signé, vous recevez le certificat ou le certificat de l’autorité de certification interne du fournisseur d’API.

Import de certificat

Pour importer le certificat AEM, procédez comme suit :

  1. Connectez-vous à l’instance de création AEM en tant qu’administrateur ou administratrice.

  2. Accédez à Instance de création AEM > Outils > Sécurité > Utilisateurs > Créer ou sélectionner un utilisateur existant.

    Création ou sélection d’un utilisateur existant ou d’une utilisatrice existante.

    À des fins de démonstration, une nouvelle personne nommée mtl-demo-user est créée.

  3. Pour ouvrir les Propriétés, cliquez sur le nom.

  4. Cliquez sur l’onglet KeyStore, puis cliquez sur le bouton Créer un KeyStore. Ensuite, dans la boîte de dialogue Définir le mot de passe d’accès au KeyStore, définissez un mot de passe pour le KeyStore de cette personne, puis cliquez sur Enregistrer.

    Créer le KeyStore

  5. Dans le nouvel écran, sous la section Ajouter une clé privée à partir du fichier DER, procédez comme suit :

    1. Saisissez l’alias.

    2. Importez la clé privée AEM au format DER, générée ci-dessus.

    3. Importez les fichiers de chaîne de certificats, générés ci-dessus.

    4. Cliquez sur Envoyer

      Import d’une clé privée AEM.

  6. Vérifiez que le certificat a bien été importé.

    Clé privée AEM et certificat importé.

Si le fournisseur d’API utilise un certificat d’autorité de certification auto-signé, importez le certificat reçu dans le TrustStore d’AEM, et suivez les étapes ici.

De même, si AEM utilise un certificat auto-signé de l’autorité de certification, demandez au fournisseur d’API de l’importer.

Prototype du code d’appel de l’API mTLS à l’aide de HttpClient

Mettez à jour le code Java™ comme ci-dessous. Pour utiliser l’annotation @Reference afin d’obtenir le service KeyStoreService d’AEM, le code d’appel doit être un composant/service OSGi ou un modèle Sling (et @OsgiService y est utilisé).

...

// 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;
}

...
  • Injectez le service OSGi com.adobe.granite.keystore.KeyStoreService prêt à l’emploi dans votre composant OSGi.
  • Procurez-vous le KeyStore AEM de la personne à l’aide de KeyStoreService et ResourceResolver. C’est ce que fait la méthode getAEMKeyStore(...).
  • Si le fournisseur d’API utilise un certificat auto-signé d’autorité de certification, obtenez le TrustStore global d’AEM. C’est ce que fait la méthode getAEMTrustStore(...).
  • Créez un objet de SSLContextBuilder, voir les détails de l’API Java™.
  • Chargez le KeyStore AEM de la personne dans SSLContextBuilder à l’aide de la méthode loadKeyMaterial(final KeyStore keystore,final char[] keyPassword).
  • Le mot de passe du KeyStore est le mot de passe qui a été défini lors de la création du KeyStore. Il doit être stocké dans la configuration OSGi. Voir Valeurs de configuration du secret.

Éviter les modifications du KeyStore JVM

Pour appeler efficacement les API mTLS avec des certificats privés, une approche conventionnelle consiste à modifier le KeyStore JVM. Pour ce faire, vous devez importer les certificats privés à l’aide de la commande keytool Java™.

Toutefois, cette méthode n’est pas alignée sur les bonnes pratiques en matière de sécurité et AEM offre une option supérieure grâce à l’utilisation des KeyStores spécifiques à la personne et du TrustStore global et de KeyStoreService.

Package de solution

L’exemple de projet Node.js illustré dans la vidéo peut être téléchargé ici.

Le code du servlet AEM est disponible dans la branche tutorial/web-api-invocation de projet de sites WKND, voir ici.

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