Fix for Service Unavailable in PowerShell DSC Pull Server

Introduction

HTTP 503: Service Unavailable

I recently tried to setup a Microsoft Windows PowerShell Desired State Configuration (DSC) Pull Server, and was receiving an error from IIS. I used the xDscWebService DSC Resource, from the xPSDesiredStateConfiguration PowerShell module, to configure the DSC Pull Server. When I tried to browse to the IIS Web Service for the Pull Server, I was receiving a HTTP 503: Service Unavailable message from Internet Explorer. I believe it is important to note that the Microsoft Windows Azure Pack (WAP) is also installed on the same server where I am trying to deploy the DSC Pull Server.

Missing .NET Framework HTTP Activation

The first thing I noticed, with Microsoft’s help, is that the IIS AppPool named PSWS was in the Stopped state. I tried starting the PSWS AppPool manually from the IIS management console, but it stopped again very quickly, as if it were crashing. In order to resolve this, I installed the NET-HTTP-Activation Windows Feature in Windows Server 2012 R2. I used the PowerShell script below to achieve this.

Get-WindowsFeature -Name NET-HTTP-Activation | Install-WindowsFeature;

IIS Errors in the Event Log

IIS Errors for DSC Pull Service

The next thing I noticed was in the Application and System event logs. IIS was throwing some odd error messages. The first message was repeated about 10 times in the Application event log. The file UxCertAuthModule.dll appears to be related to the Microsoft Windows Azure Pack (WAP). For whatever reason, this module will not load, and it’s causing the PSWS IIS AppPool to crash. Based upon this behavior, I am going to assume that the Windows Azure Pack and PowerShell DSC Pull Server are not supported on the same server.

I searched through the ApplicationHost.config file for IIS, and found that the UxCertAuthModule.dll was declared under the globalModules section, however this ISAPI module is not being loaded under the web.config file for the DSC Pull Server web service. This is why I am confused as to why this ISAPI module is causing the PSWS AppPool to crash.

IIS-W3SVC-WP: Event ID 2280: The Module DLL C:/Windows/system32/inetsrv/UxCertAuthModule.dll failed to load.  The data is the error.

In the System event log, I was seeing the following warning repeated 5 times, followed by the error below it:

WARNING: WAS: Event ID 5139: A listener channel for protocol 'http' in worker process '3272' serving application pool 'PSWS' reported a listener channel failure.  The data field contains the error number.
ERROR: WAS: Event ID 5002: Application pool 'PSWS' is being automatically disabled due to a series of failures in the process(es) serving that application pool.

Resolution

PowerShell DSC Pull Server Endpoint

To resolve this problem, I decided to uninstall the Windows Azure Pack from the Windows Server 2012 R2 instance that I was trying to load the PowerShell DSC Pull Server web service onto. There are a bunch of different components that need to be individually removed, which you’ll notice in the Programs and Features applet in Control Panel.

After removing the Windows Azure Pack components (some of which would not remove correctly), I deleted the PullSvc and DscConformance applications from the Default Web Site in IIS, and then removed IIS from the server. After rebooting, I re-installed IIS, and re-ran the DSC configuration to deploy the Pull & Conformance Services. Upon doing this, the Pull Service endpoint responded correctly.

Pull Server DSC Configuration

I made a couple of tweaks to my PowerShell DSC configuration to deploy the Pull Server. Please find the full configuration below, which is intended to be executed on the Pull Server locally. Before leveraging this script, you will need to deploy the xPSDesiredStateConfiguration PowerShell module to your $env:ProgramFiles/WindowsPowerShell/Modules directory.

Please Note: Because of my blog software, I had to use forward slashes instead of backslashes. Please change the forward slashes to backslashes in the script code.

configuration DscWebService 
{ 
    param 
    ( 
        [ValidateNotNullOrEmpty()] 
        [string] $CertificateThumbPrint = 'AllowUnencryptedTraffic'
    ) 

    Import-DSCResource -ModuleName xPSDesiredStateConfiguration;

    WindowsFeature DSCServiceFeature 
    { 
        Ensure = 'Present';
        Name   = 'DSC-Service';
    } 

    WindowsFeature WinAuth 
    { 
        Ensure = 'Present';
        Name   = 'web-Windows-Auth';
    } 

    WindowsFeature NETHTTPActivation
    { 
        Ensure = 'Present';
        Name   = 'NET-HTTP-Activation';
    } 

    xDscWebService PSDSCPullServer 
    { 
        Ensure                  = 'Present';
        EndpointName            = 'PullSvc'; 
        Port                    = 10100;
        PhysicalPath            = "$env:SystemDriveinetpubwwwrootPSDSCPullServer";
        CertificateThumbPrint   = $CertificateThumbPrint;
        ModulePath              = "$env:PROGRAMFILES/WindowsPowerShell/DscServiceModules";
        ConfigurationPath       = "$env:PROGRAMFILES/WindowsPowerShell/DscServiceConfiguration";
        State                   = 'Started';
        DependsOn               = '[WindowsFeature]DSCServiceFeature';
    } 

    xDscWebService PSDSCConformanceService
    {   
        Ensure                  = 'Present';
        EndpointName            = 'DscConformance';
        Port                    = 10101;
        PhysicalPath            = "$env:SystemDrive/inetpub/wwwroot/PSDSCConformanceServer";
        CertificateThumbPrint   = $CertificateThumbprint;
        State                   = 'Started';
        IsComplianceServer      = $true;
        DependsOn               = @('[WindowsFeature]DSCServiceFeature', 
                                    '[WindowsFeature]WinAuth',
                                    '[WindowsFeature]NETHTTPActivation'
                                    '[xDSCWebService]PSDSCPullServer');
    } 
}  

############# Fill these in #############
$ComputerName = 'dsc01.t.loc';
$CertificateThumbprint = '00A2F55847C5523FE6CB0C2EE132C638339EA3A8';
#########################################

# Set the path to where the MOF file should be stored
$Path = '{0}/dsc/PullServer' -f $env:SystemDrive;

# 1. Create the MOF
DscWebService -ComputerName $ComputerName -OutputPath $Path -CertificateThumbPrint $CertificateThumbprint;
# 2. Deploy the MOF to 
Start-DscConfiguration -Wait -Verbose -Path $Path -Force;
# 3. Clean up the configuration
Remove-Item -Path $Path -Recurse;

Testing the Web Services

Once the PowerShell DSC Pull & Conformance web services have been deployed using the xDscWebService resource, you can validate the web services using the “browser test.” The DSC Conformance web service will prompt you for credentials. You should be able to use a standard user account to authenticate against the web service, so just type those credentials when you’re prompted.

https://<PullServerFQDN>:10101/dscconformance/psdsccomplianceserver.svc/$metadata
https://<PullServerFQDN>:10100/pullsvc/psdscpullserver.svc/$metadata