📜 ⬆️ ⬇️

A simple way to not destroy a running Exchange / Lync with playful hands

How to quickly save IIS security settings?


Many administrators were faced with a situation where changing a couple of authorization parameters in IIS so that “it’s working right now, as it should, without torturing the user with unnecessary authorization requests” resulted in a partially completely non-working configuration of the entire system.
Unfortunately, typical IIS settings for the same Exchange 2013 in official sources do not cover all possible configurations, in particular Exchange 2010 / Lync 2013 / Exchange 2013 / Edge TMG 2010 coexistence scenarios. The task is to save (write out) all the working settings after the next “tuning” often postponed for later. Typical recommendation: " screwed IIS - reinstall the system " - it works, but it takes a lot of time.
But there is a PowerShell!
Analysis of the development of a simple but useful script, designed to reverse the situation, and is given in this article.

First of all, we need to decide on the sites whose settings you want to save. In my case, already at this step there were discrepancies with the typical setting. IIS on the Exchange 2013 server reinstalled after the intervention of skilled hands was somewhat different in appearance from what was expected:

Therefore, saving the settings “as is” is necessary not for one but two sites.
Well, we get sites:
  # for each of the found sites perform a few simple steps 
 get website |  ForEach-Object-Process {
 # getting application path to character variable 
 $ xPath = "IIS: \ sites \" + $ _. Name 
 # transition in the IIS $ xPath namespace 
 cd $ xPath 
 # output for clarity, where we hit 
 $ xPath
 # getting a collection of web applications in the current site 
 $ myWebApp = get-webApplication 
 # output all members of the collection  
 $ myWebApp 
 }


The result of the script:
The result of the script - a list of applications in all sites


Application directories on hand, what does this give us?
And here is what: now we can get an authentication method for each of them!
A good description of how to get to these settings is on this link.
For example, the code that displays whether basic authentication is enabled for the $ WebApp application in the Exchange Back End site:
')
  (Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/basicAuthentication -Name Enabled -PSPath IIS: \ sites \ "Exchange Back End" -location $ WebApp.Path) .value 


We need to “wrap” this code in an iterator in order not to enter the name of the site and the application itself. Those. one iterator will run around the sites, and inside it, the loop will bypass all site applications.

To make it easier, let's first get the settings for only one site, and display the result by simply outputting the values ​​of variables:
Option script number 1:

 get-webSite
 cd IIS: \ Sites \ "Exchange Back End"
 get-webApplication |  ForEach-Object -process { 
 $ propPath = $ _. Path
 $ propAA = (Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/anonymousAuthentication -Name Enabled -PSPath IIS: \ sites \ "Exchange Back End" -location $ _. Path) .value 
 $ propBA = (Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/basicAuthentication -Name Enabled -PSPath IIS: \ sites \ "Exchange Back End" -location $ _. Path) .value 
 $ propCA = (Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/clientCertificateMappingAuthentication -Name Enabled -PSPath IIS: \ sites \ "Exchange Back End" -location $ _. Path) .value 
 $ propDA = (Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/digestAuthentication -Name Enabled -PSPath IIS: \ sites \ "Exchange Back End" -location $ _. Path) .value 
 $ propIA = (Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/iisClientCertificateMappingAuthentication -Name Enabled -PSPath IIS: \ sites \ "Exchange Back End" -location $ _. Path) .value 
 $ propWA = (Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/windowsAuthentication -Name Enabled -PSPath IIS: \ sites \ "Exchange Back End" -location $ _. Path) .value 
 $ _. Path;  $ propAA;  $ propBA;  $ propCA;  $ propDA;  $ propIA;  $ propWA;
 } 


Already working, but ugly and not on all sites.
In powerShell there is a wonderful output formatting command: Format-Table , let's put it into practice:

 # Script text
 get-webSite
 cd IIS: \ Sites \ "Exchange Back End"
 $ myWebApp = get-webApplication
 $ myWebApp |  Format-Table -AutoSize Path, 
 @ {Label = "anonim:";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/anonymousAuthentication -Name Enabled -PSPath IIS: \ sites \ "Exchange Back End" -location $ _. Path) .value}},
 @ {Label = "Basic:";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/basicAuthentication -Name Enabled -PSPath IIS: \ sites \ "Exchange Back End" -location $ _. Path) .value}},
 @ {Label = "ClientCert:";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/clientCertificateMappingAuthentication -Name Enabled -PSPath IIS: \ sites \ "Exchange Back End" -location $ _. Path) .value}},
 @ {Label = "Digest:";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/digestAuthentication -Name Enabled -PSPath IIS: \ sites \ "Exchange Back End" -location $ _. Path) .value}},
 @ {Label = "IIS client Cert:";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/iisClientCertificateMappingAuthentication -Name Enabled -PSPath IIS: \ sites \ "Exchange Back End" -location $ _. Path) .value}},
 @ {Label = "Windows";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/windowsAuthentication -Name Enabled -PSPath IIS: \ sites \ "Exchange Back End" -location $ _. Path) .value}},
 @ {Label = "SSL Flags";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/access -Name * -PSPath IIS: \ sites \ "Exchange Back End" -location $ _. Path) .SSLflags}}

 cd IIS: \ Sites \ "Default Web Site"
 $ myWebApp = get-webApplication
 $ myWebApp |  Format-Table -AutoSize Path, 
 @ {Label = "anonim:";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/anonymousAuthentication -Name Enabled -PSPath IIS: \ sites \ "Default Web Site" -location $ _. Path) .value}},
 @ {Label = "Basic:";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/basicAuthentication -Name Enabled -PSPath IIS: \ sites \ "Default Web Site" -location $ _. Path) .value}},
 @ {Label = "ClientCert:";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/clientCertificateMappingAuthentication -Name Enabled -PSPath IIS: \ sites \ "Default Web Site" -location $ _. Path) .value}},
 @ {Label = "Digest:";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/digestAuthentication -Name Enabled -PSPath IIS: \ sites \ "Default Web Site" -location $ _. Path) .value}},
 @ {Label = "IIS client Cert:";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/iisClientCertificateMappingAuthentication -Name Enabled -PSPath IIS: \ sites \ "Default Web Site" -location $ _. Path) .value}},
 @ {Label = "Windows";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/windowsAuthentication -Name Enabled -PSPath IIS: \ sites \ "Default Web Site" -location $ _. Path) .value}},
 @ {Label = "SSL Flags";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/access -Name * -PSPath IIS: \ sites \ "Default Web Site" -location $ _. Path) .SSLflags}}
 


Here, Format-Table acts as an iterator, and I also added the SSL flag, which is significant and often lost after the “experiments”.

In order not to write wild repeating code, entering the site name with your hands, let's add an iterator over the sites, as was done at the very beginning of the article:

The final version of the script:


 get website |  ForEach-Object-Process { 
 $ xSite = "IIS: \ sites \" + $ _. Name  
 cd $ xSite  
 $ xSite 
 $ myWebApp = get-webApplication
 $ myWebApp |  Format-Table -AutoSize Path, 
 @ {Label = "anonim:";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/anonymousAuthentication -Name Enabled -PSPath $ xSite -location $ _. Path) .value}},
 @ {Label = "Basic:";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/basicAuthentication -Name Enabled -PSPath $ xSite -location $ _. Path) .value}},
 @ {Label = "ClientCert:";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/clientCertificateMappingAuthentication -Name Enabled -PSPath $ xSite -location $ _. Path) .value}},
 @ {Label = "Digest:";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/digestAuthentication -Name Enabled -PSPath $ xSite -location $ _. Path) .value}},
 @ {Label = "IIS client Cert:";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/iisClientCertificateMappingAuthentication -Name Enabled -PSPath $ xSite -location $ _. Path) .value}},
 @ {Label = "Windows";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/authentication/windowsAuthentication -Name Enabled -PSPath $ xSite -location $ _. Path) .value}},
 @ {Label = "SSL Flags";  Expression = {(Get-WebConfigurationProperty -Filter /system.webServer/security/access -Name * -PSPath $ xSite -location $ _. Path) .SSLflags}}
 } 



In this variant, $ _ within the Format-Table command refers to the current application, and $ _ in the second line refers to the current site from the ForEach-Object iterator.

So, at the output we get an excellent picture, which allows restoring the changed settings so irrelevant.

The result of the script is a table of application authorization methods.

The options for screwing the output to a file with logging time and the host name where it was performed there are many, here they were not considered. There is room for improvement.

I have already launched this script on all IIS in my organization, and now if I’m going to change something, I’ll have a chance to remember what I’ve changed. just comparing the picture "before" and "after." Comments on further improvements are welcome. About backups and the inadmissibility of changing something on the “combat” servers in the course, but life is complicated and there are exceptions to the rules.

I hope that my humble experience will save someone time.

Source: https://habr.com/ru/post/204454/


All Articles