Powershell DSC: Chiffrer les mots de passe dans les configurations

 

Cet article est la suite de Powershell DSC: Installation d’un serveur Pull 1/2 et Powershell DSC: Installation d’un serveur Pull avec HTTPS 2/2.

Comment ça marche

Lors de la création de configurations MOF, il est parfois nécessaire de fournir des credentials, c’est à dire des mots de passe et noms d’utilisateurs et de les stocker dans les fichiers MOF.

Ceci est du au fait que le LCM sur le serveur cible s’exécute en tant que SYSTEM, ce qui veut dire que pour certaines opérations (Active Directory par exemple), il n’en a pas les droits.

 

Cet article explique comment le faire de façon sécurisée afin que le mot de passe ne soit pas stocké en clair, et pire, transmis en clair sur le réseau.

Comme illustré dans l’image suivante, le processus est assez simple. Le serveur PULL chiffre le mot de passe avec la clé publique du serveur cible, qui sera le seul à pouvoir la déchiffrer.

Idéalement, chaque serveur cible doit avoir son propre certificat. Idéalement on utilise également les Group Policy Objects (GPO) pour déployer ces certificats. Et idéalement on utilise la clé publique de chaque serveur pour chiffrer les données.

Attention: Dans cet article je n’utilise qu’une seule clé privée que j’installe sur chaque serveur cible. Un scénario idéal serait d’avoir un certificat par machine cible et gérer les clé publiques ainsi que les thumbprints de chaque machine dans le script de génération de configurations.

Dans l’illustration suivante, on voit le étapes nécessaires pour que les fichiers MOFs soient sécurisés, et ensuite transmis au serveur cible pour être déchiffrés et appliqués.

process

 

  1. Sécurisation des configurations MOF avec la clé publique du serveur cible (qui pour notre exemple est unique)
  2. Installation du certificat avec clé privée sur le serveur cible. Notre exemple fera ceci automatiquement.
  3. Gestion des fichiers MOF avec génération des checksum, et déploiement  via l’approche Pull sur le serveur cible
  4. Le Local Configuration Manager (LCM) détecte la nouvelle configuration, il est lui même configuré avec le thumbprint pour savoir avec quel certificat il peut déchiffrer les fichiers MOF.
  5. Le LCM déchiffre les fichiers reçus, et les applique.

Exporter la clé privée et publiques

Il y a plusieurs façons de créer de certificats, et plusieurs façons d’en exporter les clés privées (si possible) et clés publiques.

Dans cet exemple j’utilise le MMC des certificats de la local machine car c’est visuellement plus parlant. Puis cette opération ne doit être faite qu’une seule fois pour tester le chiffrement des fichiers MOFs décrits dans cet article.

Je reviens encore une fois sur la création du certificat, bien s’assurer qu’il s’agit d’une variante de la template « Computer » modifié pour avoir la possibilité d’exporter la clé privée.

Le certificat a été créé pour le serveur PULL et je fais ces opérations à partir de là.

certexport

Première étable, qui est l’export de la clé privée.

yesexport

Ensuite je renseigne un mot de passe pour accéder au fichier PFX créé. Avec une approche de déploiement des certificats via GPOs je choisirais plutôt de sélectionner un groupe.

certpass

Sélection du nom du fichier, à noter que je place tout dans C:\DSC.

certsaveprivate

Ensuite on fait la même chose pour le fichier CER, qui contiendra la clé publique.

noprivate

Sélection du format.

derencoded

Et on renseigne le nom du fichier.

publickey

 

La partie facile est finie. Passons à plus compliqué.

Séparation des données de configuration et des environnements cible

Powershell DSC permet de séparer les informations relative à la configuration propre d’un composant et l’environnement cible sur laquelle elle sera appliquée.

Ceci veut dire qu’on peut définir la configuration pour un serveur d’un type donné, disons SQL ou IIS, en séparant quels serveurs auront cette configuration.

Ceci me permet de créer une norme d’un coté, et les serveurs cible de cette norme de l’autre.

Voici un lien avec plus d’infos: DSC Configuration Data

Plus concrètement, nous on va s’en servir pour définir la configuration de notre serveur d’un point de vue composants d’un coté, et les données relatives au serveur cible, tels que le certificat à utiliser pour chiffrer le fichier MOF et le thumbprint pour le déchiffrer, de l’autre.

Voici un exemple de bloc de config data:

Il s’agit en fait d’un hash table qui contient une clé, Allnodes, qui est lui même un array de hash tables. Un noeud (node) étant une machine cible.

On peut avoir un noeud générique appelé « * » (attention ce n’est pas un wildcard, on ne peut pas faire *PAR* pour avoir tous les noeuds de Paris).

On peut aussi avoir un noeud par machine cible. Dans l’exemple plus bas, nous allons utiliser le GUID pour référencer la machine au lieu de son nom. Le GUID est utilisé dans notre exemple pour identifier de façon unique une configuration et est assigné de façon unique à une machine, donc pour nous le GUID est la cible.

Attention : le bloc de code $ConfigData, est très sensible, et très obtus, il ne comprend que des [String]. Si vous remplacez un élément de la table avec une variable, assurez-vous que cette variable est de format String, sinon elle sera ignorée. Par exemple si on crée une variable $GUID qui contient le résultat de [guid]::NewGuid(), ce n’est pas une string. Powershell pardonne beaucoup et si on l’affiche, ça s’affichera comme une string, mais le bloc $ConfigData de DSC ne pardonne rien.

Il faut soit faire:

ou alors

voire

et ensuite on peut ajouter nos variables ainsi:

On pourra ensuite appeler notre « fonction » de configuration DSC avec le paramètre -ConfigurationData $ConfigData pour qu’il soit pris en compte.

 

Regardons maintenant la « fonction » de configuration DSC:

La fonction prend en paramètre le GUID assigné à la configuration d’un serveur donné, et les credentials nécessaires à effectuer la copie de fichiers.

On remarque le bloc $AllNodes.Nodename, ceci utilisera le bloc $ConfigData dans lequel nous avons renseigné le nom en format GUID à utiliser. Ce sera l’ID de la configuration MOF.

Ensuite on voit un bloc LocalConfigurationManager dans lequel on voit l’élément CertificateId qui contient le thumprint renseigné dans $ConfigData. Cet élément est essentiel, car il permet au LCM de dechiffrer le fichier MOF.

Et finalement on voit le bloc de ressource File, appelé CopyFile qui définit les éléments suivants:

  • Ensure = « Present », on veut s’assurer que le ou les fichiers suivants, sont présents sur la machine cible.
  • L’opération est de type Directory, ou répertoire.
  • L’opération est récursive, donc si le répertoire renseigné contient plusieurs répertoires ils seront pris en compte.
  • Les paths source et destination
  • Les credentials à utiliser, c’est à dire que dans le MOF il y aura séparément le username et le mot de passe à utiliser.

Génération des configurations MOF

La cmdlet qui suit (New-ServerConfigurations) génère les fichiers MOF en prenant en compte un bloc $ConfigData et ensuite génère également les fichiers checksum (qui servent à s’assurer que les fichiers MOF n’ont pas été altérés). Et finalement copie tous ces fichiers au bon endroits, pour que le processus DSC puisse les prendre en compte et les déployer.

La cmdlet peut soit, forcer (paramètre -Force) la génération des configurations pour tous les serveurs dans la liste, ou vérifier si des configurations existent déjà, auquel cas, elle ne s’applique qu’aux serveurs qui n’ont pas de configuration.

A noter que la cmdlet retourne un array contenant toutes les configurations à appliquer. Cet array sera l’input de la cmdlet suivante qui déploie les configurations.

 

Voici à quoi ressemble le fichier MOF généré:

On voit bien le mot de passe chiffré dans la référence $MSFT_Credential1ref.

Déploiement des configurations

La cmdlet suivante, Export-ServerConfigurations fait plusieurs choses:

  • Vérifie que le certificat se trouve bien dans le store cert:\LocalMachine\My de la machine cible, et le cas échéant la copie et l’installe.
  • Utilise Invoke-Command sur les machines cible pour reconfigurer le GUID de la configuration à récupérer et appliquer.

 

Voici comment j’invoque les deux cmdlets:

Concernant le mot de passe stocké dans un fichier, voici une petite cmdlet qui permet de le faire:

 

Le tout réuni

Voici le script en entier, il définit les paramètres de script et permet d’avoir une vision globale sur l’approche utilisée:

 

Après exécution du script on peut vérifier avec le serveur de conformité, et voici le résultat:

compliant

 

Tout est conforme sur les deux machines cible que j’ai utilisé pour cet article.

Au fait, voyons si le fichier en question s’est bien copié sur le serveur cible:

magique

Magique!

octocatToutes les sources sont dans ce repository Github