Monday, March 08, 2010

Remove secure sites using Appcmd in Windows 7 & 2008

Background

Recently we encountered some problems while installing and uninstalling Secure web site on Windows 2008 machine. We are using Windows Installer Script (WIX) to generate MSI packages. My team is responsible for building a secure service which uses Windows Identity Foundation to authenticate and authorize users. As part of installation we had to enable https binding and map port 81 to the web site.

Problems while installing and uninstalling Web site which uses SSL

Installing a web site which uses http is quite simple using WIX. While installing a SSL enabled web site, we need to register the certificate with IIS certificate collection. This can be done using the WebSite task and associating the CertificateRef task as shown below.

<Component Id="CraeteWebSite" Guid="{5624171D-82E2-4e6e-B616-C54227E8F422}">

                <iis:WebSite Directory="INSTALLDIR" Id="GHS_UserManagement" Description="GHS_UserManagement">

                    <iis:WebAddress Id="AllUnassigned" Port="81" Secure="yes" />

                    <iis:CertificateRef Id="MyCertificateUM" />

                </iis:WebSite>

            </Component>

We are using Appcmd command which is available in Windows 7 and Windows 2008 to manage IIS related activities. Appcmd is a command line tool for managing II7.

This is a nice article  on getting started with appcmd - http://learn.iis.net/page.aspx/114/getting-started-with-appcmdexe/

For more details you can also refer to Microsoft documentation of this exe at http://technet.microsoft.com/en-us/library/cc772200(WS.10).aspx

 

While uninstalling we can uninstall the Web site using the Add Remove Programs dialog. But there is an entry in the Internet service manager which is something like SITE_2. This number varies based on the concept called site ID. This can be automatically generated which is the default behaviour when a new site is added to IIS. But we can also give a unique site ID for each site.

You can read more about site identifier at Chris Crowe’s blog http://blog.crowe.co.nz/archive/2007/08/04/IIS-Web-Site-Identifiers.aspx.

Default Web Site is always assigned the site ID as 1.

These web sites which start with SITE_ <<number>> are  called as orphaned sites. These do not cause any harm and can be deleted safely.

For testing purpose we tried changing the site bindings and run it in normal http mode. In this case everything was working as expected on running the uninstaller.

We figured out that because we were adding some bindings to the Website to enable the SSL it was not able to remove all entries from IIS metabase while uninstalling the site. This resulted in orphan site being created after uninstallation. The virtual directory and the physical contents would get deleted from the file system but still IIS would show us SITE_2.

Solution

To resolve the issue of orphan site, we modified the WIX script to run the uninstall process as a two step process. In the first step we would remove the https binding for the website. This is done as part of a custom action which removes all the bindings for the site as shown below

<CustomAction Id="RemoveBindings" Property="cmd" ExeCommand="/c %windir%\system32\inetsrv\AppCmd SET SITE &quot;GHS_UserManagement&quot; /-bindings" Execute="oncePerProcess" Return="check" />

Please note the –bindings parameter which does the trick of removing all the bindings for the website.

Once that was successful in the second step we would delete the web site using AppCmd command

<CustomAction Id="DeleteWebSite" Property="cmd" ExeCommand="/c %windir%\system32\inetsrv\AppCmd DELETE SITE &quot;GHS_UserManagement&quot;" Execute="oncePerProcess" Return="check" />

This seem to delete everything from IIS without any problem.

Even after all this if the physical directory remains, we can delete that as well by running the rmdir command as follows

<CustomAction Id="RemoveUserManagementPhysicalPath" Property="cmd" ExeCommand="/c rmdir /s /q %SystemDrive%\Inetpub\wwwroot\GHS_UserManagementService" Execute="oncePerProcess" Return="check" />

Conclusion

I am not sure if this is the perfect solution. There might be a better approach to resolve this issue. But currently this works for our requirements. If anyone knows a better approach to handle this scenario I would like to hear from them.

Until next time happy programming.

No comments:

Post a Comment