User-Specified Machine Keys Overwritten by Site-Level Auto Configuration

Applies to: Azure SDK 1.3. Fixed in Azure SDK 1.4 and later.

Cause: In prior releases, the user could provide an explicit machine key by specifying the machineKey element in the site’s web configuration file.  Explicit site-level configuration would override the automatic machine-level configuration.  

Starting with SDK 1.3, automatic configuration occurs at the site-level, overriding any user-supplied value.

Resolution: A workaround is to programmatically update the site-level configuration during role instance start-up.   

securitySecurity Note
Elevated privileges are required to use IIS 7.0 Managed Configuration API for any purpose, such as programmatic configuration of sites.

The role entry point must run with elevated privileges for this workaround to function correctly.   The steps below configure the role for elevated execution privilege. This configuration applies only to the role entry point process. It does not apply to the site itself.  Note that the role entry point process remains runs with elevated privileges indefinitely.   Exercise caution.

To elevate execution privileges to enable site-level configuration

  1. Place the following snippet inside the relevant WebRole element in the service definition file.

    <Runtime executionContext="elevated" />
    
  2. Add an assembly reference to Microsoft.Web.Administration.dll to the project.  The assembly is located at %WINDIR%\system32\inetsrv\Microsoft.Web.Administration.dll.

  3. Place the following snippet into the OnStart method of the role entrypoint, and update the snippet to refer to the relevant site name. The OnStart method is usually found in the WebRole.cs file if you created the project with Visual Studio.

    using (var server = new ServerManager())
    {
        // get the site's web configuration
        var siteNameFromServiceModel = "Web"; // update this site name for your site. 
        var siteName =
            string.Format("{0}_{1}", RoleEnvironment.CurrentRoleInstance.Id, siteNameFromServiceModel);
        var siteConfig = server.Sites[siteName].GetWebConfiguration();
                    
        // get the appSettings section
        var appSettings = siteConfig.GetSection("appSettings").GetCollection()
            .ToDictionary(e => (string)e["key"], e => (string)e["value"]);
    
        // reconfigure the machine key
        var machineKeySection = siteConfig.GetSection("system.web/machineKey");
        machineKeySection.SetAttributeValue("validationKey", appSettings["validationKey"]);
        machineKeySection.SetAttributeValue("validation", appSettings["validation"]);
        machineKeySection.SetAttributeValue("decryptionKey", appSettings["decryptionKey"]);
        machineKeySection.SetAttributeValue("decryption", appSettings["decryption"]);
     
        server.CommitChanges();
    }
    
  4. Add the following namespace declarations to the source code file containing the OnStart code referred to above. .

    using System.Linq;
    using Microsoft.WindowsAzure.ServiceRuntime;
    using Microsoft.Web.Administration;
    
  5. Place the following snippet into the site’s web.config file, and update the values as appropriate.

    <appSettings>
      <add key="decryption" value="AES"/>
      <add key="decryptionKey" value="YOUR DECRYPTION KEY HERE"/>
      <add key="validation" value="SHA1"/>
      <add key="validationKey" value="YOUR ENCRYPTION KEY HERE"/>
    </appSettings>
    
  6. To verify that the machine key is updated, execute the following snippet within the site’s application and observe that the output matches the value for validationKey as set in the web.config files in the previous step.

    var machineKey = (MachineKeySection) ConfigurationManager.GetSection("system.web/machineKey");
    Debug.WriteLine(machineKey.ValidationKey);