Windows Infrastructure Testing and Compliance with InSpec

Written by Christoph Hartmann

InSpec is an infrastructure testing and compliance tool that allows you to write re-usable tests for your IT components. InSpec tests can easily be used in development and production environments to shift Compliance left. This blog post will highlight how you can leverage InSpec on Windows.

Install InSpec on Windows

First things first: We need InSpec on our workstation. There are two packages that offer an easy way to get started. For production and standalone environments, I recommend the InSpec package. Alternatively there is ChefDK, if you need Chef + Test-Kitchen + InSpec. You can download both packages from https://downloads.chef.io/.

Another option is to install InSpec via a Powershell script:

. { iwr -useb https://omnitruck.chef.io/install.ps1 } | iex; install -project inspec

Once InSpec is installed, run inspec version to verify that the installation was successful.

Write your first test

In my case, I am going to use Visual Studio Code to write the InSpec test. Open Powershell and create a new directory:

# create a directory for the test
md inspec
cd .\inspec
# open Visual Studio Code
code .

Create new directory for InSpec tests

Now, create a new file in Visual Studio Code and write down the first InSpec test:

describe service('DHCP Client') do
  it { should be_installed }
  it { should be_running }
end

This is all we need to test if the DHCP Client service is installed and running. Save the file and let’s execute the test.

Write InSpec tests in VSCode

Execute InSpec from Powershell:

inspec exec .\test.rb

Execute InSpec test

Run InSpec tests against a remote Windows machine

I passed the hello world of InSpec by running the first test on our workstation. As a next step, we run the same test against a remote Windows 2012 R2 server. We will use the same InSpec command with additional target information:

inspec exec test.rb -t winrm://Administarator@hostname -p 'P@ssword'

Execute InSpec test remotely

With a few commands, we executed an InSpec test against a local workstation and a remote server.

Resources for Windows

Above, we explained how an InSpec test is created and executed. To make this experience great, InSpec ships with a number of resources optimized for Windows environments. Those resources range from core operating system essentials to application components.

Verify Windows settings and configuration:

Audit Windows security settings:

Run custom scripts:

Verify IIS configuration:

More resources are available and documented at InSpec Docs.

Verify configuration of the Windows operating system

The following example illustrate the use of the file, user, users, package and windows_taks resource.

The result on my Windows 10 workstation will return:

Run InSpec operating system checks

Security checks for Windows

If you are interested in operating system hardening for Windows, you need to be able to verify registry_key, security_policy or audit_policy.

Have a look at Administer Security Policy Settings,User Rights Assignment, Privilege Constants and Audit Policy to learn more about possible settings.

Run security checks

Reuse existing Powershell or VBScript in InSpec

InSpec also supports running Powershell and VBScript. This allows you to re-use existing scripts inside InSpec. powershell and vbscript resources provide the required capabilities to embed scripts in InSpec.

script = <<-EOH
  Write-Output 'hello'
EOH

describe powershell(script) do
  its('stdout') { should eq "hello\r\n" }
  its('stderr') { should eq '' }
end

Besides Powershell, InSpec supports vbscript, too:

script = <<-EOH
  WScript.Echo "hello"
EOH

describe vbscript(script) do
  its('stdout') { should eq "hello\r\n" }
end

Application testing with InSpec

In addition to operating system checks, we can test IIS configurations with InSpec as well. The following example demonstrates tests for an out-of-the-box IIS server.

Compliance

Above, we introduced InSpec as an infrastructure testing tool. For compliance, additional metadata can be attached around describe tests. The following example shows the use of criticality (impact), title, tags (tag) and references (ref).

control 'windows-base-102' do
  impact 1.0
  title 'Anonymous Access to Windows Shares and Named Pipes is Disallowed'
  tag cis: ['windows_2012r2:2.3.11.8', 'windows_2016:2.3.10.9']
  ref 'CIS Microsoft Windows Server 2012 R2 Benchmark'
  ref 'CIS Microsoft Windows Server 2016 RTM (Release 1607) Benchmark'
  describe registry_key('HKLM\System\CurrentControlSet\Services\LanManServer\Parameters') do
    it { should exist }
    its('RestrictNullSessAccess') { should eq 1 }
  end
end

In most cases, you do not want to start from scratch to develop compliance benchmarks. The DevSec.io project already provides industry best-practices for Linux and Windows operating systems. The Windows benchmark is currently in development and contributions are welcome to cover more areas. Let’s run the DevSec Windows Baseline quickly:

inspec exec https://github.com/dev-sec/windows-baseline

Are you compliant?

Run DevSec Windows Baseline

I recommend you have a look at the following DevSec profiles:

Those benchmark already support Windows 2012+, Windows 2016 and Windows Nano.

Summary

This blog post covered the following:

  • InSpec installation on Windows
  • InSpec resources for Windows
  • Execute InSpec tests locally and remotely
  • InSpec Compliance profiles for Windows

You should be prepared to start your first tests with InSpec in your own environment. If you feel that something is missing, please let me know.