Chiffrement du fichier de configuration

Contexte


J'ai eu la tâche de configurer CI. Il a été décidé d'utiliser la transformation des fichiers de configuration et de stocker les données confidentielles sous forme cryptée. Vous pouvez les chiffrer et les déchiffrer à l'aide du conteneur de clés.

Conteneur à clés


Chaque système d'exploitation Windows possède des ensembles de clés générées. La clé est générée soit sur le compte, soit sur la machine. Les clés générées par la machine peuvent être affichées le long de ce chemin C: \ ProgramData \ Microsoft \ Crypto \ RSA \ MachineKeys. C'est là que la clé que nous allons créer ensuite ira.

Création de clé


Nous démarrons cmd depuis l'administrateur et basculons vers le répertoire avec aspnet_regiis, je l'ai C: \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319

Exécutez la commande

aspnet_regiis -pc "TestKey" -exp 

exp - est ajouté afin que vous puissiez exporter la clé à l'avenir
TestKey - le nom de notre conteneur de clés

Exportation de clé


L'équipe

 aspnet_regiis -px "TestKey" :\TestKey.xml -pri 

TestKey - nom Key Container
C: \ TestKey.xml - le chemin où le fichier sera exporté
pri - ajouter une clé privée à exporter

Clé d'importation


L'équipe

 aspnet_regiis -pi "TestKey" :\TestKey.xml 

TestKey - nom Key Container
C: \ TestKey.xml - le chemin à partir duquel le fichier sera exporté

Définition des droits


Pour que votre application ou IIS fonctionne avec le conteneur de clés, vous devez configurer les droits pour celui-ci.

Cela se fait par l'équipe

 aspnet_regiis -pa "TestKey" "NT AUTHORITY\NETWORK SERVICE" 

TestKey - nom Key Container
AUTORITÉ NT \ SERVICE RÉSEAU - qui aura accès à la clé

Par défaut, IIS a ApplicationPoolIdentity pour le pool.

La documentation Microsoft (voir lien 2) décrit ApplicationPoolIdentity comme suit:

  • ApplicationPoolIdentity : lorsqu'un nouveau pool d'applications est créé, IIS crĂ©e un compte virtuel qui porte le nom du nouveau pool d'applications et qui exĂ©cute le processus de travail du pool d'applications sous ce compte. Il s'agit Ă©galement d'un compte le moins privilĂ©giĂ©.

Par conséquent, pour qu'IIS puisse déchiffrer la configuration, l'identité doit être configurée dans le pool pour le compte, ou vous pouvez sélectionner "SERVICE RÉSEAU" et lui donner des droits.

Ajout d'une section Ă  la configuration


 <configProtectedData defaultProvider="RsaProtectedConfigurationProvider"> <providers> <add name="CustomRsaProtectedConfigurationProvider" type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" description="Uses RsaCryptoServiceProvider to encrypt and decrypt" keyContainerName="TestKey" cspProviderName="" useMachineContainer="true" useOAEP="false"/> </providers> </configProtectedData> 

Le conteneur de clés et RsaProtectedConfigurationProvider sont également définis globalement dans les fichiers

C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ Config \ machine.config, C: \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319 \ Config \ machine.config

 <configProtectedData defaultProvider="RsaProtectedConfigurationProvider"> <providers> <add name="RsaProtectedConfigurationProvider" type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" description="Uses RsaCryptoServiceProvider to encrypt and decrypt" keyContainerName="NetFrameworkConfigurationKey" cspProviderName="" useMachineContainer="true" useOAEP="false"/> <add name="DataProtectionConfigurationProvider" type="System.Configuration.DpapiProtectedConfigurationProvider,System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" description="Uses CryptProtectData and CryptUnProtectData Windows APIs to encrypt and decrypt" useMachineProtection="true" keyEntropy=""/> </providers> </configProtectedData> = "System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b03f5f7f11d50a3a" Description = "Utilise RSACryptoServiceProvider pour crypter et décrypter" keyContainerName = "NetFrameworkConfigurationKey" cspProviderName <configProtectedData defaultProvider="RsaProtectedConfigurationProvider"> <providers> <add name="RsaProtectedConfigurationProvider" type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" description="Uses RsaCryptoServiceProvider to encrypt and decrypt" keyContainerName="NetFrameworkConfigurationKey" cspProviderName="" useMachineContainer="true" useOAEP="false"/> <add name="DataProtectionConfigurationProvider" type="System.Configuration.DpapiProtectedConfigurationProvider,System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" description="Uses CryptProtectData and CryptUnProtectData Windows APIs to encrypt and decrypt" useMachineProtection="true" keyEntropy=""/> </providers> </configProtectedData> 

Cryptage


Le cryptage lui-même peut être effectué de trois manières.

Chiffrement de la ligne de commande


 aspnet_regiis.exe -pef connectionStrings :\Site -prov "CustomRsaProtectedConfigurationProvider" 

C: \ Site - chemin d'accès au fichier avec la configuration.

CustomRsaProtectedConfigurationProvider - notre fournisseur spécifié dans la configuration appelée conteneur de clés.

Cryptage via une application écrite


 private static string provider = "CustomRsaProtectedConfigurationProvider"; public static void ProtectConfiguration() { Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); ConfigurationSection connStrings = config.ConnectionStrings; if (connStrings != null && !connStrings.SectionInformation.IsProtected && !connStrings.ElementInformation.IsLocked) { connStrings.SectionInformation.ProtectSection(provider); connStrings.SectionInformation.ForceSave = true; config.Save(ConfigurationSaveMode.Full); } } public static void UnProtectConfiguration(string path) { Configuration config = ConfigurationManager.OpenExeConfiguration(path); ConfigurationSection connStrings = config.ConnectionStrings; if (connStrings != null && connStrings.SectionInformation.IsProtected && !connStrings.ElementInformation.IsLocked) { connStrings.SectionInformation.UnprotectSection(); } } 

Vélo


Lorsqu'il y a une transformation de fichier et que vous devez crypter des sections séparément de la configuration entière, alors seule une version auto-écrite convient. Nous créons une instance de la classe RsaProtectedConfigurationProvider, prenons un nœud de XML et le chiffrons séparément, puis remplaçons le nœud dans notre XML d'origine par notre chiffré et enregistrons le résultat.

 public void Protect(string filePath, string sectionName = null) { XmlDocument xmlDocument = new XmlDocument { PreserveWhitespace = true }; xmlDocument.Load(filePath); if (xmlDocument.DocumentElement == null) { throw new InvalidXmlException($"Invalid Xml document"); } sectionName = !string.IsNullOrEmpty(sectionName) ? sectionName : xmlDocument.DocumentElement.Name; var xmlElement = xmlDocument.GetElementsByTagName(sectionName)[0] as XmlElement; var config = new NameValueCollection { { "keyContainerName", _settings.KeyContainerName }, { "useMachineContainer", _settings.UseMachineContainer ? "true" : "false" } }; var rsaProvider = new RsaProtectedConfigurationProvider(); rsaProvider.Initialize(_encryptionProviderSettings.ProviderName, config); var encryptedData = rsaProvider.Encrypt(xmlElement); encryptedData = xmlDocument.ImportNode(encryptedData, true); var createdXmlElement = xmlDocument.CreateElement(sectionName); var xmlAttribute = xmlDocument.CreateAttribute("configProtectionProvider"); xmlAttribute.Value = _encryptionProviderSettings.ProviderName; createdXmlElement.Attributes.Append(xmlAttribute); createdXmlElement.AppendChild(encryptedData); if (createdXmlElement.ParentNode == null || createdXmlElement.ParentNode.NodeType == XmlNodeType.Document || xmlDocument.DocumentElement == null) { XmlDocument docNew = new XmlDocument { InnerXml = createdXmlElement.OuterXml }; docNew.Save(filePath); } else { xmlDocument.DocumentElement.ReplaceChild(createdXmlElement, xmlElement); xmlDocument.Save(filePath); } } 

Les références


1.docs.microsoft.com/en-us/previous-versions/53tyfkaw
2.support.microsoft.com/en-za/help/4466942/understanding-identities-in-iis

Source: https://habr.com/ru/post/fr462379/


All Articles