XPath, PowerShell and custom trust level in ASP.NET

When you manage IIS and related products you often need to deal with configuration files that are not part of IIS configuration. You cannot use cmdlets from IIS7 PowerShell snapin for those files, but you could use XPath engine, provided by managed framework in System.Xml.XPath and there is a lot of common in XPath queries that we use for configuration APIs and for other configuration XML files. It is expected -- as soon as structure of files is similar to the structure of configuration tree, same XPath queries should produce similar results.

Let's take a specific example. Often administrators need to change default trust level in ASP.NET to permit more operations. Recommended trust level is Medium, and it is often a default. I will show you how to change this level to custom. At the end we will have PowerShell script that you could use as a template for your modifications.

Step by step explanations of changes that we need to perform are given in the detailed article of Walter Olivier, I will follow steps outlined in this article.

We will have path to .Net Framework as parameter of our script. If you are running PowerShell from Visual Studio environment, path to framework is defined through environment variables, and in PowerShell it could be calculated as

$frameworkPath = join-path $env:FrameworkDir $env:FrameworkVersion

On my computer result is 'C:\Windows\Microsoft.NET\Framework64\v2.0.50727'.

Our general approach to XML files modification will be the following: load file, create XML document object from its content, create XPath navigator for this document, move around the document using this navigator and make changes, save document back to the file. First we have to define new configuration file with custom trust settings, we will load existing file, modify what we want to change, add new data and then store it under new name,

$frameworkPath = join-path $frameworkPath 'CONFIG'
$cfg = [xml](cat (join-path $frameworkPath web_mediumtrust.config))
$nav = $cfg.CreateNavigator()

delete-node $nav "//IPermission[@class='WebPermission']/ConnectAccess"
$nav.CreateAttribute("","Unrestricted","","true")
# If not required, delete PrintingPermission and EnvironmentPermission
delete-node $nav "//IPermission[@class='PrintingPermission']"
delete-node $nav "//IPermission[@class='EnvironmentPermission']"

# save new configuration file
$filePath = join-path $frameworkPath "web_CustomTrust.config"
$cfg.Save($filePath)

Function delete-node is defined the following way:

function delete-node {
   param(
       [Xml.Xpath.XPathNavigator]$n,
       [string]$path
   )
   $node = $n.SelectSingleNode($path)
   $n.MoveTo($node)
   $n.DeleteSelf()
}

Next we need to modify root web.config file to be aware of our new custom trust settings:

# make a backup of root web.config
copy-item (join-path $frameworkPath web.config) `
(join-path $frameworkPath web.config.backup)
# add trust level
$cfg = [xml](cat (join-path $frameworkPath web.config))
$nav = $cfg.CreateNavigator()

$node = $nav.SelectSingleNode('//securityPolicy')
$nav.MoveTo($node)
# add new trustLevel
$nav.AppendChild('<trustLevel name="Custom" `
policyFile="web_CustomTrust.config" />')

# lock this section
$node = $nav.SelectSingleNode(`
'//location/system.web/securityPolicy/parent::node()/parent::node()/@allowOverride')
$nav.MoveTo($node)
$nav.SetValue("false")

$filePath = join-path $frameworkPath "web.config"
$cfg.Save($filePath)

You could download whole script here. You will need to change extension to 'ps1' before using it.

As you could see, modifying configuration files directly as XML is not a complicated task. When you know a bit about XPath and how it is used in IIS snapin, you could edit "unincorporated" configuration files almost the same way. The only problem is that some configuration files used in ASP.NET do not have a schema, and you should figure out your XPath expressions looking to the XML structure. Path to the entity inside of XML file could be expressed either as fully qualified path from the root, or as shortcut. Normally, when you running XPath queries against IIS configuration, it is not a good idea to use XPath shortcut '//', like '//IPermission' above. Full expression for this shortcut is /descendant-or-self::node()/IPermission. It tells XPath engine that it should walk whole tree and select any elements with name 'IPermission'. Depending on the size of the tree it could be expensive. When you running query against small XML file, and select just one one, it is not very expensive, and usually these shortcuts could help you to write your queries faster.


Sergei

No Comments