3

I recently deployed an ASP.Net Web API project to our Azure App Service test slot but started receiving an error when making requests to the API endpoints. Through remote debugging, it became clear that the app was extracting my dev connection strings from the deployed web.config file.

The connection strings are supposed to come from the Application Settings we set up via the Azure Portal - and, in previous deployments, they were - but that's not the case.

Why would this happen and what can be done to ensure the correct behaviour occurs? We absolutely don't want our production database secrets being put into GIT via the web.config...

Aatif Akhter
  • 2,126
  • 1
  • 25
  • 46
Zac Seth
  • 2,742
  • 5
  • 37
  • 56
  • Are you deploying the project first time to a deployment slot? If yes, you'll have to add the configuration to the application settings of the deployment slot also. – Flemin Adambukulam Sep 09 '16 at 14:24
  • Can you please post the name of the .NET framework method you are using for reading the configuration? – Abhay Saraf Sep 10 '16 at 06:57
  • @AbhaySaraf - It's using `ConfigurationManager.ConnectionStrings["..."].ConnectionString` to read the setting values. I should note that this is ASP.Net Web API 2 – Zac Seth Sep 13 '16 at 10:48
  • Did you ever resolve this? I am encountering the same issue. – RJBreneman Aug 02 '19 at 22:11
  • This is working as expected because if you create a new AppDomain in addition to the AppDomain in which ASP.NET is running already, App-Service-provided app-settings will not be injected correctly. We inject app-settings using reflection when the app is starting up using an ASP.NET request handler module so that trick will only work for ASP.NET’s app domain(s). – DashleenBhandari-MSFT Aug 05 '19 at 04:34
  • @RJBreneman Sorry for the late reply. It's been a couple of years since I worked on this and, unfortunately, I can't remember the details. – Zac Seth Aug 13 '19 at 10:11
  • I'm experiencing the same problem too - the problem started sometime after I updated my application to clear the default ASP.NET `IHttpModule` collection - I always thought the Azure App Service App Settings were being added from a Configuration Provider – Dai Jun 26 '20 at 04:28
  • @DashleenBhandari-MSFT But thank you for the hint to look for an `IHttpModule`! I opened my Azure App Service's machine-wide `web.config` and my slot's `applicationHost.config` file and I saw references to a `EnvSettings` module! I searched my Azure App Service's filesystem for `EnvSettings.dll` but couldn't find it - I eventually found it in the GAC (where it has a different name). I was able to extricate `EnvSettings.dll` back onto my computer and I'm disassembling it now to find out why it isn't working. – Dai Jun 26 '20 at 04:30

3 Answers3

2

I recently experienced the same problem and fixed it:

  • In Azure App Services, the machine-wide web.config file is located at D:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.config.

  • This file differs to a normal machine-wide web.config file because it has this extra element:

    <system.web>
        ...
        <compilation>
            <assemblies>
                <add assembly="EnvSettings, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
                ...
            </assemblies>
        </compilation>
    </system.web>
    
  • The EnvSettings.dll assembly is located inside D:\Program Files\IIS\Microsoft Web Hosting Framework (unfortunately this directory is access-controlled and I can't get into it).

    • But EnvSettings.dll is mirrored in the GAC, so I was able to copy it from there.
  • Inside EnvSettings.dll is an [assembly: PreApplicationStartMethod] attribute that runs a method in EnvSettings.dll which copiesthe APPSETTING_ and database connection-string settings from Environment Variables into the .NET Framework ConfigurationManager.AppSettings and ConfigurationManager.ConnectionStrings collections.

    • Note this copying only happens once (during application startup), and only in the first AppDomain - so if you have other AppDomain instances in your application they won't see the updated ConfigurationManager.
  • Therefore, if you see that your Azure Portal configuration settings for your App Service are not being used when you dump your ConfigurationManager, then the following is likely happening:

    • You used <clear /> in your <compilation><assemblies> element, which stops EnvSettings.dll from being loaded at all.
      • In which case you need to either add back the <add assembly="EnvSettings... element from above to your own web.config, or find some other way to load it.
        • I don't recommend saving EnvSettings.dll locally and adding an assembly reference to your project, as EnvSettings.dll is part of the Microsoft Web Hosting Framework.
    • Or you have code that is clearing or resetting ConfigurationManager after EnvSettings populates it for you.
    • Or something else is going on that I have no idea about!

As an alternative to having EnvSettings.dll copy your settings over, another option is to copy the environment-variables over yourself - and as you control the code that does this it means you can call it whenever you need to (e.g. if you ever reset them).

Here's the code I used:

public static class AzureAppSettingsConfigurationLoader
{
    public static void Apply()
    {
        foreach( DictionaryEntry environmentVariable in Environment.GetEnvironmentVariables() )
        {
            String name  = (String)environmentVariable.Key;
            String value = (String)environmentVariable.Value;
            
            if( name.StartsWith( "APPSETTING_", StringComparison.OrdinalIgnoreCase ) )
            {
                String appSettingName = name.Substring( "APPSETTING_".Length );
                ConfigurationManager.AppSettings[ appSettingName ] = value;
            }
            else if( name.StartsWith( "SQLAZURECONNSTR_", StringComparison.OrdinalIgnoreCase ) )
            {
                String csName = name.Substring( "SQLAZURECONNSTR_".Length );

                ConfigurationManager.ConnectionStrings.Add( new ConnectionStringSettings( csName, value, providerName: ""System.Data.SqlClient" ) );
            }
        }
    }
}
Dai
  • 141,631
  • 28
  • 261
  • 374
-1

See my sample here: http://mvc5appsettings.azurewebsites.net/

// My web.config also has a "HERO_TEXT" key in
// that reads "Value from web.config"
string hero = ConfigurationManager.AppSettings["HERO_TEXT"];

Pulling App Settings

Wiki page on App Settings for .NET:
https://github.com/projectkudu/kudu/wiki/Managing-settings-and-secrets

As already mentioned here, make sure you have that App Setting in the right slot.

evilSnobu
  • 24,582
  • 8
  • 41
  • 71
-4

As I know, the settings in Azure portal will override existing setting in Web.config. So If you want to ignore the Azure Application settings in portal and use Web.config instead. I am afraid you need to configure the settings in web.config, and remove the same key/pair in Azure portal.

Jambor - MSFT
  • 3,175
  • 1
  • 13
  • 16
  • 1
    I *don't* want to ignore the Azure Application settings - but that's what's happening. I've checked carefully and can confirm that the Azure Application setting keys match up to the values we're using in code. – Zac Seth Sep 13 '16 at 11:03
  • 1
    This is the opposite of the problem he is having. The problem he's having is that they're NOT overwriting the web.config settings. – BrainSlugs83 Dec 01 '18 at 01:23