Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, teacher and consultant. Jeff has written for numerous online sites and print publications and is a frequent speaker at technology conferences and user groups. His latest book is PowerShell Scripting and Toolmaking.

How to Query the DSC Compliance Server

If you’ve been paying attention to PowerShell, then you’ve probably picked up on the fact the Desired State Configuration (DSC) is the next big thing. Microsoft is devoting a lot of resources to DSC and you’ve most likely seen a lot of discussion about it in the PowerShell community. I’m going to assume you at least have a passing understanding of the technology, because I want to talk about a feature that I think will be important to you but one that you probably don’t know much about.

When you set up an HTTP pull server, you can also configure a compliance server. This is a web service designed to capture node information. When a server pulls a configuration, information should be captured by the compliance server. The theory is that you can later query the server to discover servers that are not in compliance with their desired configuration. This is especially important if you aren’t using an ApplyAndAutoCorrect setting. While this is an important feature, there is not a lot of official documentation on it, and I suspect it is still being finalized. What I am going to show you is something I’ve worked on using PowerShell 4.0. Since PowerShell 5.0 is still in preview and possibly changing with each release, I wanted to stick with what you could use in production today. That said, there may be changes with PowerShell 5.0 officially ships. For now, let’s take a look at how you can query a compliance server.

When you set up the compliance server, you define a port and endpoint name. These elements are used to construct a URI to connect to the web service.

You could try opening this in a browser.

Viewing the compliance server from a browser. (Image Credit: Jeff Hicks)
Viewing the compliance server from a browser. (Image Credit: Jeff Hicks) 

Although this isn’t entirely helpful, I can see there are three items. If you examine the source or view with a browser plugin that shows the underlying XML, then you’ll see something like this:

Viewing the source code in the browser. (Image Credit: Jeff Hicks)
Viewing the source code in the browser. (Image Credit: Jeff Hicks)

There is data, but a browser doesn’t help you. However, we can use PowerShell to reveal more information. Here’s a function from a Microsoft blog article that demonstrates how to retrieve node information from a compliance server.

I’ve adjusted the code to set a default value for my compliance server. The function uses Invoke-Webrequest to get the web service and converts the result to a JSON object. You’ll get a result like this:

Yes, you get an object for each node, but it’s far from complete. For example, what is the computer name? All I see is an IP address? What does a StatusCode of 0 really mean?

And the time values make my head hurt trying to convert them into something meaningful. In addition, depending on how you set up your compliance server or where you are querying it, you might need to provide credentials. Because of this, I created a more complete advanced function that incorporates some suggestions I came across from other members of the PowerShell community.

Now I can run a command like this:

Desired State Configuration status. (Image Credit: Jeff Hicks)
Desired State Configuration status. (Image Credit: Jeff Hicks) 

Here’s what a result looks like in more detail:

Detailed result in Windows PowerShell. (Image Credit: Jeff Hicks)
Detailed result in Windows PowerShell. (Image Credit: Jeff Hicks)

I use the Resolve-DNSName cmdlet in this function to find the computer name from the IP address. I also use a hash table to decode the status code to a more descriptive property. Of course, converting the time values to a [datetime] object is pretty easy. The last addition I made was to query the computer for its local configuration manager settings, assuming it is up and running. I thought it would be helpful to see the mode and refresh values. Now at a glance I have a better understanding about the state of a node. Because I am writing objects to the pipeline, I can export or convert the results. I can also filter the results to find non-compliant servers.

The last thing I want to talk about is filtering. In developing my function, it seemed to me that I should be able to filter for a specific IP address.

Judging from the error message in the HTML response, I’m figuring this is a bug. I’ve mentioned it to the PowerShell team at Microsoft and am waiting to hear back from them. In the meantime, I discovered a workaround.

The compliance server uses an oData compliant web service, which means there are rules it should follow. Don’t worry if you don’t know what oData is or how to use it. You shouldn’t. I discovered I could use an oData method like Trim=() in a filter.

In my function, I added code to update the URI if the user needs to filter by IP address. If the user requests to filter by IP Address, I resolve the name and use that IP address in the filter.

Using the get-dscnodestatus cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)
Using the get-dscnodestatus cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks) 

As I mentioned, I think there is still work to be done on the compliance server feature, and I expect it to change. I hope this function will help you out. If you are trying to get up to speed with DSC, there are a number of articles on the Petri IT Knowledgebase. There is coverage in my PowerShell in Depth 2nd edition book, and I have courses on Pluralsight.

Related Topics:

  • PowerShell

    Don't have a login but want to join the conversation? Sign up for a Petri Account