Remove a DSC config

  • Context:

I’ve recently setup a Desired State Configuration (DSC) configuration on a computer that had the Hyper-V role installed.
The DSC configuration was supposed to apply once and reboot the computer once done.

  • Problem:

I was using a script resource but I failed to make it bulletproof.
The test part of the script resource always failed and returned false when the Hyper-V role was present.
It created a reboot loop.
I had to find a quick way to stop the DSC config to apply and remove it.

  • Solution:
Stop-DscConfiguration -Force -Verbose
Remove-DscConfigurationDocument -Stage Current,Pending -Force -Verbose

Advertisements

Register a remote endpoint with DSC

  • Context:

I’ve been using Desired State Configuration (DSC) recently on a Windows 10 computer to create a custom remote endpoint configuration.

  • Issues:

Using the Register-PSSessionConfiguration with a -Force switch parameter breaks the push.
The error message says:
The WS-Management service cannot process the operation. The operation is being attempted on a client session that is unusable. This may be related to a recent restart of the WS-Management service. Please create a new client session and retry the operation if re-executing the operation does not have undesired behavior.
+ CategoryInfo : InvalidOperation: (root/Microsoft/…gurationManager:String) [], CimException
+ FullyQualifiedErrorId : HRESULT 0x803381fa
+ PSComputerName : localhost

If you specify a -Verbose switch parameter when you push the configuration with Start-DscConfiguration cmdlet, the verbose stream of the Register-PSSessionConfiguration cmdlet is still streamed although it’s explicitly turned off.

  • Solution:

The solution consisted in:

  1. turning off the verbose stream from the Register-PSSessionConfiguration cmdlet by enclosing this cmdlet in scriptblock executed by the Start-Job cmdlet.
  2. removing the -Force switch parameter that restarts and breaks the push
  3. using a -NoRestartService switch parameter with the Register-PSSessionConfiguration cmdlet

Create an ASCII encoded file with DSC

  • Context:

I’ve been using Desired State Configuration (DSC) recently to create a cmd file on every users’ desktop.

  • Issue:

DSC creates a UTF8 file with a BOM. The file is executed but not its first line. The File DSC resource doesn’t allow to specify an encoding

  • Solution:

I’ve used a File resource to create the content and a dependent child script resource that removes the BOM.

# Remove BOM because File DSC resource creates a UTF8 file with BOM
[System.IO.File]::WriteAllLines(
  'C:\Users\Public\Desktop\myCmdFile.cmd',
  (Get-Content -Path 'C:\Users\Public\Desktop\myCmdFile.cmd'), 
  (New-Object System.Text.UTF8Encoding($False))
)

Minimal WSMan requirement to push locally a Desired State Configuration

I’ve been working on a deployment scenario where I’ll provision new computers from a PBR (Push Button Reset) image.

These laptops will run Windows 8.1 and the PBR image is actually a sysprep image that is configured to run a post-install script.

When the PC is provisionned or reset, the PBR image is applied/expanded to the C: drive and the post-install script is run at the end of the OOBE (Out-of-Box Experience) phase, just before the user can logon.

To configure Windows Updates settings, some registry keys, services,… DSC (Desired State Configuration) is the way to go as it’ll ensure the PC remains compliant even if there’s a drift later between 2 resets or/and the PC isn’t connected to any network.

As you may know DSC depends on WSMan and not on PSRemoting.
There’s a myth about PSRemoting that was uncovered by PowerShell Magazine and Windows PowerShell MVP Aleksandar Nikolic:
DSC-RemotingMyth

If I push a DSC config without configuring WSMan, I hit a wall and get this message:
The client cannot connect to the destination specified in the request.
Verify that the service on the destination is running and is accepting requests.
Consult the logs and documentation for the WS-Management service running on the destination, most commonly IIS or WinRM.
If the destination is the WinRM service, run the following command on the destination to analyze and configure the WinRM service: “winrm quickconfig”.
+ CategoryInfo : ConnectionError: (root/Microsoft/…gurationManager:String) [], CimException
+ FullyQualifiedErrorId : HRESULT 0x80338012
+ PSComputerName : localhost


I’d also get the above error message whenever the WinRM service is stopped or the WSMan listener is absent.

To fix it, I should run the following the Set-WSManQuickConfig because the computer isn’t joined to a domain.

Set-WSManQuickConfig -SkipNetworkProfileCheck

This would enable the WinRM firewall rule for the ‘Public’ profile and expose the WinRM to the localNetwork it’s connected to.
It would also set the LocalAccountTokenFilterPolicy registry value to remove the UAC remote restriction.

The above steps aren’t required to push locally (vs. over the wire) a DSC configuration.
The attack surface can actually be reduced so that the DSC configuration can only be pushed locally.
The non-domain joined Windows 8.1 PBR images can leverage DSC as soon as I:

# 1. Enable and start the WinRM service
Stop-Service -Name WinRM -PassThru | 
Set-Service -StartupType Automatic -PassThru | 
Start-Service

# 2. Enable and restrict the firewall rules 
# to localhost instead of LocalNetwork
Get-NetFirewallRule -Name @(
    'WINRM-HTTP-In-TCP', # Pubic
    'WINRM-HTTP-In-TCP-NoScope') | #Domain,Private
Enable-NetFirewallRule -PassThru | 
Get-NetFirewallAddressFilter | 
Set-NetFirewallAddressFilter -RemoteAddress "127.0.0.1"

# 3. Add a listener (the firewall already enforces a restriction)
Get-ChildItem -Path WSMan:\localhost\Listener -Include listener* | 
Remove-Item -Recurse
New-WSManInstance winrm/config/Listener -SelectorSet @{
    Address="*";
    Transport="http";
}

# 4. Disable Kerberos, not required in workgroup for local authentication
Set-Item -Path WSMan:\localhost\Service\Auth\Kerberos  -Value $false -Force
Set-Item -Path WSMan:\localhost\Service\Auth\Negotiate -Value $true  -Force

Voilà, my post-installation DSC configuration can be pushed locally whenever Windows 8.1 is reset on the device.

Deploy Sysmon with PowerShell Desired State Configuration

The technet page of sysmon 2.0 provided the following advanced configuration sample:

@'
<Sysmon schemaversion="1.0">
    <Configuration>
        <!-- Capture all hashes -->
        <Hashing>*</Hashing>
        <!-- Enable network logging -->
        <Network />
    </Configuration>
    <Rules>
        <!-- Log all drivers except if the signature -->
        <!-- contains Microsoft or Windows -->
        <DriverLoad default="include">
        <Signature condition="contains">microsoft</Signature>
        <Signature condition="contains">windows</Signature>
        </DriverLoad>
        <!-- Do not log process termination -->
        <ProcessTerminate />
        <!-- Log network connection if the destination port equal 443 -->
        <NetworkConnect>
        <DestinationPort>443</DestinationPort>
        </NetworkConnect>
    </Rules>
</Sysmon>
'@


If you want to do more advanced stuff, my fellow Windows PowerSell MVP Carlos Perez wrote an awesome module named Posh-Sysmon that would help you create XML configuration for Sysmon.

April 20, 2015, Sysmon 3.0 was published 🙂
It delivers a version 2.0 of the XML schema which looks like this:

@'
<Sysmon schemaversion="2.0">
 <!-- Capture all hashes -->
 <HashAlgorithms>*</HashAlgorithms>
 <EventFiltering>
  <!-- Log all drivers except if the signature -->
  <!-- contains Microsoft or Windows -->
  <DriverLoad onmatch="include">
   <Signature condition="contains">microsoft</Signature>
   <Signature condition="contains">windows</Signature>
  </DriverLoad>
  <!-- Do not log process termination -->
  <ProcessTerminate onmatch="include"/>
  <!-- Log network connection if the destination port equal 443 -->
  <NetworkConnect onmatch="include">
   <DestinationPort>443</DestinationPort>
  </NetworkConnect>
 </EventFiltering>
</Sysmon>
'@

sysmon.v3.sample.config

In March 2015, I’ve asked the following question to Thomas Garnier who co-authored this awesome sysmon tool with Mark Russinovich.

Unfortunately, there’s no way currently in version 2.0 or 3.0 to dump the configuration directly to XML 😐
But, that’s not a huge problem for PowerShell 😉
The only trick that made the reverse engineering experience consistent was to read the dumped rules from the bottom up 😎

Let’s see a capture of the DSC configuration that deploys sysmon when it runs for the first time:
deploy-sysmon.1
If I run the same configuration a 2nd time, all the TEST phases performed are skipped (which is a good thing):
deploy-sysmon.2

Quick and dirty!
But Sysmon got deployed and configured through Desired State Configuration on a Windows Server 2012 R2 and its built-in PowerShell version 4.0

PS: If you check the different revisions of the gist file, you can get a DSC configuration that works against sysmon version 2.0 😀

Deploy and configure EMET 5.2 with PSDSC

I’ve been using EMET (The Enhanced Mitigation Experience Toolkit) and advocating for it since 2010…

Now with DSC (Desired State Configuration) and PowerShell, it can be fairly easy to deploy and configure it compared to my previous post about Applocker.

I’ve created two scripts, one to install EMET and one to remove it (because of continuous delivery of every product, right?) that can be run as of Windows 8.1 and Windows 2012 R2. Yes, DSC is built-in PowerShell version 4.0 that was released along with Windows 8.1 in August 2013.

The configuration of EMET 5.2 is based on XML files although EMET 5.2 can also get its configuration by GPO in a domain environment.
The XML configuration that you’ll find below is an export made with the EMET_Conf.exe after an import from the “Recommended Software.xml” profile provided under “C:\Program Files (x86)\EMET 5.2\Deployment\Protection Profiles\”.
Although I probably could, I chose to not handle Certificate Pinning rules because a new GUID for each rule is generated by the XML export made with EMET_conf.exe. If I did, it would have complicated the comparison made by the Test-TargetResource and probably slow it down.
I know that the built-in package DSC resource can download the file from the web if I specify a URL as a package source but I preferred to rely on my own custom script to download the file as it performs some additional steps such as checking the integrity of the file (is it the hash we expect) and whether the file is digitally signed (and recognized as such for the time being).


The initial download takes around 9 seconds.
DSC-Install-EMET52.download
Let’s see what output we get when I first push the configuration:
DSC-Install-EMET52.run1.Package
DSC-Install-EMET52.run1.Config

If I push the configuration as 2nd time, all TEST steps for each resource return false because they are in their expected state and all the SET operations are skipped:
DSC-Install-EMET52.run2

Here’s what happens when I remove EMET 5.2 for the first time if it’s present:
DSC-remove-EMET-1
If I run the removal a 2nd time, I get:
DSC-remove-EMET-2

Configure Applocker with Desired State Configuration

I was working with Desired State Configuration and wondered why a custom DSC resources hasn’t been published yet for Applocker.
Bitlocker has already its experimental DSC resource. Why Applocker doesn’t have one?

I also wondered what it really takes to configure Applocker with PowerShell Desired State Configuration.

First a quick disclaimer is required:

  • Do not apply this on your servers/workstations if you don’t understand what Applocker does.
  • The deny rules are just examples. I don’t have anything against these software editors.
  • Yes, I know that’s not the most secure Applocker configuration as the example below mixes both a very permissive (default) whitelist and a very specific blacklist.

Let’s also quickly examine the Applocker requirements:

  • Applocker rules can be imported from/exported to a XML file using the GUI or using the cmdlets of the built-in Applocker module (it exists since PowerShell version 2.0 on Windows 7).
    XML seems to better way to go although the Applocker policy can be found in the registry under the HKLM\SOFTWARE\Policies\Microsoft\Windows\SrpV2 key.
  • The applocker policy depends on the ‘Application Identity’ service to be enforced.

Based on the above light requirements, it seems that built-in DSC resources would actually make it and allow to deploy an Applocker policy locally.

To configure Applocker, I need first to export the Applocker policy to XML and dump its indented representation to a file.
To solve the indentation issue, I’ve used the Format-XML function written by Jeffrey Snover that you can find on this page.

# http://blogs.msdn.com/b/powershell/archive/2008/01/18/format-xml.aspx
function Format-XML ([xml]$xml, $indent=2)
{
    $StringWriter = New-Object System.IO.StringWriter
    $XmlWriter = New-Object System.XMl.XmlTextWriter $StringWriter
    $xmlWriter.Formatting = "indented"
    $xmlWriter.Indentation = $Indent
    $xml.WriteContentTo($XmlWriter)
    $XmlWriter.Flush()
    $StringWriter.Flush()
    Write-Output $StringWriter.ToString()
}
Format-XML ([xml](Get-AppLockerPolicy -Effective -Xml)) -indent 2 | 
Out-File -FilePath ~/Documents\Applocker-pol.xml -Encoding ascii

The second step consists in creating the file locally with the XML content thanks to the built-in File DSC resource.
To decide whether to apply the policy, I’ll export the current effective Applocker policy and compare it to the XML file.
Once the Applocker policy is applied, I’ll start the required service.

Here is what the DSC configuration looks like to deploy locally an Applocker policy.

It only takes a service, a file, a script resource and less than 5 seconds to deploy an Applocker policy locally. 😎


If I apply it one more time, we can see that all the tests performed are skipped as my system is already in the desired state.


If I open the local group policy editor, we can see the following:

The above configuration was just for testing purposes, right 😉
Here’s how to achieve the exact opposite, i.e., clear the local Applocker policy and stop the required service.

Let’s remove the existing Applocker local policy for the 1rst time:

Again, applied one more time, we can see that all the tests performed are skipped as my system is already in the desired state.


Nice, isn’t it? DSC and PowerShell bring more than just automation! I love it 😀