C’est la blague bien connue du développement : Le fameux mot de passe admin en dur dans le code ! Dans cet article, notre expert Alexandre vous donne quelques clés afin de plus jamais faire l’impasse sur les mots de passe dans un contexte de développement grâce à Secret Manager et Azure Key Vault.

L’essor actuel du Machine Learning (apprentissage automatique, branche de l’intelligence artificielle) est en partie dû à la puissance de calcul obtenue au travers du Cloud Computing, représenté en particulier par Microsoft Azure.

Qui n’a jamais laissé traîner un mot de passe ou une chaîne de connexion dans son code ? Que ça soit dans un fichier « appsettings.json », « web.config » ou dans tout autre fichier de configuration, des informations sensibles se retrouvent souvent dans nos systèmes de gestion de version.Lorsque l’on travaille sur du code open source l’oubli d’un mot de passe dans un fichier publié sur un dépôt public (sous GitHub par exemple) peut avoir des conséquences désastreuses. Mais même lorsque travaille sur un dépôt privé d’entreprise, archiver des chaines de connexion sql, des identifiants d’accès à un web service, … est une mauvaise pratique qui peut conduire à de graves problèmes de sécurité. Et ceci encore plus lorsque l’on n’archive pas seulement la configuration de son environnement de développement mais aussi celle des environnements QA, Staging ou Production.Alors que faire pour éviter de laisser des secrets dans son code ?

Secret Manager à la rescousse !

L’idée de l’outil Secret Manager c’est que les secrets utilisés pour le développement d’une application ASP.NET (Core ou classique) ne soient pas stockés dans l’arborescence du projet et donc pas archivés en même temps que votre code.

Pour autant lors de son exécution votre code va aller chercher ces secrets et fonctionnera comme si ceux-ci étaient dans un de vos fichiers de configuration. Rien de magique en réalité, les secrets sont simplement stockés dans un dossier de votre profil utilisateur.

L’outil Secret Manager est depuis quelques temps directement intégré dans Visual Studio. Un petit clic droit sur votre csproj et Visual Studio vous ouvre un fichier secrets.json dans lequel vous allez pouvoir stocker tous vos secrets.Si vous êtes un utilisateur de vscode ou juste un fan de la ligne de commande, vous pouvez manipulez directement vos secrets depuis votre terminal avec la commande « dotnet user-secrets ».


Plus d’infos sur l’outil Secret Manager dans la documentation microsoft.

Et pour vous aider à enlever de votre code toutes vos chaines de connexion, clés d’accès, … Microsoft vous propose un analyseur de code statique « CredScan » dans son extension « Continuous Delivery Tools for Visual Studio « .

Bon c’est plutôt pas mal Secret Manager mais cela ne suffit pas. Même si en l’utilisant les secrets ne risquent plus de se retrouver dans votre répertoire git ou svn, ils sont stockés en clair sur votre poste dans un fichier secrets.json … D’autre part cela implique de communiquer au reste de l’équipe de développement dès que l’on ajoute ou modifie un secret, donc pas vraiment pratique. D’autant plus que cela peut très vite se transformer en envoi de mail avec l’ensemble des secrets lorsqu’un nouveau développeur rejoint l’équipe et là niveau sécurité on repassera.

C’est là qu’interviennent des services de gestion des secrets comme Azure Key Vault.

Présentation d’Azure Key Vault

Pour créer un nouveau Key Vault, rendez-vous dans de votre portail Azure :

 

Une fois le coffre créé, l’écran « Secrets » vous permet d’ajouter/modifier et supprimer des secrets (un écran similaire permet de gérer les clés et certificats).

 

L’écran Access Policies vous permet de configurer les utilisateurs ou applications de votre Azure Active Directory qui peuvent accéder à votre Key Vault et leurs différentes permissions d’accès. Pensez bien à enregistrer votre application dans votre Azure Active Directory au préalable quand vous développez une application qui va accéder à votre Key Vault.

 

Ce sont les principaux écrans qui nous intéressent ici, mais n’hésitez pas à vous balader sur les autres écrans et à aller lire la documentation Microsoft car Azure Key Vault dispose de nombreuses autres fonctionnalités.

Vous pouvez accéder aux secrets contenus dans votre Key Vault de différentes manières : Azure CLI, Azure Powershell, tâche d’Azure Pipelines, API Rest ou un des SDK Azure Key Vault (.NET, Java, Python, Node.js).

Mentionnons quand même le prix du service. La création d’un Azure Key Vault en elle-même ne vous coûtera rien, le service étant facturé au nombre d’opérations (création, mise à jour, récupération d’un secret …) effectués. Par exemple en version Standard, vous payerez 0,026€ toutes les 10 000 opérations sur des secrets donc autant dire que c’est un service qui ne vous coûtera pas très cher. Vous trouverez plus de détails sur les tarifs ici.

Bon rentrons maintenant un peu plus dans le vif du sujet : comment va-t-on pouvoir accéder aux secrets stockés sur Azure Key Vault depuis une application .NET ?

Utilisation d’Azure Key Vault depuis une application ASP.NET Core

Lorsque vous créez une nouveau projet ASP.NET Core 2.2, Visual Studio génère le Program.cs suivant :

La méthode CreateDefaultBuilder apparue en ASP.NET Core 2.2 retourne une instance de WebHostBuilder avec un certain nombre de valeurs préconfigurées par défaut. C’est cette méthode qui s’occupe notamment d’ajouter à la configuration les paires clé/valeur du fichier appsettings.json (et des sous fichiers appsettings.<Environnement>.json) dans lequel on avait l’habitude de mettre les chaines de connexion, les clés d’api, …. bref les secrets. (Pour la petite histoire c’est elle aussi qui ajoute à la configuration les secrets du fichier secrets.json dont on parlait tout à l’heure.)

Lorsque l’on utilise l’Azure Key Vault, les secrets sont stockés dans notre coffre sur Azure donc on doit ajouter le package nuget Microsoft.Extensions.Configuration.AzureKeyVault et quelques lignes pour que le code se connecte à notre Key Vault et ajoute les secrets à la configuration de l’application.

La connexion à l’Azure Key Vault et la récupération des secrets s’effectue à l’aide de la méthode AddAzureKeyVault. Il est nécessaire de lui fournir un « clientId » et un « clientSecret » pour qu’Azure vérifie qu’elle est bien autorisée à récupérer les secrets. « ClientId » et « ClientSecret » sont des informations que l’on obtient lorsque l’on enregistre une nouvelle application dans l’Azure Active Directory, tandis que l’ajout de l’accès de l’application au KeyVault se configure dans l’écran Access Policies dont on parlait précédemment.

Dans le code ci-dessus, ces informations sont récupérées depuis la configuration mais cela ne veut pas dire que l’on met le « clientId » et le « clientSecret » dans le fichier appsettings.json. Ce n’est pas la peine de s’embêter à enfermer tous nos secrets dans un coffre-fort pour ensuite laisser la clé trainer le bureau ! La bonne manière de faire c’est plutôt d’injecter ces informations directement dans le pipeline de release de votre application dans votre usine logicielle (que vous utilisiez Azure Devops, Bitbucket ou autre).

Comme vous pouvez le remarquez, on ne va pas passer de « clientId » et de « clientSecret » à la méthode AddAzureKeyVault lorsque l’on est dans un environnement de développement (c’est-à-dire en local sur notre poste). En fait dans ce cas c’est l’identité de l’utilisateur avec lequel on est connecté dans Visual Studio qui va être utilisée, donc à partir du moment où notre utilisateur est autorisé à accéder à l’Azure Key Vault (section Access Policies de l’Azure Key Vault dans le portail Azure) tout va fonctionner directement.

En local c’est un peu le cas idéal, le cas où l’on n’a pas besoin de secret pour se connecter à l’Azure Key Vault, l’identité de notre utilisateur suffit. Ce qui serait top c’est que l’on n’ait pas besoin non plus de secrets (clientId et clientSecret là en l’occurrence) pour déployer notre application dans un autre environnement (dev, Q/A, production…). Et bien si vous déployez votre application dans Azure c’est possible, et c’est ce que l’on va voir maintenant.

Azure Key Vault pour une application déployée dans Azure

Lorsque votre application est déployée sur Azure sur un App Service par exemple, elle a déjà une identité dans Azure auprès de l’Active Directory. C’est ce qu’on appelle la Managed Identity (anciennement Managed Service Identity), si vous voulez avoir plus d’informations sur le sujet c’est ici. Il faut par contre bien penser à activer le « Managed Service identity » dans les settings de votre App Service lorsque vous voulez l’utiliser.

 

 

Dans notre cas présent ce qui nous intéresse surtout, c’est que l’on n’a pas besoin d’enregistrer notre application dans l’Azure Active Directory, ni de récupérer un « clientid » et un « clientSecret » ; on a juste à lui donner accès à notre Key Vault depuis l’écran Access Policies. Le code devient alors :

En fait lorsqu’on utilise Azure l’ajout d’un Azure Key Vault peut se faire encore plus simplement grâce aux connected services.

Concrètement un petit clic droit sur votre csproj dans Visual Studio, sélectionnez « Overview » puis allez dans Connected Services » dans l’écran qui s’ouvre et vous pouvez ajouter une connexion vers un Key Vault existant ou vers un nouveau Key Vault. C’est juste l’affaire de quelques clics mais si vous voulez la procédure détaillée je vais éviter de recopier la documentation Microsoft qui l’explique déjà très bien sur cette page.

Une fois que service connecté Azure Key Vault, nul besoin d’ajouter de ligne de code dans notre Program.cs, on laisse la configuration du template de base et on peut directement accéder à nos secrets dans l’application. C’est si simple que ça en parait magique ! En réalité lorsque vous ajoutez un Azure Key Vault en tant que connected service, le package Nuget Microsoft.AspNetCore.AzureKeyVault.HostingStartup est ajouté au projet et c’est lui qui se charge de faire le « AddAzureKeyVault ». Le code de ce package utilise 2 variables d’environnements :

  • ASPNETCORE_HOSTINGSTARTUP__KEYVAULT__CONFIGURATIONENABLED : permet d'activer/désactiver la connexion au Key Vault
  • ASPNETCORE_HOSTINGSTARTUP__KEYVAULT__CONFIGURATIONVAULT : url du key vault.

Pour le développement local ces variables sont modifiables dans le fichier launchsettings.json du dossier Properties du projet.

Et voilà on est passé d’un code avec quelques lignes de configuration spécifiques et des identifiants pour se connecter à l’Azure Key Vault, à un code sans aucun secret ni ligne de code supplémentaire ! Par contre jusqu’à présent on a surtout parlé de la gestion des secrets dans notre environnement de développement et pas trop de ce qu’il se passe lorsque l’on veut utiliser Azure Key Vault dans nos différents environnements. Penchons-nous donc un peu sur le sujet.

Déploiement d’une application ASP.NET Core avec Key Vault via Azure DevOps

Il est recommandé d’avoir un Key Vault par environnement. On aura donc une url de key vault différente pour chaque environnement qu’il va falloir injecter lors des déploiements.

Regardons ce que cela donne si on utilise Azure DevOps (anciennement VSTS) pour déployer notre application ASP.NET Core avec Key Vault en connected service.

 

 

Ci-dessus le pipeline de déploiement : on a 1 artifact qui correspond au package généré par la build de l’application et 3 environnements (dev, integ et prod) où l’on va vouloir déployer notre application. On a un Azure App Service dans chacun de nos environnements qu’on a on a bien pris soin d’autoriser sur le Key Vault associé à l’environnement.

Par exemple ici notre Key Vault d’intégration a bien l’App Service d’intégration TestAzureKeyVaultInteg configuré dans ses access policies.

 

 

Notre tâche de déploiement est identique sur chaque environnement si ce n’est le nom de l’App Service sur lequel on veut déployer.

 

 

On injecte les variables d’environnement utilisé par le service connecté Azure Key Vault via la section « Application and configuration settings » de la tâche de déploiement.

Sur l’image, dans les app settings on peut voir « $(ASPNETCORE_HOSTINGSTARTUP__KEYVAULT__CONFIGURATIONENABLED) » et « $(ASPNETCORE_HOSTINGSTARTUP__KEYVAULT__CONFIGURATIONVAULT) » qui font simplement référence à des variables d’environnement définis dans la release avec une valeur différente par environnement.

 

 

On a donc une application qui est déployée dans plusieurs environnements et qui s’exécute sans aucun secret dans le code, ni même dans Azure DevOps. Grâce à Azure Key Vault, tous les secrets sont stockés de manière sécurisée avec une historisation de leurs valeurs, une gestion des permissions et un monitoring des accès aux secrets.

 

A noter
Si l’on n’avait pas utilisé les Managed Identities (si l’application n’était pas hébergée dans Azure par exemple), on aurait pu stocker au niveau des variables d’environnement de la release les clientId et clientSecret des différents environnements à injecter lors des déploiements.

Conclusion

J’ai surtout parlé de l’utilisation d’Azure Key Vault pour des applications .NET et dans un environnement Azure mais bien évidemment vous pouvez utiliser Azure Key Vault pour des applications écrites avec d’autres technos et déployées en dehors d’Azure. D’autre part même si Azure Key Vault présente de nombreuses avantages, libre à vous d’utiliser un autre service, l’essentiel étant d’opter pour une gestion sécurisée de vos secrets et de ne plus les mettre dans votre code source.

alexandre_nedelec

Passionné par le développement applicatif, Alexandre est un expert confirmé de .NET et de la plateforme Azure. Bien que le C# soit son langage de prédilection, il apprécie tout particulièrement de s’aventurer dans la découverte de nouveaux langages.

Son crédo ? Continuer d’apprendre tout en partageant ses connaissances avec ses pairs !

Envie d'en savoir plus ?

Retrouvez l’ensemble de nos actualités AZEO par ici !