registry_key

Use the registry_key InSpec audit resource to test key values in the Windows registry.

Syntax

A registry_key resource block declares the item in the Windows registry, the path to a setting under that item, and then one (or more) name/value pairs to be tested.

Use a registry key name and path:

describe registry_key('Task Scheduler','HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Schedule') do
  its('Start') { should eq 2 }
end

Use only a registry key path:

describe registry_key('Task Scheduler','HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Schedule') do
  its('Start') { should eq 2 }
end

Or use a Ruby Hash:

describe registry_key({
  name: 'Task Scheduler',
  hive: 'HKEY_LOCAL_MACHINE',
  key: '\SYSTEM\CurrentControlSet\services\Schedule'
}) do
  its('Start') { should eq 2 }
end

Registry Key Path Separators

A Windows registry key can be used as a string in Ruby code, such as when a registry key is used as the name of a recipe. In Ruby, when a registry key is enclosed in a double-quoted string (" "), the same backslash character (\) that is used to define the registry key path separator is also used in Ruby to define an escape character. Therefore, the registry key path separators must be escaped when they are enclosed in a double-quoted string. For example, the following registry key:

HKCU\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Themes

may be encloused in a single-quoted string with a single backslash:

'HKCU\SOFTWARE\path\to\key\Themes'

or may be enclosed in a double-quoted string with an extra backslash as an escape character:

"HKCU\\SOFTWARE\\path\\to\\key\\Themes"

Please make sure that you use backslashes instead of forward slashes. Forward slashes will not work for registry keys.

# The following will not work:
# describe registry_key('HKLM/SOFTWARE/Microsoft/NET Framework Setup/NDP/v4/Full/1033') do
#   its('Release') { should eq 378675 }
# end
# You should use:
describe registry_key('HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\1033') do
  its('Release') { should eq 378675 }
end

Matchers

This InSpec audit resource has the following matchers:

be

Use the be matcher to use a comparison operator—= (equal to), > (greater than), < (less than), >= (greater than or equal to), and <= (less than or equal to)—to compare two values: its('value') { should be >= value }, its('value') { should be < value }, and so on.

children

The children matcher return all of the child items of a registry key. A regular expression may be used to filter child items:

describe registry_key('Key Name', '\path\to\key').children(regex)
  ...
end

For example, to get all child items for a registry key:

describe registry_key('Task Scheduler','HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet').children do
  it { should_not eq [] }
end

The following example shows how find a property that may exist against multiple registry keys, and then test that property for every registry key in which that property is located:

describe registry_key({
  hive: 'HKEY_USERS'
}).children(/^S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]{3,}\\Software\\Policies\\Microsoft\\Windows\\Installer/).each { |key|
    describe registry_key(key) do
      its('AlwaysInstallElevated') { should eq 'value' }
    end
  }

cmp

Use the cmp matcher compare two values, such as comparing strings to numbers, comparing a single value to an array of values, comparing an array of strings to a regular expression, improving the printing of octal values, and comparing while ignoring case sensitivity.

Compare a single value to an array:

describe some_resource do
  its('users') { should cmp 'root' }
  its('users') { should cmp ['root'] }
end

Compare strings and regular expressions:

describe some_resource do
  its('setting') { should cmp /raw/i }
end

Compare strings and numbers:

describe some_resource do
  its('setting') { should eq '2' }
end

vs:

describe some_resource do
  its('setting') { should cmp '2' }
  its('setting') { should cmp 2 }
end

Ignoring case sensitivity:

describe some_resource do
  its('setting') { should cmp 'raw' }
  its('setting') { should cmp 'RAW' }
end

Printing octal values:

describe some_resource('/proc/cpuinfo') do
  its('mode') { should cmp '0345' }
end

expected: 0345
got: 0444

eq

Use the eq matcher to test the equality of two values: its('Port') { should eq '22' }.

Using its('Port') { should eq 22 } will fail because 22 is not a string value! Use the cmp matcher for less restrictive value comparisons.

exist

The exist matcher tests if the registry key is present:

it { should exist }

have_property

The have_property matcher tests if a property exists for a registry key:

it { should have_property 'value' }

have_property_value

The have_property_value matcher tests if a property value exists for a registry key:

it { should have_property_value 'value' }

have_value

The have_value matcher tests if a value exists for a registry key:

it { should have_value 'value' }

include

Use the include matcher to verify that a string value is included in a list: its('list') { should include 'string' }.

match

Use the match matcher to check if a string matches a regular expression: its('string') { should_not match /regex/ }.

name

The name matcher tests the value for the specified registry setting:

its('name') { should eq 'value' }

Any name with a dot will not work as expected: its('explorer.exe') { should eq 'test' }. This issue is tracked in https://github.com/chef/inspec/issues/1281

# instead of:
# its('explorer.exe') { should eq 'test' }
# use the following solution:
it { should have_property_value('explorer.exe', :string, 'test') }

Examples

The following examples show how to use this InSpec audit resource.

Test the start time for the Schedule service

describe registry_key('Task Scheduler','HKEY_LOCAL_MACHINE\...\Schedule') do
  its('Start') { should eq 2 }
end

where 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Schedule' is the full path to the setting.

Use a regular expression in responses

describe registry_key({
  hive: 'HKEY_LOCAL_MACHINE',
  key: 'SOFTWARE\Microsoft\Windows NT\CurrentVersion'
}) do
  its('ProductName') { should match /^[a-zA-Z0-9\(\)\s]*2012\s[rR]2[a-zA-Z0-9\(\)\s]*$/ }
end