Where did Compliance Server Go ?

To a world of better compliance, probably :slight_smile:

Hi all,

Based on questions in the forum and the lack of descriptive examples, i wrote down
some examples scripts to ease up the configuration and usage.

Quick Background - To enable nodes to report status to a central location, v4 DSC
had an option to create a compliance server via a resource inside
xPSDesiredStateConfiguration with a matching IsComplianceServer toggle bit in the
Pull Server creation script.

In V5 theres no more ComplianceServer, thoght the Compliance server resource and
toggle are still inside, most likely for backward compatibility.

You will see a couple examples for v5 DSC that still use the resource and the toggle,
including, unfortunatly again, Sample_xDscWebService.ps1 that comes with the latest
version 3.7.0.0 of xPSDesiredStateConfiguration resource.

Do note, from tests done by Justin King, if you want to use the new method of node
registration via RegistrationKey, you really do NOT want to use IsComplianceServer=$True :slight_smile:

More Info:
https://powershell.org/forums/topic/confignames-being-awfully-quiet/

That said the PowerShell documentation on Microsoft site as its being updated from the
GITHub repo does contain fixed examples if somewhat limited in explaining. Its being
update quite often and published to the public. Hop to the PowerShell DSC Docs GitHub link if youre into contributing.

More Info:
https://msdn.microsoft.com/en-us/powershell/dsc/pullserver

Scenario
Srv1 was our Pull Server
Srv3 is our Pull client getting resources from Srv1

We dont want the reporting to be registered at SRV1, so we build a new Pull Server
on Srv2 and update the LCM on Srv3 accordingly.

Note that you can also separate the resource a.k.a. modules to be pulled from another
server. Secondly, im not going into how to get a certificate or install it, as its out of scope.

CreatePullServer_SRV1.ps1

# Configuration for creating a PullServer V2 (PS 5.0)
Configuration CreatePullServer

{

     param

    (

         [ValidateNotNullOrEmpty()][string] $ComputerName,

         [ValidateNotNullOrEmpty()][String] $CertificateThumbprint

    )


    Import-DSCResource -ModuleName xPSDesiredStateConfiguration -ModuleVersion 3.7.0.0


    Node $ComputerName

    {

         WindowsFeature DSCServiceFeature

        {

            Ensure     = 'Present'

            Name       = 'DSC-Service'

        }


        xDscWebService PSDSCPullServer

        {

             Ensure                       =  'Present'

             EndpointName                 =  'PSDSCPullServer'

             Port                         =  8080

             PhysicalPath                 =  'D:\WebSites\PSDSCPullServer'

             CertificateThumbPrint        =  $CertificateThumbprint

             State                        =  'Started'

             ModulePath                   =  'C:\Program Files\WindowsPowerShell\DscService\Modules'

             ConfigurationPath            =  'C:\Program Files\WindowsPowerShell\DscService\Configuration'

             RegistrationKeyPath          =  'C:\Program Files\WindowsPowerShell\DscService'

             AcceptSelfSignedCertificates =  $false

             IsComplianceServer           =  $false

             DependsOn                    =  '[File]RegistrationKeyFile'

         }

 
          File RegistrationKeyFile

         {

            Ensure          = 'Present'

            Type            = 'File'

            DestinationPath = 'C:\Program Files\WindowsPowerShell\DscService\RegistrationKeys.txt'

            Contents        = '5e2e5153-62b8-44a3-958e-198eafc7218a'

            DependsOn       = '[WindowsFeature]DSCServiceFeature'

         }

    }

}

# Certificate should also be installed at the target server beforehand

$myCertPath = '.\DSCPullServer.pfx'
$myCertThumbprint = (Get-PfxCertificate -FilePath $myCertPath).Thumbprint


CreatePullServer -ComputerName SRV1 -CertificateThumbprint  $myCertThumbprint -OutputPath  '.\'

Start-DscConfiguration -ComputerName SRV1 -path '.\'  -Force -Wait -Verbose
  

Iā€™ve bound the creation of the pull server to the creation of the RegistraionKeys.txt but you
can obviously remove that.

The code for SRV2, follows:

Note i didnt change the RegistrationKey as its not needed, but of course you can, as long
as you remember to change it in the LCM script as well.

And most importantly, we are NOT using IsComplianceServer at all. I used it in the script
just to not have any doubts and not take it for granted that $false is the default value :slight_smile:

CreatePullServer_SRV2.ps1

# Configuration for creating a PullServer for ReportServer V2 (PS 5.0)
Configuration CreatePullServer

{

     param

    (

         [ValidateNotNullOrEmpty()][string] $ComputerName,

         [ValidateNotNullOrEmpty()][String] $CertificateThumbprint

    )


    Import-DSCResource -ModuleName xPSDesiredStateConfiguration -ModuleVersion 3.7.0.0


    Node $ComputerName

    {

         WindowsFeature DSCServiceFeature

        {

            Ensure     = 'Present'

            Name       = 'DSC-Service'

        }


        xDscWebService PSDSCPullServer

        {

             Ensure                       =  'Present'

             EndpointName                 =  'PSDSCReportServer'

             Port                         =  8080

             PhysicalPath                 =  'D:\WebSites\PSDSCReportServer'

             CertificateThumbPrint        =  $CertificateThumbprint

             State                        =  'Started'

             ModulePath                   =  'C:\Program Files\WindowsPowerShell\DscService\Modules'

             ConfigurationPath            =  'C:\Program Files\WindowsPowerShell\DscService\Configuration'

             RegistrationKeyPath          =  'C:\Program Files\WindowsPowerShell\DscService'

             AcceptSelfSignedCertificates =  $false

             IsComplianceServer           =  $false

             DependsOn                    =  '[File]RegistrationKeyFile'

         }

 
          File RegistrationKeyFile

         {

            Ensure          = 'Present'

            Type            = 'File'

            DestinationPath = 'C:\Program Files\WindowsPowerShell\DscService\RegistrationKeys.txt'

            Contents        = '5e2e5153-62b8-44a3-958e-198eafc7218a'

            DependsOn       = '[WindowsFeature]DSCServiceFeature'

         }

    }

}

# Certificate should also be installed at the target server beforehand

$myCertPath = '.\DSCPullServer.pfx'
$myCertThumbprint = (Get-PfxCertificate -FilePath $myCertPath).Thumbprint
 

CreatePullServer -ComputerName SRV2 -CertificateThumbprint  $myCertThumbprint -OutputPath  '.\'

Start-DscConfiguration -ComputerName SRV2 -path '.\'  -Force -Wait -Verbose 

And last but not least SRV3 LCM script

MetaConfig_SplitReport.ps1

# Configuration for creating a LCM V2 (PS 5.0)
[DSCLocalConfigurationManager()]

Configuration LCMMetaConfig

{

     param

    (

         [ValidateNotNullOrEmpty()][string] $ComputerName

    )
    

    node $ComputerName

    {

         Settings

        {

            RefreshMode='Pull'

            ConfigurationMode              = 'ApplyAndMonitor'

            ActionAfterReboot              = 'ContinueConfiguration'

            RebootNodeIfNeeded             = $false

            ConfigurationModeFrequencyMins = '15'

            RefreshFrequencyMins           = '30'

            AllowModuleOverwrite           = $true

        }

 
         ConfigurationRepositoryWeb PullServerConfig

        {

            ServerURL                     = 'https://SRV1:8080/PSDSCPullServer.svc'

            RegistrationKey               = '5e2e5153-62b8-44a3-958e-198eafc7218a'

            ConfigurationNames            = @("SRV_Base")

        }
 

         ReportServerWeb ReportServerConfig

        {

            ServerURL                    = 'https://SRV2:8080/PSDSCReportServer.svc'

            RegistrationKey              = '5e2e5153-62b8-44a3-958e-198eafc7218a'

        }

    }

}

 

LCMMetaConfig -ComputerName SRV3 -OutputPath '.\' 

Set-DscLocalConfigurationManager -ComputerName SRV3 -Path '.\'  -Verbose


Initialy, you do not want to split the locations.

Unless you manage 1000 servers, then you might say the traffic back and forth
especialy every 30 min (if thats the LCM settings you set) plus pulling the resources
when there are changes, might be an excess on the network bandwith.
Even more if the server you installed the Pull Server on, isnt a dedicated one and has
more web sites.

The main reason the separation was made is basically for Push mode, to allow those
using that method to still get a central repository for node status.

Remember that in LCM v5, you can now query two new parameters

LCMState
LCMStateDetail

To get the current state information, but its limited and obviously holds no history.

More Info:
https://msdn.microsoft.com/en-us/powershell/wmf/dsc_statestatus

OK, Pull Server and Report Server sorted.
What do i do with it exactly ??

Well the Report Server is an OData endpoint which exposes the information via REST
API. This means you can use Invoke-WebRequest to get JSON back and then parse it.

This is a bit out of scope for this time, but do follow the link and im sure
you can find other links generaly explaining what Invoke-WebRequest is and how to
handle JSON objects.

https://msdn.microsoft.com/en-us/powershell/dsc/reportserver

Hope this clears some questions previously posted and maybe future ones.

Changes will be done to this post to reflect changes in the future :slight_smile:

Have fun DSCing or maybe Complying ? :slight_smile:

Arie H.

Thanks, Arie!

Pleasure.

Do go over https://powershell.org/forums/topic/reportserver-or-complianceserver/

If you havenā€™t yet for Erics post. Still hope he can re-confirm my question as it potentially changes my post and script.

@Arie, going by your example above. If I wanted to setup a pull server and a reporting server on 1 server then all I need to do is just setup a Pull server, and then point nodes to the Pull server address and tell them to use that as a reporting server?

So in your example, SRV1 and SRV2 are both pull servers and reporting servers, youā€™re just telling the nodes to use SRV2 for reporting?

Yes exactly to the second question. Any creation of a Pull server creates a local database, for holding node information.

Thatā€™s why you need to register a node by RegistrationKeys. So yes, the lcm of the node will register to one server for configuration and will register to the other pull server for reporting, it will just not pull configurations from the second server.

I doubt people will use this in a pull server method unless, as I pointed in my post, they have allot of nodes to manage or are seeing heavy traffic to the iis web server as its not a dedicated pull server. The ability to point the lcm to a Reporting sever was mainly done for Push mode.

The only other usage in a Pull Server scenario is if they use PartialConfiguriation, then potentialy you can get one partial config from SRV1 and a second partial config from SRV2 while reporting to SRV2. I wonder if they thought about ā€œpartial reportingā€ when we use partial configs. Food for thought and tests I guess.

As for your first question, my understanding and logic as its based on the online documentation, is that if you create a pull server it will act as all three components, config, resource, reporting by default, with out you needing to set anything in the LCM apart for ConfigurationRepositoryWeb.

Howeverā€¦if you follow the link in last post and read Ericā€™s reply it kinda changes things which is why I asked for a reconfirmation. Judging by Nanaā€™s reply, and the latest online documentation, then my initial thought was right and you donā€™t need to use any ReportServerWeb block in the LCM if you want that one pull server to be all the mini roles.

Hi Arie, I had a go at this today. I could not get this new PS5 ReportServer working. As far as I can tell it doesnā€™t seem to exist at all. I tried a WIDE range of configurations and multiple server deployments / snapshot reverting.

I get this in event log ā€œHttp Client 4eaf16f4-5787-4918-a5bf-8eade295b015 failed for WebReportManager for configuration The attempt to send status report to the server https://labserver01.lab.local:8080/PSDSCPullServer.svc/Node(ConfigurationId=ā€˜4eaf16f4-5787-4918-a5bf-8eade295b015ā€™)/SendStatusReport returned unexpected response code BadRequest.ā€

I can say that the ā€œComplianceā€ system appears to work perfectly in PS5. See belowā€¦

Pull Server Config

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

xDscWebService PSDSCPullServer
{
    Ensure                  = 'Present'
    EndpointName            = 'PSDSCPullServer'
    Port                    = 8080
    PhysicalPath            = 'C:\inetpub\wwwroot\PSDSCPullServer'
    CertificateThumbPrint   = $Node.DSCHTTPSThumprint
    ModulePath              = 'C:\Program Files\WindowsPowerShell\DscService\Modules'
    ConfigurationPath       = 'C:\Program Files\WindowsPowerShell\DscService\Configuration'
    State                   = 'Started'
    DependsOn               = '[WindowsFeature]DSCServiceFeature'
}

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

xDscWebService PSDSCComplianceServer
{
    Ensure                  = 'Present'
    EndpointName            = 'PSDSCComplianceServer'
    Port                    = 9080
    PhysicalPath            = 'C:\inetpub\wwwroot\PSDSCComplianceServer'
    CertificateThumbPrint   = $Node.DSCHTTPSThumprint
    State                   = 'Started'
    IsComplianceServer      = $True
    DependsOn               = '[WindowsFeature]DSCServiceFeature','[xDSCWebService]PSDSCPullServer','[WindowsFeature]WinAuth'
}

Node LCM Config

Node $ServerName {
	Settings
    {
		AllowModuleOverwrite = $True
        ConfigurationMode =  $ConfigurationMode
		RefreshMode = 'Pull'
        RefreshFrequencyMins = $RefreshFrequencyMins
        RebootNodeIfNeeded = $RebootIfNeeded
        ActionAfterReboot = 'ContinueConfiguration'
        ConfigurationModeFrequencyMins = $ConfigurationModeFrequencyMins
		ConfigurationID = $GUID
        CertificateID = $CertThumbprint
        DebugMode = $DebugMode
    }

    ConfigurationRepositoryWeb DSCHTTP 
    {
        ServerURL = "https://labserver01.lab.local:8080/PSDSCPullServer.svc"
        AllowUnsecureConnection = -not($Secure)
    }

}

Test 1:

Start-Process -FilePath iexplore.exe -ArgumentList 'https://labserver01.lab.local:9080/PSDSCComplianceServer.svc/$metadata'

Test 2:

(Invoke-RestMethod -Uri 'https://labserver01.lab.local:9080/PSDSCComplianceServer.svc/Status' -UseDefaultCredentials -Method Get -Headers @{Accept="application/json"}).Value

TargetName : 192.168.32.24
ConfigurationId : 9355df0b-2fcf-46f2-a3fb-8877940bc9a4
ServerCheckSum : AF4135C145A1A373AA53C635E34C3087102BEBFBBFEAB32773154758B8C88C01
TargetCheckSum : AF4135C145A1A373AA53C635E34C3087102BEBFBBFEAB32773154758B8C88C01
NodeCompliant : True
LastComplianceTime : 2016-03-22T05:51:45.1207538Z
LastHeartbeatTime : 2016-03-22T05:51:45.1207538Z
Dirty : True
StatusCode : 0

The sample you used is a v4 and not a v5, so ā€œI can say that the ā€œComplianceā€ system appears to work perfectly in PS5.ā€ Needs to be changed to P4.

Iā€™ll run the script again this week to follow the trail, based on the original reply by Eric and update.

Hi Arie, now you are confusion me :wink: Maybe itā€™s better to sayā€¦

ā€œThe PS4 method of reporting works perfectly within PS5ā€.

So PS5 supports a ā€œReporting Serverā€ (new method) and a ā€œCompliance Serverā€ (old method).

The sample I gave was the PS4 reporting method within PS5.

Hehe true. Thatā€™s because PS5 is backward compatible. But youā€™re back to handling GUIDs which is meh :wink:

The Configuration ID method rocks if youā€™re using your own custom built CMDB :wink: in our environment everything is 100% automated when deploying servers. I never have to look at GUIDs.

Registration keys are nice for testing/lab environment (edit the registration key .txt file;-P) but if you have the backend workflow system setup, Configuration IDs are the way to go. Well thatā€™s my personal opinion anyway.

Arie, they have removed IsComplianceServer in xPSDesiredStateConfiguration v3.8.0.0. Noooo! Now I have no way to get a server report from a pull server.

See Remove compliance server and fix db choice by rayhayes Ā· Pull Request #86 Ā· dsccommunity/xPSDesiredStateConfiguration Ā· GitHub

Do you have a working example of using the new method (Report Server)? I canā€™t find any articles or official DSC docs that show you how to setup the new reporting way (what the pull server config and node lcm look like etc). Iā€™m guessing your sample has not been tested because you donā€™t show any report queries. I tried your sample but without the registration keys and it doesnā€™t work (as per my previous post). I really hope they havenā€™t made registrations keys a requirement for the new reporting method. Itā€™s not documented anywhere.

ā€¦and there goes the backward compatibility I was referring to.
At least they removed the bug forcing us to use mdb as a data source which led to inability to install pull server on core without GUIā€¦

Use 3.7.0.0 or donā€™t swap to wmf 5.0.
Iā€™ll push my testing.

I heavily use partial configurations so Iā€™m stuck with PS5. Iā€™ll be forced to stay on 3.7.0.0 unless your test shows that this new mystical reporting system actually works :wink: Looking forward to your tests (hopefully with and without registration keys).

I left an issue on their github repo just to be sure.

I just added my 2 cents to your github repo post. Hopefully someone can clear up the confusions.

https://github.com/PowerShell/xPSDesiredStateConfiguration/issues/93

Are you sure you used my scripts ?
Going over the error message you posted before your scripts is a bit mind boggling as youā€™re getting an error about a ConfigurationID, which I dont use as its a v4 method. If anything the error should have been mentioning the AgentIDā€¦

It seems the latest updates to the online doc and 3.8.0.0 do require you to add a ReportServerWeb block to the LCM in cases where the pull server is also your report server. Though theres some inconsistency in the samples so i opened a new issue and closed the first one.

Hi Arie, I now have proof (at least I think so) that the new report server system in PS v5 does not work in a Configuration ID setup.

I created Sample_RegistrationKeys.ps1 which sets up a DSC Pull Server, configures a nodes LCM and then retrieves some report data.

I then cloned Sample_RegistrationKeys.ps1 to Sample_ConfigurationIDs.ps1 and simply commented out the registration key related stuff and added a configuration ID.

Sample_RegistrationKeys.ps1 (h-ttps://gist.github.com/Zuldan/c679bae20de0c2dcf1aa)
Sample_ConfigurationIDs.ps1 (h-ttps://gist.github.com/Zuldan/c0fd292838b8d35c6383)

(remove the ā€˜-ā€™ from https)

Sample_RegistrationKeys.ps1 is able to retrieve report data
Sample_ConfigurationIDs.ps1 cannot retrieve report data

I think the clue may sit here https://msdn.microsoft.com/en-us/powershell/dsc/pullserver

ā€œThe lack of the ConfigurationID property in the metaconfiguration file implicitly means that pull server is supporting the V2 version of the pull server protocol so an initial registration is required. Conversely, the presents of a ConfigurationID means that the V1 version of the pull server protocol is used and there is no registration processing.ā€

Iā€™m taking that as when a ConfigurationID is used, the reporting mode is v1 and the new Report Server only works with reporting mode v2?

This error appears in the the DSC WinEvent log on the node when Sample_ConfigurationIDs.ps1 is used.

Log Name: Microsoft-Windows-DSC/Operational
Source: Microsoft-Windows-DSC
Date: 3/23/2016 4:32:51 PM
Event ID: 4260
Task Category: None
Level: Error
Keywords:
User: SYSTEM
Computer: LABSERVER02
Description:
Job {AAFECED4-F0B8-11E5-80C7-005056B644A2} :
Http Client 1d545e3b-60c3-47a0-bf65-5afc05182fd1 failed for WebReportManager for configuration The attempt to send status report to the server https://LABSERVER01:8080/PSDSCPullServer.svc/Node(ConfigurationId=ā€˜1d545e3b-60c3-47a0-bf65-5afc05182fd1ā€™)/SendStatusReport returned unexpected response code BadRequestā€¦

If you could kindly have a peak at the samples when you get a chance to see if maybe Iā€™m doing something wrong. If you canā€™t see any issues then Iā€™m going to raise it on UserVoice or Github and request the owners of the xPSDesiredStateConfiguration repo not to remove IsComplianceServer yet, because if they do, people who use ConfigurationIDā€™s will have no way to report if they want to use v3.8.0.0

The scripts seem ok, except the GetReport function at the end of the ConfigurationID sample needs to point to ā€œ$serviceURL/Nodes(ConfigurationID=ā€˜$ConfigIDā€™)/Reportsā€

And the GetReport function usage needs to change to get the ConfigurationID

Perfect! thanks for the heads up. Iā€™ll make the adjustment and raise an issue on Github with the samples.

Some other questions you may know the answer toā€¦

  1. When retrieving report data for an agentid (registration key mode), how do you tell if the node is Compliant or not? There is a field that says ā€œSuccessā€ but that could mean anything.

  2. How do you retrieve the status of all nodes in the report database? This was pretty easy to do with a compliance server.