BLOG | NGINX

Protection des clés privées SSL dans NGINX avec HashiCorp Vault

NGINX-Partie-de-F5-horiz-black-type-RGB
Vignette d'Owen Garrett
Owen Garrett
Publié le 16 avril 2019

Dans le premier article de cette série , nous décrivons plusieurs approches pour améliorer la sécurité de vos clés privées SSL. L'article s'est terminé par une démonstration d'un point de distribution de mot de passe à distance (PDP) utilisé pour partager en toute sécurité des mots de passe de cryptage avec les instances NGINX.

Les systèmes de gestion des secrets comme HashiCorp Vault fonctionnent de manière similaire à cet exemple de PDP :

  • Ils utilisent un service de secrets central (ou hautement disponible et distribué) accessible via HTTPS ou une autre API
  • Les clients sont authentifiés par des jetons d'authentification ou d'autres moyens
  • Les jetons peuvent être révoqués si nécessaire pour contrôler l'accès au secret

Dans cet article, nous montrons comment configurer HashiCorp Vault pour distribuer des mots de passe SSL. Pour encore plus de sécurité, vous pouvez configurer un module de sécurité matériel externe (HSM).

Pour éliminer complètement le stockage sur disque des paires certificat-clé SSL, consultez le troisième article de cette série, Utilisation du magasin de clés-valeurs NGINX Plus pour sécuriser les clés SSL éphémères du coffre-fort HashiCorp . Il explique comment générer des clés SSL éphémères à partir de HashiCorp Vault et les stocker en mémoire dans le magasin de clés-valeurs NGINX Plus.

Cet article s'applique à la fois à NGINX Open Source et à NGINX Plus. Pour faciliter la lecture, nous ferons référence à NGINX tout au long du document.

Utilisation de HashiCorp Vault pour protéger les clés privées SSL

Les instructions de cette section configurent un serveur PDP central utilisant Vault pour distribuer les mots de passe SSL. Ils sont basés sur les instructions de DigitalOcean ; modifiez-les si nécessaire pour les conformer à vos propres politiques Vault.

Dans notre exemple, chaque serveur Web distant dispose d’un jeton d’authentification unique. Ces jetons peuvent être utilisés pour accéder aux secrets dans le chemin secret/webservers/ de Vault, et nous stockons les mots de passe SSL dans secret/webservers/ssl_passwords .

Nous verrons comment sécuriser les jetons et comment révoquer les jetons d’authentification individuels si nécessaire.

Téléchargez, installez et initialisez HashiCorp Vault sur le serveur PDP

  1. Suivez les instructions de DigitalOcean pour télécharger et extraire Vault sur votre serveur PDP. Nous utilisons l'exemple de fichier /etc/vault.hcl suivant pour rendre Vault accessible à distance et pour désactiver TLS (pour faciliter l'utilisation lors des tests) :

    backend "fichier" { chemin = "/var/lib/vault"
    }
    
    écouteur "tcp" {
    adresse = "0.0.0.0:8200"
    tls_disable = 1
    }
    
  2. Démarrez Vault à l'aide des scripts de démarrage (si vous les avez créés) ou manuellement :

    utilisateur@pdp:~$ sudo /usr/local/bin/vault server -config=/etc/vault.hcl
    
  3. Initialisez Vault et obtenez le jeton racine initial :

    utilisateur@pdp:~$ export VAULT_ADDR=http://localhost:8200 utilisateur@pdp:~$ vault init -key-shares=3 -key-threshold=2 utilisateur@pdp:~$ opérateur de coffre-fort descellement du jeton racine initial : 86c5c2a4-8ab2-24dd-1816-48449c83114e
    
  4. Nous devons fournir le jeton racine initial dans la plupart des commandes suivantes. Pour plus de commodité, nous l'affectons à la variable shell root_token :

    utilisateur@pdp:~$ root_token=86c5c2a4-8ab2-24dd-1816-48449c83114e
    

Conservez les secrets

  1. Toujours en travaillant sur le serveur PDP, créez un fichier temporaire appelé /tmp/ssl_passwords.txt avec les mots de passe qu'il contient.

  2. Stockez ce fichier en tant que secret dans Vault et vérifiez que vous pouvez le récupérer :

    utilisateur@pdp:~$ VAULT_TOKEN=$root_token vault kv put secret/webservers/ssl_passwords value=@/tmp/ssl_passwords.txt utilisateur@pdp:~$ VAULT_TOKEN=$root_token vault kv get -field=value secret/webservers/ssl_passwords mot de passe1 mot de passe2 ...
    
  3. Pour des raisons de sécurité, supprimez /tmp/ssl_passwords.txt .

  4. Créez une spécification de politique dans un fichier appelé web.hcl avec le contenu suivant :

    chemin "secret/webservers/*" {
    capacités = ["lecture"]
    }
    
  5. Chargez la politique dans Vault, en la nommant web :

    utilisateur@pdp:~$ VAULT_TOKEN=$root_token politique de coffre-fort écriture web web.hcl
    
  6. Créez un nouveau jeton d’authentification, associez-le à la politique Web et incluez éventuellement le paramètre display-name pour lui donner un nom convivial. Notez les valeurs de token et de token_accessor ; vous les utiliserez dans les commandes suivantes :

    utilisateur@pdp:~$ VAULT_TOKEN=$root_token vault token create -policy=web -display-name=webserver1 Valeur clé --- ----- token dcf75ffd-a245-860f-6960-dc9e834d3385 token_accessor 0c1d6181-7adf-7b42-27be-b70cfa264048
    

    Le serveur Web NGINX utilise ce jeton pour récupérer les mots de passe SSL. La politique Web empêche le serveur Web de récupérer des secrets en dehors du chemin secret/webservers/* .

Vérifiez que le serveur Web peut récupérer le jeton

  1. En travaillant sur le serveur Web NGINX, installez le binaire Vault.
  2. Déclarez l'emplacement du serveur Vault distant (ici, http://pdp:8200 ), puis vérifiez que la machine du serveur Web peut récupérer les mots de passe SSL à l'aide du jeton :

    utilisateur@web1:~$ export VAULT_ADDR=http://pdp:8200 utilisateur@web1:~$ VAULT_TOKEN=dcf75ffd-a245-860f-6960-dc9e834d3385 vault kv get -field=value secret/webservers/ssl_passwords mot de passe1 mot de passe2 ...
    

Configurer le connecteur NGINX Vault sur le serveur Web

  1. Dans le cadre de la configuration de l’exemple PDP dans le premier article , nous avons créé un script shell appelé connector.sh sur l’hôte NGINX (machine serveur Web). Ici, nous le modifions pour utiliser Vault :

    #!/bin/sh
    # Utilisation : connector_v.sh 
    
    CONNECTOR=$1
    CREDS=$2
    
    [ -e $CONNECTOR ] && /bin/rm -f $CONNECTOR
    
    mkfifo $CONNECTOR ; chmod 600 $CONNECTOR
    
    export VAULT_ADDR=http://pdp:8200
    export VAULT_TOKEN=$CREDS
    
    while true ; do
    vault kv get -field=value secret/webservers/ssl_passwords > $CONNECTOR
    sleep 0.1 # condition de concurrence, assure la fin du fichier
    done
    
  2. Exécutez le script en tant que processus d’arrière-plan, appelé comme suit :

    root@web1:~# ./connector_v.sh /var/run/nginx/ssl_passwords \dcf75ffd-a245-860f-6960-dc9e834d3385 &
    
  3. Testez le connecteur en lisant le chemin du connecteur :

    root@web1:~$ cat /var/run/nginx/ssl_passwords mot de passe1 mot de passe2 ...
    
  4. Configurez NGINX pour lire le fichier ssl_passwords au démarrage et pour utiliser le contenu comme mots de passe pour décrypter les clés privées cryptées. Vous pouvez inclure la directive ssl_password_file soit dans un bloc serveur (comme celui créé pour la configuration standard dans le premier article) soit dans le contexte http pour l'appliquer à plusieurs serveurs virtuels :

    fichier_mot_de_passe_ssl /var/run/nginx/ssl_passwords;
    
  5. Vérifiez que NGINX peut lire le mot de passe et décrypter les clés SSL :

    root@web1:~# nginx -t nginx : la syntaxe du fichier de configuration /etc/nginx/nginx.conf est correcte nginx : le test du fichier de configuration /etc/nginx/nginx.conf est réussi
    

Révoquer le jeton d’authentification d’un serveur Web

Vous pouvez facilement révoquer l’accès si le serveur Web est compromis ou lorsqu’il est mis hors service. Pour ce faire, vous pouvez directement révoquer le jeton d’authentification utilisé par le serveur Web :

utilisateur@pdp:~$ VAULT_TOKEN=$root_token jeton de coffre-fort révocation dcf75ffd-a245-860f-6960-dc9e834d3385

Les jetons Vault sont des éléments de données sensibles et de nombreux workflows Vault ne stockent pas de copies des jetons émis à un client authentifié. Si une copie d’un jeton est divulguée, un attaquant peut se faire passer pour le client.

Au lieu de cela, il est courant de gérer un jeton actif à l'aide de son accesseur , qui donne des droits limités sur le jeton et ne peut pas être utilisé pour récupérer la valeur du jeton. Plutôt que de stocker les jetons lorsqu’ils sont émis, stockez leur accesseur correspondant.

Si vous devez déterminer l'accesseur pour le jeton d'authentification d'un serveur Web, exécutez la commande vault list pour récupérer la liste des accesseurs, et la commande vault token lookup sur chaque accesseur pour trouver celui avec le nom d'affichage et la politique appropriés :

utilisateur@pdp:~$ VAULT_TOKEN=$root_token vault token lookup -accessor 0c1d6181-7adf-7b42-27be-b70cfa264048 Clé Valeur --- ----- ... nom-d'affichage webserver1 ... politique web ...

Vous pouvez ensuite révoquer le jeton en utilisant son accesseur :

utilisateur@pdp:~$ VAULT_TOKEN=$root_token révocation du jeton de coffre-fort -accesseur 0c1d6181-7adf-7b42-27be-b70cfa264048

Conséquences en matière de sécurité

L’utilisation de Vault présente un profil de sécurité similaire à celui de l’exemple PDP décrit dans le premier article . Les clés privées SSL ne peuvent être obtenues que si le mot de passe correspondant est obtenu, et pour cela, un attaquant doit connaître la valeur d'un jeton d'authentification actuel.

Le principal avantage de l’utilisation de Vault est d’automatiser et de faire évoluer le magasin de secrets.

Utilisation d'un HSM externe pour gérer les clés privées

Aucune des solutions que nous avons abordées jusqu’à présent dans la série ne protège la clé privée lorsqu’un attaquant obtient un accès root au serveur NGINX. Si un attaquant peut accéder à la mémoire d'exécution de NGINX ou générer un vidage de mémoire, il existe des techniques bien connues pour analyser la mémoire du processus et localiser les données de clé privée.

Les modules de sécurité matérielle externes (HSM) résolvent ce problème en stockant les clés privées SSL dans du matériel externe inviolable. Ils proposent le décryptage en tant que service, et NGINX accède à ce service chaque fois qu'il doit effectuer une opération SSL qui nécessite le kay.

Le serveur NGINX ne voit jamais les données de la clé privée SSL. Un attaquant qui obtient un accès root sur le serveur ne peut pas obtenir la clé privée SSL, mais peut déchiffrer les données à la demande en accédant au service de déchiffrement HSM à l'aide des informations d'identification NGINX.

Configuration de NGINX pour accéder à un HSM

NGINX délègue toutes les opérations de clés privées SSL à une bibliothèque cryptographique appelée OpenSSL. Les périphériques HSM tiers peuvent être mis à disposition de NGINX à l’aide du moteur OpenSSL du fournisseur HSM.

La configuration NGINX est spécifique à chaque HSM de fournisseur, mais suit généralement un chemin simple :

  • Configurez NGINX pour utiliser le moteur OpenSSL du fournisseur plutôt que le moteur logiciel par défaut :

    moteur de clé de certificat ssl : vendor-hsm-engine : ... ;
    
  • Au lieu d’utiliser la véritable clé privée, configurez NGINX pour utiliser la « fausse » clé fournie par le fournisseur. Cette clé contient un handle qui identifie la vraie clé sur le périphérique HSM :

    clé_certificat_ssl clé.privée.ssl/vendor;
    

    La clé peut également contenir les informations d’identification permettant d’accéder au périphérique HSM, ou les informations d’identification peuvent être fournies à l’aide d’une configuration supplémentaire spécifique au fournisseur.

  • (Facultatif) Appliquez les réglages souhaités, comme l’augmentation du nombre de processus de travail NGINX, pour optimiser les performances de NGINX et du HSM.

Pour un exemple de configuration HSM, reportez-vous à la documentation CloudHSM d'Amazon .

Conséquences en matière de sécurité

Les HSM externes sont une méthode hautement sécurisée de stockage des clés privées SSL. Un attaquant disposant d’un accès root au serveur NGINX est en mesure d’exploiter les informations d’identification NGINX pour décrypter des données arbitraires à l’aide du HSM, mais n’est pas en mesure d’obtenir la clé privée non chiffrée. Un HSM rend beaucoup plus difficile pour un attaquant d’usurper l’identité d’un site Web ou de décrypter des données arbitraires hors ligne.

Conclusion

Il est essentiel de garantir que les données secrètes telles que la clé privée SSL soient entièrement protégées, car les conséquences de leur divulgation sont très graves.

Pour de nombreuses organisations disposant de processus de sécurité appropriés, il suffit de stocker la clé privée sur les équilibreurs de charge frontaux, puis de limiter et d'auditer tous les accès à ces serveurs (la configuration standard décrite dans le premier article).

Pour les organisations qui doivent déployer fréquemment la configuration NGINX, les mesures décrites dans cet article et dans le premier peuvent être utilisées pour limiter les utilisateurs ou les entités qui peuvent voir les données de la clé privée.

Dans le troisième article de cette série, Utilisation du magasin de clés-valeurs NGINX Plus pour sécuriser les clés SSL éphémères de HashiCorp Vault , nous expliquons comment automatiser l'approvisionnement des clés et des certificats de Vault vers le magasin de clés-valeurs de NGINX Plus, à l'aide de l' API NGINX Plus .

Notez à nouveau qu’aucune de ces méthodes ne réduit la nécessité de sécuriser entièrement les instances NGINX en cours d’exécution contre l’accès à distance ou la manipulation de la configuration.

Essayez NGINX Plus par vous-même – démarrez votre essai gratuit de 30 jours dès aujourd’hui ou contactez-nous pour discuter de vos cas d’utilisation .


« Cet article de blog peut faire référence à des produits qui ne sont plus disponibles et/ou qui ne sont plus pris en charge. Pour obtenir les informations les plus récentes sur les produits et solutions F5 NGINX disponibles, explorez notre famille de produits NGINX . NGINX fait désormais partie de F5. Tous les liens NGINX.com précédents redirigeront vers un contenu NGINX similaire sur F5.com."