Tuesday 29 December 2009

S3ToConfig: Loading configuration for a .NET app from a remote source

This post has moved to http://wishfulcode.com/2009/12/29/s3toconfig-loading-configuration-for-a-net-app-from-a-remote-source/

It would be great if the configuration section framework built in to .NET was not hard-coded to be FileSystem-based, but could be loaded, via a provider-framework, from any data source.

Whilst the framework was not built like this, this article explains how the encryption mechanism for configuration sections is provider-based and can be used to load data from sources other than files (a SQL Database in the article's case). In our desire to have a farm of apps running without a difficult deployment process for configuration updates (both for server services, asp.net sites, and client tools), we wanted to deploy a number of apps but keep the configuration files on shared storage. And since our environment is completely inside Amazon EC2, it made sense to keep the configuration centrally on the redundant and scalable storage system already provided, Amazon S3.

It's actually a very simple process to have an application load configuration remotely from S3. The main app.config file needs to be on the local filesystem with the executable, but each configuration section (built-in or custom), even the AppSettings section, can be fetched from S3 on startup, by defining a custom encryption provider and putting the settings for the provider as the fake 'encrypted data'.

You can view the code or download the released verion for loading configuration remotely from S3 on CodePlex, here.

An example of how to use it is:
  1. Add the Natol.S3ToConfig.ProtectedConfiguration.dll file to your projects bin folder, or the GAC on the machine
  2. Define the custom configuration provider in your app.config or web.config after the configSections element:
    <configprotecteddata defaultprovider="s3ConfigSectionProvider">
    <providers><add name="s3ConfigSectionProvider" type="Natol.S3ToConfig.ProtectedConfiguration.ProtectedConfigurationProvider, Natol.S3ToConfig.ProtectedConfiguration"></add>
    </providers></configprotecteddata>
    

  3. Add a file to Amazon S3 at your desired location, giving it a key that represents the function of both your app and the context it runs in (remembering amazon s3 bucket names are globally unique). In this file, put the contents of your configuration section, eg:
    <sampleconfig><settings sampleconfigsetting="This Setting came from s3"></settings></sampleconfig>
    

  4. Replace the contents of your static configuration section with an EncyptedData element containing the location of your new configuration object in Amazon S3 and let it know our custom provider should handle the 'decryption', eg:
    <sampleconfig configprotectionprovider="s3ConfigSectionProvider"> <encrypteddata> <s3providerinfo s3accesskey="REPLACE_WITH_YOUR_VALUE" s3secretkey="REPLACE_WITH_YOUR_VALUE" s3bucketname="REPLACE_WITH_YOUR_VALUE" objectkey="test-s3toconfig-sampleconsoleapplication-sampleconfig"></s3providerinfo> </encrypteddata></sampleconfig>
    

  5. That's it. Your configuration section will work exactly as normal, even calling ConfigurationManager.RefreshSection() which will then reload from S3... :-) Seriously - try the demo
Future Possibilities
It would be nice to support notification of when the configuration is updated, in the same way that the .NET Framework monitors the FileSystem-based .config files.
It would also be great to support writing back to the remote data store if the configuration has changed, depending on the per