2016-09-30 2 views
0

Nous avons un certain nombre d'applications et de services qui doivent partager un fichier de configuration d'application externe. Le fichier externe contient une configSection avec des informations que nous chiffrons. Chaque service et application réside dans son propre dossier d'application, et c'est là que les problèmes commencent à s'aggraver. Dans App.config, les fichiers externes peuvent être référencés avec l'attribut 'configSource' ou 'file'. 'ConfigSource' ne peut pas être utilisé car le fichier de configuration externe ne réside pas dans le dossier de l'application ou dans les sous-dossiers de l'application. Threrefore nous devons utiliser l'attribut 'file'.Configuration externe de l'application et cryptage des paramètres

<customSettings file=”path to setting”/> 

Le 'CustomSettings' configSection a été défini comme suit:

<configSections> 
    <section name="customSettings" type="System.Configuration.NameValueFileSectionHandler, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> 
</configSections> 

Je puis essayer de chiffrer le configSection en utilisant le code comme ceci:

Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 
ConfigurationSection section = config.GetSection("customSettings"); 

if (!section.SectionInformation.IsProtected) 
{ 
    section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider"); 
    config.Save(); 
} 

Parce que je suis en utilisant l'attribut de fichier (je suspecte). La section config est chiffrée dans App.config et le fichier externe ne l'est pas. Ce qui est chiffré dans App.config est juste

<customSettings file=”path to setting”/> 

. Ce qui est plutôt inutile.

Cela signifie que les applications et services individuels ne peuvent pas crypter le fichier de configuration externe. J'ai alors eu l'idée de placer une petite application résidant dans le même répertoire que le fichier de configuration externe. Le but de cette application était de chiffrer le fichier de configuration externe en utilisant l'attribut 'configSource' à la place. Cette approche ne fonctionne pas du tout. Rien ne se passe, et rien n'est chiffré.

Pour examiner un peu plus loin, j'ai placé le 'customSettings' dans le App.config et crypté la section avec succès. J'ai ensuite copié les données cryptées dans le fichier externe pour tester si le cryptage pourrait fonctionner dans le fichier de configuration externe. Cela fonctionne très bien avec le 'configSource' mais déclenche une exception lors de l'utilisation de l'attribut 'file'.

Exception lancée:

Unrecognized attribute 'configProtectionProvider' 

Puisque nous devons utiliser l'attribut « fichier » dans le app.config j'ai maintenant 2 problèmes.

  1. Impossible de crypter le fichier externe.
  2. Si le fichier externe est chiffré manuellement, je ne peux pas le lire en utilisant l'attribut 'fichier'.
+0

J'ai résolu le premier problème que j'avais. Il s'est avéré que j'avais besoin d'appeler: 'section.SectionInformation.ForceSave = true;' Avant de réellement enregistrer la configuration. Le fichier de configuration externe est maintenant crypté lorsque vous utilisez l'attribut configSource –

Répondre

0

Après beaucoup de recherche et en regardant dans le code pour NameValueFileSectionHandler je me suis rendu compte que la classe n'a pas été en mesure de résoudre configSection pointé par l'attribut file="file path", si la configSection externe où chiffrée. Je ne sais pas si c'était un bug ou non dans NameValueFileSectionHandler. Peut-être que quelqu'un ici peut répondre à cela.

Cependant, j'ai fini par écrire mon propre NameValueFileSectionHandler qui pourrait renvoyer un NameValueCollection et gérer des fichiers de configuration externes cryptés.

public class NameValueFileProtectedSectionHandler : IConfigurationSectionHandler 
{ 
    public object Create(object parent, object configContext, XmlNode section) 
    { 
     object result = parent; 

     XmlNode fileAttribute = section.Attributes.RemoveNamedItem("file"); 

     if (fileAttribute == null && fileAttribute.Value.Length == 0) 
     { 
      return new NameValueSectionHandler().Create(result, null, section); 
     } 

     IConfigErrorInfo configXmlNode = fileAttribute as IConfigErrorInfo; 

     if (configXmlNode == null) 
     { 
      return null; 
     } 

     string directory = Path.GetDirectoryName(configXmlNode.Filename); 
     string absoluteFilePath = Path.GetFullPath(directory + fileAttribute.Value); 

     if (!File.Exists(absoluteFilePath)) 
     { 
      throw new ConfigurationErrorsException(string.Format("external config file: {0} does not exists", absoluteFilePath)); 
     } 

     var configXmlDocument = new ConfigXmlDocument(); 
     try 
     { 
      configXmlDocument.Load(absoluteFilePath); 
     } 
     catch (XmlException e) 
     { 
      throw new ConfigurationErrorsException(e.Message, e, absoluteFilePath, e.LineNumber); 
     } 

     if (section.Name != configXmlDocument.DocumentElement.Name) 
     { 
      throw new ConfigurationErrorsException(string.Format("Section name '{0}' in app.config does not match section name '{1}' in file '{2}'", section.Name, configXmlDocument.DocumentElement.Name, absoluteFilePath)); 
     } 

     var nodeToDecrypt = configXmlDocument.DocumentElement["EncryptedData"]; 

     if (nodeToDecrypt == null) 
     { 
      throw new ConfigurationErrorsException(string.Format("External encrypted file {0} does not contain EncryptedData element", absoluteFilePath)); 
     } 

     var protectionProvider = new DpapiProtectedConfigurationProvider(); 
     var decryptedConfigSection = protectionProvider.Decrypt(nodeToDecrypt); 

     result = new NameValueSectionHandler().Create(result, null, decryptedConfigSection); 

     return result; 
    } 
} 

Le gestionnaire est limité au chiffrement de configuration par défaut. Mais je pourrais imaginer qu'il serait possible d'étendre la fonction Créer pour prendre en charge les fournisseurs personnalisés tels que définis dans le fichier app.config.

1

Une option que vous pourriez prendre est de créer une section de configuration personnalisée, évitez d'utiliser la section appsettings et comptez sur la section de configuration personnalisée. Vous aurez besoin de créer votre propre gestionnaire pour lire dans le fichier externe bien sûr.Vous pourriez pointer vers n'importe quel fichier à ce moment et le fichier entier pourrait être obfusqué et non conforme à la norme XML

Ou vous pouvez ajouter un paramètre dans les paramètres de l'application qui pointe vers le fichier crypté et lu dans le fichier manuellement

+0

Merci pour le bon point que vous avez fait. J'ai créé mon propre gestionnaire. Mais fait, il était en ligne avec la façon dont 'NameValueFileSectionHandler' le fait. Donc, pour avoir autant de synergies avec ce qui est déjà disponible dans l'espace de noms .NET System.Configuration. Consultez ma solution ci-dessus. –