IIS 7 Configuration Paths - iis

I am trying to make my c++ ahadmin application compatible to IIS 7. My app needs to read the websites configuration (via metabase properties in IIS 6).
I read a lot of articles about the configuration paths and I think I have a good idea of how it work - however I am not sure of one thing:
To get to the configuration, I can either commit the MACHINE/WEBROOT/APPHOST/ path or the MACHINE/WEBROOT/APPHOST/Default Web Site.
I understand that the latter refers to the actual web.config of the specific website, and the former refers to the general applicationHost.config file, in which general settings are set.
My app doesn't know however whether a web.config file exists.
My question: if I want to get to this path - Object.ConfiguredObject.Site.Bindings, do I need to commit the APPHOST path or the APPHOST/Default Web Site path?
How do I know that in runtime?

You will always commit your bindings to MACHINE/WEBROOT/APPHOST.
You should go have a look at the schema files in:
%systemroot%\System32\inetsrv\config\schema
They will help you identify where settings should belong.
Update:
Per your comment:
So for example, AccessSSLFlags would
be mapped to
ConfigurationSection.AccessSection.SslFlags
- what section will I commit in that case? How do I know which section I
need to commit?
That all depends. IIS7 supports a mechanism called Feature Delegation. If a feature is delegated then this means a user can configure that feature in their local web.config. Some features are configured under system.webServer, others system.web.
What a user can and can't configure locally in his/her web.config is controlled by entries in two files:
%systemrooot%\system32\inetsrv\config\administration.config
%systemrooot%\system32\inetsrv\config\applicationHost.config
If you go and look at the IIS7 configuration schema in:
%systemroot%\System32\inetsrv\config\schema\IIS_schema.xml
What you'll find is that there are two main types of section:
system.applicationHost/xxxx
system.webServer/xxxx
Anything that is configurable under system.applicationHost is generally not considered a user modifiable configuration item. In fact if you open applicationHost.config you will see:
<sectionGroup name="system.applicationHost">
<section name="applicationPools" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
<section name="configHistory" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
<section name="customMetadata" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
<section name="listenerAdapters" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
<section name="log" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
<section name="serviceAutoStartProviders" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
<section name="sites" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
<section name="webLimits" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
</sectionGroup>
Notice the allowDefinition="AppHostOnly"? That's basically telling you that these settings can't be configured in web.config.
The scope of how feature delegation works is far too wide to cover in an answer so I suggest you read the article linked to above.

It sounds like you are trying to build a generic tool to manage configuration, and so you might want to consider to follow a similar pattern that IIS Manager follows; in short, it always tries to save configuration to the deepest path possible. What this means is that it will always Commit it to the place where it can, by looking at if the section is locked or not. It uses Managed code (Microsoft.Web.Administration), but you can access the same data from C++ using AppHostElement.GetMetadata("isLocked").
By the way if you are using C++, I would STRONGLY recommend using AHADMIN directly (and not WMI, or anything else), in particular IAppHostWritableAdminManager.
So the algorithm would be, set the CommitPath to the same value as the GetAdminSection configuration path specified. Then check for IsLocked, if it is then remove the last "path part" (trim starting the last '/'), and read again till you find the place where the section is unlocked. That is the deepest place where you can save it. Also, you will need to switch to MACHINE/WEBROOT at some point if it is a system.web section. IsLocked will respect things like Section Definition allow location, and other things that are required. If you want to make it bullet proof you would even need to check for attribute-level locking, but I think that is quite advanced.

Related

Service Fabric Default Publish Profile other than Local.xml

Our company is developing our new applications using Service Fabric.
A common problem we have, multiple developers use queues, databases, storages that are on remote servers, and each one has different configuration for this, all the settings are stored on ApplicationParameters file per environment, for Local development there is a single Local.5Node.xml. It is very common developers checkin their credentials and overwrite others when we get latest version of these files.
I'm trying to customize the ServiceFabric deployment script 'Deploy-FabricApplication.ps1' to use a custom PublishProfile depending on windows credentials of logged user. I can achieve that updating the deployment file, it works well when we deploy using the publish, but it seems that the default behavior of ServiceFabric when we hit F5(debug) is overwrite the parameters with a specific Local.5Node.xml application parameters.
I explored all service fabric .ps1 files and couldn't find where this is defined. I guess this is defined on .targets file, so I don't know how can I avoid this default behaviour.
Is there any other approach to use custom PublishProfiles on local development machines other than Local.5Node.xml?
I actually just ran into this with setting up some team specific environments. I borrowed information from the following sources:
Web Config Transformation
Replace String In File With MSBUILD
I added multiple parameters files based on what was needed for the different teams. Each one containing their specific resource settings.
I also added a Local.1Node.Template.xml and Local.5Node.Template.xml. I even removed the Local.1Node.xml and Local.5Node.xml from source control and set them up to be ignored while leaving them in the projects so that Visual Studio doesn't think they are truly missing. The contents of the 1Node (5Node is the same except for replacing 1Node with 5Node) are as follows:
<?xml version="1.0" encoding="utf-8"?>
<PublishProfile xmlns="http://schemas.microsoft.com/2015/05/fabrictools">
<ClusterConnectionParameters />
<ApplicationParameterFile Path="..\ApplicationParameters\Local.1Node.$(Configuration).xml" />
</PublishProfile>
I then edited the sfproj file for the Service Fabric project to contain the following MSBuild Task and Target:
<UsingTask TaskName="ReplaceFileText" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<InputFilename ParameterType="System.String" Required="true" />
<OutputFilename ParameterType="System.String" Required="true" />
<MatchExpression ParameterType="System.String" Required="true" />
<ReplacementText ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Core" />
<Using Namespace="System" />
<Using Namespace="System.IO" />
<Using Namespace="System.Text.RegularExpressions" />
<Code Type="Fragment" Language="cs">
<![CDATA[
File.WriteAllText(
OutputFilename,
Regex.Replace(File.ReadAllText(InputFilename), MatchExpression, ReplacementText)
);
]]>
</Code>
</Task>
</UsingTask>
<Target Name="UpdateProfile" BeforeTargets="UpdateServiceFabricApplicationManifest">
<ReplaceFileText InputFilename="PublishProfiles\Local.1Node.Template.xml" OutputFilename="PublishProfiles\Local.1Node.xml" MatchExpression="\$\(Configuration\)" ReplacementText="$(Configuration)" />
<ReplaceFileText InputFilename="PublishProfiles\Local.5Node.Template.xml" OutputFilename="PublishProfiles\Local.5Node.xml" MatchExpression="\$\(Configuration\)" ReplacementText="$(Configuration)" />
</Target>
The final step was to setup the different Build Configurations for the teams. I created a FT1-Debug through FT6-Debug based on the Debug configuration in the Service Fabric Service project and the Service Fabric Host project. I left all of my other projects alone.
At this point everyone on the different teams can debug locally with the correct configuration for the cluster they are doing work in just by changing the Build Configuration and pressing F5 to debug.
The VS extension for Service Fabric define a hard coded publish profile when we debug the solution using Visual Studio, it check how many nodes my cluster has and create a link to Local.5Node.xml and Local.1Node.xml depending how many nodes my cluster have.
To accomplish the same results, we end up using custom Application Parameters per developer and each developer update the Publish Profile (Local.5node.xml) to point to their respective Application parameter files.
It is not automated as the required feature, but can solve the main problem.

How to override web.config values in custom section in Azure Web App?

It is possible in Azure Web App to override web.config AppSettings section easily. E.g. if I have the following web.config:
<appSettings>
<add key="AllowedCORSOrigin" value="http://localhost:26674"/>
</appSettings>
I can override it in the app settings UI in the portal like that:
I have also a custom section in the web.config:
<AdWordsApi>
<add key="OAuth2RefreshToken" value="TOKEN" />
</AdWordsApi>
Is it possible to override it somehow as well? I have tried AdWordsApi.OAuth2RefreshToken and AdWordsApi:OAuth2RefreshToken, but that does not work that easily.
P.S. It's interesting to know if it's possible with other custom sections like e.g if I want another authentication mode on the server.
<system.web>
<authentication mode="None" />
</system.web>
Short answer is that it is not possible.
The mechanism you describes only works with App Settings and Connection Strings. High level, the way it works is:
Your Azure App Settings become environment variables
At runtime, a special module sets those dynamically in the .NET config system. Note that the physical web.config is never modified.
But it would be hard to make such mechanism work on arbitrary config sections, as those could not be dynamically affected without modifying the physical file.
If you are using Visual Studio use web.config transformations to change configuration settings depending on whether you are running locally or deploying to Azure:
How to Transform Web.config
In simple terms you create one more more build configurations (typically Debug & Release). In your Visual Studio solution right-click on your existing web.config file and click "Add Config Transform", this will create a Web.Debug.Config and Web.Release.Config file which you can then customise with specific settings depending on the environment. Link this with your Azure build configuration and you can then have any combination of settings for local and remote deployment.
This is old but leaving this reference to how to use Azure Resource Manager to potentially solve this.
You can transform the values by the listed in VSTS by doing the following steps in App.Release.config:-
Add xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform" in configuration section
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
</configuration>
Add xdt:Transform="Replace" in custom section like below
<AdWordsApi xdt:Transform="Replace">
<add key="OAuth2RefreshToken" value="TOKEN" />
</AdWordsApi>
Create variable token in the release pipeline e.g OAuth2RefreshToken
Then in file config use it as following
<AdWordsApi xdt:Transform="Replace">
<add key="OAuth2RefreshToken" value="#{OAuth2RefreshToken}#" />
</AdWordsApi>
If you are adding any in web.config --> Appsetting, you can overirde it in Azure App Service using variable prefix
Key Name: APPSETTING_AllowedCORSOrigin
Value: http://localhost:26674
https://learn.microsoft.com/en-us/azure/app-service/reference-app-settings?tabs=kudu%2Cdotnet#variable-prefixes

Override applicationSettings "MySite.Properties.Settings.MySetting" in Azure Website

I have a website (not web role) that I'm deploying to Azure, using the Basic tier. The web.config file has the following auto-generated section for website settings:
<applicationSettings>
<MySite.Web.Properties.Settings>
<setting name="MySetting" serializeAs="String">
<value>coolValue</value>
</setting>
</MySite.Web.Properties.Settings>
</applicationSettings>
I'm trying to override the value of MySetting in Azure's Web Apps -> MySite -> Configure -> app settings section. The idea being that the live website has a different value than the development version. I'm trying to avoid storing the live website's value in the web.config file (nor doing transforms).
I've tried the following values in the app settings section of the azure web app configuration section:
MySetting = somethingElse
MySite.Web.Properties.Settings.MySetting = somethingElse
Neither of these things worked. I like the new strongly-typed settings class in .NET, and don't really want to flatten the app settings out (using the old way).
Does anyone know how to override these types of settings in Azure?
Have you added the applicationSettings to the section group?
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="Tools.Instrumentation.Properties.Settings"
type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
requirePermission="false" />
</sectionGroup>
</configSections>
One alternative is to set the App Settings from the Azure Portal. Go to the Azure Portal->Navigate to your website->Settings->App Settings and set the key, value pair there.
All settings will show up as environment variables, so you can set different values for the same settings in your test and production environments.
See here for more info:
http://azure.microsoft.com/blog/2013/07/17/windows-azure-web-sites-how-application-strings-and-connection-strings-work/
I asked around Microsoft's support & could not get an answer for this issue as I wanted to do this too. Fortunately while trying to better understand Microsoft's Web Deploy I discovered how to do this.
First, you'll need to use an external config file instead of just adding them into the web.config file. In your web.config file replace the following:
<applicationSettings>
<MySite.Web.Properties.Settings>
<setting name="MySetting" serializeAs="String">
<value>coolValue</value>
</setting>
</MySite.Web.Properties.Settings>
</applicationSettings>
Use an external configuration file like this instead:
<applicationSettings>
<MySite.Web.Properties.Settings configSource="BusinessLogic.config" />
</applicationSettings>
Also in your web.config file you will need to add the following to your configSections:
<configSections>
<sectionGroup name="applicationSettings">
<section name="MySite.Web.Properties.Settings" />
</sectionGroup>
</configSections>
You can read the MSDN article for more on this if need be.
In your BusinessLogic.config file, located in your root with your web.config file you would add your settings:
<MySite.Web.Properties.Settings>
<setting name="SecretPassword" serializeAs="String">
<value>1234567890abc!##</value>
</setting>
</MyApplication.Properties.Settings>
Now manually add this same BusinessLogic.config file to your site on Azure with the settings you want it to have in Azure.
Finally open up your .csproj file and look for the following XML configuration:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
Within there you can exclude files from deployment by adding a line like this:
<ExcludeFilesFromDeployment>BusinessLogic.config</ExcludeFilesFromDeployment>
If you need to exclude more files, you can separate them with a semicolon.
Now in my case when I commit all these files to my git repository, Azure will automatically grab them & put them in a temporary file where it will build the project and then deploy it to the folder where the website lives. Upon deploying it will notice to ignore the BusinessLogic.config file and the file you manually placed in Azure will be used instead.

How to update applicationhost.config programmatically

During the deploy to production we have to add a number of additional entries to the application's web.config, for example adding subkeys to system.identityModel/identityConfiguration/audienceUris, which is declared at the top of the web.config file as
<configSections>
<section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection,
System.IdentityModel, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=B77A5C561934E089" />
</configSections>
In an ideal world we would do this using config transforms at build time, but we've made a design decision to use msdeploy parameters instead, which don't allow the injection of XML nodes in parameters (in spite of various posts that suggest you can). There are solutions that allow you to use both but we don't have time to integrate those into our deployment infrastructure right now.
Ideally we would achieve our end using appcmd to add nodes in the msdeploy post-sync task, but it seems that out of the box appcmd does not expose these custom sections unless you also declare them in applicationhost.config.
Is there a way to use appcmd or other tools to programmatically update applicationhost.config to add these declarations or do we just have to work with the XML directly?

Oracle padding security related query

I am still unable to figure out the following which are related to Oracle padding security issue. The no. 1 point is in general which I wanted to know the easy way to change the Machine key. The no. 2 point is related to Security issue.
If I change the machine key then how easily I can change the user passwords stored in the DB. User passwords are also encrypted with same machine key. Changing the key will make passwords to become invalid. Please correct me if I am mistaken.
In webresource.axd?d=..., What is the data type stored in 'd' parameter. How it will allow to download any arbitrary file. I know only that it can allow embedded resources to download. But can someone show an example to download web.config file using webresource.axd. Everybody talks that web.config can be downloaded but I did not find an example of doing that.
I will be glad to know if someone can answer with simple example. Please do not point me to ScotGu blog and after reading his blog and recommendation I do not want to visit his blog again and am surprised to know how he is leading asp.net team.
I'll try to answer your questions from what I have learned about the issue so far.
User passwords in the DB are not at all related to the machine key of the app. The ASP.NET worker process by default generates a new machine key every time your app is restarted.
(Thus, if the DB passwords were dependent on the machine key, they would become invalid in every few days.)
About downloading Web.config, we don't really know. Some people think that it is dependent on another security hole. If you use MVC (or WebForms without these), it is the safest if you disable the .axd requests. (Handle *.axd with HttpForbiddenHandler)
For example:
<httpHandlers>
...
<remove verb="*" path="*.axd"/>
<add validate="false" verb="*" path="*.axd" type="System.Web.HttpForbiddenHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</httpHandlers>
Or do the same in the system.webServer section if you are using IIS 7.

Resources